void MeshGeometry::render(RenderContext& rc, double /* clock */) const { if (!m_hwBuffersCurrent) { realize(); } // Track the last used material in order to avoid redundant // material bindings. unsigned int lastMaterialIndex = Submesh::DefaultMaterialIndex; rc.pushModelView(); rc.scaleModelView(m_meshScale); // Render all submeshes GLVertexBuffer* boundVertexBuffer = NULL; for (unsigned int i = 0; i < m_submeshes.size(); ++i) { const Submesh& submesh = *m_submeshes[i]; if (i < m_submeshBuffers.size() && m_submeshBuffers[i]) { boundVertexBuffer = m_submeshBuffers[i]; rc.bindVertexBuffer(submesh.vertices()->vertexSpec(), m_submeshBuffers[i], submesh.vertices()->stride()); } else { if (boundVertexBuffer) { boundVertexBuffer->unbind(); boundVertexBuffer = false; } rc.bindVertexArray(submesh.vertices()); } const vector<PrimitiveBatch*>& batches = submesh.primitiveBatches(); const vector<unsigned int>& materials = submesh.materials(); assert(batches.size() == materials.size()); // Render all batches in the submesh for (unsigned int j = 0; j < batches.size(); j++) { // If we have a new material, bind it unsigned int materialIndex = materials[j]; if (materialIndex != lastMaterialIndex) { if (materialIndex < m_materials.size()) { rc.bindMaterial(m_materials[materialIndex].ptr()); } lastMaterialIndex = materialIndex; } rc.drawPrimitives(*batches[j]); } } if (boundVertexBuffer) { boundVertexBuffer->unbind(); } rc.popModelView(); }
void MeshGeometry::renderShadow(RenderContext& rc, double /* clock */) const { if (!m_hwBuffersCurrent) { realize(); } // Use an extremely basic material to avoid wasting time // with pixel shader calculations when we're just interested // in depth values. Material simpleMaterial; rc.bindMaterial(&simpleMaterial); rc.pushModelView(); rc.scaleModelView(m_meshScale); // Render all submeshes GLVertexBuffer* boundVertexBuffer = NULL; for (unsigned int i = 0; i < m_submeshes.size(); ++i) { const Submesh& submesh = *m_submeshes[i]; if (i < m_submeshBuffers.size() && m_submeshBuffers[i]) { boundVertexBuffer = m_submeshBuffers[i]; rc.bindVertexBuffer(submesh.vertices()->vertexSpec(), m_submeshBuffers[i], submesh.vertices()->stride()); } else { if (boundVertexBuffer) { boundVertexBuffer->unbind(); boundVertexBuffer = false; } rc.bindVertexArray(submesh.vertices()); } const vector<PrimitiveBatch*>& batches = submesh.primitiveBatches(); const vector<unsigned int>& materials = submesh.materials(); assert(batches.size() == materials.size()); // Render all batches in the submesh for (unsigned int j = 0; j < batches.size(); j++) { // Skip mostly transparent items when drawing into the shadow // buffer. // TODO: Textures with transparent parts aren't handled here unsigned int materialIndex = materials[j]; if (materialIndex >= m_materials.size() || m_materials[materialIndex]->opacity() > 0.5f) { rc.drawPrimitives(*batches[j]); } } } if (boundVertexBuffer) { boundVertexBuffer->unbind(); } rc.popModelView(); }