void MeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("MeshPartPayload::render"); gpu::Batch& batch = *(args->_batch); ShapeKey key = getShapeKey(); auto locations = args->_pipeline->locations; assert(locations); // Bind the model transform and the skinCLusterMatrices if needed bindTransform(batch, locations); //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); // apply material properties bindMaterial(batch, locations); // TODO: We should be able to do that just in the renderTransparentJob if (key.isTranslucent() && locations->lightBufferUnit >= 0) { PerformanceTimer perfTimer("DLE->setupTransparent()"); DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit); } if (args) { args->_details._materialSwitches++; } // Draw! { PerformanceTimer perfTimer("batch.drawIndexed()"); drawCall(batch); } if (args) { const int INDICES_PER_TRIANGLE = 3; args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } }
void addPlumberPipeline(ShapePlumber& plumber, const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) { // These key-values' pipelines are added by this functor in addition to the key passed assert(!key.isWireframe()); assert(!key.isDepthBiased()); assert(key.isCullFace()); gpu::ShaderPointer program = gpu::Shader::createProgram(vertex, pixel); for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); bool isBiased = (i & 2); bool isWireframed = (i & 4); auto state = std::make_shared<gpu::State>(); PrepareStencil::testMaskDrawShape(*state); // Depth test depends on transparency state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); state->setBlendFunction(key.isTranslucent(), gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); ShapeKey::Builder builder(key); if (!isCulled) { builder.withoutCullFace(); } state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE); if (isWireframed) { builder.withWireframe(); state->setFillMode(gpu::State::FILL_LINE); } if (isBiased) { builder.withDepthBias(); state->setDepthBias(1.0f); state->setDepthBiasSlopeScale(1.0f); } plumber.addPipeline(builder.build(), program, state, key.isTranslucent() ? &lightBatchSetter : &batchSetter); } }
void ModelMeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); if (!_model->_readyWhenAdded || !_model->_isVisible) { return; // bail asap } gpu::Batch& batch = *(args->_batch); ShapeKey key = getShapeKey(); if (!key.isValid()) { return; } // render the part bounding box #ifdef DEBUG_BOUNDING_PARTS { AABox partBounds = getPartBounds(_meshIndex, partIndex); bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE; glm::vec4 cubeColor; if (isSkinned) { cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f); } else if (inView) { cubeColor = glm::vec4(1.0f, 0.0f, 1.0f, 1.0f); } else { cubeColor = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f); } Transform transform; transform.setTranslation(partBounds.calcCenter()); transform.setScale(partBounds.getDimensions()); batch.setModelTransform(transform); DependencyManager::get<GeometryCache>()->renderWireCube(batch, 1.0f, cubeColor); } #endif //def DEBUG_BOUNDING_PARTS auto locations = args->_pipeline->locations; assert(locations); // Bind the model transform and the skinCLusterMatrices if needed _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); bindTransform(batch, locations); //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); // apply material properties bindMaterial(batch, locations); // TODO: We should be able to do that just in the renderTransparentJob if (key.isTranslucent() && locations->lightBufferUnit >= 0) { PerformanceTimer perfTimer("DLE->setupTransparent()"); DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit); } if (args) { args->_details._materialSwitches++; } // Draw! { PerformanceTimer perfTimer("batch.drawIndexed()"); drawCall(batch); } if (args) { const int INDICES_PER_TRIANGLE = 3; args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } }