From 62841598920b36358aec2a6e182adf85c12670e7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 24 Mar 2015 14:58:41 -0700 Subject: [PATCH] Revisiting the rendering pipeline pick and trying to use our brand new gpu::Pipeline --- libraries/gpu/src/gpu/GLBackendState.cpp | 37 +-- libraries/gpu/src/gpu/State.cpp | 8 +- libraries/gpu/src/gpu/State.h | 29 +- libraries/model/src/model/Stage.cpp | 1 - libraries/render-utils/src/Model.cpp | 328 ++++++++++------------- libraries/render-utils/src/Model.h | 165 ++++++------ 6 files changed, 254 insertions(+), 314 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 73ed649e83..6a93e2c842 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -102,16 +102,14 @@ void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool ADD_ENABLE_DISABLE_COMMAND(GL_LINE_SMOOTH); } -void generateDepthEnable(GLBackend::GLState::Commands& commands, bool enable) { - ADD_ENABLE_DISABLE_COMMAND(GL_DEPTH_TEST); -} - -void generateDepthWriteMask(GLBackend::GLState::Commands& commands, bool write) { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthMask, write))); -} - -void generateDepthFunc(GLBackend::GLState::Commands& commands, State::ComparisonFunction function) { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthFunc, GL_COMPARISON_FUNCTIONS[function]))); +void generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) { + if (!test._enabled) { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_DEPTH_TEST)))); + } else { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_DEPTH_TEST)))); + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthMask, test._writeMask))); + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthFunc, GL_COMPARISON_FUNCTIONS[test._function]))); + } } void generateStencilEnable(GLBackend::GLState::Commands& commands, bool enable) { @@ -228,9 +226,6 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { bool depthBias = false; - bool depthEnabled = false; - bool depthState = false; - bool stencilEnabled = false; bool stencilState = false; @@ -275,16 +270,11 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { break; } - case State::DEPTH_ENABLE: { - depthEnabled = bool(field.second._integer); - generateDepthEnable(object->_commands, depthEnabled); - break; - } - case State::DEPTH_WRITE_MASK: - case State::DEPTH_FUNC: { - depthState = true; + case State::DEPTH_TEST: { + generateDepthTest(object->_commands, State::DepthTest(field.second._integer)); break; } + case State::STENCIL_ENABLE: { stencilEnabled = bool(field.second._integer); generateStencilEnable(object->_commands, stencilEnabled); @@ -337,11 +327,6 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { generateDepthBias(object->_commands, state); } - if (depthEnabled) { - generateDepthWriteMask(object->_commands, state.getDepthWriteMask()); - generateDepthFunc(object->_commands, state.getDepthFunc()); - } - if (stencilEnabled) { generateStencilState(object->_commands, state); generateStencilWriteMask(object->_commands, state.getStencilWriteMask()); diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 59ecdc6766..13dd24fbcc 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -20,25 +20,25 @@ State::~State() } void State::set(Field field, bool value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._integer = value; _stamp++; } void State::set(Field field, uint32 value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._unsigned_integer = value; _stamp++; } void State::set(Field field, int32 value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._integer = value; _stamp++; } void State::set(Field field, float value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._float = value; _stamp++; } diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index d92cd7c603..c3c73cefa4 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -42,9 +42,7 @@ public: MULTISAMPLE_ENABLE, ANTIALISED_LINE_ENABLE, - DEPTH_ENABLE, - DEPTH_WRITE_MASK, - DEPTH_FUNC, + DEPTH_TEST, STENCIL_ENABLE, STENCIL_READ_MASK, @@ -149,6 +147,18 @@ public: WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ), }; + class DepthTest { + public: + DepthTest(bool enable, bool writeMask, ComparisonFunction func) : + _function(func), _writeMask(writeMask), _enabled(enable) {} + uint8 _function = ALWAYS; + bool _writeMask = false; + bool _enabled = false; + + int32 getRaw() const { return *(reinterpret_cast(this)); } + DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + }; + class StencilTest { public: int8 _failOp = STENCIL_OP_KEEP; @@ -217,13 +227,12 @@ public: bool getMultisampleEnable() const { return get(MULTISAMPLE_ENABLE)._integer; } bool getAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE)._integer; } - void setDepthEnable(bool enable) { set(DEPTH_ENABLE, enable); } - void setDepthWriteMask(bool enable) { set(DEPTH_WRITE_MASK, enable); } - void setDepthFunc(ComparisonFunction func) { set(DEPTH_FUNC, func); } - bool getDepthEnable() const { return get(DEPTH_ENABLE)._integer; } - bool getDepthWriteMask() const { return get(DEPTH_WRITE_MASK)._integer; } - ComparisonFunction getDepthFunc() const { return ComparisonFunction(get(DEPTH_FUNC)._integer); } - + void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { set(DEPTH_TEST, DepthTest(enable, writeMask, func).getRaw()); } + DepthTest getDepthTest() const { return DepthTest(get(DEPTH_TEST)._integer); } + bool getDepthTestEnabled() const { return getDepthTest()._enabled; } + bool getDepthTestWriteMask() const { return getDepthTest()._writeMask; } + ComparisonFunction getDepthTestFunc() const { return ComparisonFunction(getDepthTest()._function); } + void setStencilEnable(bool enable) { set(STENCIL_ENABLE, enable); } void setStencilReadMask(uint8 mask) { set(STENCIL_READ_MASK, mask); } void setStencilWriteMask(uint8 mask) { set(STENCIL_WRITE_MASK, mask); } diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 30828da094..a1a673a80b 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -217,7 +217,6 @@ SunSkyStage::SunSkyStage() : auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment)); auto skyState = gpu::StatePointer(new gpu::State()); - skyState->setDepthEnable(false); skyState->setStencilEnable(false); skyState->setBlendEnable(false); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d640876086..7a40b2feed 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -94,48 +94,81 @@ Model::~Model() { deleteGeometry(); } -gpu::ShaderPointer Model::_program; -gpu::ShaderPointer Model::_normalMapProgram; -gpu::ShaderPointer Model::_specularMapProgram; -gpu::ShaderPointer Model::_normalSpecularMapProgram; -gpu::ShaderPointer Model::_translucentProgram; +Model::RenderPipelineLib Model::_renderPipelineLib; +const GLint MATERIAL_GPU_SLOT = 3; -gpu::ShaderPointer Model::_lightmapProgram; -gpu::ShaderPointer Model::_lightmapNormalMapProgram; -gpu::ShaderPointer Model::_lightmapSpecularMapProgram; -gpu::ShaderPointer Model::_lightmapNormalSpecularMapProgram; +void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key, + gpu::ShaderPointer& vertexShader, + gpu::ShaderPointer& pixelShader ) { -gpu::ShaderPointer Model::_shadowProgram; + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); + slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); -gpu::ShaderPointer Model::_skinProgram; -gpu::ShaderPointer Model::_skinNormalMapProgram; -gpu::ShaderPointer Model::_skinSpecularMapProgram; -gpu::ShaderPointer Model::_skinNormalSpecularMapProgram; -gpu::ShaderPointer Model::_skinTranslucentProgram; + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); + bool makeResult = gpu::Shader::makeProgram(*program, slotBindings); + + + Locations* locations = new Locations(); + initLocations(program, *locations); -gpu::ShaderPointer Model::_skinShadowProgram; + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + if (key.isShadow()) { + state->setCullMode(gpu::State::CULL_FRONT); + } else { + state->setCullMode(gpu::State::CULL_BACK); + } -Model::Locations Model::_locations; -Model::Locations Model::_normalMapLocations; -Model::Locations Model::_specularMapLocations; -Model::Locations Model::_normalSpecularMapLocations; -Model::Locations Model::_translucentLocations; + if (key.isTranslucent()) { + } else { + state->setBlendEnable(false); + } -Model::Locations Model::_lightmapLocations; -Model::Locations Model::_lightmapNormalMapLocations; -Model::Locations Model::_lightmapSpecularMapLocations; -Model::Locations Model::_lightmapNormalSpecularMapLocations; + /* + GLBATCH(glDisable)(GL_BLEND); + GLBATCH(glEnable)(GL_ALPHA_TEST); + + if (mode == SHADOW_RENDER_MODE) { + GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); + } + */ -Model::SkinLocations Model::_skinLocations; -Model::SkinLocations Model::_skinNormalMapLocations; -Model::SkinLocations Model::_skinSpecularMapLocations; -Model::SkinLocations Model::_skinNormalSpecularMapLocations; -Model::SkinLocations Model::_skinShadowLocations; -Model::SkinLocations Model::_skinTranslucentLocations; + + auto it = insert(value_type(key.getRaw(), + RenderPipeline( + gpu::PipelinePointer( gpu::Pipeline::create(program, state) ), + std::shared_ptr(locations) + ))); + +} + + +void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model::Locations& locations) { + locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold"); + locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); + locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); + locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); + + locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); + locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); + +#if (GPU_FEATURE_PROFILE == GPU_CORE) + locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); +#else + locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer"); +#endif + locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); + + locations.clusterIndices = program->getInputs().findLocation("clusterIndices");; + locations.clusterWeights = program->getInputs().findLocation("clusterWeights");; + +} AbstractViewStateInterface* Model::_viewState = NULL; -const GLint MATERIAL_GPU_SLOT = 3; void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); @@ -167,33 +200,6 @@ void Model::setOffset(const glm::vec3& offset) { _snappedToRegistrationPoint = false; } -void Model::initProgram(gpu::ShaderPointer& program, Model::Locations& locations) { - locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold"); - locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); - locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); - locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); - - locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); - locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); - -#if (GPU_FEATURE_PROFILE == GPU_CORE) - locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); -#else - locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer"); -#endif - -} - -void Model::initSkinProgram(gpu::ShaderPointer& program, Model::SkinLocations& locations) { - - initProgram(program, locations); - - locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); - - locations.clusterIndices = program->getInputs().findLocation("clusterIndices");; - locations.clusterWeights = program->getInputs().findLocation("clusterWeights");; -} - QVector Model::createJointStates(const FBXGeometry& geometry) { QVector jointStates; for (int i = 0; i < geometry.joints.size(); ++i) { @@ -227,7 +233,7 @@ void Model::initJointTransforms() { } void Model::init() { - if (_program.isNull()) { + if (_renderPipelineLib.empty()) { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); @@ -257,74 +263,69 @@ void Model::init() { auto modelLightmapSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag))); auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag))); + // Fill the renderPipelineLib + _renderPipelineLib.addRenderPipeline( + RenderKey(0), + modelVertex, modelPixel); - bool makeResult = false; + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS), + modelNormalMapVertex, modelNormalMapPixel); - // Programs - _program = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelPixel)); - makeResult = gpu::Shader::makeProgram(*_program, slotBindings); - initProgram(_program, _locations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_SPECULAR), + modelVertex, modelSpecularMapPixel); - _normalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalMapPixel)); - makeResult = gpu::Shader::makeProgram(*_normalMapProgram, slotBindings); - initProgram(_normalMapProgram, _normalMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + modelNormalMapVertex, modelNormalSpecularMapPixel); - _specularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_specularMapProgram, slotBindings); - initProgram(_specularMapProgram, _specularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_TRANSLUCENT), + modelVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_DEPTH_ONLY), + modelShadowVertex, modelShadowPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP), + modelLightmapVertex, modelLightmapPixel); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS), + modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); - _normalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_normalSpecularMapProgram, slotBindings); - initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_SPECULAR), + modelLightmapVertex, modelLightmapSpecularMapPixel); - _translucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelTranslucentPixel)); - makeResult = gpu::Shader::makeProgram(*_translucentProgram, slotBindings); - initProgram(_translucentProgram, _translucentLocations); - - _shadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelShadowVertex, modelShadowPixel)); - makeResult = gpu::Shader::makeProgram(*_shadowProgram, slotBindings); - Model::Locations tempShadowLoc; - initProgram(_shadowProgram, tempShadowLoc); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); - _lightmapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapProgram, slotBindings); - initProgram(_lightmapProgram, _lightmapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED), + skinModelVertex, modelPixel); - _lightmapNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalMapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapNormalMapProgram, slotBindings); - initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS), + skinModelNormalMapVertex, modelNormalMapPixel); - _lightmapSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapSpecularMapProgram, slotBindings); - initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR), + skinModelVertex, modelSpecularMapPixel); - _lightmapNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapNormalSpecularMapProgram, slotBindings); - initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + skinModelNormalMapVertex, modelNormalSpecularMapPixel); - _skinProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelPixel)); - makeResult = gpu::Shader::makeProgram(*_skinProgram, slotBindings); - initSkinProgram(_skinProgram, _skinLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY), + skinModelShadowVertex, modelShadowPixel); - _skinNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalMapPixel)); - makeResult = gpu::Shader::makeProgram(*_skinNormalMapProgram, slotBindings); - initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations); - - _skinSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_skinSpecularMapProgram, slotBindings); - initSkinProgram(_skinSpecularMapProgram, _skinSpecularMapLocations); - - _skinNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_skinNormalSpecularMapProgram, slotBindings); - initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations); - - _skinShadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelShadowVertex, modelShadowPixel)); - makeResult = gpu::Shader::makeProgram(*_skinShadowProgram, slotBindings); - initSkinProgram(_skinShadowProgram, _skinShadowLocations); - - _skinTranslucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelTranslucentPixel)); - makeResult = gpu::Shader::makeProgram(*_skinTranslucentProgram, slotBindings); - initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), + skinModelVertex, modelTranslucentPixel); } } @@ -2249,81 +2250,24 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - Locations*& locations, SkinLocations*& skinLocations) { - gpu::ShaderPointer program = _program; - locations = &_locations; - gpu::ShaderPointer skinProgram = _skinProgram; - skinLocations = &_skinLocations; - if (mode == SHADOW_RENDER_MODE) { - program = _shadowProgram; - skinProgram = _skinShadowProgram; - skinLocations = &_skinShadowLocations; - } else if (translucent && alphaThreshold == 0.0f) { - program = _translucentProgram; - locations = &_translucentLocations; - skinProgram = _skinTranslucentProgram; - skinLocations = &_skinTranslucentLocations; - - } else if (hasLightmap) { - if (hasTangents) { - if (hasSpecular) { - program = _lightmapNormalSpecularMapProgram; - locations = &_lightmapNormalSpecularMapLocations; - skinProgram.reset(); - skinLocations = NULL; - } else { - program = _lightmapNormalMapProgram; - locations = &_lightmapNormalMapLocations; - skinProgram.reset(); - skinLocations = NULL; - } - } else if (hasSpecular) { - program = _lightmapSpecularMapProgram; - locations = &_lightmapSpecularMapLocations; - skinProgram.reset(); - skinLocations = NULL; - } else { - program = _lightmapProgram; - locations = &_lightmapLocations; - skinProgram.reset(); - skinLocations = NULL; - } - } else { - if (hasTangents) { - if (hasSpecular) { - program = _normalSpecularMapProgram; - locations = &_normalSpecularMapLocations; - skinProgram = _skinNormalSpecularMapProgram; - skinLocations = &_skinNormalSpecularMapLocations; - } else { - program = _normalMapProgram; - locations = &_normalMapLocations; - skinProgram = _skinNormalMapProgram; - skinLocations = &_skinNormalMapLocations; - } - } else if (hasSpecular) { - program = _specularMapProgram; - locations = &_specularMapLocations; - skinProgram = _skinSpecularMapProgram; - skinLocations = &_skinSpecularMapLocations; - } - } + Locations*& locations) { - gpu::ShaderPointer activeProgram = program; - Locations* activeLocations = locations; - - if (isSkinned) { - activeProgram = skinProgram; - activeLocations = skinLocations; - locations = skinLocations; + RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); + auto pipeline = _renderPipelineLib.find(key.getRaw()); + if (pipeline == _renderPipelineLib.end()) { + qDebug() << "No good, couldn;t find a pipeline from the key ?" << key.getRaw(); + return; } - GLuint glprogram = gpu::GLBackend::getShaderID(activeProgram); + gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram(); + locations = (*pipeline).second._locations.get(); + + GLuint glprogram = gpu::GLBackend::getShaderID(program); GLBATCH(glUseProgram)(glprogram); - if ((activeLocations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) { - GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); + if ((locations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) { + GLBATCH(glUniform1f)(locations->alphaThreshold, alphaThreshold); } } @@ -2335,7 +2279,6 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool bool pickProgramsNeeded = true; Locations* locations; - SkinLocations* skinLocations; foreach(Model* model, _modelsInScene) { QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); @@ -2343,11 +2286,11 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations); } } } @@ -2379,11 +2322,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } Locations* locations; - SkinLocations* skinLocations; pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, - args, locations, skinLocations); + args, locations); meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, - args, locations, skinLocations, forceRenderSomeMeshes); + args, locations, forceRenderSomeMeshes); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2391,7 +2333,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - Locations* locations, SkinLocations* skinLocations, bool forceRenderSomeMeshes) { + Locations* locations, bool forceRenderSomeMeshes) { PROFILE_RANGE(__FUNCTION__); auto textureCache = DependencyManager::get(); @@ -2462,7 +2404,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod const MeshState& state = _meshStates.at(i); if (state.clusterMatrices.size() > 1) { - GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, + GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); batch.setModelTransform(Transform()); } else { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 2e3f358635..bce534416c 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -18,12 +18,16 @@ #include #include +#include +#include + #include #include #include #include #include #include +#include #include "PhysicsEntity.h" #include @@ -318,50 +322,6 @@ private: int _blendNumber; int _appliedBlendNumber; -/* - static gpu::PipelinePointer _program; - static gpu::PipelinePointer _normalMapProgram; - static gpu::PipelinePointer _specularMapProgram; - static gpu::PipelinePointer _normalSpecularMapProgram; - static gpu::PipelinePointer _translucentProgram; - - static gpu::PipelinePointer _lightmapProgram; - static gpu::PipelinePointer _lightmapNormalMapProgram; - static gpu::PipelinePointer _lightmapSpecularMapProgram; - static gpu::PipelinePointer _lightmapNormalSpecularMapProgram; - - static gpu::PipelinePointer _shadowProgram; - - static gpu::PipelinePointer _skinProgram; - static gpu::PipelinePointer _skinNormalMapProgram; - static gpu::PipelinePointer _skinSpecularMapProgram; - static gpu::PipelinePointer _skinNormalSpecularMapProgram; - static gpu::PipelinePointer _skinTranslucentProgram; - - static gpu::PipelinePointer _skinShadowProgram; -*/ - - static gpu::ShaderPointer _program; - static gpu::ShaderPointer _normalMapProgram; - static gpu::ShaderPointer _specularMapProgram; - static gpu::ShaderPointer _normalSpecularMapProgram; - static gpu::ShaderPointer _translucentProgram; - - static gpu::ShaderPointer _lightmapProgram; - static gpu::ShaderPointer _lightmapNormalMapProgram; - static gpu::ShaderPointer _lightmapSpecularMapProgram; - static gpu::ShaderPointer _lightmapNormalSpecularMapProgram; - - static gpu::ShaderPointer _shadowProgram; - - static gpu::ShaderPointer _skinProgram; - static gpu::ShaderPointer _skinNormalMapProgram; - static gpu::ShaderPointer _skinSpecularMapProgram; - static gpu::ShaderPointer _skinNormalSpecularMapProgram; - static gpu::ShaderPointer _skinTranslucentProgram; - - static gpu::ShaderPointer _skinShadowProgram; - class Locations { public: int tangent; @@ -372,38 +332,10 @@ private: int emissiveParams; int glowIntensity; int materialBufferUnit; - }; - - static Locations _locations; - static Locations _normalMapLocations; - static Locations _specularMapLocations; - static Locations _normalSpecularMapLocations; - static Locations _translucentLocations; - - static Locations _lightmapLocations; - static Locations _lightmapNormalMapLocations; - static Locations _lightmapSpecularMapLocations; - static Locations _lightmapNormalSpecularMapLocations; - - static void initProgram(ProgramObject& program, Locations& locations, bool link = true); - static void initProgram(gpu::ShaderPointer& program, Locations& locations); - - class SkinLocations : public Locations { - public: int clusterMatrices; int clusterIndices; int clusterWeights; }; - - static SkinLocations _skinLocations; - static SkinLocations _skinNormalMapLocations; - static SkinLocations _skinSpecularMapLocations; - static SkinLocations _skinNormalSpecularMapLocations; - static SkinLocations _skinShadowLocations; - static SkinLocations _skinTranslucentLocations; - - static void initSkinProgram(ProgramObject& program, SkinLocations& locations); - static void initSkinProgram(gpu::ShaderPointer& program, SkinLocations& locations); QVector _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes bool _calculatedMeshBoxesValid; @@ -489,12 +421,12 @@ private: QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, Locations* locations, SkinLocations* skinLocations, + RenderArgs* args, Locations* locations, bool forceRenderSomeMeshes = false); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - Locations*& locations, SkinLocations*& skinLocations); + Locations*& locations); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); @@ -502,17 +434,90 @@ private: static AbstractViewStateInterface* _viewState; - /* class RenderKey { + class RenderKey { public: - enum Flag { - TRANSLUCENT = 0, - HAS_LIGHTMAP, + enum FlagBit { + IS_TRANSLUCENT_FLAG = 0, + HAS_LIGHTMAP_FLAG, + HAS_TANGENTS_FLAG, + HAS_SPECULAR_FLAG, + HAS_EMISSIVE_FLAG, + IS_SKINNED_FLAG, + IS_STEREO_FLAG, + IS_DEPTH_ONLY_FLAG, + IS_SHADOW_FLAG, + + NUM_FLAGS, }; + + enum Flag { + IS_TRANSLUCENT = (1 << IS_TRANSLUCENT_FLAG), + HAS_LIGHTMAP = (1 << HAS_LIGHTMAP_FLAG), + HAS_TANGENTS = (1 << HAS_TANGENTS_FLAG), + HAS_SPECULAR = (1 << HAS_SPECULAR_FLAG), + HAS_EMISSIVE = (1 << HAS_EMISSIVE_FLAG), + IS_SKINNED = (1 << IS_SKINNED_FLAG), + IS_STEREO = (1 << IS_STEREO_FLAG), + IS_DEPTH_ONLY = (1 << IS_DEPTH_ONLY_FLAG), + IS_SHADOW = (1 << IS_SHADOW_FLAG), - RenderMode mode; + }; + typedef unsigned short Flags; + + + bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); } + + bool isTranslucent() const { return isFlag(IS_TRANSLUCENT); } + bool hasLightmap() const { return isFlag(HAS_LIGHTMAP); } + bool hasTangents() const { return isFlag(HAS_TANGENTS); } + bool HasSpecular() const { return isFlag(HAS_SPECULAR); } + bool HasEmissive() const { return isFlag(HAS_EMISSIVE); } + bool isSkinned() const { return isFlag(IS_SKINNED); } + bool isStereo() const { return isFlag(IS_STEREO); } + bool isDepthOnly() const { return isFlag(IS_DEPTH_ONLY); } + bool isShadow() const { return isFlag(IS_SHADOW); } // = depth only but with back facing + + Flags _flags = 0; + short _spare = 0; + + int getRaw() { return *reinterpret_cast(this); } + + RenderKey(RenderMode mode, + bool translucent, float alphaThreshold, bool hasLightmap, + bool hasTangents, bool hasSpecular, bool isSkinned) : + RenderKey( ((translucent && (alphaThreshold == 0.0f)) ? IS_TRANSLUCENT : 0) + | (hasLightmap && (mode != SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly + | (hasTangents && (mode != SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0) + | (hasSpecular && (mode != SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0) + | (isSkinned ? IS_SKINNED : 0) + | ((mode == SHADOW_RENDER_MODE) ? IS_DEPTH_ONLY : 0) + | ((mode == SHADOW_RENDER_MODE) ? IS_SHADOW : 0)) {} + + RenderKey(int bitmask) : _flags(bitmask) {} }; -*/ + + + class RenderPipeline { + public: + gpu::PipelinePointer _pipeline; + std::shared_ptr _locations; + RenderPipeline(gpu::PipelinePointer& pipeline, std::shared_ptr& locations) : + _pipeline(pipeline), _locations(locations) {} + }; + + typedef std::unordered_map BaseRenderPipelineMap; + class RenderPipelineLib : public BaseRenderPipelineMap { + public: + typedef RenderKey Key; + + + void addRenderPipeline(Key& key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); + + void initLocations(gpu::ShaderPointer& program, Locations& locations); + }; + static RenderPipelineLib _renderPipelineLib; + }; Q_DECLARE_METATYPE(QPointer)