gpu::PipelinePointer DeferredLightingEffect::getPipeline(SimpleProgramKey config) { auto it = _simplePrograms.find(config); if (it != _simplePrograms.end()) { return it.value(); } auto state = std::make_shared<gpu::State>(); if (config.isCulled()) { state->setCullMode(gpu::State::CULL_BACK); } else { state->setCullMode(gpu::State::CULL_NONE); } state->setDepthTest(true, true, gpu::LESS_EQUAL); if (config.hasDepthBias()) { state->setDepthBias(1.0f); state->setDepthBiasSlopeScale(1.0f); } state->setBlendFunction(false, 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); gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader; gpu::PipelinePointer pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); _simplePrograms.insert(config, pipeline); return pipeline; }
void ModelRender::RenderPipelineLib::addRenderPipeline(ModelRender::RenderKey key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), ModelRender::SKINNING_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), ModelRender::MATERIAL_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), ModelRender::DIFFUSE_MAP_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), ModelRender::NORMAL_MAP_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), ModelRender::SPECULAR_MAP_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), ModelRender::LIGHTMAP_MAP_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ModelRender::LIGHT_BUFFER_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT)); gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); gpu::Shader::makeProgram(*program, slotBindings); auto locations = std::make_shared<Locations>(); initLocations(program, *locations); auto state = std::make_shared<gpu::State>(); // Backface on shadow if (key.isShadow()) { state->setCullMode(gpu::State::CULL_FRONT); state->setDepthBias(1.0f); state->setDepthBiasSlopeScale(4.0f); } else { state->setCullMode(gpu::State::CULL_BACK); } // Z test depends if transparent or not state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); // Blend on transparent state->setBlendFunction(key.isTranslucent(), gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, // For transparent only, this keep the highlight intensity gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); // Good to go add the brand new pipeline auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); insert(value_type(key.getRaw(), RenderPipeline(pipeline, locations))); if (!key.isWireFrame()) { RenderKey wireframeKey(key.getRaw() | RenderKey::IS_WIREFRAME); auto wireframeState = std::make_shared<gpu::State>(state->getValues()); wireframeState->setFillMode(gpu::State::FILL_LINE); // create a new RenderPipeline with the same shader side and the wireframe state auto wireframePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, wireframeState)); insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations))); } }