summaryrefslogtreecommitdiffstats
path: root/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp')
m---------src/Runtime/ogl-runtime0
-rw-r--r--src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp1964
2 files changed, 0 insertions, 1964 deletions
diff --git a/src/Runtime/ogl-runtime b/src/Runtime/ogl-runtime
new file mode 160000
+Subproject 427fddb50d43aa21a90fc7356ee3cdd8a908df5
diff --git a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp b/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp
deleted file mode 100644
index 5b2c51d4..00000000
--- a/src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp
+++ /dev/null
@@ -1,1964 +0,0 @@
-/****************************************************************************
-**
-** 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 "Qt3DSRenderPathManager.h"
-#include "foundation/Qt3DSFoundation.h"
-#include "foundation/Qt3DSBroadcastingAllocator.h"
-#include "foundation/Qt3DSAtomic.h"
-#include "foundation/Qt3DSIntrinsics.h"
-#include "foundation/Qt3DSContainers.h"
-#include "EASTL/string.h"
-#include "Qt3DSRenderContextCore.h"
-#include "foundation/Utils.h"
-#include "foundation/StringConversionImpl.h"
-#include "render/Qt3DSRenderVertexBuffer.h"
-#include "render/Qt3DSRenderInputAssembler.h"
-#include "Qt3DSRenderPath.h"
-#include "EASTL/sort.h"
-#include "render/Qt3DSRenderContext.h"
-#include "render/Qt3DSRenderVertexBuffer.h"
-#include "render/Qt3DSRenderShaderProgram.h"
-#include "Qt3DSRenderShaderCodeGenerator.h"
-#include "Qt3DSRenderDynamicObjectSystem.h"
-#include "Qt3DSRenderCamera.h"
-#include "Qt3DSRenderPathRenderContext.h"
-#include "Qt3DSRenderShaderCodeGeneratorV2.h"
-#include "Qt3DSRenderDefaultMaterialShaderGenerator.h"
-#include "Qt3DSRenderCustomMaterialShaderGenerator.h"
-#include "Qt3DSRenderCustomMaterial.h"
-#include "Qt3DSRenderCustomMaterialSystem.h"
-#include "render/Qt3DSRenderShaderProgram.h"
-#include "rendererimpl/Qt3DSVertexPipelineImpl.h"
-#include "foundation/Qt3DSMathUtils.h"
-#include "render/Qt3DSRenderPathRender.h"
-#include "render/Qt3DSRenderPathSpecification.h"
-#include "Qt3DSRenderPathSubPath.h"
-#include "Qt3DSImportPath.h"
-#include "Qt3DSRenderPathMath.h"
-#include "Qt3DSRenderInputStreamFactory.h"
-#include "foundation/Qt3DSMutex.h"
-
-using namespace qt3ds::render;
-using qt3ds::render::NVRenderCachedShaderProperty;
-using qt3ds::render::NVRenderCachedShaderBuffer;
-using qt3ds::render::NVRenderStencilFunctionArgument;
-using qt3ds::render::NVRenderBoolOp;
-using qt3ds::render::NVRenderStencilOperationArgument;
-using qt3ds::render::NVRenderStencilOp;
-
-typedef qt3dsimp::SPathBuffer TImportPathBuffer;
-using namespace qt3ds::render::path;
-
-typedef eastl::pair<CRegisteredString, CRegisteredString> TStrStrPair;
-
-namespace eastl {
-template <>
-struct hash<TStrStrPair>
-{
- size_t operator()(const TStrStrPair &item) const
- {
- return eastl::hash<CRegisteredString>()(item.first)
- ^ eastl::hash<CRegisteredString>()(item.second);
- }
-};
-}
-
-struct SPathShaderMapKey
-{
- CRegisteredString m_Name;
- SShaderDefaultMaterialKey m_MaterialKey;
- size_t m_HashCode;
- SPathShaderMapKey(CRegisteredString inName, SShaderDefaultMaterialKey inKey)
- : m_Name(inName)
- , m_MaterialKey(inKey)
- {
- m_HashCode = eastl::hash<TStrStrPair>()(m_Name) ^ m_MaterialKey.hash();
- }
- bool operator==(const SPathShaderMapKey &inKey) const
- {
- return m_Name == inKey.m_Name && m_MaterialKey == inKey.m_MaterialKey;
- }
-};
-
-namespace eastl {
-template <>
-struct hash<SPathShaderMapKey>
-{
- size_t operator()(const SPathShaderMapKey &inKey) const { return inKey.m_HashCode; }
-};
-}
-
-namespace {
-
-struct SPathSubPathBuffer
-{
- NVAllocatorCallback &m_Allocator;
- nvvector<SPathAnchorPoint> m_SourceData;
- SPathDirtyFlags m_Flags;
- SPathSubPath &m_SubPath;
- bool m_Closed;
-
- QT3DSI32 m_RefCount;
-
- SPathSubPathBuffer(NVAllocatorCallback &alloc, SPathSubPath &inSubPath)
- : m_Allocator(alloc)
- , m_SourceData(alloc, "m_SourceData")
- , m_SubPath(inSubPath)
- , m_Closed(false)
- , m_RefCount(0)
- {
- }
-
- void addRef() { atomicIncrement(&m_RefCount); }
- void release()
- {
- atomicDecrement(&m_RefCount);
- if (m_RefCount <= 0) {
- NVAllocatorCallback &alloc(m_Allocator);
- NVDelete(alloc, this);
- }
- }
-};
-
-struct SImportPathWrapper
-{
- NVAllocatorCallback &m_Alloc;
- qt3dsimp::SPathBuffer *m_Path;
- QT3DSI32 m_RefCount;
-
- SImportPathWrapper(NVAllocatorCallback &inAlloc, qt3dsimp::SPathBuffer &inPath)
- : m_Alloc(inAlloc)
- , m_Path(&inPath)
- , m_RefCount(0)
- {
- }
-
- ~SImportPathWrapper() { m_Path->Free(m_Alloc); }
-
- void addRef() { ++m_RefCount; }
- void release()
- {
- --m_RefCount;
- if (m_RefCount <= 0) {
- NVAllocatorCallback &alloc(m_Alloc);
- NVDelete(alloc, this);
- }
- }
-};
-
-typedef NVScopedRefCounted<SImportPathWrapper> TPathBufferPtr;
-
-struct SPathBuffer
-{
- NVAllocatorCallback &m_Allocator;
- nvvector<NVScopedRefCounted<SPathSubPathBuffer>> m_SubPaths;
- TPathBufferPtr m_PathBuffer;
-
- NVScopedRefCounted<NVRenderVertexBuffer> m_PatchData;
- NVScopedRefCounted<NVRenderInputAssembler> m_InputAssembler;
- NVScopedRefCounted<NVRenderPathRender> m_PathRender;
-
- QT3DSVec2 m_BeginTaperData;
- QT3DSVec2 m_EndTaperData;
- QT3DSU32 m_NumVertexes;
- PathTypes::Enum m_PathType;
- QT3DSF32 m_Width;
- QT3DSF32 m_CPUError;
- NVBounds3 m_Bounds;
- Option<STaperInformation> m_BeginTaper;
- Option<STaperInformation> m_EndTaper;
- CRegisteredString m_SourcePath;
-
- // Cached data for geometry paths
-
- SPathDirtyFlags m_Flags;
-
- QT3DSI32 m_RefCount;
-
- SPathBuffer(NVAllocatorCallback &alloc)
- : m_Allocator(alloc)
- , m_SubPaths(alloc, "m_SubPaths")
- , m_NumVertexes(0)
- , m_PathType(PathTypes::Geometry)
- , m_Width(0.0f)
- , m_CPUError(0.0f)
- , m_Bounds(NVBounds3::empty())
- , m_RefCount(0)
- {
- }
-
- void addRef() { atomicIncrement(&m_RefCount); }
- void release()
- {
- atomicDecrement(&m_RefCount);
- if (m_RefCount <= 0) {
- NVAllocatorCallback &alloc(m_Allocator);
- NVDelete(alloc, this);
- }
- }
-
- void ClearGeometryPathData()
- {
- m_PatchData = NULL;
- m_InputAssembler = NULL;
- }
-
- void ClearPaintedPathData() { m_PathRender = NULL; }
-
- qt3dsimp::SPathBuffer GetPathData(qt3dsimp::IPathBufferBuilder &inSpec)
- {
- if (m_SubPaths.size()) {
- inSpec.Clear();
- for (QT3DSU32 idx = 0, end = m_SubPaths.size(); idx < end; ++idx) {
- const SPathSubPathBuffer &theSubPathBuffer(*m_SubPaths[idx]);
- for (QT3DSU32 equationIdx = 0, equationEnd = theSubPathBuffer.m_SourceData.size();
- equationIdx < equationEnd; ++equationIdx) {
- const SPathAnchorPoint &thePoint = theSubPathBuffer.m_SourceData[equationIdx];
- if (equationIdx == 0) {
- inSpec.MoveTo(thePoint.m_Position);
- } else {
- const SPathAnchorPoint &thePrevPoint =
- theSubPathBuffer.m_SourceData[equationIdx - 1];
- QT3DSVec2 c1 = IPathManager::GetControlPointFromAngleDistance(
- thePrevPoint.m_Position, thePrevPoint.m_OutgoingAngle,
- thePrevPoint.m_OutgoingDistance);
- QT3DSVec2 c2 = IPathManager::GetControlPointFromAngleDistance(
- thePoint.m_Position, thePoint.m_IncomingAngle,
- thePoint.m_IncomingDistance);
- QT3DSVec2 p2 = thePoint.m_Position;
- inSpec.CubicCurveTo(c1, c2, p2);
- }
- }
- if (theSubPathBuffer.m_Closed)
- inSpec.Close();
- }
- return inSpec.GetPathBuffer();
- } else if (m_PathBuffer.mPtr)
- return *m_PathBuffer.mPtr->m_Path;
- return qt3dsimp::SPathBuffer();
- }
-
- void SetPathType(PathTypes::Enum inPathType)
- {
- if (inPathType != m_PathType) {
- switch (m_PathType) {
- case PathTypes::Geometry:
- ClearGeometryPathData();
- break;
- case PathTypes::Painted:
- ClearPaintedPathData();
- break;
- default:
- QT3DS_ALWAYS_ASSERT_MESSAGE("Unexpected path type");
- // No further processing for unexpected path type
- return;
- }
- m_Flags.clearOrSet(true, PathDirtyFlagValues::PathType);
- }
- m_PathType = inPathType;
- }
-
- static Option<STaperInformation> ToTaperInfo(PathCapping::Enum capping, QT3DSF32 capOffset,
- QT3DSF32 capOpacity, QT3DSF32 capWidth)
- {
- if (capping == PathCapping::Noner)
- return Empty();
-
- return STaperInformation(capOffset, capOpacity, capWidth);
- }
-
- void SetBeginTaperInfo(PathCapping::Enum capping, QT3DSF32 capOffset, QT3DSF32 capOpacity,
- QT3DSF32 capWidth)
- {
- Option<STaperInformation> newBeginInfo =
- ToTaperInfo(capping, capOffset, capOpacity, capWidth);
- if (!OptionEquals(newBeginInfo, m_BeginTaper)) {
- m_BeginTaper = newBeginInfo;
- m_Flags.clearOrSet(true, PathDirtyFlagValues::BeginTaper);
- }
- }
-
- void SetEndTaperInfo(PathCapping::Enum capping, QT3DSF32 capOffset, QT3DSF32 capOpacity,
- QT3DSF32 capWidth)
- {
- Option<STaperInformation> newEndInfo =
- ToTaperInfo(capping, capOffset, capOpacity, capWidth);
- if (!OptionEquals(newEndInfo, m_EndTaper)) {
- m_EndTaper = newEndInfo;
- m_Flags.clearOrSet(true, PathDirtyFlagValues::EndTaper);
- }
- }
-
- void SetWidth(QT3DSF32 inWidth)
- {
- if (inWidth != m_Width) {
- m_Width = inWidth;
- m_Flags.clearOrSet(true, PathDirtyFlagValues::Width);
- }
- }
-
- void SetCPUError(QT3DSF32 inError)
- {
- if (inError != m_CPUError) {
- m_CPUError = inError;
- m_Flags.clearOrSet(true, PathDirtyFlagValues::CPUError);
- }
- }
-};
-
-struct SPathGeneratedShader
-{
- NVAllocatorCallback &m_Allocator;
- NVRenderShaderProgram &m_Shader;
- NVRenderCachedShaderProperty<QT3DSF32> m_Width;
- NVRenderCachedShaderProperty<QT3DSF32> m_InnerTessAmount;
- NVRenderCachedShaderProperty<QT3DSF32> m_EdgeTessAmount;
- NVRenderCachedShaderProperty<QT3DSVec2> m_BeginTaperData;
- NVRenderCachedShaderProperty<QT3DSVec2> m_EndTaperData;
- NVRenderCachedShaderProperty<QT3DSMat44> m_WireframeViewMatrix;
-
- QT3DSI32 m_RefCount;
-
- SPathGeneratedShader(NVRenderShaderProgram &sh, NVAllocatorCallback &alloc)
- : m_Allocator(alloc)
- , m_Shader(sh)
- , m_Width("pathWidth", sh)
- , m_InnerTessAmount("tessInnerLevel", sh)
- , m_EdgeTessAmount("tessEdgeLevel", sh)
- , m_BeginTaperData("beginTaperInfo", sh)
- , m_EndTaperData("endTaperInfo", sh)
- , m_WireframeViewMatrix("viewport_matrix", sh)
- , m_RefCount(0)
- {
- m_Shader.addRef();
- }
- ~SPathGeneratedShader() { m_Shader.release(); }
-
- void addRef() { ++m_RefCount; }
- void release()
- {
- --m_RefCount;
- if (m_RefCount <= 0) {
- NVAllocatorCallback &allocator(m_Allocator);
- NVDelete(allocator, this);
- }
- }
-};
-
-struct SPathVertexPipeline : public SVertexPipelineImpl
-{
-
- SPathVertexPipeline(IShaderProgramGenerator &inProgGenerator,
- IMaterialShaderGenerator &inMaterialGenerator, NVAllocatorCallback &inAlloc,
- IStringTable &inStringTable, bool inWireframe)
- : SVertexPipelineImpl(inAlloc, inMaterialGenerator, inProgGenerator, inStringTable,
- inWireframe)
- {
- }
-
- // Trues true if the code was *not* set.
- bool SetCode(GenerationFlagValues::Enum inCode)
- {
- if (((QT3DSU32)m_GenerationFlags & inCode) != 0)
- return true;
- m_GenerationFlags |= inCode;
- return false;
- }
-
- void AssignTessEvalVarying(const char8_t *inVarName, const char8_t *inVarValueExpr)
- {
- const char8_t *ext = "";
- if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
- ext = "TE";
- TessEval() << "\t" << inVarName << ext << " = " << inVarValueExpr << ";" << Endl;
- }
-
- void AssignOutput(const char8_t *inVarName, const char8_t *inVarValueExpr) override
- {
- AssignTessEvalVarying(inVarName, inVarValueExpr);
- }
-
- void InitializeTessShaders()
- {
- IShaderStageGenerator &theTessControl(TessControl());
- IShaderStageGenerator &theTessEval(TessEval());
-
- // first setup tessellation control shader
- theTessControl.AddUniform("tessEdgeLevel", "float");
- theTessControl.AddUniform("tessInnerLevel", "float");
-
- theTessControl.AddInclude("tessellationPath.glsllib");
-
- theTessControl.Append("void main() {\n");
- theTessControl.Append(
- "\tgl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;");
- theTessControl.Append("\ttessShader( tessEdgeLevel, tessInnerLevel );\n");
-
- bool hasGeometryShader =
- ProgramGenerator().GetStage(ShaderGeneratorStages::Geometry) != NULL;
-
- // second setup tessellation control shader
- eastl::string outExt("");
- if (hasGeometryShader)
- outExt = "TE";
-
- theTessEval.AddInclude("tessellationPath.glsllib");
- theTessEval.AddUniform("normal_matrix", "mat3");
- theTessEval.AddUniform("model_view_projection", "mat4");
- theTessEval.AddUniform("pathWidth", "float");
- theTessEval.AddUniform("material_diffuse", "vec4");
- AddInterpolationParameter("varTexCoord0", "vec2");
- AddInterpolationParameter("varTessOpacity", "float");
-
- theTessEval.Append("void main() {\n");
- theTessEval.Append("\tSTessShaderResult shaderResult = tessShader( pathWidth );\n");
- theTessEval.Append("\tvec3 pos = shaderResult.m_Position;\n");
- AssignTessEvalVarying("varTessOpacity", "shaderResult.m_Opacity");
- AssignTessEvalVarying("varTexCoord0", "shaderResult.m_TexCoord.xy");
- if (hasGeometryShader)
- theTessEval << "\tvec2 varTexCoord0 = shaderResult.m_TexCoord.xy;\n";
-
- theTessEval << "\tvec3 object_normal = vec3(0.0, 0.0, 1.0);\n";
- theTessEval << "\tvec3 world_normal = normal_matrix * object_normal;\n";
- theTessEval << "\tvec3 tangent = vec3( shaderResult.m_Tangent, 0.0 );\n";
- theTessEval << "\tvec3 binormal = vec3( shaderResult.m_Binormal, 0.0 );\n";
-
- // These are necessary for texture generation.
- theTessEval << "\tvec3 uTransform;" << Endl;
- theTessEval << "\tvec3 vTransform;" << Endl;
-
- if (m_DisplacementImage) {
- MaterialGenerator().GenerateImageUVCoordinates(*this, m_DisplacementIdx, 0,
- *m_DisplacementImage);
- theTessEval.AddUniform("displaceAmount", "float");
- theTessEval.AddUniform("model_matrix", "mat4");
- theTessEval.AddInclude("defaultMaterialFileDisplacementTexture.glsllib");
- IDefaultMaterialShaderGenerator::SImageVariableNames theVarNames =
- MaterialGenerator().GetImageVariableNames(m_DisplacementIdx);
-
- theTessEval.AddUniform(theVarNames.m_ImageSampler, "sampler2D");
- IDefaultMaterialShaderGenerator::SImageVariableNames theNames =
- MaterialGenerator().GetImageVariableNames(m_DisplacementIdx);
- theTessEval << "\tpos = defaultMaterialFileDisplacementTexture( "
- << theNames.m_ImageSampler << ", displaceAmount, "
- << theNames.m_ImageFragCoords << outExt.c_str() << ", vec3( 0.0, 0.0, 1.0 )"
- << ", pos.xyz );" << Endl;
- }
- }
- void FinalizeTessControlShader() {}
-
- void FinalizeTessEvaluationShader()
- {
- eastl::string outExt("");
- if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
- outExt = "TE";
-
- IShaderStageGenerator &tessEvalShader(
- *ProgramGenerator().GetStage(ShaderGeneratorStages::TessEval));
- tessEvalShader.Append("\tgl_Position = model_view_projection * vec4( pos, 1.0 );\n");
- }
-
- void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
- SRenderableImage *displacementImage) override
- {
- SetupDisplacement(displacementImageIdx, displacementImage);
-
- TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
- theStages |= ShaderGeneratorStages::TessControl;
- theStages |= ShaderGeneratorStages::TessEval;
- if (m_Wireframe) {
- theStages |= ShaderGeneratorStages::Geometry;
- }
- ProgramGenerator().BeginProgram(theStages);
- InitializeTessShaders();
- if (m_Wireframe) {
- InitializeWireframeGeometryShader();
- }
- // Open up each stage.
- IShaderStageGenerator &vertexShader(Vertex());
-
- vertexShader.AddIncoming("attr_pos", "vec4");
-
- // useless vert shader because real work is done in TES.
- vertexShader << "void main()\n"
- "{\n";
- vertexShader << "\tgl_Position = attr_pos;\n"; // if tessellation is enabled pass down
- // object coordinates;
- vertexShader << "}\n";
- }
-
- 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 = varTessOpacity * material_diffuse.a;" << Endl;
- }
- void DoGenerateUVCoords(QT3DSU32) override
- {
- // these are always generated regardless
- }
-
- // fragment shader expects varying vertex normal
- // lighting in vertex pipeline expects world_normal
- void DoGenerateWorldNormal() override { AssignTessEvalVarying("varNormal", "world_normal"); }
- void DoGenerateObjectNormal() override
- {
- AssignTessEvalVarying("varObjectNormal", "object_normal");
- }
- void DoGenerateWorldPosition() override
- {
- TessEval().AddUniform("model_matrix", "mat4");
- TessEval()
- << "\tvec3 local_model_world_position = vec3((model_matrix * vec4(pos, 1.0)).xyz);\n";
- }
- void DoGenerateVarTangentAndBinormal() override
- {
- TessEval().AddUniform("normal_matrix", "mat3");
- AssignOutput("varTangent", "normal_matrix * tangent");
- AssignOutput("varBinormal", "normal_matrix * binormal");
- }
-
- void DoGenerateVertexColor() override
- {
- Vertex().AddIncoming("attr_color", "vec3");
- Vertex() << "\tvarColor = attr_color;" << Endl;
- }
-
- void EndVertexGeneration(bool) override
- {
-
- if (HasTessellation()) {
- // finalize tess control shader
- FinalizeTessControlShader();
- // finalize tess evaluation shader
- FinalizeTessEvaluationShader();
-
- TessControl().Append("}");
- TessEval().Append("}");
- }
- if (m_Wireframe) {
- // finalize geometry shader
- FinalizeWireframeGeometryShader();
- Geometry().Append("}");
- }
- }
-
- void EndFragmentGeneration(bool) override { Fragment().Append("}"); }
-
- void AddInterpolationParameter(const char8_t *inName, const char8_t *inType) override
- {
- m_InterpolationParameters.insert(eastl::make_pair(Str(inName), Str(inType)));
- Fragment().AddIncoming(inName, inType);
- if (HasTessellation()) {
- eastl::string nameBuilder;
- nameBuilder.assign(inName);
- if (ProgramGenerator().GetEnabledStages() & ShaderGeneratorStages::Geometry)
- nameBuilder.append("TE");
-
- TessEval().AddOutgoing(nameBuilder.c_str(), inType);
- }
- }
-
- IShaderStageGenerator &ActiveStage() override { return TessEval(); }
-};
-
-struct SPathXYGeneratedShader
-{
- NVAllocatorCallback &m_Allocator;
- NVRenderShaderProgram &m_Shader;
- NVRenderCachedShaderProperty<QT3DSVec4> m_RectDimensions;
- NVRenderCachedShaderProperty<QT3DSMat44> m_ModelMatrix;
- NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPosition;
- NVRenderCachedShaderProperty<QT3DSVec2> m_CameraProperties;
- QT3DSI32 m_RefCount;
-
- SPathXYGeneratedShader(NVRenderShaderProgram &sh, NVAllocatorCallback &alloc)
- : m_Allocator(alloc)
- , m_Shader(sh)
- , m_RectDimensions("uni_rect_dimensions", sh)
- , m_ModelMatrix("model_matrix", sh)
- , m_CameraPosition("camera_position", sh)
- , m_CameraProperties("camera_properties", sh)
- , m_RefCount(0)
- {
- m_Shader.addRef();
- }
- virtual ~SPathXYGeneratedShader() { m_Shader.release(); }
- void addRef() { ++m_RefCount; }
- void release()
- {
- --m_RefCount;
- if (m_RefCount <= 0) {
- NVAllocatorCallback &allocator(m_Allocator);
- NVDelete(allocator, this);
- }
- }
-};
-
-// 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 SXYRectVertexPipeline : public SVertexPipelineImpl
-{
-
- SXYRectVertexPipeline(IShaderProgramGenerator &inProgGenerator,
- IMaterialShaderGenerator &inMaterialGenerator,
- NVAllocatorCallback &inAlloc, IStringTable &inStringTable)
- : SVertexPipelineImpl(inAlloc, inMaterialGenerator, inProgGenerator, inStringTable, false)
- {
- }
-
- void BeginVertexGeneration(QT3DSU32 displacementImageIdx,
- SRenderableImage *displacementImage) override
- {
- m_DisplacementIdx = displacementImageIdx;
- m_DisplacementImage = displacementImage;
-
- TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
- ProgramGenerator().BeginProgram(theStages);
- // Open up each stage.
- IShaderStageGenerator &vertexShader(Vertex());
- vertexShader.AddIncoming("attr_pos", "vec2");
- vertexShader.AddUniform("uni_rect_dimensions", "vec4");
-
- vertexShader << "void main()" << Endl << "{" << Endl;
- vertexShader << "\tvec3 uTransform;" << Endl;
- vertexShader << "\tvec3 vTransform;" << Endl;
-
- vertexShader.AddUniform("model_view_projection", "mat4");
- vertexShader
- << "\tfloat posX = mix( uni_rect_dimensions.x, uni_rect_dimensions.z, attr_pos.x );"
- << Endl;
- vertexShader
- << "\tfloat posY = mix( uni_rect_dimensions.y, uni_rect_dimensions.w, attr_pos.y );"
- << Endl;
- vertexShader << "\tvec3 pos = vec3(posX, posY, 0.0 );" << Endl;
- vertexShader.Append("\tgl_Position = model_view_projection * vec4(pos, 1.0);");
- }
-
- void OutputParaboloidDepthShaders()
- {
- TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
- ProgramGenerator().BeginProgram(theStages);
- IShaderStageGenerator &vertexShader(Vertex());
- vertexShader.AddIncoming("attr_pos", "vec2");
- vertexShader.AddUniform("uni_rect_dimensions", "vec4");
- vertexShader.AddUniform("model_view_projection", "mat4");
- vertexShader << "void main()" << Endl << "{" << Endl;
- vertexShader
- << "\tfloat posX = mix( uni_rect_dimensions.x, uni_rect_dimensions.z, attr_pos.x );"
- << Endl;
- vertexShader
- << "\tfloat posY = mix( uni_rect_dimensions.y, uni_rect_dimensions.w, attr_pos.y );"
- << Endl;
- vertexShader << "\tvec3 pos = vec3(posX, posY, 0.0 );" << Endl;
- IShaderProgramGenerator::OutputParaboloidDepthTessEval(vertexShader);
- vertexShader << "}" << Endl;
-
- IShaderProgramGenerator::OutputParaboloidDepthFragment(Fragment());
- }
-
- void OutputCubeFaceDepthShaders()
- {
- TShaderGeneratorStageFlags theStages(IShaderProgramGenerator::DefaultFlags());
- ProgramGenerator().BeginProgram(theStages);
- IShaderStageGenerator &vertexShader(Vertex());
- IShaderStageGenerator &fragmentShader(Fragment());
- vertexShader.AddIncoming("attr_pos", "vec2");
- vertexShader.AddUniform("uni_rect_dimensions", "vec4");
- vertexShader.AddUniform("model_matrix", "mat4");
- vertexShader.AddUniform("model_view_projection", "mat4");
-
- vertexShader.AddOutgoing("world_pos", "vec4");
- vertexShader.Append("void main() {");
- vertexShader.Append(
- " float posX = mix( uni_rect_dimensions.x, uni_rect_dimensions.z, attr_pos.x );");
- vertexShader.Append(
- " float posY = mix( uni_rect_dimensions.y, uni_rect_dimensions.w, attr_pos.y );");
- vertexShader.Append(" world_pos = model_matrix * vec4( posX, posY, 0.0, 1.0 );");
- vertexShader.Append(" world_pos /= world_pos.w;");
- vertexShader.Append(
- " gl_Position = model_view_projection * vec4( posX, posY, 0.0, 1.0 );");
- vertexShader.Append("}");
-
- fragmentShader.AddUniform("camera_position", "vec3");
- fragmentShader.AddUniform("camera_properties", "vec2");
-
- BeginFragmentGeneration();
- fragmentShader.Append(
- "\tfloat dist = 0.5 * length( world_pos.xyz - camera_position );"); // Why?
- fragmentShader.Append(
- "\tdist = (dist - camera_properties.x) / (camera_properties.y - camera_properties.x);");
- fragmentShader.Append("\tfragOutput = vec4(dist);");
- fragmentShader.Append("}");
- }
-
- 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) override { Vertex() << "\tvarTexCoord0 = attr_pos;" << Endl; }
-
- // fragment shader expects varying vertex normal
- // lighting in vertex pipeline expects world_normal
- void DoGenerateWorldNormal() override
- {
- IShaderStageGenerator &vertexGenerator(Vertex());
- vertexGenerator.AddUniform("normal_matrix", "mat3");
- vertexGenerator.Append(
- "\tvec3 world_normal = normalize(normal_matrix * vec3( 0.0, 0.0, 1.0) ).xyz;");
- vertexGenerator.Append("\tvarNormal = world_normal;");
- }
-
- void DoGenerateObjectNormal() override
- {
- AddInterpolationParameter("varObjectNormal", "vec3");
- Vertex().Append("\tvarObjectNormal = vec3(0.0, 0.0, 1.0 );");
- }
-
- void DoGenerateWorldPosition() override
- {
- Vertex().Append("\tvec3 local_model_world_position = (model_matrix * vec4(pos, 1.0)).xyz;");
- AssignOutput("varWorldPos", "local_model_world_position");
- }
-
- void DoGenerateVarTangentAndBinormal() override
- {
- Vertex().AddIncoming("attr_textan", "vec3");
- Vertex().AddIncoming("attr_binormal", "vec3");
- Vertex() << "\tvarTangent = normal_matrix * vec3(1.0, 0.0, 0.0);" << Endl
- << "\tvarBinormal = normal_matrix * vec3(0.0, 1.0, 0.0);" << Endl;
- }
-
- void DoGenerateVertexColor() override
- {
- Vertex().AddIncoming("attr_color", "vec3");
- Vertex() << "\tvarColor = attr_color;" << Endl;
- }
-
- void EndVertexGeneration(bool) override { Vertex().Append("}"); }
-
- void EndFragmentGeneration(bool) override { Fragment().Append("}"); }
-
- void AddInterpolationParameter(const char8_t *inName, const char8_t *inType) override
- {
- m_InterpolationParameters.insert(eastl::make_pair(Str(inName), Str(inType)));
- Vertex().AddOutgoing(inName, inType);
- Fragment().AddIncoming(inName, inType);
- }
-
- IShaderStageGenerator &ActiveStage() override { return Vertex(); }
-};
-
-struct SPathManager : public IPathManager
-{
- typedef nvhash_map<SPath *, NVScopedRefCounted<SPathBuffer>> TPathBufferHash;
- typedef nvhash_map<SPathSubPath *, NVScopedRefCounted<SPathSubPathBuffer>>
- TPathSubPathBufferHash;
- typedef nvhash_map<SPathShaderMapKey, NVScopedRefCounted<SPathGeneratedShader>> TShaderMap;
- typedef nvhash_map<SPathShaderMapKey, NVScopedRefCounted<SPathXYGeneratedShader>>
- TPaintedShaderMap;
- typedef nvhash_map<CRegisteredString, TPathBufferPtr> TStringPathBufferMap;
-
- IQt3DSRenderContextCore &m_CoreContext;
- IQt3DSRenderContext *m_RenderContext;
- eastl::string m_IdBuilder;
- TPathSubPathBufferHash m_SubPathBuffers;
- TPathBufferHash m_Buffers;
- nvvector<SResultCubic> m_SubdivResult;
- nvvector<QT3DSF32> m_KeyPointVec;
- nvvector<QT3DSVec4> m_PatchBuffer;
- TShaderMap m_PathGeometryShaders;
- TPaintedShaderMap m_PathPaintedShaders;
- TStringPathBufferMap m_SourcePathBufferMap;
- Mutex m_PathBufferMutex;
-
- NVScopedRefCounted<SPathGeneratedShader> m_DepthShader;
- NVScopedRefCounted<SPathGeneratedShader> m_DepthDisplacementShader;
- NVScopedRefCounted<SPathGeneratedShader> m_GeometryShadowShader;
- NVScopedRefCounted<SPathGeneratedShader> m_GeometryCubeShadowShader;
- NVScopedRefCounted<SPathGeneratedShader> m_GeometryDisplacementShadowShader;
-
- NVScopedRefCounted<SPathXYGeneratedShader> m_PaintedDepthShader;
- NVScopedRefCounted<SPathXYGeneratedShader> m_PaintedShadowShader;
- NVScopedRefCounted<SPathXYGeneratedShader> m_PaintedCubeShadowShader;
- NVScopedRefCounted<NVRenderInputAssembler> m_PaintedRectInputAssembler;
- NVScopedRefCounted<NVRenderVertexBuffer> m_PaintedRectVertexBuffer;
- NVScopedRefCounted<NVRenderIndexBuffer> m_PaintedRectIndexBuffer;
-
- nvvector<NVScopedRefCounted<NVRenderDepthStencilState>> m_DepthStencilStates;
-
- NVScopedRefCounted<NVRenderPathSpecification> m_PathSpecification;
- NVScopedRefCounted<qt3dsimp::IPathBufferBuilder> m_PathBuilder;
-
- QT3DSI32 m_RefCount;
-
- SPathManager(IQt3DSRenderContextCore &inRC)
- : m_CoreContext(inRC)
- , m_RenderContext(NULL)
- , m_SubPathBuffers(inRC.GetAllocator(), "m_SubPathBuffers")
- , m_Buffers(inRC.GetAllocator(), "m_Buffers")
- , m_SubdivResult(inRC.GetAllocator(), "m_SubdivResult")
- , m_KeyPointVec(inRC.GetAllocator(), "m_KeyPointVec")
- , m_PatchBuffer(inRC.GetAllocator(), "m_QuadStrip")
- , m_PathGeometryShaders(inRC.GetAllocator(), "m_PathGeometryShaders")
- , m_PathPaintedShaders(inRC.GetAllocator(), "m_PathPaintedShaders")
- , m_SourcePathBufferMap(inRC.GetAllocator(), "m_SourcePathBufferMap")
- , m_PathBufferMutex(inRC.GetAllocator())
- , m_DepthStencilStates(inRC.GetAllocator(), "m_DepthStencilStates")
- , m_RefCount(0)
- {
- }
-
- virtual ~SPathManager() { m_PaintedRectInputAssembler = NULL; }
-
- NVAllocatorCallback &GetAllocator() { return m_CoreContext.GetAllocator(); }
- IStringTable &GetStringTable() { return m_CoreContext.GetStringTable(); }
- NVFoundationBase &GetFoundation() { return m_CoreContext.GetFoundation(); }
-
- void addRef() override { atomicIncrement(&m_RefCount); }
- void release() override
- {
- atomicDecrement(&m_RefCount);
- if (m_RefCount <= 0) {
- NVAllocatorCallback &alloc(GetAllocator());
- NVDelete(alloc, this);
- }
- }
- // Called during binary load which is heavily threaded.
- void SetPathSubPathData(const SPathSubPath &inPath,
- NVConstDataRef<SPathAnchorPoint> inPathCubicCurves) override
- {
- Mutex::ScopedLock __locker(m_PathBufferMutex);
- eastl::pair<TPathSubPathBufferHash::iterator, bool> inserter =
- m_SubPathBuffers.insert(eastl::make_pair((SPathSubPath *)&inPath,
- NVScopedRefCounted<SPathSubPathBuffer>(NULL)));
- if (!inserter.first->second)
- inserter.first->second = QT3DS_NEW(GetAllocator(), SPathSubPathBuffer)(
- GetAllocator(), const_cast<SPathSubPath &>(inPath));
- SPathSubPathBuffer &theBuffer = *inserter.first->second.mPtr;
- theBuffer.m_SourceData.assign(inPathCubicCurves.begin(), inPathCubicCurves.end());
- theBuffer.m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
- }
-
- SPathBuffer *GetPathBufferObject(const SPath &inPath)
- {
- eastl::pair<TPathBufferHash::iterator, bool> inserter = m_Buffers.insert(
- eastl::make_pair((SPath *)&inPath, NVScopedRefCounted<SPathBuffer>(NULL)));
- if (inserter.second) {
- inserter.first->second = QT3DS_NEW(GetAllocator(), SPathBuffer)(GetAllocator());
- }
- return inserter.first->second.mPtr;
- }
-
- SPathSubPathBuffer *GetPathBufferObject(const SPathSubPath &inSubPath)
- {
- TPathSubPathBufferHash::iterator iter = m_SubPathBuffers.find((SPathSubPath *)&inSubPath);
- if (iter != m_SubPathBuffers.end())
- return iter->second.mPtr;
- return NULL;
- }
-
- NVDataRef<SPathAnchorPoint> GetPathSubPathBuffer(const SPathSubPath &inPath) override
- {
- SPathSubPathBuffer *theBuffer = GetPathBufferObject(inPath);
- if (theBuffer)
- return toDataRef(theBuffer->m_SourceData.data(), (QT3DSU32)theBuffer->m_SourceData.size());
- return NVDataRef<SPathAnchorPoint>();
- }
-
- NVDataRef<SPathAnchorPoint> ResizePathSubPathBuffer(const SPathSubPath &inPath,
- QT3DSU32 inNumAnchors) override
- {
- SPathSubPathBuffer *theBuffer = GetPathBufferObject(inPath);
- if (theBuffer == NULL)
- SetPathSubPathData(inPath, NVConstDataRef<SPathAnchorPoint>());
- theBuffer = GetPathBufferObject(inPath);
- theBuffer->m_SourceData.resize(inNumAnchors);
- theBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
- return toDataRef(theBuffer->m_SourceData.data(), (QT3DSU32)theBuffer->m_SourceData.size());
- }
-
- // This needs to be done using roots of the first derivative.
- NVBounds3 GetBounds(const SPath &inPath) override
- {
- NVBounds3 retval(NVBounds3::empty());
-
- SPathBuffer *thePathBuffer = GetPathBufferObject(inPath);
- if (thePathBuffer) {
- SPathDirtyFlags geomDirtyFlags(
- PathDirtyFlagValues::SourceData | PathDirtyFlagValues::BeginTaper
- | PathDirtyFlagValues::EndTaper | PathDirtyFlagValues::Width
- | PathDirtyFlagValues::CPUError);
-
- if ((((QT3DSU32)thePathBuffer->m_Flags) & (QT3DSU32)geomDirtyFlags) == 0) {
- return thePathBuffer->m_Bounds;
- }
- }
-
- for (SPathSubPath *theSubPath = inPath.m_FirstSubPath; theSubPath;
- theSubPath = theSubPath->m_NextSubPath) {
- SPathSubPathBuffer *theBuffer = GetPathBufferObject(*theSubPath);
- if (!theBuffer)
- continue;
-
- QT3DSU32 numAnchors = theBuffer->m_SourceData.size();
- for (QT3DSU32 idx = 0, end = numAnchors; idx < end; ++idx) {
- const SPathAnchorPoint &thePoint(theBuffer->m_SourceData[idx]);
- QT3DSVec2 position(thePoint.m_Position);
- retval.include(QT3DSVec3(position.x, position.y, 0.0f));
- if (idx) {
- QT3DSVec2 incoming(IPathManagerCore::GetControlPointFromAngleDistance(
- thePoint.m_Position, thePoint.m_IncomingAngle,
- thePoint.m_IncomingDistance));
- retval.include(QT3DSVec3(incoming.x, incoming.y, 0.0f));
- }
-
- if (idx < (numAnchors - 1)) {
- QT3DSVec2 outgoing(IPathManagerCore::GetControlPointFromAngleDistance(
- thePoint.m_Position, thePoint.m_OutgoingAngle,
- thePoint.m_OutgoingDistance));
- retval.include(QT3DSVec3(outgoing.x, outgoing.y, 0.0f));
- }
- }
- }
-
- return retval;
- }
-
- IPathManager &OnRenderSystemInitialize(IQt3DSRenderContext &context) override
- {
- m_RenderContext = &context;
- return *this;
- }
-
- // find a point that will join these two curves *if* they are not first derivative continuous
- static Option<QT3DSVec2> GetAdjoiningPoint(QT3DSVec2 prevC2, QT3DSVec2 point, QT3DSVec2 C1, QT3DSF32 pathWidth)
- {
- QT3DSVec2 incomingDxDy = (point - prevC2);
- QT3DSVec2 outgoingDxDy = (C1 - point);
- incomingDxDy.normalize();
- outgoingDxDy.normalize();
- float determinant = (incomingDxDy.x * outgoingDxDy.y) - (incomingDxDy.y * outgoingDxDy.x);
- if (fabs(determinant) > .001f) {
- float mult = determinant > 0.0f ? 1.0f : -1.0f;
- QT3DSVec2 incomingNormal(incomingDxDy.y, -incomingDxDy.x);
- QT3DSVec2 outgoingNormal(outgoingDxDy.y, -outgoingDxDy.x);
-
- QT3DSVec2 leftEdge = point + mult * incomingNormal * pathWidth;
- QT3DSVec2 rightEdge = point + mult * outgoingNormal * pathWidth;
-
- return (leftEdge + rightEdge) / 2.0f;
- }
- return Empty();
- }
-
- Option<eastl::pair<QT3DSU32, QT3DSF32>> FindBreakEquation(QT3DSF32 inTaperStart)
- {
- QT3DSF32 lengthTotal = 0;
- for (QT3DSU32 idx = 0, end = m_SubdivResult.size(); idx < end; ++idx) {
- if (lengthTotal + m_SubdivResult[idx].m_Length > inTaperStart) {
- QT3DSF32 breakTValue = (inTaperStart - lengthTotal) / m_SubdivResult[idx].m_Length;
- nvvector<SResultCubic>::iterator breakIter = m_SubdivResult.begin() + idx;
- SCubicBezierCurve theCurve(breakIter->m_P1, breakIter->m_C1, breakIter->m_C2,
- breakIter->m_P2);
- eastl::pair<SCubicBezierCurve, SCubicBezierCurve> subdivCurve =
- theCurve.SplitCubicBezierCurve(breakTValue);
- QT3DSF32 originalBreakT =
- breakIter->m_TStart + (breakIter->m_TStop - breakIter->m_TStart) * breakTValue;
- // Update the existing item to point to the second equation
- breakIter->m_P1 = subdivCurve.second.m_Points[0];
- breakIter->m_C1 = subdivCurve.second.m_Points[1];
- breakIter->m_C2 = subdivCurve.second.m_Points[2];
- breakIter->m_P2 = subdivCurve.second.m_Points[3];
- QT3DSF32 originalLength = breakIter->m_Length;
- QT3DSF32 originalStart = breakIter->m_TStart;
- breakIter->m_Length *= (1.0f - breakTValue);
- breakIter->m_TStart = originalBreakT;
- SResultCubic newCubic(subdivCurve.first.m_Points[0], subdivCurve.first.m_Points[1],
- subdivCurve.first.m_Points[2], subdivCurve.first.m_Points[3],
- breakIter->m_EquationIndex, originalStart, originalBreakT,
- originalLength * breakTValue);
-
- m_SubdivResult.insert(breakIter, newCubic);
- return eastl::make_pair(idx, breakTValue);
- }
- lengthTotal += m_SubdivResult[idx].m_Length;
- }
- return Empty();
- }
-
- bool PrepareGeometryPathForRender(const SPath &inPath, SPathBuffer &inPathBuffer)
- {
-
- m_SubdivResult.clear();
- m_KeyPointVec.clear();
- const SPath &thePath(inPath);
-
- inPathBuffer.SetBeginTaperInfo(thePath.m_BeginCapping, thePath.m_BeginCapOffset,
- thePath.m_BeginCapOpacity, thePath.m_BeginCapWidth);
- inPathBuffer.SetEndTaperInfo(thePath.m_EndCapping, thePath.m_EndCapOffset,
- thePath.m_EndCapOpacity, thePath.m_EndCapWidth);
- inPathBuffer.SetWidth(inPath.m_Width);
- inPathBuffer.SetCPUError(inPath.m_LinearError);
-
- SPathDirtyFlags geomDirtyFlags(PathDirtyFlagValues::SourceData
- | PathDirtyFlagValues::BeginTaper
- | PathDirtyFlagValues::EndTaper | PathDirtyFlagValues::Width
- | PathDirtyFlagValues::CPUError);
-
- bool retval = false;
- if (!inPathBuffer.m_PatchData
- || (((QT3DSU32)inPathBuffer.m_Flags) & (QT3DSU32)geomDirtyFlags) != 0) {
- qt3dsimp::SPathBuffer thePathData = inPathBuffer.GetPathData(*m_PathBuilder);
-
- QT3DSU32 dataIdx = 0;
- QT3DSVec2 prevPoint(0, 0);
- QT3DSU32 equationIdx = 0;
- for (QT3DSU32 commandIdx = 0, commandEnd = thePathData.m_Commands.size();
- commandIdx < commandEnd; ++commandIdx) {
- switch (thePathData.m_Commands[commandIdx]) {
- case qt3dsimp::PathCommand::MoveTo:
- prevPoint =
- QT3DSVec2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
- dataIdx += 2;
- break;
- case qt3dsimp::PathCommand::CubicCurveTo: {
- QT3DSVec2 c1(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
- dataIdx += 2;
- QT3DSVec2 c2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
- dataIdx += 2;
- QT3DSVec2 p2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
- dataIdx += 2;
- OuterAdaptiveSubdivideBezierCurve(
- m_SubdivResult, m_KeyPointVec, SCubicBezierCurve(prevPoint, c1, c2, p2),
- NVMax(inPath.m_LinearError, 1.0f), equationIdx);
- ++equationIdx;
- prevPoint = p2;
- } break;
- case qt3dsimp::PathCommand::Close:
- break;
-
- default:
- QT3DS_ASSERT(false);
- break;
- }
- }
-
- QT3DSF32 theLocalWidth = inPath.m_Width / 2.0f;
-
- QT3DSVec2 theBeginTaperData(theLocalWidth, thePath.m_GlobalOpacity);
- QT3DSVec2 theEndTaperData(theLocalWidth, thePath.m_GlobalOpacity);
-
- QT3DSF32 pathLength = 0.0f;
- for (QT3DSU32 idx = 0, end = m_SubdivResult.size(); idx < end; ++idx)
- pathLength += m_SubdivResult[idx].m_Length;
-
- if (thePath.m_BeginCapping == PathCapping::Taper
- || thePath.m_EndCapping == PathCapping::Taper) {
- QT3DSF32 maxTaperStart = pathLength / 2.0f;
- if (thePath.m_BeginCapping == PathCapping::Taper) {
- // Can't start more than halfway across the path.
- QT3DSF32 taperStart = NVMin(thePath.m_BeginCapOffset, maxTaperStart);
- QT3DSF32 endTaperWidth = thePath.m_BeginCapWidth;
- QT3DSF32 endTaperOpacity = thePath.m_GlobalOpacity * thePath.m_BeginCapOpacity;
- theBeginTaperData = QT3DSVec2(endTaperWidth, endTaperOpacity);
- // Find where we need to break the current equations.
- Option<eastl::pair<QT3DSU32, QT3DSF32>> breakEquationAndT(
- FindBreakEquation(taperStart));
- if (breakEquationAndT.hasValue()) {
- QT3DSU32 breakEquation = breakEquationAndT->first;
-
- QT3DSF32 lengthTotal = 0;
- for (QT3DSU32 idx = 0, end = breakEquation; idx <= end; ++idx) {
- SResultCubic &theCubic = m_SubdivResult[idx];
- theCubic.m_Mode = SResultCubic::BeginTaper;
-
- theCubic.m_TaperMultiplier[0] = lengthTotal / taperStart;
- lengthTotal += theCubic.m_Length;
- theCubic.m_TaperMultiplier[1] = lengthTotal / taperStart;
- }
- }
- }
- if (thePath.m_EndCapping == PathCapping::Taper) {
- QT3DSF32 taperStart = NVMin(thePath.m_EndCapOffset, maxTaperStart);
- QT3DSF32 endTaperWidth = thePath.m_EndCapWidth;
- QT3DSF32 endTaperOpacity = thePath.m_GlobalOpacity * thePath.m_EndCapOpacity;
- theEndTaperData = QT3DSVec2(endTaperWidth, endTaperOpacity);
- // Invert taper start so that the forward search works.
- Option<eastl::pair<QT3DSU32, QT3DSF32>> breakEquationAndT(
- FindBreakEquation(pathLength - taperStart));
-
- if (breakEquationAndT.hasValue()) {
- QT3DSU32 breakEquation = breakEquationAndT->first;
- ++breakEquation;
-
- QT3DSF32 lengthTotal = 0;
- for (QT3DSU32 idx = breakEquation, end = m_SubdivResult.size(); idx < end;
- ++idx) {
- SResultCubic &theCubic = m_SubdivResult[idx];
- theCubic.m_Mode = SResultCubic::EndTaper;
-
- theCubic.m_TaperMultiplier[0] = 1.0f - (lengthTotal / taperStart);
- lengthTotal += theCubic.m_Length;
- theCubic.m_TaperMultiplier[1] = 1.0f - (lengthTotal / taperStart);
- }
- }
- }
- }
-
- NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
- // Create quads out of each point.
- if (m_SubdivResult.empty())
- return false;
-
- // Generate patches.
- m_PatchBuffer.clear();
- QT3DSF32 pathWidth = thePath.m_Width / 2.0f;
- // texture coords
- float texCoordU = 0.0;
-
- for (QT3DSU32 idx = 0, end = m_SubdivResult.size(); idx < end; ++idx) {
- // create patches
- SResultCubic thePoint(m_SubdivResult[idx]);
-
- m_PatchBuffer.push_back(CreateVec4(thePoint.m_P1, thePoint.m_C1));
- m_PatchBuffer.push_back(CreateVec4(thePoint.m_C2, thePoint.m_P2));
-
- // Now we need to take care of cases where the control points of the adjoining
- // SubPaths
- // do not line up; i.e. there is a discontinuity of the 1st derivative
- // The simplest way to do this is to move the edge vertex to a halfway point
- // between a line bisecting the two control lines
- QT3DSVec2 incomingAdjoining(thePoint.m_P1);
- QT3DSVec2 outgoingAdjoining(thePoint.m_P2);
- if (idx) {
- SResultCubic previousCurve = m_SubdivResult[idx - 1];
- if (previousCurve.m_EquationIndex != thePoint.m_EquationIndex) {
- QT3DSF32 anchorWidth =
- thePoint.GetP1Width(pathWidth, theBeginTaperData.x, theEndTaperData.x);
- Option<QT3DSVec2> adjoining = GetAdjoiningPoint(
- previousCurve.m_C2, thePoint.m_P1, thePoint.m_C1, anchorWidth);
- if (adjoining.hasValue())
- incomingAdjoining = *adjoining;
- }
- }
- if (idx < (end - 1)) {
- SResultCubic nextCurve = m_SubdivResult[idx + 1];
- if (nextCurve.m_EquationIndex != thePoint.m_EquationIndex) {
- QT3DSF32 anchorWidth =
- thePoint.GetP2Width(pathWidth, theBeginTaperData.x, theEndTaperData.x);
- Option<QT3DSVec2> adjoining = GetAdjoiningPoint(thePoint.m_C2, thePoint.m_P2,
- nextCurve.m_C1, anchorWidth);
- if (adjoining.hasValue())
- outgoingAdjoining = *adjoining;
- }
- }
- m_PatchBuffer.push_back(CreateVec4(incomingAdjoining, outgoingAdjoining));
-
- QT3DSVec4 taperData(0.0f);
- taperData.x = thePoint.m_TaperMultiplier.x;
- taperData.y = thePoint.m_TaperMultiplier.y;
- // Note we could put a *lot* more data into this thing.
- taperData.z = (QT3DSF32)thePoint.m_Mode;
- m_PatchBuffer.push_back(taperData);
-
- // texture coord generation
- // note we only generate u here. v is generated in the tess shader
- // u coord for P1 and C1
- QT3DSVec2 udata(texCoordU, texCoordU + (thePoint.m_Length / pathLength));
- texCoordU = udata.y;
- m_PatchBuffer.push_back(QT3DSVec4(udata.x, udata.y, 0.0, 0.0));
- }
-
- // buffer size is 3.0*4.0*bufSize
- QT3DSU32 bufSize = (QT3DSU32)m_PatchBuffer.size() * sizeof(QT3DSVec4);
- QT3DSU32 stride = sizeof(QT3DSVec4);
-
- if ((!inPathBuffer.m_PatchData) || inPathBuffer.m_PatchData->Size() < bufSize) {
- inPathBuffer.m_PatchData = theRenderContext.CreateVertexBuffer(
- qt3ds::render::NVRenderBufferUsageType::Dynamic, bufSize, stride,
- toU8DataRef(m_PatchBuffer.data(), (QT3DSU32)m_PatchBuffer.size()));
- inPathBuffer.m_NumVertexes = (QT3DSU32)m_PatchBuffer.size();
- inPathBuffer.m_InputAssembler = NULL;
- } else {
- QT3DS_ASSERT(inPathBuffer.m_PatchData->Size() >= bufSize);
- inPathBuffer.m_PatchData->UpdateBuffer(
- toU8DataRef(m_PatchBuffer.data(), (QT3DSU32)m_PatchBuffer.size()));
- }
-
- if (!inPathBuffer.m_InputAssembler) {
- qt3ds::render::NVRenderVertexBufferEntry theEntries[] = {
- qt3ds::render::NVRenderVertexBufferEntry(
- "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 4),
- };
-
- NVRenderDrawMode::Enum primType = NVRenderDrawMode::Patches;
-
- NVRenderAttribLayout *theLayout =
- theRenderContext.CreateAttributeLayout(toConstDataRef(theEntries, 1));
- // How many vertices the TCS shader has access to in order to produce its output
- // array of vertices.
- const QT3DSU32 inputPatchVertexCount = 5;
- inPathBuffer.m_InputAssembler = theRenderContext.CreateInputAssembler(
- theLayout, toConstDataRef(inPathBuffer.m_PatchData.mPtr), NULL,
- toConstDataRef(stride), toConstDataRef((QT3DSU32)0), primType,
- inputPatchVertexCount);
- }
- inPathBuffer.m_BeginTaperData = theBeginTaperData;
- inPathBuffer.m_EndTaperData = theEndTaperData;
-
- // cache bounds
- NVBounds3 bounds = GetBounds(inPath);
- inPathBuffer.m_Bounds.minimum = bounds.minimum;
- inPathBuffer.m_Bounds.maximum = bounds.maximum;
- }
-
- return retval;
- }
-
- IMaterialShaderGenerator *GetMaterialShaderGenertator(SPathRenderContext &inRenderContext)
- {
- bool isDefaultMaterial =
- (inRenderContext.m_Material.m_Type == GraphObjectTypes::DefaultMaterial);
-
- IMaterialShaderGenerator *theMaterialGenerator = NULL;
- if (isDefaultMaterial)
- theMaterialGenerator = &m_RenderContext->GetDefaultMaterialShaderGenerator();
- else
- theMaterialGenerator = &m_RenderContext->GetCustomMaterialShaderGenerator();
-
- return theMaterialGenerator;
- }
-
- CRegisteredString GetMaterialNameForKey(SPathRenderContext &inRenderContext)
- {
- bool isDefaultMaterial =
- (inRenderContext.m_Material.m_Type == GraphObjectTypes::DefaultMaterial);
-
- if (!isDefaultMaterial) {
- ICustomMaterialSystem &theMaterialSystem(m_RenderContext->GetCustomMaterialSystem());
- const SCustomMaterial &theCustomMaterial(
- reinterpret_cast<const SCustomMaterial &>(inRenderContext.m_Material));
-
- return m_RenderContext->GetStringTable().RegisterStr(
- theMaterialSystem.GetShaderName(theCustomMaterial));
- }
-
- return m_RenderContext->GetStringTable().RegisterStr("");
- }
-
- bool PreparePaintedPathForRender(const SPath &inPath, SPathBuffer &inPathBuffer)
- {
- NVRenderContext &theContext(this->m_RenderContext->GetRenderContext());
- if (!inPathBuffer.m_PathRender
- || (((QT3DSU32)inPathBuffer.m_Flags) & PathDirtyFlagValues::SourceData)) {
- if (!inPathBuffer.m_PathRender) {
- inPathBuffer.m_PathRender = theContext.CreatePathRender();
- }
-
- if (inPathBuffer.m_PathRender == NULL || m_PathSpecification == NULL) {
- // QT3DS_ASSERT( false );
- return false;
- }
-
- m_PathSpecification->Reset();
- qt3dsimp::SPathBuffer thePathData = inPathBuffer.GetPathData(*m_PathBuilder);
-
- QT3DSU32 dataIdx = 0;
- for (QT3DSU32 commandIdx = 0, commandEnd = thePathData.m_Commands.size();
- commandIdx < commandEnd; ++commandIdx) {
-
- switch (thePathData.m_Commands[commandIdx]) {
- case qt3dsimp::PathCommand::MoveTo:
- m_PathSpecification->MoveTo(
- QT3DSVec2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]));
- dataIdx += 2;
- break;
- case qt3dsimp::PathCommand::CubicCurveTo: {
- QT3DSVec2 c1(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
- dataIdx += 2;
- QT3DSVec2 c2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
- dataIdx += 2;
- QT3DSVec2 p2(thePathData.m_Data[dataIdx], thePathData.m_Data[dataIdx + 1]);
- dataIdx += 2;
- m_PathSpecification->CubicCurveTo(c1, c2, p2);
- } break;
- case qt3dsimp::PathCommand::Close:
- m_PathSpecification->ClosePath();
- break;
- default:
- QT3DS_ASSERT(false);
- break;
- }
- }
-
- inPathBuffer.m_PathRender->SetPathSpecification(*m_PathSpecification);
-
- // cache bounds
- NVBounds3 bounds = GetBounds(inPath);
- inPathBuffer.m_Bounds.minimum = bounds.minimum;
- inPathBuffer.m_Bounds.maximum = bounds.maximum;
-
- return true;
- }
-
- return false;
- }
-
- bool PrepareForRender(const SPath &inPath) override
- {
- SPathBuffer *thePathBuffer = GetPathBufferObject(inPath);
- if (!thePathBuffer) {
- return false;
- }
- NVRenderContext &theContext(this->m_RenderContext->GetRenderContext());
- if (!m_PathSpecification)
- m_PathSpecification = theContext.CreatePathSpecification();
- if (!m_PathSpecification)
- return false;
- if (!m_PathBuilder)
- m_PathBuilder = qt3dsimp::IPathBufferBuilder::CreateBuilder(GetFoundation());
-
- thePathBuffer->SetPathType(inPath.m_PathType);
- bool retval = false;
- if (inPath.m_PathBuffer.IsValid() == false) {
- thePathBuffer->m_PathBuffer = NULL;
- // Ensure the SubPath list is identical and clear, percolating any dirty flags up to the
- // path buffer.
- QT3DSU32 SubPathIdx = 0;
- for (const SPathSubPath *theSubPath = inPath.m_FirstSubPath; theSubPath;
- theSubPath = theSubPath->m_NextSubPath, ++SubPathIdx) {
- SPathSubPathBuffer *theSubPathBuffer = GetPathBufferObject(*theSubPath);
- if (theSubPathBuffer == NULL)
- continue;
- thePathBuffer->m_Flags =
- (QT3DSU32)(thePathBuffer->m_Flags | theSubPathBuffer->m_Flags);
-
- if (theSubPathBuffer->m_Closed != theSubPath->m_Closed) {
- thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
- theSubPathBuffer->m_Closed = theSubPath->m_Closed;
- }
-
- if (thePathBuffer->m_SubPaths.size() <= SubPathIdx
- || thePathBuffer->m_SubPaths[SubPathIdx] != theSubPathBuffer) {
- thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
- if (thePathBuffer->m_SubPaths.size() <= SubPathIdx)
- thePathBuffer->m_SubPaths.push_back(theSubPathBuffer);
- else
- thePathBuffer->m_SubPaths[SubPathIdx] = theSubPathBuffer;
- }
-
- theSubPathBuffer->m_Flags.Clear();
- }
-
- if (SubPathIdx != thePathBuffer->m_SubPaths.size()) {
- thePathBuffer->m_SubPaths.resize(SubPathIdx);
- thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
- }
- } else {
- thePathBuffer->m_SubPaths.clear();
- eastl::pair<TStringPathBufferMap::iterator, bool> inserter =
- m_SourcePathBufferMap.insert(
- eastl::make_pair(inPath.m_PathBuffer, TPathBufferPtr()));
- if (inserter.second) {
- NVScopedRefCounted<IRefCountedInputStream> theStream =
- m_CoreContext.GetInputStreamFactory().GetStreamForFile(
- inPath.m_PathBuffer.c_str());
- if (theStream) {
- qt3dsimp::SPathBuffer *theNewBuffer =
- qt3dsimp::SPathBuffer::Load(*theStream, GetFoundation());
- if (theNewBuffer)
- inserter.first->second = QT3DS_NEW(GetAllocator(), SImportPathWrapper)(
- GetAllocator(), *theNewBuffer);
- }
- }
- if (thePathBuffer->m_PathBuffer != inserter.first->second) {
- thePathBuffer->m_PathBuffer = inserter.first->second;
- thePathBuffer->m_Flags.clearOrSet(true, PathDirtyFlagValues::SourceData);
- }
- }
-
- if (inPath.m_PathType == PathTypes::Geometry)
- retval = PrepareGeometryPathForRender(inPath, *thePathBuffer);
- else
- retval = PreparePaintedPathForRender(inPath, *thePathBuffer);
- thePathBuffer->m_Flags.Clear();
- return retval;
- }
-
- void SetMaterialProperties(NVRenderShaderProgram &inShader, SPathRenderContext &inRenderContext,
- SLayerGlobalRenderProperties &inRenderProperties)
- {
- IMaterialShaderGenerator *theMaterialGenerator =
- GetMaterialShaderGenertator(inRenderContext);
- NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
- theRenderContext.SetActiveShader(&inShader);
-
- theMaterialGenerator->SetMaterialProperties(
- inShader, inRenderContext.m_Material, inRenderContext.m_CameraVec,
- inRenderContext.m_ModelViewProjection, inRenderContext.m_NormalMatrix,
- inRenderContext.m_Path.m_GlobalTransform, inRenderContext.m_FirstImage,
- inRenderContext.m_Opacity, inRenderProperties);
- }
-
- void DoRenderGeometryPath(SPathGeneratedShader &inShader, SPathRenderContext &inRenderContext,
- SLayerGlobalRenderProperties &inRenderProperties,
- SPathBuffer &inPathBuffer)
- {
- if (inPathBuffer.m_InputAssembler == NULL)
- return;
-
- SetMaterialProperties(inShader.m_Shader, inRenderContext, inRenderProperties);
- NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
-
- inShader.m_BeginTaperData.Set(inPathBuffer.m_BeginTaperData);
- inShader.m_EndTaperData.Set(inPathBuffer.m_EndTaperData);
- if (inRenderContext.m_EnableWireframe) {
- // we need the viewport matrix
- NVRenderRect theViewport(theRenderContext.GetViewport());
- QT3DSMat44 vpMatrix;
- vpMatrix.column0 = QT3DSVec4((float)theViewport.m_Width / 2.0f, 0.0, 0.0, 0.0);
- vpMatrix.column1 = QT3DSVec4(0.0, (float)theViewport.m_Height / 2.0f, 0.0, 0.0);
- vpMatrix.column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
- vpMatrix.column3 =
- QT3DSVec4((float)theViewport.m_Width / 2.0f + (float)theViewport.m_X,
- (float)theViewport.m_Height / 2.0f + (float)theViewport.m_Y, 0.0, 1.0);
-
- inShader.m_WireframeViewMatrix.Set(vpMatrix);
- }
-
- QT3DSF32 tessEdgeValue = NVMin(64.0f, NVMax(1.0f, inRenderContext.m_Path.m_EdgeTessAmount));
- QT3DSF32 tessInnerValue = NVMin(64.0f, NVMax(1.0f, inRenderContext.m_Path.m_InnerTessAmount));
- inShader.m_EdgeTessAmount.Set(tessEdgeValue);
- inShader.m_InnerTessAmount.Set(tessInnerValue);
- inShader.m_Width.Set(inRenderContext.m_Path.m_Width / 2.0f);
- theRenderContext.SetInputAssembler(inPathBuffer.m_InputAssembler);
- theRenderContext.SetCullingEnabled(false);
- NVRenderDrawMode::Enum primType = NVRenderDrawMode::Patches;
- theRenderContext.Draw(primType, (QT3DSU32)inPathBuffer.m_NumVertexes, 0);
- }
-
- NVRenderDepthStencilState *GetDepthStencilState()
- {
- NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
- NVRenderBoolOp::Enum theDepthFunction = theRenderContext.GetDepthFunction();
- bool isDepthEnabled = theRenderContext.IsDepthTestEnabled();
- bool isStencilEnabled = theRenderContext.IsStencilTestEnabled();
- bool isDepthWriteEnabled = theRenderContext.IsDepthWriteEnabled();
- for (QT3DSU32 idx = 0, end = m_DepthStencilStates.size(); idx < end; ++idx) {
- NVRenderDepthStencilState &theState = *m_DepthStencilStates[idx];
- if (theState.GetDepthFunc() == theDepthFunction
- && theState.GetDepthEnabled() == isDepthEnabled
- && theState.GetDepthMask() == isDepthWriteEnabled)
- return &theState;
- }
- NVRenderStencilFunctionArgument theArg(NVRenderBoolOp::NotEqual, 0, 0xFF);
- NVRenderStencilOperationArgument theOpArg(NVRenderStencilOp::Keep, NVRenderStencilOp::Keep,
- NVRenderStencilOp::Zero);
- m_DepthStencilStates.push_back(theRenderContext.CreateDepthStencilState(
- isDepthEnabled, isDepthWriteEnabled, theDepthFunction, isStencilEnabled, theArg, theArg,
- theOpArg, theOpArg));
- return m_DepthStencilStates.back();
- }
-
- static void DoSetCorrectiveScale(const QT3DSMat44 &mvp, QT3DSMat44 &outScale, NVBounds3 pathBounds)
- {
- // Compute the projected locations for the paraboloid and regular projection
- // and thereby set the appropriate scaling factor.
- QT3DSVec3 points[4];
- QT3DSVec3 projReg[4], projParab[4];
- points[0] = pathBounds.minimum;
- points[1] = QT3DSVec3(pathBounds.maximum.x, pathBounds.minimum.y, pathBounds.minimum.z);
- points[2] = pathBounds.maximum;
- points[3] = QT3DSVec3(pathBounds.minimum.x, pathBounds.maximum.y, pathBounds.maximum.z);
-
- // Do the two different projections.
- for (int i = 0; i < 4; ++i) {
- QT3DSVec4 tmp;
- tmp = mvp.transform(QT3DSVec4(points[i], 1.0f));
- tmp /= tmp.w;
- projReg[i] = tmp.getXYZ();
- projParab[i] = tmp.getXYZ().getNormalized();
- projParab[i] /= projParab[i].z + 1.0f;
- }
-
- NVBounds3 boundsA, boundsB;
- for (int i = 0; i < 4; ++i) {
- boundsA.include(projReg[i]);
- boundsB.include(projParab[i]);
- }
- QT3DSF32 xscale =
- (boundsB.maximum.x - boundsB.minimum.x) / (boundsA.maximum.x - boundsA.minimum.x);
- QT3DSF32 yscale =
- (boundsB.maximum.y - boundsB.minimum.y) / (boundsA.maximum.y - boundsA.minimum.y);
- QT3DSF32 zscale = (boundsB.maximum - boundsB.minimum).magnitudeSquared()
- / (boundsA.maximum - boundsA.minimum).magnitudeSquared();
- // The default minimum here is just a stupid figure that looks good on our content because
- // we'd
- // been using it for a little while before. Just for demo.
- xscale = NVMin<QT3DSF32>(0.5333333f, NVMin<QT3DSF32>(xscale, yscale));
- yscale = NVMin<QT3DSF32>(0.5333333f, NVMin<QT3DSF32>(xscale, yscale));
- outScale.scale(QT3DSVec4(xscale, yscale, zscale, 1.0f));
- }
-
- void DoRenderPaintedPath(SPathXYGeneratedShader &inShader, SPathRenderContext &inRenderContext,
- SLayerGlobalRenderProperties &inRenderProperties,
- SPathBuffer &inPathBuffer, bool isParaboloidPass = false)
- {
- if (!inPathBuffer.m_PathRender)
- return;
- NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
- if (!m_PaintedRectInputAssembler) {
- QT3DSVec2 vertexes[] = {
- QT3DSVec2(0.0, 0.0), QT3DSVec2(1.0, 0.0), QT3DSVec2(1.0, 1.0), QT3DSVec2(0.0, 1.0),
- };
-
- QT3DSU8 indexes[] = {
- 0, 1, 2, 2, 3, 0,
- };
-
- QT3DSU32 stride = sizeof(QT3DSVec2);
-
- NVRenderVertexBufferEntry theBufferEntries[] = { NVRenderVertexBufferEntry(
- "attr_pos", qt3ds::render::NVRenderComponentTypes::QT3DSF32, 2, 0) };
-
- m_PaintedRectVertexBuffer = theRenderContext.CreateVertexBuffer(
- qt3ds::render::NVRenderBufferUsageType::Static, 4 * sizeof(QT3DSVec2), sizeof(QT3DSVec2),
- toU8DataRef(vertexes, 4));
- m_PaintedRectIndexBuffer = theRenderContext.CreateIndexBuffer(
- qt3ds::render::NVRenderBufferUsageType::Static,
- qt3ds::render::NVRenderComponentTypes::QT3DSU8, 6, toU8DataRef(indexes, 6));
- NVRenderAttribLayout *theAttribLayout =
- theRenderContext.CreateAttributeLayout(toConstDataRef(theBufferEntries, 1));
- m_PaintedRectInputAssembler = theRenderContext.CreateInputAssembler(
- theAttribLayout, toConstDataRef(m_PaintedRectVertexBuffer.mPtr),
- m_PaintedRectIndexBuffer.mPtr, toConstDataRef(stride), toConstDataRef((QT3DSU32)0),
- qt3ds::render::NVRenderDrawMode::Triangles);
- }
-
- // our current render target needs stencil
- QT3DS_ASSERT(theRenderContext.GetStencilBits() > 0);
-
- theRenderContext.SetDepthStencilState(GetDepthStencilState());
-
- // http://developer.download.nvidia.com/assets/gamedev/files/Mixing_Path_Rendering_and_3D.pdf
- theRenderContext.SetPathStencilDepthOffset(-.05f, -1.0f);
-
- // Stencil out the geometry.
- QT3DSMat44 pathMdlView = QT3DSMat44::createIdentity();
- // Why is this happening? Well, it's because the painted-on path rendering is always
- // a flat splatted 2D object. This is bad because a paraboloid projection demands a very
- // different
- // non-linear space into which we must draw. Path Rendering does not allow this sort of
- // spatial
- // warping internally, and all we end up passing in as a simple perspective projection.
- // So for the fix, I'm scaling the actual "object" size so that it fits into the correctly
- // projected
- // polygon inside the paraboloid depth pass. Obviously, this scaling factor is wrong, and
- // not generic
- // enough to cover cases like polygons covering a large spread of the FOV and so on. It's
- // really
- // just a filthy awful, morally deplorable HACK. But it's basically the quickest fix at
- // hand.
- // This is also about the only possible approach that *could* work short of rendering the
- // paths in
- // a render-to-texture pass and splatting that texture on a sufficiently tessellated quad.
- // Unless
- // there's a way to program NVPR's internal projection scheme, that is.
- // Geometry-based paths will work out better, I think, because they're actually creating
- // geometry.
- // This is essentially a 2D painting process inside a quad where the actual rendered region
- // isn't
- // exactly where NVPR thinks it should be because they're not projecting points the same
- // way.
- if (isParaboloidPass) {
- DoSetCorrectiveScale(inRenderContext.m_ModelViewProjection, pathMdlView,
- inPathBuffer.m_PathRender->GetPathObjectStrokeBox());
- }
-
- bool isStencilEnabled = theRenderContext.IsStencilTestEnabled();
- theRenderContext.SetStencilTestEnabled(true);
- theRenderContext.SetPathProjectionMatrix(inRenderContext.m_ModelViewProjection);
- theRenderContext.SetPathModelViewMatrix(pathMdlView);
-
- if (inRenderContext.m_IsStroke) {
- inPathBuffer.m_PathRender->SetStrokeWidth(inRenderContext.m_Path.m_Width);
- inPathBuffer.m_PathRender->StencilStroke();
- } else
- inPathBuffer.m_PathRender->StencilFill();
-
- // The stencil buffer will dictate whether this object renders or not. So we need to ignore
- // the depth test result.
- NVRenderBoolOp::Enum theDepthFunc = theRenderContext.GetDepthFunction();
- theRenderContext.SetDepthFunction(NVRenderBoolOp::AlwaysTrue);
- // Now render the path; this resets the stencil buffer.
- SetMaterialProperties(inShader.m_Shader, inRenderContext, inRenderProperties);
- NVBounds3 rectBounds = inPathBuffer.m_PathRender->GetPathObjectStrokeBox();
- if (isParaboloidPass) {
- rectBounds.scale(1.570796326795f);
- } // PKC : More of the same ugly hack.
- inShader.m_RectDimensions.Set(QT3DSVec4(rectBounds.minimum.x, rectBounds.minimum.y,
- rectBounds.maximum.x, rectBounds.maximum.y));
- theRenderContext.SetInputAssembler(m_PaintedRectInputAssembler);
- theRenderContext.SetCullingEnabled(false);
- // Render exactly two triangles
- theRenderContext.Draw(NVRenderDrawMode::Triangles, 6, 0);
- theRenderContext.SetStencilTestEnabled(isStencilEnabled);
- theRenderContext.SetDepthFunction(theDepthFunc);
- }
-
- void RenderDepthPrepass(SPathRenderContext &inRenderContext,
- SLayerGlobalRenderProperties inRenderProperties,
- TShaderFeatureSet inFeatureSet) override
- {
- SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
- if (!thePathBuffer) {
- return;
- }
-
- if (thePathBuffer->m_PathType == PathTypes::Geometry) {
- QT3DSU32 displacementIdx = 0;
- QT3DSU32 imageIdx = 0;
- SRenderableImage *displacementImage = 0;
-
- for (SRenderableImage *theImage = inRenderContext.m_FirstImage;
- theImage != NULL && displacementImage == NULL;
- theImage = theImage->m_NextImage, ++imageIdx) {
- if (theImage->m_MapType == ImageMapTypes::Displacement) {
- displacementIdx = imageIdx;
- displacementImage = theImage;
- }
- }
-
- NVScopedRefCounted<SPathGeneratedShader> &theDesiredDepthShader =
- displacementImage == NULL ? m_DepthShader : m_DepthDisplacementShader;
-
- if (!theDesiredDepthShader) {
- IDefaultMaterialShaderGenerator &theMaterialGenerator(
- m_RenderContext->GetDefaultMaterialShaderGenerator());
- SPathVertexPipeline thePipeline(
- m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
- m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable(), false);
- thePipeline.BeginVertexGeneration(displacementIdx, displacementImage);
- thePipeline.BeginFragmentGeneration();
- thePipeline.Fragment().Append("\tfragOutput = vec4(1.0, 1.0, 1.0, 1.0);");
- thePipeline.EndVertexGeneration(false);
- thePipeline.EndFragmentGeneration(false);
- const char8_t *shaderName = "path depth";
- if (displacementImage)
- shaderName = "path depth displacement";
-
- SShaderCacheProgramFlags theFlags;
- NVRenderShaderProgram *theProgram =
- thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
- inFeatureSet);
- if (theProgram) {
- theDesiredDepthShader =
- QT3DS_NEW(m_RenderContext->GetAllocator(),
- SPathGeneratedShader)(*theProgram, m_RenderContext->GetAllocator());
- }
- }
- if (theDesiredDepthShader) {
- DoRenderGeometryPath(*theDesiredDepthShader, inRenderContext, inRenderProperties,
- *thePathBuffer);
- }
- } else {
- // painted path, go stroke route for now.
- if (!m_PaintedDepthShader) {
- IDefaultMaterialShaderGenerator &theMaterialGenerator(
- m_RenderContext->GetDefaultMaterialShaderGenerator());
- SXYRectVertexPipeline thePipeline(
- m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
- m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
- thePipeline.BeginVertexGeneration(0, NULL);
- thePipeline.BeginFragmentGeneration();
- thePipeline.Fragment().Append("\tfragOutput = vec4(1.0, 1.0, 1.0, 1.0);");
- thePipeline.EndVertexGeneration(false);
- thePipeline.EndFragmentGeneration(false);
- const char8_t *shaderName = "path painted depth";
- SShaderCacheProgramFlags theFlags;
- NVRenderShaderProgram *theProgram =
- thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
- inFeatureSet);
- if (theProgram) {
- m_PaintedDepthShader =
- QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
- *theProgram, m_RenderContext->GetAllocator());
- }
- }
- if (m_PaintedDepthShader) {
-
- DoRenderPaintedPath(*m_PaintedDepthShader, inRenderContext, inRenderProperties,
- *thePathBuffer);
- }
- }
- }
-
- void RenderShadowMapPass(SPathRenderContext &inRenderContext,
- SLayerGlobalRenderProperties inRenderProperties,
- TShaderFeatureSet inFeatureSet) override
- {
- SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
- if (!thePathBuffer) {
- return;
- }
-
- if (inRenderContext.m_Material.m_Type != GraphObjectTypes::DefaultMaterial)
- return;
-
- if (thePathBuffer->m_PathType == PathTypes::Painted) {
- // painted path, go stroke route for now.
- if (!m_PaintedShadowShader) {
- IDefaultMaterialShaderGenerator &theMaterialGenerator(
- m_RenderContext->GetDefaultMaterialShaderGenerator());
- SXYRectVertexPipeline thePipeline(
- m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
- m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
- thePipeline.OutputParaboloidDepthShaders();
- const char8_t *shaderName = "path painted paraboloid depth";
- SShaderCacheProgramFlags theFlags;
- NVRenderShaderProgram *theProgram =
- thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
- inFeatureSet);
- if (theProgram) {
- m_PaintedShadowShader =
- QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
- *theProgram, m_RenderContext->GetAllocator());
- }
- }
- if (m_PaintedShadowShader) {
- // Setup the shader paraboloid information.
- NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
- theRenderContext.SetActiveShader(&m_PaintedShadowShader->m_Shader);
-
- DoRenderPaintedPath(*m_PaintedShadowShader, inRenderContext, inRenderProperties,
- *thePathBuffer, true);
- }
- } else {
- // Until we've also got a proper path render path for this, we'll call the old-fashioned
- // stuff.
- RenderDepthPrepass(inRenderContext, inRenderProperties, inFeatureSet);
- // QT3DS_ASSERT( false );
- }
- }
-
- void RenderCubeFaceShadowPass(SPathRenderContext &inRenderContext,
- SLayerGlobalRenderProperties inRenderProperties,
- TShaderFeatureSet inFeatureSet) override
- {
- SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
- if (!thePathBuffer) {
- return;
- }
-
- if (inRenderContext.m_Material.m_Type != GraphObjectTypes::DefaultMaterial)
- return;
-
- if (thePathBuffer->m_PathType == PathTypes::Painted) {
- if (!m_PaintedCubeShadowShader) {
- IDefaultMaterialShaderGenerator &theMaterialGenerator(
- m_RenderContext->GetDefaultMaterialShaderGenerator());
- SXYRectVertexPipeline thePipeline(
- m_RenderContext->GetShaderProgramGenerator(), theMaterialGenerator,
- m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
- thePipeline.OutputCubeFaceDepthShaders();
- const char8_t *shaderName = "path painted cube face depth";
- SShaderCacheProgramFlags theFlags;
- NVRenderShaderProgram *theProgram =
- thePipeline.ProgramGenerator().CompileGeneratedShader(shaderName, theFlags,
- inFeatureSet);
- if (theProgram) {
- m_PaintedCubeShadowShader =
- QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
- *theProgram, m_RenderContext->GetAllocator());
- }
- }
- if (m_PaintedCubeShadowShader) {
- // Setup the shader information.
- NVRenderContext &theRenderContext(m_RenderContext->GetRenderContext());
- theRenderContext.SetActiveShader(&m_PaintedCubeShadowShader->m_Shader);
-
- m_PaintedCubeShadowShader->m_CameraPosition.Set(
- inRenderContext.m_Camera.GetGlobalPos());
- m_PaintedCubeShadowShader->m_CameraProperties.Set(
- QT3DSVec2(1.0f, inRenderContext.m_Camera.m_ClipFar));
- m_PaintedCubeShadowShader->m_ModelMatrix.Set(inRenderContext.m_ModelMatrix);
-
- DoRenderPaintedPath(*m_PaintedCubeShadowShader, inRenderContext, inRenderProperties,
- *thePathBuffer, false);
- }
- } else {
- // Until we've also got a proper path render path for this, we'll call the old-fashioned
- // stuff.
- RenderDepthPrepass(inRenderContext, inRenderProperties, inFeatureSet);
- }
- }
-
- void RenderPath(SPathRenderContext &inRenderContext,
- SLayerGlobalRenderProperties inRenderProperties,
- TShaderFeatureSet inFeatureSet) override
- {
- SPathBuffer *thePathBuffer = GetPathBufferObject(inRenderContext.m_Path);
- if (!thePathBuffer) {
- return;
- }
-
- bool isDefaultMaterial =
- (inRenderContext.m_Material.m_Type == GraphObjectTypes::DefaultMaterial);
-
- if (thePathBuffer->m_PathType == PathTypes::Geometry) {
- IMaterialShaderGenerator *theMaterialGenerator =
- GetMaterialShaderGenertator(inRenderContext);
-
- // we need a more evolved key her for custom materials
- // the same key can still need a different shader
- SPathShaderMapKey sPathkey = SPathShaderMapKey(GetMaterialNameForKey(inRenderContext),
- inRenderContext.m_MaterialKey);
- eastl::pair<TShaderMap::iterator, bool> inserter = m_PathGeometryShaders.insert(
- eastl::make_pair(sPathkey, NVScopedRefCounted<SPathGeneratedShader>(NULL)));
- if (inserter.second) {
- SPathVertexPipeline thePipeline(
- m_RenderContext->GetShaderProgramGenerator(), *theMaterialGenerator,
- m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable(),
- m_RenderContext->GetWireframeMode());
-
- NVRenderShaderProgram *theProgram = NULL;
-
- if (isDefaultMaterial) {
- theProgram = theMaterialGenerator->GenerateShader(
- inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
- inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
- inRenderContext.m_Opacity < 1.0, "path geometry pipeline-- ");
- } else {
- ICustomMaterialSystem &theMaterialSystem(
- m_RenderContext->GetCustomMaterialSystem());
- const SCustomMaterial &theCustomMaterial(
- reinterpret_cast<const SCustomMaterial &>(inRenderContext.m_Material));
-
- theProgram = theMaterialGenerator->GenerateShader(
- inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
- inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
- inRenderContext.m_Opacity < 1.0, "path geometry pipeline-- ",
- theMaterialSystem.GetShaderName(theCustomMaterial));
- }
-
- if (theProgram)
- inserter.first->second =
- QT3DS_NEW(m_RenderContext->GetAllocator(),
- SPathGeneratedShader)(*theProgram, m_RenderContext->GetAllocator());
- }
- if (!inserter.first->second)
- return;
-
- DoRenderGeometryPath(*inserter.first->second.mPtr, inRenderContext, inRenderProperties,
- *thePathBuffer);
- } else {
- IMaterialShaderGenerator *theMaterialGenerator =
- GetMaterialShaderGenertator(inRenderContext);
-
- // we need a more evolved key her for custom materials
- // the same key can still need a different shader
- SPathShaderMapKey sPathkey = SPathShaderMapKey(GetMaterialNameForKey(inRenderContext),
- inRenderContext.m_MaterialKey);
- eastl::pair<TPaintedShaderMap::iterator, bool> inserter = m_PathPaintedShaders.insert(
- eastl::make_pair(sPathkey, NVScopedRefCounted<SPathXYGeneratedShader>(NULL)));
-
- if (inserter.second) {
- SXYRectVertexPipeline thePipeline(
- m_RenderContext->GetShaderProgramGenerator(), *theMaterialGenerator,
- m_RenderContext->GetAllocator(), m_RenderContext->GetStringTable());
-
- NVRenderShaderProgram *theProgram = NULL;
-
- if (isDefaultMaterial) {
- theProgram = theMaterialGenerator->GenerateShader(
- inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
- inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
- inRenderContext.m_Opacity < 1.0, "path painted pipeline-- ");
- } else {
- ICustomMaterialSystem &theMaterialSystem(
- m_RenderContext->GetCustomMaterialSystem());
- const SCustomMaterial &theCustomMaterial(
- reinterpret_cast<const SCustomMaterial &>(inRenderContext.m_Material));
-
- theProgram = theMaterialGenerator->GenerateShader(
- inRenderContext.m_Material, inRenderContext.m_MaterialKey, thePipeline,
- inFeatureSet, inRenderProperties.m_Lights, inRenderContext.m_FirstImage,
- inRenderContext.m_Opacity < 1.0, "path painted pipeline-- ",
- theMaterialSystem.GetShaderName(theCustomMaterial));
- }
-
- if (theProgram)
- inserter.first->second =
- QT3DS_NEW(m_RenderContext->GetAllocator(), SPathXYGeneratedShader)(
- *theProgram, m_RenderContext->GetAllocator());
- }
- if (!inserter.first->second)
- return;
-
- DoRenderPaintedPath(*inserter.first->second.mPtr, inRenderContext, inRenderProperties,
- *thePathBuffer);
- }
- }
-};
-}
-
-QT3DSVec2 IPathManagerCore::GetControlPointFromAngleDistance(QT3DSVec2 inPosition, float inIncomingAngle,
- float inIncomingDistance)
-{
- if (inIncomingDistance == 0.0f)
- return inPosition;
- float angleRad = degToRad(inIncomingAngle);
- float angleSin = NVSin(angleRad);
- float angleCos = NVCos(angleRad);
- QT3DSVec2 relativeAngles = QT3DSVec2(angleCos * inIncomingDistance, angleSin * inIncomingDistance);
- return inPosition + relativeAngles;
-}
-
-QT3DSVec2 IPathManagerCore::GetAngleDistanceFromControlPoint(QT3DSVec2 inPosition, QT3DSVec2 inControlPoint)
-{
- QT3DSVec2 relative = inControlPoint - inPosition;
- float angleRad = atan2(relative.y, relative.x);
- float distance = relative.magnitude();
- return QT3DSVec2(radToDeg(angleRad), distance);
-}
-
-IPathManagerCore &IPathManagerCore::CreatePathManagerCore(IQt3DSRenderContextCore &ctx)
-{
- return *QT3DS_NEW(ctx.GetAllocator(), SPathManager)(ctx);
-}