summaryrefslogtreecommitdiffstats
path: root/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp')
-rw-r--r--src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp2999
1 files changed, 2999 insertions, 0 deletions
diff --git a/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp b/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp
new file mode 100644
index 00000000..50620f88
--- /dev/null
+++ b/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp
@@ -0,0 +1,2999 @@
+/****************************************************************************
+**
+** 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<NVRenderDepthStencilState> 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() 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() 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)
+ {
+ // 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());
+
+ SShaderDefaultMaterialKey theKey(inRenderable.m_ShaderDescription);
+ theKey.ToString(m_GeneratedShaderString, m_DefaultMaterialShaderKeyProperties);
+ 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));
+ 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());
+ }
+
+ // -------------- 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<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetParaboloidDepthTessLinearShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetParaboloidDepthTessPhongShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetParaboloidDepthTessNPatchShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ 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<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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);
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram();
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetCubeDepthTessLinearShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetCubeDepthTessPhongShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetCubeDepthTessNPatchShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ 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<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetOrthographicDepthTessLinearShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetOrthographicDepthTessPhongShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetOrthographicDepthTessNPatchShader()
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+
+ return theDepthShader.getValue();
+ }
+
+ // ---------------------------------
+
+ SRenderableDepthPrepassShader *Qt3DSRendererImpl::GetDepthPrepassShader(bool inDisplaced)
+ {
+ Option<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram();
+ }
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), SShaderCacheProgramFlags(), TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ 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<NVScopedRefCounted<SRenderableDepthPrepassShader>> &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("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ }
+
+ SShaderCacheProgramFlags theFlags;
+ theFlags.SetTessellationEnabled(true);
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ name.c_str(), theFlags, TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ theDepthPrePassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ 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("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ }
+
+ SShaderCacheProgramFlags theFlags;
+ theFlags.SetTessellationEnabled(true);
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ "depth tess phong prepass shader", theFlags, TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ m_DepthTessPhongPrepassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ m_DepthTessPhongPrepassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ 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("}");
+ } else if (theCache.IsShaderCachePersistenceEnabled()) {
+ // we load from shader cache set default shader stages
+ GetProgramGenerator().BeginProgram(TShaderGeneratorStageFlags(
+ ShaderGeneratorStages::Vertex | ShaderGeneratorStages::TessControl
+ | ShaderGeneratorStages::TessEval | ShaderGeneratorStages::Fragment));
+ }
+
+ SShaderCacheProgramFlags theFlags;
+ theFlags.SetTessellationEnabled(true);
+
+ depthShaderProgram = GetProgramGenerator().CompileGeneratedShader(
+ "depth tess npatch prepass shader", theFlags, TShaderFeatureSet());
+
+ if (depthShaderProgram) {
+ m_DepthTessNPatchPrepassShader = NVScopedRefCounted<SRenderableDepthPrepassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(),
+ SRenderableDepthPrepassShader)(*depthShaderProgram, GetContext()));
+ } else {
+ m_DepthTessNPatchPrepassShader =
+ NVScopedRefCounted<SRenderableDepthPrepassShader>();
+ }
+ }
+ 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<SDefaultAoPassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(*aoPassShaderProgram,
+ GetContext()));
+ } else {
+ m_DefaultAoPassShader = NVScopedRefCounted<SDefaultAoPassShader>();
+ }
+ }
+ 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<SDefaultAoPassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(
+ *depthShaderProgram, GetContext()));
+ } else {
+ m_FakeDepthShader = NVScopedRefCounted<SDefaultAoPassShader>();
+ }
+ }
+ 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<SDefaultAoPassShader>(
+ QT3DS_NEW(GetContext().GetAllocator(), SDefaultAoPassShader)(*cubeShaderProgram,
+ GetContext()));
+ } else {
+ m_FakeCubemapDepthShader = NVScopedRefCounted<SDefaultAoPassShader>();
+ }
+ }
+ 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<STextDepthShader>();
+ } else {
+ GenerateXYQuad();
+ m_TextDepthPrepassShader = NVScopedRefCounted<STextDepthShader>(
+ 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("\tif( theLayerTexture.a == 0.0 ) discard;\n");
+ fragmentGenerator.Append("\tfragOutput = theLayerTexture;\n");
+ fragmentGenerator.Append("}");
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "layer shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SLayerSceneShader> 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<SLayerProgAABlendShader> 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("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "cubemap shadow blur X shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SShadowmapPreblurShader> 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("}");
+
+ NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader(
+ "cubemap shadow blur Y shader", SShaderCacheProgramFlags(), TShaderFeatureSet());
+ NVScopedRefCounted<SShadowmapPreblurShader> 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<SShadowmapPreblurShader> 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<SShadowmapPreblurShader> 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<SAdvancedModeBlendShader> 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<SAdvancedModeBlendShader> 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<SAdvancedModeBlendShader> retval;
+ if (theShader)
+ retval = QT3DS_NEW(m_Context->GetAllocator(), SAdvancedModeBlendShader)(*theShader);
+ m_AdvancedModeColorDodgeBlendShader = retval;
+ return m_AdvancedModeColorDodgeBlendShader.getValue();
+
+ }
+#endif
+}
+}