/**************************************************************************** ** ** Copyright (C) 2008-2012 NVIDIA Corporation. ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt 3D Studio. ** ** $QT_BEGIN_LICENSE:GPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 or (at your option) any later version ** approved by the KDE Free Qt Foundation. The licenses are as published by ** the Free Software Foundation and appearing in the file LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "Qt3DSRendererImpl.h" #include "foundation/Qt3DSFoundation.h" #include "Qt3DSRenderLight.h" #include "Qt3DSRenderContextCore.h" #include "Qt3DSRenderShaderCache.h" #include "Qt3DSRenderDynamicObjectSystem.h" #include "Qt3DSRenderShaderCodeGeneratorV2.h" #include "Qt3DSRenderDefaultMaterialShaderGenerator.h" #include "Qt3DSVertexPipelineImpl.h" // This adds support for the depth buffers in the shader so we can do depth // texture-based effects. #define QT3DS_RENDER_SUPPORT_DEPTH_TEXTURE 1 namespace qt3ds { namespace render { void STextShader::Render(NVRenderTexture2D &inTexture, const STextScaleAndOffset &inScaleAndOffset, const QT3DSVec4 &inTextColor, const QT3DSMat44 &inMVP, const QT3DSVec2 &inCameraVec, NVRenderContext &inRenderContext, NVRenderInputAssembler &inInputAssemblerBuffer, QT3DSU32 count, const STextTextureDetails &inTextTextureDetails, const QT3DSVec3 &inBackgroundColor) { inRenderContext.SetCullingEnabled(false); inRenderContext.SetActiveShader(&m_Shader); m_MVP.Set(inMVP); m_Sampler.Set(&inTexture); m_TextColor.Set(inTextColor); m_Dimensions.Set(QT3DSVec4(inScaleAndOffset.m_TextScale.x, inScaleAndOffset.m_TextScale.y, inScaleAndOffset.m_TextOffset.x, inScaleAndOffset.m_TextOffset.y)); m_CameraProperties.Set(inCameraVec); STextureDetails theTextureDetails = inTexture.GetTextureDetails(); QT3DSF32 theWidthScale = (QT3DSF32)inTextTextureDetails.m_TextWidth / (QT3DSF32)theTextureDetails.m_Width; QT3DSF32 theHeightScale = (QT3DSF32)inTextTextureDetails.m_TextHeight / (QT3DSF32)theTextureDetails.m_Height; m_BackgroundColor.Set(inBackgroundColor); m_TextDimensions.Set( QT3DSVec3(theWidthScale, theHeightScale, inTextTextureDetails.m_FlipY ? 1.0f : 0.0f)); inRenderContext.SetInputAssembler(&inInputAssemblerBuffer); inRenderContext.Draw(NVRenderDrawMode::Triangles, count, 0); } void STextShader::RenderPath(NVRenderPathFontItem &inPathFontItem, NVRenderPathFontSpecification &inPathFontSpec, const STextScaleAndOffset &inScaleAndOffset, const QT3DSVec4 &inTextColor, const QT3DSMat44 &inViewProjection, const QT3DSMat44 &inModel, const QT3DSVec2 &, NVRenderContext &inRenderContext, const STextTextureDetails &inTextTextureDetails, const QT3DSVec3 &inBackgroundColor) { qt3ds::render::NVRenderBoolOp::Enum theDepthFunction = inRenderContext.GetDepthFunction(); bool isDepthEnabled = inRenderContext.IsDepthTestEnabled(); bool isStencilEnabled = inRenderContext.IsStencilTestEnabled(); bool isDepthWriteEnabled = inRenderContext.IsDepthWriteEnabled(); qt3ds::render::NVRenderStencilFunctionArgument theArg(qt3ds::render::NVRenderBoolOp::NotEqual, 0, 0xFF); qt3ds::render::NVRenderStencilOperationArgument theOpArg(qt3ds::render::NVRenderStencilOp::Keep, qt3ds::render::NVRenderStencilOp::Keep, qt3ds::render::NVRenderStencilOp::Zero); NVScopedRefCounted depthStencilState = inRenderContext.CreateDepthStencilState(isDepthEnabled, isDepthWriteEnabled, theDepthFunction, false, theArg, theArg, theOpArg, theOpArg); inRenderContext.SetActiveShader(NULL); inRenderContext.SetCullingEnabled(false); inRenderContext.SetDepthStencilState(depthStencilState); // setup transform QT3DSMat44 offsetMatrix = QT3DSMat44::createIdentity(); offsetMatrix.setPosition(QT3DSVec3( inScaleAndOffset.m_TextOffset.x - (QT3DSF32)inTextTextureDetails.m_TextWidth / 2.0f, inScaleAndOffset.m_TextOffset.y - (QT3DSF32)inTextTextureDetails.m_TextHeight / 2.0f, 0.0)); QT3DSMat44 pathMatrix = inPathFontItem.GetTransform(); inRenderContext.SetPathProjectionMatrix(inViewProjection); inRenderContext.SetPathModelViewMatrix(inModel * offsetMatrix * pathMatrix); // first pass inPathFontSpec.StencilFillPathInstanced(inPathFontItem); // second pass inRenderContext.SetActiveProgramPipeline(m_ProgramPipeline); m_TextColor.Set(inTextColor); m_BackgroundColor.Set(inBackgroundColor); inRenderContext.SetStencilTestEnabled(true); inPathFontSpec.CoverFillPathInstanced(inPathFontItem); inRenderContext.SetStencilTestEnabled(isStencilEnabled); inRenderContext.SetDepthFunction(theDepthFunction); inRenderContext.SetActiveProgramPipeline(NULL); } void STextShader::Render2D(NVRenderTexture2D &inTexture, const QT3DSVec4 &inTextColor, const QT3DSMat44 &inMVP, NVRenderContext &inRenderContext, NVRenderInputAssembler &inInputAssemblerBuffer, QT3DSU32 count, QT3DSVec2 inVertexOffsets) { // inRenderContext.SetCullingEnabled( false ); inRenderContext.SetBlendingEnabled(true); inRenderContext.SetDepthWriteEnabled(false); inRenderContext.SetDepthTestEnabled(false); inRenderContext.SetActiveShader(&m_Shader); qt3ds::render::NVRenderBlendFunctionArgument blendFunc( NVRenderSrcBlendFunc::SrcAlpha, NVRenderDstBlendFunc::OneMinusSrcAlpha, NVRenderSrcBlendFunc::One, NVRenderDstBlendFunc::One); qt3ds::render::NVRenderBlendEquationArgument blendEqu(NVRenderBlendEquation::Add, NVRenderBlendEquation::Add); inRenderContext.SetBlendFunction(blendFunc); inRenderContext.SetBlendEquation(blendEqu); m_MVP.Set(inMVP); m_Sampler.Set(&inTexture); m_TextColor.Set(inTextColor); m_VertexOffsets.Set(inVertexOffsets); inRenderContext.SetInputAssembler(&inInputAssemblerBuffer); inRenderContext.Draw(NVRenderDrawMode::Triangles, count, 0); } using eastl::make_pair; static inline void AddVertexDepth(SShaderVertexCodeGenerator &vertexShader) { // near plane, far plane vertexShader.AddInclude("viewProperties.glsllib"); vertexShader.AddVarying("vertex_depth", "float"); // the w coordinate is the unormalized distance to the object from the camera // We want the normalized distance, with 0 representing the far plane and 1 representing // the near plane, of the object in the vertex depth variable. vertexShader << "\tvertex_depth = calculateVertexDepth( camera_properties, gl_Position );" << Endl; } // Helper implements the vertex pipeline for mesh subsets when bound to the default material. // Should be completely possible to use for custom materials with a bit of refactoring. struct SSubsetMaterialVertexPipeline : public SVertexPipelineImpl { Qt3DSRendererImpl &m_Renderer; SSubsetRenderable &m_Renderable; TessModeValues::Enum m_TessMode; SSubsetMaterialVertexPipeline(Qt3DSRendererImpl &renderer, SSubsetRenderable &renderable, bool inWireframeRequested) : SVertexPipelineImpl(renderer.GetQt3DSContext().GetAllocator(), renderer.GetQt3DSContext().GetDefaultMaterialShaderGenerator(), renderer.GetQt3DSContext().GetShaderProgramGenerator(), renderer.GetQt3DSContext().GetStringTable(), false) , m_Renderer(renderer) , m_Renderable(renderable) , m_TessMode(TessModeValues::NoTess) { if (m_Renderer.GetContext().IsTessellationSupported()) { m_TessMode = renderable.m_TessellationMode; } if (m_Renderer.GetContext().IsGeometryStageSupported() && m_TessMode != TessModeValues::NoTess) m_Wireframe = inWireframeRequested; } void InitializeTessControlShader() { if (m_TessMode == TessModeValues::NoTess || ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl) == NULL) return; IShaderStageGenerator &tessCtrlShader( *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); SetupTessIncludes(ShaderGeneratorStages::TessControl, m_TessMode); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctWorldPos[0] = varWorldPos[0];"); tessCtrlShader.Append("\tctWorldPos[1] = varWorldPos[1];"); tessCtrlShader.Append("\tctWorldPos[2] = varWorldPos[2];"); if (m_TessMode == TessModeValues::TessPhong || m_TessMode == TessModeValues::TessNPatch) { tessCtrlShader.Append("\tctNorm[0] = varObjectNormal[0];"); tessCtrlShader.Append("\tctNorm[1] = varObjectNormal[1];"); tessCtrlShader.Append("\tctNorm[2] = varObjectNormal[2];"); } if (m_TessMode == TessModeValues::TessNPatch) { tessCtrlShader.Append("\tctTangent[0] = varTangent[0];"); tessCtrlShader.Append("\tctTangent[1] = varTangent[1];"); tessCtrlShader.Append("\tctTangent[2] = varTangent[2];"); } tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); } void InitializeTessEvaluationShader() { if (m_TessMode == TessModeValues::NoTess || ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval) == NULL) return; IShaderStageGenerator &tessEvalShader( *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); SetupTessIncludes(ShaderGeneratorStages::TessEval, m_TessMode); if (m_TessMode == TessModeValues::TessLinear) m_Renderer.GetQt3DSContext() .GetDefaultMaterialShaderGenerator() .AddDisplacementImageUniforms(tessEvalShader, m_DisplacementIdx, m_DisplacementImage); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddUniform("normal_matrix", "mat3"); tessEvalShader.Append("void main() {"); if (m_TessMode == TessModeValues::TessNPatch) { tessEvalShader.Append("\tctNorm[0] = varObjectNormalTC[0];"); tessEvalShader.Append("\tctNorm[1] = varObjectNormalTC[1];"); tessEvalShader.Append("\tctNorm[2] = varObjectNormalTC[2];"); tessEvalShader.Append("\tctTangent[0] = varTangentTC[0];"); tessEvalShader.Append("\tctTangent[1] = varTangentTC[1];"); tessEvalShader.Append("\tctTangent[2] = varTangentTC[2];"); } tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); } void FinalizeTessControlShader() { IShaderStageGenerator &tessCtrlShader( *ProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); // add varyings we must pass through typedef TStrTableStrMap::const_iterator TParamIter; for (TParamIter iter = m_InterpolationParameters.begin(), end = m_InterpolationParameters.end(); iter != end; ++iter) { tessCtrlShader << "\t" << iter->first.c_str() << "TC[gl_InvocationID] = " << iter->first.c_str() << "[gl_InvocationID];\n"; } } void FinalizeTessEvaluationShader() { IShaderStageGenerator &tessEvalShader( *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); eastl::string outExt(""); if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry) outExt = "TE"; // add varyings we must pass through typedef TStrTableStrMap::const_iterator TParamIter; if (m_TessMode == TessModeValues::TessNPatch) { for (TParamIter iter = m_InterpolationParameters.begin(), end = m_InterpolationParameters.end(); iter != end; ++iter) { tessEvalShader << "\t" << iter->first.c_str() << outExt.c_str() << " = gl_TessCoord.z * " << iter->first.c_str() << "TC[0] + "; tessEvalShader << "gl_TessCoord.x * " << iter->first.c_str() << "TC[1] + "; tessEvalShader << "gl_TessCoord.y * " << iter->first.c_str() << "TC[2];\n"; } // transform the normal if (m_GenerationFlags & GenerationFlagValues::WorldNormal) tessEvalShader << "\n\tvarNormal" << outExt.c_str() << " = normalize(normal_matrix * teNorm);\n"; // transform the tangent if (m_GenerationFlags & GenerationFlagValues::TangentBinormal) { tessEvalShader << "\n\tvarTangent" << outExt.c_str() << " = normalize(normal_matrix * teTangent);\n"; // transform the binormal tessEvalShader << "\n\tvarBinormal" << outExt.c_str() << " = normalize(normal_matrix * teBinormal);\n"; } } else { for (TParamIter iter = m_InterpolationParameters.begin(), end = m_InterpolationParameters.end(); iter != end; ++iter) { tessEvalShader << "\t" << iter->first.c_str() << outExt.c_str() << " = gl_TessCoord.x * " << iter->first.c_str() << "TC[0] + "; tessEvalShader << "gl_TessCoord.y * " << iter->first.c_str() << "TC[1] + "; tessEvalShader << "gl_TessCoord.z * " << iter->first.c_str() << "TC[2];\n"; } // displacement mapping makes only sense with linear tessellation if (m_TessMode == TessModeValues::TessLinear && m_DisplacementImage) { IDefaultMaterialShaderGenerator::SImageVariableNames theNames = m_Renderer.GetQt3DSContext() .GetDefaultMaterialShaderGenerator() .GetImageVariableNames(m_DisplacementIdx); tessEvalShader << "\tpos.xyz = defaultMaterialFileDisplacementTexture( " << theNames.m_ImageSampler << ", displaceAmount, " << theNames.m_ImageFragCoords << outExt.c_str(); tessEvalShader << ", varObjectNormal" << outExt.c_str() << ", pos.xyz );" << Endl; tessEvalShader << "\tvarWorldPos" << outExt.c_str() << "= (model_matrix * pos).xyz;" << Endl; tessEvalShader << "\tvarViewVector" << outExt.c_str() << "= normalize(camera_position - " << "varWorldPos" << outExt.c_str() << ");" << Endl; } // transform the normal tessEvalShader << "\n\tvarNormal" << outExt.c_str() << " = normalize(normal_matrix * varObjectNormal" << outExt.c_str() << ");\n"; } tessEvalShader.Append("\tgl_Position = model_view_projection * pos;\n"); } void BeginVertexGeneration(QT3DSU32 displacementImageIdx, SRenderableImage *displacementImage) override { m_DisplacementIdx = displacementImageIdx; m_DisplacementImage = displacementImage; TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags()); if (m_TessMode != TessModeValues::NoTess) { theStages |= ShaderGeneratorStages::TessControl; theStages |= ShaderGeneratorStages::TessEval; } if (m_Wireframe) { theStages |= ShaderGeneratorStages::Geometry; } ProgramGenerator().BeginProgram(theStages); if (m_TessMode != TessModeValues::NoTess) { InitializeTessControlShader(); InitializeTessEvaluationShader(); } if (m_Wireframe) { InitializeWireframeGeometryShader(); } // Open up each stage. IShaderStageGenerator &vertexShader(Vertex()); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader << "void main()" << Endl << "{" << Endl; vertexShader << "\tvec3 uTransform;" << Endl; vertexShader << "\tvec3 vTransform;" << Endl; if (displacementImage) { GenerateUVCoords(); MaterialGenerator().GenerateImageUVCoordinates(*this, displacementImageIdx, 0, *displacementImage); if (!HasTessellation()) { vertexShader.AddUniform("displaceAmount", "float"); // we create the world position setup here // because it will be replaced with the displaced position SetCode(GenerationFlagValues::WorldPosition); vertexShader.AddUniform("model_matrix", "mat4"); vertexShader.AddInclude("defaultMaterialFileDisplacementTexture.glsllib"); IDefaultMaterialShaderGenerator::SImageVariableNames theVarNames = MaterialGenerator().GetImageVariableNames(displacementImageIdx); vertexShader.AddUniform(theVarNames.m_ImageSampler, "sampler2D"); vertexShader << "\tvec3 displacedPos = defaultMaterialFileDisplacementTexture( " << theVarNames.m_ImageSampler << ", displaceAmount, " << theVarNames.m_ImageFragCoords << ", attr_norm, attr_pos );" << Endl; AddInterpolationParameter("varWorldPos", "vec3"); vertexShader.Append("\tvec3 local_model_world_position = (model_matrix * " "vec4(displacedPos, 1.0)).xyz;"); AssignOutput("varWorldPos", "local_model_world_position"); } } // for tessellation we pass on the position in object coordinates // Also note that gl_Position is written in the tess eval shader if (HasTessellation()) vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); else { vertexShader.AddUniform("model_view_projection", "mat4"); if (displacementImage) vertexShader.Append( "\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);"); else vertexShader.Append( "\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);"); } if (HasTessellation()) { GenerateWorldPosition(); GenerateWorldNormal(); GenerateObjectNormal(); GenerateVarTangentAndBinormal(); } } void BeginFragmentGeneration() override { Fragment().AddUniform("material_diffuse", "vec4"); Fragment() << "void main()" << Endl << "{" << Endl; // We do not pass object opacity through the pipeline. Fragment() << "\tfloat object_opacity = material_diffuse.a;" << Endl; } void AssignOutput(const char8_t *inVarName, const char8_t *inVarValue) override { Vertex() << "\t" << inVarName << " = " << inVarValue << ";\n"; } void DoGenerateUVCoords(QT3DSU32 inUVSet = 0) override { QT3DS_ASSERT(inUVSet == 0 || inUVSet == 1); if (inUVSet == 0) { Vertex().AddIncoming("attr_uv0", "vec2"); Vertex() << "\tvarTexCoord0 = attr_uv0;" << Endl; } else if (inUVSet == 1) { Vertex().AddIncoming("attr_uv1", "vec2"); Vertex() << "\tvarTexCoord1 = attr_uv1;" << Endl; } } // fragment shader expects varying vertex normal // lighting in vertex pipeline expects world_normal void DoGenerateWorldNormal() override { IShaderStageGenerator &vertexGenerator(Vertex()); vertexGenerator.AddIncoming("attr_norm", "vec3"); vertexGenerator.AddUniform("normal_matrix", "mat3"); if (HasTessellation() == false) { vertexGenerator.Append( "\tvec3 world_normal = normalize(normal_matrix * attr_norm).xyz;"); vertexGenerator.Append("\tvarNormal = world_normal;"); } } void DoGenerateObjectNormal() override { AddInterpolationParameter("varObjectNormal", "vec3"); Vertex().Append("\tvarObjectNormal = attr_norm;"); } void DoGenerateWorldPosition() override { Vertex().Append( "\tvec3 local_model_world_position = (model_matrix * vec4(attr_pos, 1.0)).xyz;"); AssignOutput("varWorldPos", "local_model_world_position"); } void DoGenerateVarTangentAndBinormal() override { Vertex().AddIncoming("attr_textan", "vec3"); Vertex().AddIncoming("attr_binormal", "vec3"); bool hasNPatchTessellation = m_TessMode == TessModeValues::TessNPatch; if (!hasNPatchTessellation) { Vertex() << "\tvarTangent = normal_matrix * attr_textan;" << Endl << "\tvarBinormal = normal_matrix * attr_binormal;" << Endl; } else { Vertex() << "\tvarTangent = attr_textan;" << Endl << "\tvarBinormal = attr_binormal;" << Endl; } } void DoGenerateVertexColor() override { Vertex().AddIncoming("attr_color", "vec3"); Vertex().Append("\tvarColor = attr_color;"); } void EndVertexGeneration(bool) override { if (HasTessellation()) { // finalize tess control shader FinalizeTessControlShader(); // finalize tess evaluation shader FinalizeTessEvaluationShader(); TessControl().Append("}"); TessEval().Append("}"); } if (m_Wireframe) { // finalize geometry shader FinalizeWireframeGeometryShader(); Geometry().Append("}"); } Vertex().Append("}"); } void EndFragmentGeneration(bool) override { Fragment().Append("}"); } void AddInterpolationParameter(const char8_t *inName, const char8_t *inType) override { m_InterpolationParameters.insert(eastl::make_pair(Str(inName), Str(inType))); Vertex().AddOutgoing(inName, inType); Fragment().AddIncoming(inName, inType); if (HasTessellation()) { eastl::string nameBuilder(inName); nameBuilder.append("TC"); TessControl().AddOutgoing(nameBuilder.c_str(), inType); nameBuilder.assign(inName); if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry) { nameBuilder.append("TE"); Geometry().AddOutgoing(inName, inType); } TessEval().AddOutgoing(nameBuilder.c_str(), inType); } } IShaderStageGenerator &ActiveStage() override { return Vertex(); } }; NVRenderShaderProgram *Qt3DSRendererImpl::GenerateShader(SSubsetRenderable &inRenderable, TShaderFeatureSet inFeatureSet, bool depth) { // build a string that allows us to print out the shader we are generating to the log. // This is time consuming but I feel like it doesn't happen all that often and is very // useful to users looking at the log file. QLatin1String logPrefix("mesh subset pipeline-- "); m_GeneratedShaderString.clear(); m_GeneratedShaderString.assign(logPrefix.data()); if (depth) m_GeneratedShaderString.append("depth--"); SShaderDefaultMaterialKey theKey(inRenderable.m_ShaderDescription); theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties, depth ? SShaderDefaultMaterialKeyProperties::DepthKey : SShaderDefaultMaterialKeyProperties::DefaultKey); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(m_GeneratedShaderString.c_str()); NVRenderShaderProgram *cachedProgram = theCache.GetProgram(theCacheKey, inFeatureSet); if (cachedProgram) return cachedProgram; SSubsetMaterialVertexPipeline pipeline( *this, inRenderable, m_DefaultMaterialShaderKeyProperties.m_WireframeMode.GetValue(theKey)); if (depth) { return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateDepthPassShader( inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet, inRenderable.m_FirstImage, inRenderable.m_RenderableFlags.HasTransparency(), logPrefix.data()); } return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateShader( inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet, m_CurrentLayer->m_Lights, inRenderable.m_FirstImage, inRenderable.m_RenderableFlags.HasTransparency(), logPrefix.data()); } NVRenderShaderProgram *Qt3DSRendererImpl::GenerateShadowShader(SSubsetRenderable &inRenderable, TShaderFeatureSet inFeatureSet, RenderLightTypes::Enum lightType) { // build a string that allows us to print out the shader we are generating to the log. // This is time consuming but I feel like it doesn't happen all that often and is very // useful to users looking at the log file. QLatin1String logPrefix("mesh subset pipeline-- "); m_GeneratedShaderString.clear(); m_GeneratedShaderString.assign(logPrefix.data()); if (lightType == RenderLightTypes::Point) m_GeneratedShaderString.append("shadowcube--"); else m_GeneratedShaderString.append("shadowmap--"); SShaderDefaultMaterialKey theKey(inRenderable.m_ShaderDescription); theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties, SShaderDefaultMaterialKeyProperties::DepthKey); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(m_GeneratedShaderString.c_str()); NVRenderShaderProgram *cachedProgram = theCache.GetProgram(theCacheKey, inFeatureSet); if (cachedProgram) return cachedProgram; SSubsetMaterialVertexPipeline pipeline( *this, inRenderable, m_DefaultMaterialShaderKeyProperties.m_WireframeMode.GetValue(theKey)); if (lightType == RenderLightTypes::Point) { return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateCubeDepthShader( inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet, inRenderable.m_FirstImage, inRenderable.m_RenderableFlags.HasTransparency(), logPrefix.data()); } return m_qt3dsContext.GetDefaultMaterialShaderGenerator().GenerateOrthoDepthShader( inRenderable.m_Material, inRenderable.m_ShaderDescription, pipeline, inFeatureSet, inRenderable.m_FirstImage, inRenderable.m_RenderableFlags.HasTransparency(), logPrefix.data()); } // -------------- Special cases for shadows ------------------- SRenderableDepthPrepassShader * Qt3DSRendererImpl::GetParaboloidDepthShader(TessModeValues::Enum inTessMode) { if (!m_qt3dsContext.GetRenderContext().IsTessellationSupported() || inTessMode == TessModeValues::NoTess) { return GetParaboloidDepthNoTessShader(); } else if (inTessMode == TessModeValues::TessLinear) { return GetParaboloidDepthTessLinearShader(); } else if (inTessMode == TessModeValues::TessPhong) { return GetParaboloidDepthTessPhongShader(); } else if (inTessMode == TessModeValues::TessNPatch) { return GetParaboloidDepthTessNPatchShader(); } return GetParaboloidDepthNoTessShader(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetParaboloidDepthNoTessShader() { Option> &theDepthShader = m_ParaboloidDepthShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("paraboloid depth shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); IShaderProgramGenerator::OutputParaboloidDepthVertex(vertexShader); IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetParaboloidDepthTessLinearShader() { Option> &theDepthShader = m_ParaboloidDepthTessLinearShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("paraboloid depth tess linear shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); // vertexShader.AddOutgoing("world_pos", "vec4"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); // vertexShader.Append("\tworld_pos = attr_pos;"); vertexShader.Append("}"); tessCtrlShader.AddInclude("tessellationLinear.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); // tessCtrlShader.AddOutgoing( "outUVTC", "vec2" ); // tessCtrlShader.AddOutgoing( "outNormalTC", "vec3" ); tessCtrlShader.Append("void main() {\n"); // tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];"); // tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];"); // tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationLinear.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddOutgoing("world_pos", "vec4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); IShaderProgramGenerator::OutputParaboloidDepthTessEval(tessEvalShader); tessEvalShader.Append("}"); IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetParaboloidDepthTessPhongShader() { Option> &theDepthShader = m_ParaboloidDepthTessPhongShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("paraboloid depth tess phong shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); // vertexShader.AddOutgoing("world_pos", "vec4"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); // vertexShader.Append("\tworld_pos = attr_pos;"); vertexShader.Append("}"); tessCtrlShader.AddInclude("tessellationPhong.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); // tessCtrlShader.AddOutgoing( "outUVTC", "vec2" ); // tessCtrlShader.AddOutgoing( "outNormalTC", "vec3" ); tessCtrlShader.Append("void main() {\n"); // tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];"); // tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];"); // tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationPhong.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddOutgoing("world_pos", "vec4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); IShaderProgramGenerator::OutputParaboloidDepthTessEval(tessEvalShader); tessEvalShader.Append("}"); IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetParaboloidDepthTessNPatchShader() { Option> &theDepthShader = m_ParaboloidDepthTessNPatchShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("paraboloid depth tess NPatch shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); // vertexShader.AddOutgoing("world_pos", "vec4"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); // vertexShader.Append("\tworld_pos = attr_pos;"); vertexShader.Append("}"); tessCtrlShader.AddInclude("tessellationNPatch.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); // tessCtrlShader.AddOutgoing( "outUVTC", "vec2" ); // tessCtrlShader.AddOutgoing( "outNormalTC", "vec3" ); tessCtrlShader.Append("void main() {\n"); // tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];"); // tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];"); // tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationNPatch.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddOutgoing("world_pos", "vec4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); IShaderProgramGenerator::OutputParaboloidDepthTessEval(tessEvalShader); tessEvalShader.Append("}"); IShaderProgramGenerator::OutputParaboloidDepthFragment(fragmentShader); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader * Qt3DSRendererImpl::GetCubeShadowDepthShader(TessModeValues::Enum inTessMode) { if (!m_qt3dsContext.GetRenderContext().IsTessellationSupported() || inTessMode == TessModeValues::NoTess) { return GetCubeDepthNoTessShader(); } else if (inTessMode == TessModeValues::TessLinear) { return GetCubeDepthTessLinearShader(); } else if (inTessMode == TessModeValues::TessPhong) { return GetCubeDepthTessPhongShader(); } else if (inTessMode == TessModeValues::TessNPatch) { return GetCubeDepthTessNPatchShader(); } return GetCubeDepthNoTessShader(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetCubeDepthNoTessShader() { Option> &theDepthShader = m_CubemapDepthShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("cubemap face depth shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { // GetProgramGenerator().BeginProgram( // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex | // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) ); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage( // ShaderGeneratorStages::Geometry ) ); IShaderProgramGenerator::OutputCubeFaceDepthVertex(vertexShader); // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader ); IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetCubeDepthTessLinearShader() { Option> &theDepthShader = m_CubemapDepthTessLinearShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("cubemap face depth linear tess shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { // GetProgramGenerator().BeginProgram( // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex | // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) ); GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage( // ShaderGeneratorStages::Geometry ) ); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("}"); // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader ); IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader); tessCtrlShader.AddInclude("tessellationLinear.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationLinear.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddUniform("model_matrix", "mat4"); tessEvalShader.AddOutgoing("world_pos", "vec4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tworld_pos = model_matrix * pos;"); tessEvalShader.Append("\tworld_pos /= world_pos.w;"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;"); tessEvalShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetCubeDepthTessPhongShader() { Option> &theDepthShader = m_CubemapDepthTessPhongShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("cubemap face depth phong tess shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { // GetProgramGenerator().BeginProgram( // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex | // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) ); GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage( // ShaderGeneratorStages::Geometry ) ); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddIncoming("attr_norm", "vec3"); vertexShader.AddOutgoing("outNormal", "vec3"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("\toutNormal = attr_norm;"); vertexShader.Append("}"); // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader ); IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader); tessCtrlShader.AddInclude("tessellationPhong.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctNorm[0] = outNormal[0];"); tessCtrlShader.Append("\tctNorm[1] = outNormal[1];"); tessCtrlShader.Append("\tctNorm[2] = outNormal[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationPhong.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddUniform("model_matrix", "mat4"); tessEvalShader.AddOutgoing("world_pos", "vec4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tworld_pos = model_matrix * pos;"); tessEvalShader.Append("\tworld_pos /= world_pos.w;"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;"); tessEvalShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetCubeDepthTessNPatchShader() { Option> &theDepthShader = m_CubemapDepthTessNPatchShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("cubemap face depth npatch tess shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { // GetProgramGenerator().BeginProgram( // TShaderGeneratorStageFlags(ShaderGeneratorStages::Vertex | // ShaderGeneratorStages::Fragment | ShaderGeneratorStages::Geometry) ); GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); // IShaderStageGenerator& geometryShader( *GetProgramGenerator().GetStage( // ShaderGeneratorStages::Geometry ) ); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddIncoming("attr_norm", "vec3"); vertexShader.AddOutgoing("outNormal", "vec3"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("\toutNormal = attr_norm;"); vertexShader.Append("}"); // IShaderProgramGenerator::OutputCubeFaceDepthGeometry( geometryShader ); IShaderProgramGenerator::OutputCubeFaceDepthFragment(fragmentShader); tessCtrlShader.AddOutgoing("outNormalTC", "vec3"); tessCtrlShader.AddInclude("tessellationNPatch.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctNorm[0] = outNormal[0];"); tessCtrlShader.Append("\tctNorm[1] = outNormal[1];"); tessCtrlShader.Append("\tctNorm[2] = outNormal[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append( "\toutNormalTC[gl_InvocationID] = outNormal[gl_InvocationID];\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationNPatch.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddUniform("model_matrix", "mat4"); tessEvalShader.AddOutgoing("world_pos", "vec4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tctNorm[0] = outNormalTC[0];"); tessEvalShader.Append("\tctNorm[1] = outNormalTC[1];"); tessEvalShader.Append("\tctNorm[2] = outNormalTC[2];"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tworld_pos = model_matrix * pos;"); tessEvalShader.Append("\tworld_pos /= world_pos.w;"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;"); tessEvalShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader * Qt3DSRendererImpl::GetOrthographicDepthShader(TessModeValues::Enum inTessMode) { if (!m_qt3dsContext.GetRenderContext().IsTessellationSupported() || inTessMode == TessModeValues::NoTess) { return GetOrthographicDepthNoTessShader(); } else if (inTessMode == TessModeValues::TessLinear) { return GetOrthographicDepthTessLinearShader(); } else if (inTessMode == TessModeValues::TessPhong) { return GetOrthographicDepthTessPhongShader(); } else if (inTessMode == TessModeValues::TessNPatch) { return GetOrthographicDepthTessNPatchShader(); } return GetOrthographicDepthNoTessShader(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetOrthographicDepthNoTessShader() { Option> &theDepthShader = m_OrthographicDepthShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("orthographic depth shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.AddOutgoing("outDepth", "vec3"); vertexShader.Append("void main() {"); vertexShader.Append( " gl_Position = model_view_projection * vec4( attr_pos, 1.0 );"); vertexShader.Append(" outDepth.x = gl_Position.z / gl_Position.w;"); vertexShader.Append("}"); fragmentShader.Append("void main() {"); fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;"); fragmentShader.Append("\tfragOutput = vec4(depth);"); fragmentShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetOrthographicDepthTessLinearShader() { Option> &theDepthShader = m_OrthographicDepthTessLinearShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("orthographic depth tess linear shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("}"); fragmentShader.Append("void main() {"); fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;"); fragmentShader.Append("\tfragOutput = vec4(depth);"); fragmentShader.Append("}"); tessCtrlShader.AddInclude("tessellationLinear.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationLinear.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddOutgoing("outDepth", "vec3"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;"); tessEvalShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;"); tessEvalShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetOrthographicDepthTessPhongShader() { Option> &theDepthShader = m_OrthographicDepthTessPhongShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("orthographic depth tess phong shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddIncoming("attr_norm", "vec3"); vertexShader.AddOutgoing("outNormal", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("\toutNormal = attr_norm;"); vertexShader.Append("}"); fragmentShader.Append("void main() {"); fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;"); fragmentShader.Append("\tfragOutput = vec4(depth);"); fragmentShader.Append("}"); tessCtrlShader.AddInclude("tessellationPhong.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctNorm[0] = outNormal[0];"); tessCtrlShader.Append("\tctNorm[1] = outNormal[1];"); tessCtrlShader.Append("\tctNorm[2] = outNormal[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationPhong.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddOutgoing("outDepth", "vec3"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;"); tessEvalShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;"); tessEvalShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetOrthographicDepthTessNPatchShader() { Option> &theDepthShader = m_OrthographicDepthTessNPatchShader; if (theDepthShader.hasValue() == false) { TStrType name; name.assign("orthographic depth tess npatch shader"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddIncoming("attr_norm", "vec3"); vertexShader.AddOutgoing("outNormal", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); fragmentShader.AddUniform("model_view_projection", "mat4"); fragmentShader.AddUniform("camera_properties", "vec2"); fragmentShader.AddUniform("camera_position", "vec3"); fragmentShader.AddUniform("camera_direction", "vec3"); fragmentShader.AddInclude("depthpass.glsllib"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("\toutNormal = attr_norm;"); vertexShader.Append("}"); fragmentShader.Append("void main() {"); // fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);"); fragmentShader.Append("\tfloat depth = (outDepth.x - camera_properties.x) / " "(camera_properties.y - camera_properties.x);"); fragmentShader.Append("\tfragOutput = vec4(depth);"); fragmentShader.Append("}"); tessCtrlShader.AddInclude("tessellationNPatch.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.AddOutgoing("outNormalTC", "vec3"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctNorm[0] = outNormal[0];"); tessCtrlShader.Append("\tctNorm[1] = outNormal[1];"); tessCtrlShader.Append("\tctNorm[2] = outNormal[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationNPatch.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.AddUniform("model_matrix", "mat4"); tessEvalShader.AddOutgoing("outDepth", "vec3"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;"); tessEvalShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;"); tessEvalShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthShader = NVScopedRefCounted(); } } return theDepthShader.getValue(); } // --------------------------------- SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetDepthPrepassShader(bool inDisplaced) { Option> &theDepthPrePassShader = (!inDisplaced) ? m_DepthPrepassShader : m_DepthPrepassShaderDisplaced; if (theDepthPrePassShader.hasValue() == false) { // check if we do displacement mapping TStrType name; name.assign("depth prepass shader"); if (inDisplaced) name.append(" displacement"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.Append("void main() {"); if (inDisplaced) { GetQt3DSContext() .GetDefaultMaterialShaderGenerator() .AddDisplacementMappingForDepthPass(vertexShader); } else { vertexShader.Append( "\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);"); } vertexShader.Append("}"); fragmentShader.Append("void main() {"); fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);"); fragmentShader.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet()); } if (depthShaderProgram) { theDepthPrePassShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthPrePassShader = NVScopedRefCounted(); } } return theDepthPrePassShader.getValue(); } SRenderableDepthPrepassShader * Qt3DSRendererImpl::GetDepthTessPrepassShader(TessModeValues::Enum inTessMode, bool inDisplaced) { if (!m_qt3dsContext.GetRenderContext().IsTessellationSupported() || inTessMode == TessModeValues::NoTess) { return GetDepthPrepassShader(inDisplaced); } else if (inTessMode == TessModeValues::TessLinear) { return GetDepthTessLinearPrepassShader(inDisplaced); } else if (inTessMode == TessModeValues::TessPhong) { return GetDepthTessPhongPrepassShader(); } else if (inTessMode == TessModeValues::TessNPatch) { return GetDepthTessNPatchPrepassShader(); } return GetDepthPrepassShader(inDisplaced); } SRenderableDepthPrepassShader * Qt3DSRendererImpl::GetDepthTessLinearPrepassShader(bool inDisplaced) { Option> &theDepthPrePassShader = (!inDisplaced) ? m_DepthTessLinearPrepassShader : m_DepthTessLinearPrepassShaderDisplaced; if (theDepthPrePassShader.hasValue() == false) { // check if we do displacement mapping TStrType name; name.assign("depth tess linear prepass shader"); if (inDisplaced) name.append(" displacement"); IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr(name.c_str()); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); if (inDisplaced) { vertexShader.AddIncoming("attr_uv0", "vec2"); vertexShader.AddIncoming("attr_norm", "vec3"); vertexShader.AddUniform("displacementMap_rot", "vec4"); vertexShader.AddUniform("displacementMap_offset", "vec3"); vertexShader.AddOutgoing("outNormal", "vec3"); vertexShader.AddOutgoing("outUV", "vec2"); } vertexShader.AddOutgoing("outWorldPos", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.AddUniform("model_matrix", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); if (inDisplaced) { vertexShader.Append("\toutNormal = attr_norm;"); vertexShader.Append("\tvec3 uTransform = vec3( displacementMap_rot.x, " "displacementMap_rot.y, displacementMap_offset.x );"); vertexShader.Append("\tvec3 vTransform = vec3( displacementMap_rot.z, " "displacementMap_rot.w, displacementMap_offset.y );"); vertexShader.AddInclude( "defaultMaterialLighting.glsllib"); // getTransformedUVCoords is in the // lighting code addition. vertexShader << "\tvec2 uv_coords = attr_uv0;" << Endl; vertexShader << "\toutUV = getTransformedUVCoords( vec3( uv_coords, 1.0), " "uTransform, vTransform );\n"; } vertexShader.Append("\toutWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;"); vertexShader.Append("}"); fragmentShader.Append("void main() {"); fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);"); fragmentShader.Append("}"); tessCtrlShader.AddInclude("tessellationLinear.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.AddOutgoing("outUVTC", "vec2"); tessCtrlShader.AddOutgoing("outNormalTC", "vec3"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];"); tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];"); tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); if (inDisplaced) { tessCtrlShader.Append("\toutUVTC[gl_InvocationID] = outUV[gl_InvocationID];"); tessCtrlShader.Append( "\toutNormalTC[gl_InvocationID] = outNormal[gl_InvocationID];"); } tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationLinear.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); if (inDisplaced) { tessEvalShader.AddUniform("displacementSampler", "sampler2D"); tessEvalShader.AddUniform("displaceAmount", "float"); tessEvalShader.AddInclude("defaultMaterialFileDisplacementTexture.glsllib"); } tessEvalShader.AddOutgoing("outUV", "vec2"); tessEvalShader.AddOutgoing("outNormal", "vec3"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); if (inDisplaced) { tessEvalShader << "\toutUV = gl_TessCoord.x * outUVTC[0] + gl_TessCoord.y * " "outUVTC[1] + gl_TessCoord.z * outUVTC[2];" << Endl; tessEvalShader << "\toutNormal = gl_TessCoord.x * outNormalTC[0] + gl_TessCoord.y * " "outNormalTC[1] + gl_TessCoord.z * outNormalTC[2];" << Endl; tessEvalShader << "\tvec3 displacedPos = defaultMaterialFileDisplacementTexture( " "displacementSampler , displaceAmount, outUV , outNormal, pos.xyz );" << Endl; tessEvalShader.Append( "\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);"); } else tessEvalShader.Append("\tgl_Position = model_view_projection * pos;"); tessEvalShader.Append("}"); SShaderCacheProgramFlags theFlags; theFlags.SetTessellationEnabled(true); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( name.c_str(), theFlags, TShaderFeatureSet()); } if (depthShaderProgram) { theDepthPrePassShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { theDepthPrePassShader = NVScopedRefCounted(); } } return theDepthPrePassShader->mPtr; } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetDepthTessPhongPrepassShader() { if (m_DepthTessPhongPrepassShader.hasValue() == false) { IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr("depth tess phong prepass shader"); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddIncoming("attr_norm", "vec3"); vertexShader.AddOutgoing("outNormal", "vec3"); vertexShader.AddOutgoing("outWorldPos", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.AddUniform("model_matrix", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("\toutWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;"); vertexShader.Append("\toutNormal = attr_norm;"); vertexShader.Append("}"); fragmentShader.Append("void main() {"); fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);"); fragmentShader.Append("}"); tessCtrlShader.AddInclude("tessellationPhong.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];"); tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];"); tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];"); tessCtrlShader.Append("\tctNorm[0] = outNormal[0];"); tessCtrlShader.Append("\tctNorm[1] = outNormal[1];"); tessCtrlShader.Append("\tctNorm[2] = outNormal[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationPhong.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;\n"); tessEvalShader.Append("}"); SShaderCacheProgramFlags theFlags; theFlags.SetTessellationEnabled(true); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( "depth tess phong prepass shader", theFlags, TShaderFeatureSet()); } if (depthShaderProgram) { m_DepthTessPhongPrepassShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { m_DepthTessPhongPrepassShader = NVScopedRefCounted(); } } return m_DepthTessPhongPrepassShader->mPtr; } SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetDepthTessNPatchPrepassShader() { if (m_DepthTessNPatchPrepassShader.hasValue() == false) { IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr("depth tess npatch prepass shader"); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags( ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment)); IShaderStageGenerator &vertexShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &tessCtrlShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessControl)); IShaderStageGenerator &tessEvalShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::TessEval)); IShaderStageGenerator &fragmentShader( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexShader.AddIncoming("attr_pos", "vec3"); vertexShader.AddIncoming("attr_norm", "vec3"); vertexShader.AddOutgoing("outNormal", "vec3"); vertexShader.AddOutgoing("outWorldPos", "vec3"); vertexShader.AddUniform("model_view_projection", "mat4"); vertexShader.AddUniform("model_matrix", "mat4"); vertexShader.Append("void main() {"); vertexShader.Append("\tgl_Position = vec4(attr_pos, 1.0);"); vertexShader.Append("\toutWorldPos = (model_matrix * vec4(attr_pos, 1.0)).xyz;"); vertexShader.Append("\toutNormal = attr_norm;"); vertexShader.Append("}"); fragmentShader.Append("void main() {"); fragmentShader.Append("\tfragOutput = vec4(0.0, 0.0, 0.0, 0.0);"); fragmentShader.Append("}"); tessCtrlShader.AddOutgoing("outNormalTC", "vec3"); tessCtrlShader.AddInclude("tessellationNPatch.glsllib"); tessCtrlShader.AddUniform("tessLevelInner", "float"); tessCtrlShader.AddUniform("tessLevelOuter", "float"); tessCtrlShader.Append("void main() {\n"); tessCtrlShader.Append("\tctWorldPos[0] = outWorldPos[0];"); tessCtrlShader.Append("\tctWorldPos[1] = outWorldPos[1];"); tessCtrlShader.Append("\tctWorldPos[2] = outWorldPos[2];"); tessCtrlShader.Append("\tctNorm[0] = outNormal[0];"); tessCtrlShader.Append("\tctNorm[1] = outNormal[1];"); tessCtrlShader.Append("\tctNorm[2] = outNormal[2];"); tessCtrlShader.Append( "\tctTangent[0] = outNormal[0];"); // we don't care for the tangent tessCtrlShader.Append("\tctTangent[1] = outNormal[1];"); tessCtrlShader.Append("\tctTangent[2] = outNormal[2];"); tessCtrlShader.Append( "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;"); tessCtrlShader.Append("\ttessShader( tessLevelOuter, tessLevelInner);\n"); tessCtrlShader.Append( "\toutNormalTC[gl_InvocationID] = outNormal[gl_InvocationID];\n"); tessCtrlShader.Append("}"); tessEvalShader.AddInclude("tessellationNPatch.glsllib"); tessEvalShader.AddUniform("model_view_projection", "mat4"); tessEvalShader.Append("void main() {"); tessEvalShader.Append("\tctNorm[0] = outNormalTC[0];"); tessEvalShader.Append("\tctNorm[1] = outNormalTC[1];"); tessEvalShader.Append("\tctNorm[2] = outNormalTC[2];"); tessEvalShader.Append( "\tctTangent[0] = outNormalTC[0];"); // we don't care for the tangent tessEvalShader.Append("\tctTangent[1] = outNormalTC[1];"); tessEvalShader.Append("\tctTangent[2] = outNormalTC[2];"); tessEvalShader.Append("\tvec4 pos = tessShader( );\n"); tessEvalShader.Append("\tgl_Position = model_view_projection * pos;\n"); tessEvalShader.Append("}"); SShaderCacheProgramFlags theFlags; theFlags.SetTessellationEnabled(true); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( "depth tess npatch prepass shader", theFlags, TShaderFeatureSet()); } if (depthShaderProgram) { m_DepthTessNPatchPrepassShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext())); } else { m_DepthTessNPatchPrepassShader = NVScopedRefCounted(); } } return m_DepthTessNPatchPrepassShader->mPtr; } SDefaultAoPassShader *Qt3DSRendererImpl::GetDefaultAoPassShader(TShaderFeatureSet inFeatureSet) { if (m_DefaultAoPassShader.hasValue() == false) { IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr("fullscreen AO pass shader"); NVRenderShaderProgram *aoPassShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!aoPassShaderProgram) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &theVertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &theFragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); theVertexGenerator.AddIncoming("attr_pos", "vec3"); theVertexGenerator.AddIncoming("attr_uv", "vec2"); theVertexGenerator.AddOutgoing("uv_coords", "vec2"); theVertexGenerator.Append("void main() {"); theVertexGenerator.Append("\tgl_Position = vec4(attr_pos.xy, 0.5, 1.0 );"); theVertexGenerator.Append("\tuv_coords = attr_uv;"); theVertexGenerator.Append("}"); // fragmentGenerator.AddInclude( "SSAOCustomMaterial.glsllib" ); theFragmentGenerator.AddInclude("viewProperties.glsllib"); theFragmentGenerator.AddInclude("screenSpaceAO.glsllib"); if (m_Context->GetRenderContextType() == NVRenderContextValues::GLES2) { theFragmentGenerator << "\tuniform vec4 ao_properties;" << Endl << "\tuniform vec4 ao_properties2;" << Endl << "\tuniform vec4 shadow_properties;" << Endl << "\tuniform vec4 aoScreenConst;" << Endl << "\tuniform vec4 UvToEyeConst;" << Endl; } else { theFragmentGenerator << "layout (std140) uniform cbAoShadow { " << Endl << "\tvec4 ao_properties;" << Endl << "\tvec4 ao_properties2;" << Endl << "\tvec4 shadow_properties;" << Endl << "\tvec4 aoScreenConst;" << Endl << "\tvec4 UvToEyeConst;" << Endl << "};" << Endl; } theFragmentGenerator.AddUniform("camera_direction", "vec3"); theFragmentGenerator.AddUniform("depth_sampler", "sampler2D"); theFragmentGenerator.Append("void main() {"); theFragmentGenerator << "\tfloat aoFactor;" << Endl; theFragmentGenerator << "\tvec3 screenNorm;" << Endl; // We're taking multiple depth samples and getting the derivatives at each of them // to get a more // accurate view space normal vector. When we do only one, we tend to get bizarre // values at the edges // surrounding objects, and this also ends up giving us weird AO values. // If we had a proper screen-space normal map, that would also do the trick. if (m_Context->GetRenderContextType() == NVRenderContextValues::GLES2) { theFragmentGenerator.AddUniform("depth_sampler_size", "vec2"); theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );"); theFragmentGenerator.Append("\tfloat depth = getDepthValue( " "texture2D(depth_sampler, vec2(iCoords)" " / depth_sampler_size), camera_properties );"); theFragmentGenerator.Append( "\tdepth = depthValueToLinearDistance( depth, camera_properties );"); theFragmentGenerator.Append("\tdepth = (depth - camera_properties.x) / " "(camera_properties.y - camera_properties.x);"); theFragmentGenerator.Append("\tfloat depth2 = getDepthValue( " "texture2D(depth_sampler, vec2(iCoords+ivec2(1))" " / depth_sampler_size), camera_properties );"); theFragmentGenerator.Append( "\tdepth2 = depthValueToLinearDistance( depth, camera_properties );"); theFragmentGenerator.Append("\tfloat depth3 = getDepthValue( " "texture2D(depth_sampler, vec2(iCoords-ivec2(1))" " / depth_sampler_size), camera_properties );"); } else { theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );"); theFragmentGenerator.Append("\tfloat depth = getDepthValue( " "texelFetch(depth_sampler, iCoords, 0), " "camera_properties );"); theFragmentGenerator.Append( "\tdepth = depthValueToLinearDistance( depth, camera_properties );"); theFragmentGenerator.Append("\tdepth = (depth - camera_properties.x) / " "(camera_properties.y - camera_properties.x);"); theFragmentGenerator.Append("\tfloat depth2 = getDepthValue( " "texelFetch(depth_sampler, iCoords+ivec2(1), 0), " "camera_properties );"); theFragmentGenerator.Append( "\tdepth2 = depthValueToLinearDistance( depth, camera_properties );"); theFragmentGenerator.Append("\tfloat depth3 = getDepthValue( " "texelFetch(depth_sampler, iCoords-ivec2(1), 0), " "camera_properties );"); } theFragmentGenerator.Append( "\tdepth3 = depthValueToLinearDistance( depth, camera_properties );"); theFragmentGenerator.Append("\tvec3 tanU = vec3(10, 0, dFdx(depth));"); theFragmentGenerator.Append("\tvec3 tanV = vec3(0, 10, dFdy(depth));"); theFragmentGenerator.Append("\tscreenNorm = normalize(cross(tanU, tanV));"); theFragmentGenerator.Append("\ttanU = vec3(10, 0, dFdx(depth2));"); theFragmentGenerator.Append("\ttanV = vec3(0, 10, dFdy(depth2));"); theFragmentGenerator.Append("\tscreenNorm += normalize(cross(tanU, tanV));"); theFragmentGenerator.Append("\ttanU = vec3(10, 0, dFdx(depth3));"); theFragmentGenerator.Append("\ttanV = vec3(0, 10, dFdy(depth3));"); theFragmentGenerator.Append("\tscreenNorm += normalize(cross(tanU, tanV));"); theFragmentGenerator.Append("\tscreenNorm = -normalize(screenNorm);"); theFragmentGenerator.Append("\taoFactor = \ SSambientOcclusion( depth_sampler, screenNorm, ao_properties, ao_properties2, \ camera_properties, aoScreenConst, UvToEyeConst );"); theFragmentGenerator.Append( "\tgl_FragColor = vec4(aoFactor, aoFactor, aoFactor, 1.0);"); theFragmentGenerator.Append("}"); aoPassShaderProgram = GetProgramGenerator().CompileGeneratedShader( "fullscreen AO pass shader", SShaderCacheProgramFlags(), inFeatureSet); } if (aoPassShaderProgram) { m_DefaultAoPassShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(*aoPassShaderProgram, GetContext())); } else { m_DefaultAoPassShader = NVScopedRefCounted(); } } return m_DefaultAoPassShader->mPtr; } SDefaultAoPassShader *Qt3DSRendererImpl::GetFakeDepthShader(TShaderFeatureSet inFeatureSet) { if (m_FakeDepthShader.hasValue() == false) { IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr("depth display shader"); NVRenderShaderProgram *depthShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!depthShaderProgram) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &theVertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &theFragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); theVertexGenerator.AddIncoming("attr_pos", "vec3"); theVertexGenerator.AddIncoming("attr_uv", "vec2"); theVertexGenerator.AddOutgoing("uv_coords", "vec2"); theVertexGenerator.Append("void main() {"); theVertexGenerator.Append("\tgl_Position = vec4(attr_pos.xy, 0.5, 1.0 );"); theVertexGenerator.Append("\tuv_coords = attr_uv;"); theVertexGenerator.Append("}"); theFragmentGenerator.AddUniform("depth_sampler", "sampler2D"); theFragmentGenerator.Append("void main() {"); theFragmentGenerator.Append("\tivec2 iCoords = ivec2( gl_FragCoord.xy );"); theFragmentGenerator.Append( "\tfloat depSample = texelFetch(depth_sampler, iCoords, 0).x;"); theFragmentGenerator.Append( "\tgl_FragColor = vec4( depSample, depSample, depSample, 1.0 );"); theFragmentGenerator.Append("\treturn;"); theFragmentGenerator.Append("}"); depthShaderProgram = GetProgramGenerator().CompileGeneratedShader( "depth display shader", SShaderCacheProgramFlags(), inFeatureSet); } if (depthShaderProgram) { m_FakeDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)( *depthShaderProgram, GetContext())); } else { m_FakeDepthShader = NVScopedRefCounted(); } } return m_FakeDepthShader->mPtr; } SDefaultAoPassShader *Qt3DSRendererImpl::GetFakeCubeDepthShader(TShaderFeatureSet inFeatureSet) { if (!m_FakeCubemapDepthShader.hasValue()) { IShaderCache &theCache = m_qt3dsContext.GetShaderCache(); CRegisteredString theCacheKey = m_qt3dsContext.GetStringTable().RegisterStr("cube depth display shader"); NVRenderShaderProgram *cubeShaderProgram = theCache.GetProgram(theCacheKey, TShaderFeatureSet()); if (!cubeShaderProgram) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &theVertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &theFragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); theVertexGenerator.AddIncoming("attr_pos", "vec3"); theVertexGenerator.AddIncoming("attr_uv", "vec2"); theVertexGenerator.AddOutgoing("sample_dir", "vec3"); theVertexGenerator.Append("void main() {"); theVertexGenerator.Append("\tgl_Position = vec4(attr_pos.xy, 0.5, 1.0 );"); theVertexGenerator.Append( "\tsample_dir = vec3(4.0 * (attr_uv.x - 0.5), -1.0, 4.0 * (attr_uv.y - 0.5));"); theVertexGenerator.Append("}"); theFragmentGenerator.AddUniform("depth_cube", "samplerCube"); theFragmentGenerator.Append("void main() {"); theFragmentGenerator.Append( "\tfloat smpDepth = texture( depth_cube, sample_dir ).x;"); theFragmentGenerator.Append( "\tgl_FragColor = vec4(smpDepth, smpDepth, smpDepth, 1.0);"); theFragmentGenerator.Append("}"); cubeShaderProgram = GetProgramGenerator().CompileGeneratedShader( "cube depth display shader", SShaderCacheProgramFlags(), inFeatureSet); } if (cubeShaderProgram) { m_FakeCubemapDepthShader = NVScopedRefCounted( QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(*cubeShaderProgram, GetContext())); } else { m_FakeCubemapDepthShader = NVScopedRefCounted(); } } return m_FakeCubemapDepthShader.getValue(); } STextRenderHelper Qt3DSRendererImpl::GetTextShader(bool inUsePathRendering) { STextShaderPtr &thePtr = (!inUsePathRendering) ? m_TextShader : m_TextPathShader; if (thePtr.HasGeneratedShader()) return STextRenderHelper(thePtr, *m_QuadInputAssembler); NVRenderShaderProgram *theShader = NULL; NVRenderProgramPipeline *thePipeline = NULL; if (!inUsePathRendering) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); // xy of text dimensions are scaling factors, zw are offset factors. vertexGenerator.AddUniform("text_dimensions", "vec4"); vertexGenerator.AddUniform("model_view_projection", "mat4"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator << "\tvec3 textPos = vec3(attr_pos.x * text_dimensions.x + text_dimensions.z" << ", attr_pos.y * text_dimensions.y + text_dimensions.w" << ", attr_pos.z);" << Endl; vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(textPos, 1.0);"); vertexGenerator.Append("\tuv_coords = attr_uv;"); fragmentGenerator.AddUniform("text_textcolor", "vec4"); fragmentGenerator.AddUniform("text_textdimensions", "vec3"); fragmentGenerator.AddUniform("text_image", "sampler2D"); fragmentGenerator.AddUniform("text_backgroundcolor", "vec3"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec2 theCoords = uv_coords;"); // Enable rendering from a sub-rect fragmentGenerator << "\ttheCoords.x = theCoords.x * text_textdimensions.x;" << Endl << "\ttheCoords.y = theCoords.y * text_textdimensions.y;" << Endl // flip the y uv coord if the dimension's z variable is set << "\tif ( text_textdimensions.z > 0.0 ) theCoords.y = 1.0 - theCoords.y;" << Endl; fragmentGenerator.Append( "\tvec4 c = texture2D(text_image, theCoords);"); fragmentGenerator.Append( "\tfragOutput = vec4(mix(text_backgroundcolor.rgb, " "text_textcolor.rgb, c.rgb), c.a) * text_textcolor.a;"); vertexGenerator.Append("}"); fragmentGenerator.Append("}"); const char *shaderName = "text shader"; theShader = GetProgramGenerator().CompileGeneratedShader( shaderName, SShaderCacheProgramFlags(), TShaderFeatureSet(), false); } else { GetProgramGenerator().BeginProgram( TShaderGeneratorStageFlags(ShaderGeneratorStages::Fragment)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); fragmentGenerator.AddUniform("text_textcolor", "vec4"); fragmentGenerator.AddUniform("text_backgroundcolor", "vec3"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tfragOutput = vec4(mix(text_backgroundcolor.rgb, " "text_textcolor.rgb, text_textcolor.a), text_textcolor.a );"); fragmentGenerator.Append("}"); const char *shaderName = "text path shader"; theShader = GetProgramGenerator().CompileGeneratedShader( shaderName, SShaderCacheProgramFlags(), TShaderFeatureSet(), true); // setup program pipeline if (theShader) { thePipeline = GetContext().CreateProgramPipeline(); if (thePipeline) { thePipeline->SetProgramStages( theShader, qt3ds::render::NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Fragment)); } } } if (theShader == NULL) { thePtr.Set(NULL); } else { GenerateXYQuad(); thePtr.Set(QT3DS_NEW(m_Context->GetAllocator(), STextShader)(*theShader, thePipeline)); } return STextRenderHelper(thePtr, *m_QuadInputAssembler); } STextDepthShader *Qt3DSRendererImpl::GetTextDepthShader() { if (m_TextDepthPrepassShader.hasValue() == false) { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); // xy of text dimensions are scaling factors, zw are offset factors. vertexGenerator.AddUniform("text_dimensions", "vec4"); vertexGenerator.AddUniform("model_view_projection", "mat4"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator << "\tvec3 textPos = vec3(attr_pos.x * text_dimensions.x + text_dimensions.z" << ", attr_pos.y * text_dimensions.y + text_dimensions.w" << ", attr_pos.z);" << Endl; vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(textPos, 1.0);"); vertexGenerator.Append("\tuv_coords = attr_uv;"); fragmentGenerator.AddUniform("text_textdimensions", "vec3"); fragmentGenerator.AddUniform("text_image", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec2 theCoords = uv_coords;"); // Enable rendering from a sub-rect fragmentGenerator << "\ttheCoords.x = theCoords.x * text_textdimensions.x;" << Endl << "\ttheCoords.y = theCoords.y * text_textdimensions.y;" << Endl // flip the y uv coord if the dimension's z variable is set << "\tif ( text_textdimensions.z > 0.0 ) theCoords.y = 1.0 - theCoords.y;" << Endl; fragmentGenerator.Append("\tfloat alpha_mask = texture2D( text_image, theCoords ).r;"); fragmentGenerator.Append("\tif ( alpha_mask < .05 ) discard;"); vertexGenerator.Append("}"); fragmentGenerator.Append("}"); const char *shaderName = "text depth shader"; NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( shaderName, SShaderCacheProgramFlags(), TShaderFeatureSet()); if (theShader == NULL) { m_TextDepthPrepassShader = NVScopedRefCounted(); } else { GenerateXYQuad(); m_TextDepthPrepassShader = NVScopedRefCounted( QT3DS_NEW(m_Context->GetAllocator(), STextDepthShader)( m_Context->GetAllocator(), *theShader, *m_QuadInputAssembler)); } } return m_TextDepthPrepassShader->mPtr; } STextRenderHelper Qt3DSRendererImpl::GetTextWidgetShader() { if (m_TextWidgetShader.HasGeneratedShader()) return STextRenderHelper(m_TextWidgetShader, *m_QuadInputAssembler); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); // xy of text dimensions are scaling factors, zw are offset factors. vertexGenerator.AddUniform("text_dimensions", "vec4"); vertexGenerator.AddUniform("model_view_projection", "mat4"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator << "\tvec3 textPos = vec3(attr_pos.x * text_dimensions.x + text_dimensions.z" << ", attr_pos.y * text_dimensions.y + text_dimensions.w" << ", attr_pos.z);" << Endl; vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(textPos, 1.0);"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("text_textcolor", "vec4"); fragmentGenerator.AddUniform("text_textdimensions", "vec3"); fragmentGenerator.AddUniform("text_image", "sampler2D"); fragmentGenerator.AddUniform("text_backgroundcolor", "vec3"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec2 theCoords = uv_coords;"); // Enable rendering from a sub-rect fragmentGenerator << "\ttheCoords.x = theCoords.x * text_textdimensions.x;" << Endl << "\ttheCoords.y = theCoords.y * text_textdimensions.y;" << Endl // flip the y uv coord if the dimension's z variable is set << "\tif ( text_textdimensions.z > 0.0 ) theCoords.y = 1.0 - theCoords.y;" << Endl; fragmentGenerator.Append( "\tfloat alpha_mask = texture2D( text_image, theCoords ).r * text_textcolor.a;"); fragmentGenerator.Append("\tfragOutput = vec4(mix(text_backgroundcolor.rgb, " "text_textcolor.rgb, alpha_mask), 1.0 );"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "text widget shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); if (theShader == NULL) m_TextWidgetShader.Set(NULL); else { GenerateXYQuad(); m_TextWidgetShader.Set(QT3DS_NEW(m_Context->GetAllocator(), STextShader)(*theShader)); } return STextRenderHelper(m_TextWidgetShader, *m_QuadInputAssembler); } STextRenderHelper Qt3DSRendererImpl::GetOnscreenTextShader() { if (m_TextOnscreenShader.HasGeneratedShader()) return STextRenderHelper(m_TextOnscreenShader, *m_QuadStripInputAssembler); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddUniform("model_view_projection", "mat4"); vertexGenerator.AddUniform("vertex_offsets", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tvec3 pos = attr_pos + vec3(vertex_offsets, 0.0);"); vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(pos, 1.0);"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("text_textcolor", "vec4"); fragmentGenerator.AddUniform("text_image", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tfloat alpha = texture2D( text_image, uv_coords ).a;"); fragmentGenerator.Append( "\tfragOutput = vec4(text_textcolor.r, text_textcolor.g, text_textcolor.b, alpha);"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "onscreen texture shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); if (theShader == NULL) m_TextOnscreenShader.Set(NULL); else { GenerateXYQuadStrip(); m_TextOnscreenShader.Set(QT3DS_NEW(m_Context->GetAllocator(), STextShader)(*theShader)); } return STextRenderHelper(m_TextOnscreenShader, *m_QuadStripInputAssembler); } NVRenderShaderProgram *Qt3DSRendererImpl::GetTextAtlasEntryShader() { GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddUniform("model_view_projection", "mat4"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(attr_pos, 1.0);"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("text_image", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tfloat alpha = texture2D( text_image, uv_coords ).a;"); fragmentGenerator.Append("\tfragOutput = vec4(alpha, alpha, alpha, alpha);"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "texture atlas entry shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); return theShader; } STextRenderHelper Qt3DSRendererImpl::GetShader(STextRenderable & /*inRenderable*/, bool inUsePathRendering) { return GetTextShader(inUsePathRendering); } SLayerSceneShader *Qt3DSRendererImpl::GetSceneLayerShader() { if (m_SceneLayerShader.hasValue()) return m_SceneLayerShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); // xy of text dimensions are scaling factors, zw are offset factors. vertexGenerator.AddUniform("layer_dimensions", "vec2"); vertexGenerator.AddUniform("model_view_projection", "mat4"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator << "\tvec3 layerPos = vec3(attr_pos.x * layer_dimensions.x / 2.0" << ", attr_pos.y * layer_dimensions.y / 2.0" << ", attr_pos.z);" << Endl; vertexGenerator.Append("\tgl_Position = model_view_projection * vec4(layerPos, 1.0);"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("layer_image", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec2 theCoords = uv_coords;\n"); fragmentGenerator.Append("\tvec4 theLayerTexture = texture2D( layer_image, theCoords );\n"); fragmentGenerator.Append("\tfragOutput = theLayerTexture;\n"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "layer shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SLayerSceneShader)(*theShader); m_SceneLayerShader = retval; return m_SceneLayerShader.getValue(); } SLayerProgAABlendShader *Qt3DSRendererImpl::GetLayerProgAABlendShader() { if (m_LayerProgAAShader.hasValue()) return m_LayerProgAAShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("accumulator", "sampler2D"); fragmentGenerator.AddUniform("last_frame", "sampler2D"); fragmentGenerator.AddUniform("blend_factors", "vec2"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec4 accum = texture2D( accumulator, uv_coords );"); fragmentGenerator.Append("\tvec4 lastFrame = texture2D( last_frame, uv_coords );"); fragmentGenerator.Append( "\tgl_FragColor = accum*blend_factors.y + lastFrame*blend_factors.x;"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "layer progressiveAA blend shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SLayerProgAABlendShader)(*theShader); m_LayerProgAAShader = retval; return m_LayerProgAAShader.getValue(); } SShadowmapPreblurShader *Qt3DSRendererImpl::GetCubeShadowBlurXShader() { if (m_CubeShadowBlurXShader.hasValue()) return m_CubeShadowBlurXShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); // vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords.xy = attr_pos.xy;"); vertexGenerator.Append("}"); // This with the ShadowBlurYShader design for a 2-pass 5x5 (sigma=1.0) // Weights computed using -- http://dev.theomader.com/gaussian-kernel-calculator/ fragmentGenerator.AddUniform("camera_properties", "vec2"); fragmentGenerator.AddUniform("depthCube", "samplerCube"); // fragmentGenerator.AddUniform("depthSrc", "sampler2D"); fragmentGenerator.Append("layout(location = 0) out vec4 frag0;"); fragmentGenerator.Append("layout(location = 1) out vec4 frag1;"); fragmentGenerator.Append("layout(location = 2) out vec4 frag2;"); fragmentGenerator.Append("layout(location = 3) out vec4 frag3;"); fragmentGenerator.Append("layout(location = 4) out vec4 frag4;"); fragmentGenerator.Append("layout(location = 5) out vec4 frag5;"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tfloat ofsScale = camera_properties.x / 2500.0;"); fragmentGenerator.Append("\tvec3 dir0 = vec3(1.0, -uv_coords.y, -uv_coords.x);"); fragmentGenerator.Append("\tvec3 dir1 = vec3(-1.0, -uv_coords.y, uv_coords.x);"); fragmentGenerator.Append("\tvec3 dir2 = vec3(uv_coords.x, 1.0, uv_coords.y);"); fragmentGenerator.Append("\tvec3 dir3 = vec3(uv_coords.x, -1.0, -uv_coords.y);"); fragmentGenerator.Append("\tvec3 dir4 = vec3(uv_coords.x, -uv_coords.y, 1.0);"); fragmentGenerator.Append("\tvec3 dir5 = vec3(-uv_coords.x, -uv_coords.y, -1.0);"); fragmentGenerator.Append("\tfloat depth0;"); fragmentGenerator.Append("\tfloat depth1;"); fragmentGenerator.Append("\tfloat depth2;"); fragmentGenerator.Append("\tfloat outDepth;"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir0).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir0 + vec3(0.0, 0.0, -ofsScale)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir0 + vec3(0.0, 0.0, ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir0 + vec3(0.0, 0.0, -2.0*ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir0 + vec3(0.0, 0.0, 2.0*ofsScale)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag0 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir1).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir1 + vec3(0.0, 0.0, -ofsScale)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir1 + vec3(0.0, 0.0, ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir1 + vec3(0.0, 0.0, -2.0*ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir1 + vec3(0.0, 0.0, 2.0*ofsScale)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag1 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir2).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir2 + vec3(-ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir2 + vec3(ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir2 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir2 + vec3(2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag2 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir3).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir3 + vec3(-ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir3 + vec3(ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir3 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir3 + vec3(2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag3 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir4).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir4 + vec3(-ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir4 + vec3(ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir4 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir4 + vec3(2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag4 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir5).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir5 + vec3(-ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir5 + vec3(ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir5 + vec3(-2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir5 + vec3(2.0*ofsScale, 0.0, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag5 = vec4(outDepth);"); fragmentGenerator.Append("}"); CRegisteredString featureName(m_StringTable->RegisterStr("NO_FRAG_OUTPUT")); SShaderPreprocessorFeature noFragOutputFeature(featureName, true); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "cubemap shadow blur X shader", SShaderCacheProgramFlags(), TShaderFeatureSet(&noFragOutputFeature, 1)); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader); m_CubeShadowBlurXShader = retval; return m_CubeShadowBlurXShader.getValue(); } SShadowmapPreblurShader *Qt3DSRendererImpl::GetCubeShadowBlurYShader() { if (m_CubeShadowBlurYShader.hasValue()) return m_CubeShadowBlurYShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); // vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords.xy = attr_pos.xy;"); vertexGenerator.Append("}"); // This with the ShadowBlurXShader design for a 2-pass 5x5 (sigma=1.0) // Weights computed using -- http://dev.theomader.com/gaussian-kernel-calculator/ fragmentGenerator.AddUniform("camera_properties", "vec2"); fragmentGenerator.AddUniform("depthCube", "samplerCube"); // fragmentGenerator.AddUniform("depthSrc", "sampler2D"); fragmentGenerator.Append("layout(location = 0) out vec4 frag0;"); fragmentGenerator.Append("layout(location = 1) out vec4 frag1;"); fragmentGenerator.Append("layout(location = 2) out vec4 frag2;"); fragmentGenerator.Append("layout(location = 3) out vec4 frag3;"); fragmentGenerator.Append("layout(location = 4) out vec4 frag4;"); fragmentGenerator.Append("layout(location = 5) out vec4 frag5;"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tfloat ofsScale = camera_properties.x / 2500.0;"); fragmentGenerator.Append("\tvec3 dir0 = vec3(1.0, -uv_coords.y, -uv_coords.x);"); fragmentGenerator.Append("\tvec3 dir1 = vec3(-1.0, -uv_coords.y, uv_coords.x);"); fragmentGenerator.Append("\tvec3 dir2 = vec3(uv_coords.x, 1.0, uv_coords.y);"); fragmentGenerator.Append("\tvec3 dir3 = vec3(uv_coords.x, -1.0, -uv_coords.y);"); fragmentGenerator.Append("\tvec3 dir4 = vec3(uv_coords.x, -uv_coords.y, 1.0);"); fragmentGenerator.Append("\tvec3 dir5 = vec3(-uv_coords.x, -uv_coords.y, -1.0);"); fragmentGenerator.Append("\tfloat depth0;"); fragmentGenerator.Append("\tfloat depth1;"); fragmentGenerator.Append("\tfloat depth2;"); fragmentGenerator.Append("\tfloat outDepth;"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir0).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir0 + vec3(0.0, -ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir0 + vec3(0.0, ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir0 + vec3(0.0, -2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir0 + vec3(0.0, 2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag0 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir1).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir1 + vec3(0.0, -ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir1 + vec3(0.0, ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir1 + vec3(0.0, -2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir1 + vec3(0.0, 2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag1 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir2).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir2 + vec3(0.0, 0.0, -ofsScale)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir2 + vec3(0.0, 0.0, ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir2 + vec3(0.0, 0.0, -2.0*ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir2 + vec3(0.0, 0.0, 2.0*ofsScale)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag2 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir3).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir3 + vec3(0.0, 0.0, -ofsScale)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir3 + vec3(0.0, 0.0, ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir3 + vec3(0.0, 0.0, -2.0*ofsScale)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir3 + vec3(0.0, 0.0, 2.0*ofsScale)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag3 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir4).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir4 + vec3(0.0, -ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir4 + vec3(0.0, ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir4 + vec3(0.0, -2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir4 + vec3(0.0, 2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag4 = vec4(outDepth);"); fragmentGenerator.Append("\tdepth0 = texture(depthCube, dir5).x;"); fragmentGenerator.Append( "\tdepth1 = texture(depthCube, dir5 + vec3(0.0, -ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth1 += texture(depthCube, dir5 + vec3(0.0, ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 = texture(depthCube, dir5 + vec3(0.0, -2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\tdepth2 += texture(depthCube, dir5 + vec3(0.0, 2.0*ofsScale, 0.0)).x;"); fragmentGenerator.Append( "\toutDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfrag5 = vec4(outDepth);"); fragmentGenerator.Append("}"); CRegisteredString featureName(m_StringTable->RegisterStr("NO_FRAG_OUTPUT")); SShaderPreprocessorFeature noFragOutputFeature(featureName, true); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "cubemap shadow blur Y shader", SShaderCacheProgramFlags(), TShaderFeatureSet(&noFragOutputFeature, 1)); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader); m_CubeShadowBlurYShader = retval; return m_CubeShadowBlurYShader.getValue(); } SShadowmapPreblurShader *Qt3DSRendererImpl::GetOrthoShadowBlurXShader() { if (m_OrthoShadowBlurXShader.hasValue()) return m_OrthoShadowBlurXShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords.xy = attr_uv.xy;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("camera_properties", "vec2"); fragmentGenerator.AddUniform("depthSrc", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec2 ofsScale = vec2( camera_properties.x / 7680.0, 0.0 );"); fragmentGenerator.Append("\tfloat depth0 = texture(depthSrc, uv_coords).x;"); fragmentGenerator.Append("\tfloat depth1 = texture(depthSrc, uv_coords + ofsScale).x;"); fragmentGenerator.Append("\tdepth1 += texture(depthSrc, uv_coords - ofsScale).x;"); fragmentGenerator.Append( "\tfloat depth2 = texture(depthSrc, uv_coords + 2.0 * ofsScale).x;"); fragmentGenerator.Append("\tdepth2 += texture(depthSrc, uv_coords - 2.0 * ofsScale).x;"); fragmentGenerator.Append( "\tfloat outDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfragOutput = vec4(outDepth);"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "shadow map blur X shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader); m_OrthoShadowBlurXShader = retval; return m_OrthoShadowBlurXShader.getValue(); } SShadowmapPreblurShader *Qt3DSRendererImpl::GetOrthoShadowBlurYShader() { if (m_OrthoShadowBlurYShader.hasValue()) return m_OrthoShadowBlurYShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords.xy = attr_uv.xy;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("camera_properties", "vec2"); fragmentGenerator.AddUniform("depthSrc", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec2 ofsScale = vec2( 0.0, camera_properties.x / 7680.0 );"); fragmentGenerator.Append("\tfloat depth0 = texture(depthSrc, uv_coords).x;"); fragmentGenerator.Append("\tfloat depth1 = texture(depthSrc, uv_coords + ofsScale).x;"); fragmentGenerator.Append("\tdepth1 += texture(depthSrc, uv_coords - ofsScale).x;"); fragmentGenerator.Append( "\tfloat depth2 = texture(depthSrc, uv_coords + 2.0 * ofsScale).x;"); fragmentGenerator.Append("\tdepth2 += texture(depthSrc, uv_coords - 2.0 * ofsScale).x;"); fragmentGenerator.Append( "\tfloat outDepth = 0.38774 * depth0 + 0.24477 * depth1 + 0.06136 * depth2;"); fragmentGenerator.Append("\tfragOutput = vec4(outDepth);"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "shadow map blur Y shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SShadowmapPreblurShader)(*theShader); m_OrthoShadowBlurYShader = retval; return m_OrthoShadowBlurYShader.getValue(); } #ifdef ADVANCED_BLEND_SW_FALLBACK SAdvancedModeBlendShader * Qt3DSRendererImpl::GetAdvancedBlendModeShader(AdvancedBlendModes::Enum blendMode) { // Select between blend equations. if (blendMode == AdvancedBlendModes::Overlay) { return GetOverlayBlendModeShader(); } else if (blendMode == AdvancedBlendModes::ColorBurn) { return GetColorBurnBlendModeShader(); } else if (blendMode == AdvancedBlendModes::ColorDodge) { return GetColorDodgeBlendModeShader(); } return {}; } SAdvancedModeBlendShader *Qt3DSRendererImpl::GetOverlayBlendModeShader() { if (m_AdvancedModeOverlayBlendShader.hasValue()) return m_AdvancedModeOverlayBlendShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("base_layer", "sampler2D"); fragmentGenerator.AddUniform("blend_layer", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec4 base = texture2D(base_layer, uv_coords);"); fragmentGenerator.Append("\tif (base.a != 0.0) base.rgb /= base.a;"); fragmentGenerator.Append("\telse base = vec4(0.0);"); fragmentGenerator.Append("\tvec4 blend = texture2D(blend_layer, uv_coords);"); fragmentGenerator.Append("\tif (blend.a != 0.0) blend.rgb /= blend.a;"); fragmentGenerator.Append("\telse blend = vec4(0.0);"); fragmentGenerator.Append("\tvec4 res = vec4(0.0);"); fragmentGenerator.Append("\tfloat p0 = base.a * blend.a;"); fragmentGenerator.Append("\tfloat p1 = base.a * (1.0 - blend.a);"); fragmentGenerator.Append("\tfloat p2 = blend.a * (1.0 - base.a);"); fragmentGenerator.Append("\tres.a = p0 + p1 + p2;"); NVRenderShaderProgram *theShader; fragmentGenerator.Append( "\tfloat f_rs_rd = (base.r < 0.5? (2.0 * base.r * blend.r) : " "(1.0 - 2.0 * (1.0 - base.r) * (1.0 - blend.r)));"); fragmentGenerator.Append( "\tfloat f_gs_gd = (base.g < 0.5? (2.0 * base.g * blend.g) : " "(1.0 - 2.0 * (1.0 - base.g) * (1.0 - blend.g)));"); fragmentGenerator.Append( "\tfloat f_bs_bd = (base.b < 0.5? (2.0 * base.b * blend.b) : " "(1.0 - 2.0 * (1.0 - base.b) * (1.0 - blend.b)));"); fragmentGenerator.Append("\tres.r = f_rs_rd * p0 + base.r * p1 + blend.r * p2;"); fragmentGenerator.Append("\tres.g = f_gs_gd * p0 + base.g * p1 + blend.g * p2;"); fragmentGenerator.Append("\tres.b = f_bs_bd * p0 + base.b * p1 + blend.b * p2;"); fragmentGenerator.Append("\tgl_FragColor = vec4(res.rgb * res.a, res.a);"); fragmentGenerator.Append("}"); theShader = GetProgramGenerator().CompileGeneratedShader( "advanced overlay shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SAdvancedModeBlendShader)(*theShader); m_AdvancedModeOverlayBlendShader = retval; return m_AdvancedModeOverlayBlendShader.getValue(); } SAdvancedModeBlendShader *Qt3DSRendererImpl::GetColorBurnBlendModeShader() { if (m_AdvancedModeColorBurnBlendShader.hasValue()) return m_AdvancedModeColorBurnBlendShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("base_layer", "sampler2D"); fragmentGenerator.AddUniform("blend_layer", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec4 base = texture2D(base_layer, uv_coords);"); fragmentGenerator.Append("\tif (base.a != 0.0) base.rgb /= base.a;"); fragmentGenerator.Append("\telse base = vec4(0.0);"); fragmentGenerator.Append("\tvec4 blend = texture2D(blend_layer, uv_coords);"); fragmentGenerator.Append("\tif (blend.a != 0.0) blend.rgb /= blend.a;"); fragmentGenerator.Append("\telse blend = vec4(0.0);"); fragmentGenerator.Append("\tvec4 res = vec4(0.0);"); fragmentGenerator.Append("\tfloat p0 = base.a * blend.a;"); fragmentGenerator.Append("\tfloat p1 = base.a * (1.0 - blend.a);"); fragmentGenerator.Append("\tfloat p2 = blend.a * (1.0 - base.a);"); fragmentGenerator.Append("\tres.a = p0 + p1 + p2;"); NVRenderShaderProgram *theShader; fragmentGenerator.Append( "\tfloat f_rs_rd = ((base.r == 1.0) ? 1.0 : " "(blend.r == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.r) / blend.r)));"); fragmentGenerator.Append( "\tfloat f_gs_gd = ((base.g == 1.0) ? 1.0 : " "(blend.g == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.g) / blend.g)));"); fragmentGenerator.Append( "\tfloat f_bs_bd = ((base.b == 1.0) ? 1.0 : " "(blend.b == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.b) / blend.b)));"); fragmentGenerator.Append("\tres.r = f_rs_rd * p0 + base.r * p1 + blend.r * p2;"); fragmentGenerator.Append("\tres.g = f_gs_gd * p0 + base.g * p1 + blend.g * p2;"); fragmentGenerator.Append("\tres.b = f_bs_bd * p0 + base.b * p1 + blend.b * p2;"); fragmentGenerator.Append("\tgl_FragColor = vec4(res.rgb * res.a, res.a);"); fragmentGenerator.Append("}"); theShader = GetProgramGenerator().CompileGeneratedShader( "advanced colorBurn shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SAdvancedModeBlendShader)(*theShader); m_AdvancedModeColorBurnBlendShader = retval; return m_AdvancedModeColorBurnBlendShader.getValue(); } SAdvancedModeBlendShader *Qt3DSRendererImpl::GetColorDodgeBlendModeShader() { if (m_AdvancedModeColorDodgeBlendShader.hasValue()) return m_AdvancedModeColorDodgeBlendShader.getValue(); GetProgramGenerator().BeginProgram(); IShaderStageGenerator &vertexGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Vertex)); IShaderStageGenerator &fragmentGenerator( *GetProgramGenerator().GetStage(ShaderGeneratorStages::Fragment)); vertexGenerator.AddIncoming("attr_pos", "vec3"); vertexGenerator.AddIncoming("attr_uv", "vec2"); vertexGenerator.AddOutgoing("uv_coords", "vec2"); vertexGenerator.Append("void main() {"); vertexGenerator.Append("\tgl_Position = vec4(attr_pos, 1.0 );"); vertexGenerator.Append("\tuv_coords = attr_uv;"); vertexGenerator.Append("}"); fragmentGenerator.AddUniform("base_layer", "sampler2D"); fragmentGenerator.AddUniform("blend_layer", "sampler2D"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec4 base = texture2D(base_layer, uv_coords);"); fragmentGenerator.Append("\tif (base.a != 0.0) base.rgb /= base.a;"); fragmentGenerator.Append("\telse base = vec4(0.0);"); fragmentGenerator.Append("\tvec4 blend = texture2D(blend_layer, uv_coords);"); fragmentGenerator.Append("\tif (blend.a != 0.0) blend.rgb /= blend.a;"); fragmentGenerator.Append("\telse blend = vec4(0.0);"); fragmentGenerator.Append("\tvec4 res = vec4(0.0);"); fragmentGenerator.Append("\tfloat p0 = base.a * blend.a;"); fragmentGenerator.Append("\tfloat p1 = base.a * (1.0 - blend.a);"); fragmentGenerator.Append("\tfloat p2 = blend.a * (1.0 - base.a);"); fragmentGenerator.Append("\tres.a = p0 + p1 + p2;"); NVRenderShaderProgram *theShader; fragmentGenerator.Append( "\tfloat f_rs_rd = ((base.r == 0.0) ? 0.0 : " "(blend.r == 1.0) ? 1.0 : min(base.r / (1.0 - blend.r), 1.0));"); fragmentGenerator.Append( "\tfloat f_gs_gd = ((base.g == 0.0) ? 0.0 : " "(blend.g == 1.0) ? 1.0 : min(base.g / (1.0 - blend.g), 1.0));"); fragmentGenerator.Append( "\tfloat f_bs_bd = ((base.b == 0.0) ? 0.0 : " "(blend.b == 1.0) ? 1.0 : min(base.b / (1.0 - blend.b), 1.0));"); fragmentGenerator.Append("\tres.r = f_rs_rd * p0 + base.r * p1 + blend.r * p2;"); fragmentGenerator.Append("\tres.g = f_gs_gd * p0 + base.g * p1 + blend.g * p2;"); fragmentGenerator.Append("\tres.b = f_bs_bd * p0 + base.b * p1 + blend.b * p2;"); fragmentGenerator.Append("\tgl_FragColor = vec4(res.rgb * res.a, res.a);"); fragmentGenerator.Append("}"); theShader = GetProgramGenerator().CompileGeneratedShader( "advanced colorDodge shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); NVScopedRefCounted retval; if (theShader) retval = QT3DS_NEW(m_Context->GetAllocator(), SAdvancedModeBlendShader)(*theShader); m_AdvancedModeColorDodgeBlendShader = retval; return m_AdvancedModeColorDodgeBlendShader.getValue(); } #endif } }