diff options
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp')
m--------- | src/Runtime/ogl-runtime | 0 | ||||
-rw-r--r-- | src/Runtime/ogl-runtime/src/runtimerender/Qt3DSRenderPathManager.cpp | 1964 |
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); -} |