void DebugRenderer::Render() { if (!HasContent()) return; Graphics* graphics = context_->m_Graphics.get(); // Engine does not render when window is closed or device is lost assert(graphics && graphics->IsInitialized() && !graphics->IsDeviceLost()); URHO3D_PROFILE(RenderDebugGeometry); ShaderVariation* vs = graphics->GetShader(VS, "Basic", "VERTEXCOLOR"); ShaderVariation* ps = graphics->GetShader(PS, "Basic", "VERTEXCOLOR"); unsigned numVertices = (lines_.size() + noDepthLines_.size()) * 2 + (triangles_.size() + noDepthTriangles_.size()) * 3; // Resize the vertex buffer if too small or much too large if (vertexBuffer_->GetVertexCount() < numVertices || vertexBuffer_->GetVertexCount() > numVertices * 2) vertexBuffer_->SetSize(numVertices, MASK_POSITION | MASK_COLOR, true); float* dest = (float*)vertexBuffer_->Lock(0, numVertices, true); if (!dest) return; for (unsigned i = 0; i < lines_.size(); ++i) { const DebugLine& line = lines_[i]; dest[0] = line.start_.x_; dest[1] = line.start_.y_; dest[2] = line.start_.z_; ((unsigned&)dest[3]) = line.color_; dest[4] = line.end_.x_; dest[5] = line.end_.y_; dest[6] = line.end_.z_; ((unsigned&)dest[7]) = line.color_; dest += 8; } for (unsigned i = 0; i < noDepthLines_.size(); ++i) { const DebugLine& line = noDepthLines_[i]; dest[0] = line.start_.x_; dest[1] = line.start_.y_; dest[2] = line.start_.z_; ((unsigned&)dest[3]) = line.color_; dest[4] = line.end_.x_; dest[5] = line.end_.y_; dest[6] = line.end_.z_; ((unsigned&)dest[7]) = line.color_; dest += 8; } for (unsigned i = 0; i < triangles_.size(); ++i) { const DebugTriangle& triangle = triangles_[i]; dest[0] = triangle.v1_.x_; dest[1] = triangle.v1_.y_; dest[2] = triangle.v1_.z_; ((unsigned&)dest[3]) = triangle.color_; dest[4] = triangle.v2_.x_; dest[5] = triangle.v2_.y_; dest[6] = triangle.v2_.z_; ((unsigned&)dest[7]) = triangle.color_; dest[8] = triangle.v3_.x_; dest[9] = triangle.v3_.y_; dest[10] = triangle.v3_.z_; ((unsigned&)dest[11]) = triangle.color_; dest += 12; } for (unsigned i = 0; i < noDepthTriangles_.size(); ++i) { const DebugTriangle& triangle = noDepthTriangles_[i]; dest[0] = triangle.v1_.x_; dest[1] = triangle.v1_.y_; dest[2] = triangle.v1_.z_; ((unsigned&)dest[3]) = triangle.color_; dest[4] = triangle.v2_.x_; dest[5] = triangle.v2_.y_; dest[6] = triangle.v2_.z_; ((unsigned&)dest[7]) = triangle.color_; dest[8] = triangle.v3_.x_; dest[9] = triangle.v3_.y_; dest[10] = triangle.v3_.z_; ((unsigned&)dest[11]) = triangle.color_; dest += 12; } vertexBuffer_->Unlock(); graphics->SetBlendMode(lineAntiAlias_ ? BLEND_ALPHA : BLEND_REPLACE); graphics->SetColorWrite(true); graphics->SetCullMode(CULL_NONE); graphics->SetDepthWrite(true); graphics->SetLineAntiAlias(lineAntiAlias_); graphics->SetScissorTest(false); graphics->SetStencilTest(false); graphics->SetShaders(vs, ps); graphics->SetShaderParameter(VSP_MODEL, Matrix3x4::IDENTITY); graphics->SetShaderParameter(VSP_VIEW, view_); graphics->SetShaderParameter(VSP_VIEWINV, view_.Inverse()); graphics->SetShaderParameter(VSP_VIEWPROJ, gpuProjection_ * view_); graphics->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f)); graphics->SetVertexBuffer(vertexBuffer_); unsigned start = 0; unsigned count = 0; if (!lines_.empty()) { count = lines_.size() * 2; graphics->SetDepthTest(CMP_LESSEQUAL); graphics->Draw(LINE_LIST, start, count); start += count; } if (!noDepthLines_.empty()) { count = noDepthLines_.size() * 2; graphics->SetDepthTest(CMP_ALWAYS); graphics->Draw(LINE_LIST, start, count); start += count; } graphics->SetBlendMode(BLEND_ALPHA); graphics->SetDepthWrite(false); if (!triangles_.empty()) { count = triangles_.size() * 3; graphics->SetDepthTest(CMP_LESSEQUAL); graphics->Draw(TRIANGLE_LIST, start, count); start += count; } if (!noDepthTriangles_.empty()) { count = noDepthTriangles_.size() * 3; graphics->SetDepthTest(CMP_ALWAYS); graphics->Draw(TRIANGLE_LIST, start, count); } graphics->SetLineAntiAlias(false); //todo: only set this to false if we switched it on }
void DebugRenderer::Render() { if (lines_.Empty() && noDepthLines_.Empty()) return; Graphics* graphics = GetSubsystem<Graphics>(); Renderer* renderer = GetSubsystem<Renderer>(); if (!graphics || graphics->IsDeviceLost()) return; PROFILE(RenderDebugGeometry); // Cache shaders if (!vs_) vs_ = renderer->GetVertexShader("Basic_VCol"); if (!ps_) ps_ = renderer->GetPixelShader("Basic_VCol"); unsigned numVertices = (lines_.Size() + noDepthLines_.Size()) * 2; // Resize the vertex buffer if too small or much too large if (vertexBuffer_->GetVertexCount() < numVertices || vertexBuffer_->GetVertexCount() > numVertices * 2) vertexBuffer_->SetSize(numVertices, MASK_POSITION | MASK_COLOR, true); float* dest = (float*)vertexBuffer_->Lock(0, numVertices, true); if (!dest) return; for (unsigned i = 0; i < lines_.Size(); ++i) { const DebugLine& line = lines_[i]; *dest++ = line.start_.x_; *dest++ = line.start_.y_; *dest++ = line.start_.z_; *((unsigned*)dest) = line.color_; dest++; *dest++ = line.end_.x_; *dest++ = line.end_.y_; *dest++ = line.end_.z_; *((unsigned*)dest) = line.color_; dest++; } for (unsigned i = 0; i < noDepthLines_.Size(); ++i) { const DebugLine& line = noDepthLines_[i]; *dest++ = line.start_.x_; *dest++ = line.start_.y_; *dest++ = line.start_.z_; *((unsigned*)dest) = line.color_; dest++; *dest++ = line.end_.x_; *dest++ = line.end_.y_; *dest++ = line.end_.z_; *((unsigned*)dest) = line.color_; dest++; } vertexBuffer_->Unlock(); graphics->SetBlendMode(BLEND_REPLACE); graphics->SetColorWrite(true); graphics->SetCullMode(CULL_NONE); graphics->SetDepthWrite(true); graphics->SetScissorTest(false); graphics->SetStencilTest(false); graphics->SetShaders(vs_, ps_); graphics->SetShaderParameter(VSP_MODEL, Matrix3x4::IDENTITY); graphics->SetShaderParameter(VSP_VIEWPROJ, projection_ * view_); graphics->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f)); graphics->SetVertexBuffer(vertexBuffer_); if (lines_.Size()) { graphics->SetDepthTest(CMP_LESSEQUAL); graphics->Draw(LINE_LIST, 0, lines_.Size() * 2); } if (noDepthLines_.Size()) { graphics->SetDepthTest(CMP_ALWAYS); graphics->Draw(LINE_LIST, lines_.Size() * 2, noDepthLines_.Size() * 2); } }
void PlayerGraphics::Update( Actor& a, Graphics& g ) { g.Draw( mdl, skltn, position, rotation, scale ); }
void BatchGroup::Draw(View* view) const { Graphics* graphics = view->GetGraphics(); Renderer* renderer = view->GetRenderer(); if (instances_.Size() && !geometry_->IsEmpty()) { // Draw as individual objects if instancing not supported VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer(); if (!instanceBuffer || geometryType_ != GEOM_INSTANCED) { Batch::Prepare(view, false); graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(geometry_->GetVertexBuffers(), geometry_->GetVertexElementMasks()); for (unsigned i = 0; i < instances_.Size(); ++i) { if (graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, instances_[i].worldTransform_)) graphics->SetShaderParameter(VSP_MODEL, *instances_[i].worldTransform_); graphics->Draw(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount()); } } else { Batch::Prepare(view, false); // Get the geometry vertex buffers, then add the instancing stream buffer // Hack: use a const_cast to avoid dynamic allocation of new temp vectors Vector<SharedPtr<VertexBuffer> >& vertexBuffers = const_cast<Vector<SharedPtr<VertexBuffer> >&> (geometry_->GetVertexBuffers()); PODVector<unsigned>& elementMasks = const_cast<PODVector<unsigned>&>(geometry_->GetVertexElementMasks()); vertexBuffers.Push(SharedPtr<VertexBuffer>(instanceBuffer)); elementMasks.Push(instanceBuffer->GetElementMask()); // No stream offset support, instancing buffer not pre-filled with transforms: have to fill now if (startIndex_ == M_MAX_UNSIGNED) { unsigned startIndex = 0; while (startIndex < instances_.Size()) { unsigned instances = instances_.Size() - startIndex; if (instances > instanceBuffer->GetVertexCount()) instances = instanceBuffer->GetVertexCount(); // Copy the transforms Matrix3x4* dest = (Matrix3x4*)instanceBuffer->Lock(0, instances, true); if (dest) { for (unsigned i = 0; i < instances; ++i) dest[i] = *instances_[i + startIndex].worldTransform_; instanceBuffer->Unlock(); graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(vertexBuffers, elementMasks); graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances); } startIndex += instances; } } // Stream offset supported and instancing buffer has been already filled, so just draw else { graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(vertexBuffers, elementMasks, startIndex_); graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances_.Size()); } // Remove the instancing buffer & element mask now vertexBuffers.Pop(); elementMasks.Pop(); } } }