git.s-ol.nu ~forks/DiligentFX / d2f43ce
GLTF PBR Renderer: removed RenderNodeCallback as it makes little sense and only adds overhead assiduous 10 months ago
2 changed file(s) with 120 addition(s) and 201 deletion(s). Raw diff Collapse all Expand all
121121 ALPHA_MODE_FLAG_NONE = 0,
122122
123123 /// Render opaque matetrials
124 ALPHA_MODE_FLAG_OPAQUE = 1 << GLTF::Material::ALPHAMODE_OPAQUE,
124 ALPHA_MODE_FLAG_OPAQUE = 1 << GLTF::Material::ALPHA_MODE_OPAQUE,
125125
126126 /// Render alpha-masked matetrials
127 ALPHA_MODE_FLAG_MASK = 1 << GLTF::Material::ALPHAMODE_MASK,
127 ALPHA_MODE_FLAG_MASK = 1 << GLTF::Material::ALPHA_MODE_MASK,
128128
129129 /// Render alpha-blended matetrials
130 ALPHA_MODE_FLAG_BLEND = 1 << GLTF::Material::ALPHAMODE_BLEND,
130 ALPHA_MODE_FLAG_BLEND = 1 << GLTF::Material::ALPHA_MODE_BLEND,
131131
132132 /// Render all materials
133133 ALPHA_MODE_FLAG_ALL = ALPHA_MODE_FLAG_OPAQUE | ALPHA_MODE_FLAG_MASK | ALPHA_MODE_FLAG_BLEND
177177 float WhitePoint = 3.f;
178178 };
179179
180 /// GLTF node rendering info passed to the custom render callback
181 struct GLTFNodeRenderInfo
182 {
183 /// GLTF material
184 Uint32 MaterialId = 0;
185
186 /// GLTF node transforms
187 const GLTF::Mesh::TransformData* pTransformData = nullptr;
188
189 /// Index type for indexed primitives, or VT_UNDEFINED for non-indexed ones
190 VALUE_TYPE IndexType = VT_UNDEFINED;
191 union
192 {
193 /// Index count for indexed primitives
194 Uint32 IndexCount;
195
196 /// Vertex count for non-indexed primitives
197 Uint32 VertexCount;
198 };
199 /// First index for indexed primitives
200 Uint32 FirstIndex = 0;
201
202 /// Base vertex for indexed primitives or start vertex location for non-indexed.
203 Uint32 BaseVertex = 0;
204
205 GLTFNodeRenderInfo() noexcept :
206 IndexCount{0}
207 {}
208 };
209
210180 struct ModelResourceBindings
211181 {
212182 void Clear()
224194 /// \param [in] ResourceBindings - Model shader resource bindings.
225195 /// \param [in] RenderNodeCallback - Optional render call back function that should be called
226196 /// for every GLTF node instead of rendering it.
227 /// \param [in] SRBTypeId - Optional application-defined SRB type that was given to
228 /// CreateMaterialSRB.
229 void Render(IDeviceContext* pCtx,
230 GLTF::Model& GLTFModel,
231 const RenderInfo& RenderParams,
232 const ModelResourceBindings& ResourceBindings,
233 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback = nullptr);
197 /// \param [in] ResourceBindings - GLTF model shader resource bindings.
198 void Render(IDeviceContext* pCtx,
199 GLTF::Model& GLTFModel,
200 const RenderInfo& RenderParams,
201 const ModelResourceBindings& ResourceBindings);
234202
235203 /// Creates resource bindings for a given GLTF model
236204 ModelResourceBindings CreateResourceBindings(GLTF::Model& GLTFModel,
275243
276244 void CreatePSO(IRenderDevice* pDevice);
277245
278 void RenderGLTFNode(IDeviceContext* pCtx,
279 const GLTF::Node* node,
280 GLTF::Material::ALPHA_MODE AlphaMode,
281 const float4x4& ModelTransform,
282 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback,
283 size_t SRBTypeId);
246 void RenderGLTFNode(IDeviceContext* pCtx,
247 const GLTF::Node* node,
248 GLTF::Material::ALPHA_MODE AlphaMode,
249 const float4x4& ModelTransform,
250 size_t SRBTypeId);
284251
285252 struct PSOKey
286253 {
290257 DoubleSided{_DoubleSided}
291258 {}
292259
293 GLTF::Material::ALPHA_MODE AlphaMode = GLTF::Material::ALPHAMODE_OPAQUE;
260 GLTF::Material::ALPHA_MODE AlphaMode = GLTF::Material::ALPHA_MODE_OPAQUE;
294261 bool DoubleSided = false;
295262 };
296263
297264 static size_t GetPSOIdx(const PSOKey& Key)
298265 {
299 return (Key.AlphaMode == GLTF::Material::ALPHAMODE_BLEND ? 1 : 0) + (Key.DoubleSided ? 2 : 0);
266 return (Key.AlphaMode == GLTF::Material::ALPHA_MODE_BLEND ? 1 : 0) + (Key.DoubleSided ? 2 : 0);
300267 }
301268
302269 void AddPSO(const PSOKey& Key, RefCntAutoPtr<IPipelineState> pPSO)
348315
349316 struct GLTFNodeRenderer
350317 {
351 GLTF_PBR_Renderer& Renderer;
352 IDeviceContext* const pCtx;
353 GLTF::Model& GLTFModel;
354 const RenderInfo& RenderParams;
355 const ModelResourceBindings& ResourceBindings;
356 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback;
318 GLTF_PBR_Renderer& Renderer;
319 IDeviceContext* const pCtx;
320 GLTF::Model& GLTFModel;
321 const RenderInfo& RenderParams;
322 const ModelResourceBindings& ResourceBindings;
357323
358324 const Uint32 FirstIndexLocation;
359325 const Uint32 BaseVertex;
333333 PSOCreateInfo.pPS = pPS;
334334
335335 {
336 PSOKey Key{GLTF::Material::ALPHAMODE_OPAQUE, false};
336 PSOKey Key{GLTF::Material::ALPHA_MODE_OPAQUE, false};
337337
338338 RefCntAutoPtr<IPipelineState> pSingleSidedOpaquePSO;
339339 pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pSingleSidedOpaquePSO);
360360 RT0.BlendOpAlpha = BLEND_OPERATION_ADD;
361361
362362 {
363 PSOKey Key{GLTF::Material::ALPHAMODE_BLEND, false};
363 PSOKey Key{GLTF::Material::ALPHA_MODE_BLEND, false};
364364
365365 RefCntAutoPtr<IPipelineState> pSingleSidedBlendPSO;
366366 pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pSingleSidedBlendPSO);
737737 if (material.AlphaMode != AlphaMode)
738738 continue;
739739
740 if (RenderNodeCallback == nullptr)
741 {
742 auto* pPSO = Renderer.GetPSO(PSOKey{AlphaMode, material.DoubleSided});
743 VERIFY_EXPR(pPSO != nullptr);
744 pCtx->SetPipelineState(pPSO);
745
746 VERIFY(primitive.MaterialId < ResourceBindings.MaterialSRB.size(),
747 "Material index is out of bounds. This mostl likely indicates that shader resources were initialized for a different model.");
748
749 IShaderResourceBinding* const pSRB = ResourceBindings.MaterialSRB[primitive.MaterialId].RawPtr<IShaderResourceBinding>();
750 if (pSRB == nullptr)
740 auto* pPSO = Renderer.GetPSO(PSOKey{AlphaMode, material.DoubleSided});
741 VERIFY_EXPR(pPSO != nullptr);
742 pCtx->SetPipelineState(pPSO);
743
744 VERIFY(primitive.MaterialId < ResourceBindings.MaterialSRB.size(),
745 "Material index is out of bounds. This mostl likely indicates that shader resources were initialized for a different model.");
746
747 IShaderResourceBinding* const pSRB = ResourceBindings.MaterialSRB[primitive.MaterialId].RawPtr<IShaderResourceBinding>();
748 if (pSRB == nullptr)
749 {
750 LOG_ERROR_MESSAGE("Unable to find SRB for GLTF material. Please call GLTF_PBR_Renderer::CreateResourceBindings()");
751 continue;
752 }
753 pCtx->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
754
755 size_t JointCount = Node.Mesh->Transforms.jointMatrices.size();
756 if (JointCount > Renderer.m_Settings.MaxJointCount)
757 {
758 LOG_WARNING_MESSAGE("The number of joints in the mesh (", JointCount, ") exceeds the maximum number (", Renderer.m_Settings.MaxJointCount,
759 ") reserved in the buffer. Increase MaxJointCount when initializing the renderer.");
760 JointCount = Renderer.m_Settings.MaxJointCount;
761 }
762
763 {
764 MapHelper<GLTFNodeShaderTransforms> pTransforms{pCtx, Renderer.m_TransformsCB, MAP_WRITE, MAP_FLAG_DISCARD};
765 pTransforms->NodeMatrix = Node.Mesh->Transforms.matrix * RenderParams.ModelTransform;
766 pTransforms->JointCount = static_cast<int>(JointCount);
767 }
768
769 if (JointCount != 0 && pLastAnimatedMesh != Node.Mesh.get())
770 {
771 MapHelper<float4x4> pJoints{pCtx, Renderer.m_JointsBuffer, MAP_WRITE, MAP_FLAG_DISCARD};
772 memcpy(pJoints, Node.Mesh->Transforms.jointMatrices.data(), JointCount * sizeof(float4x4));
773 pLastAnimatedMesh = Node.Mesh.get();
774 }
775
776 {
777 struct GLTFAttribs
751778 {
752 LOG_ERROR_MESSAGE("Unable to find SRB for GLTF material. Please call GLTF_PBR_Renderer::CreateResourceBindings()");
753 continue;
754 }
755 pCtx->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
756
757 size_t JointCount = Node.Mesh->Transforms.jointMatrices.size();
758 if (JointCount > Renderer.m_Settings.MaxJointCount)
759 {
760 LOG_WARNING_MESSAGE("The number of joints in the mesh (", JointCount, ") exceeds the maximum number (", Renderer.m_Settings.MaxJointCount,
761 ") reserved in the buffer. Increase MaxJointCount when initializing the renderer.");
762 JointCount = Renderer.m_Settings.MaxJointCount;
763 }
764
765 {
766 MapHelper<GLTFNodeShaderTransforms> pTransforms{pCtx, Renderer.m_TransformsCB, MAP_WRITE, MAP_FLAG_DISCARD};
767 pTransforms->NodeMatrix = Node.Mesh->Transforms.matrix * RenderParams.ModelTransform;
768 pTransforms->JointCount = static_cast<int>(JointCount);
769 }
770
771 if (JointCount != 0 && pLastAnimatedMesh != Node.Mesh.get())
772 {
773 MapHelper<float4x4> pJoints{pCtx, Renderer.m_JointsBuffer, MAP_WRITE, MAP_FLAG_DISCARD};
774 memcpy(pJoints, Node.Mesh->Transforms.jointMatrices.data(), JointCount * sizeof(float4x4));
775 pLastAnimatedMesh = Node.Mesh.get();
776 }
777
778 {
779 struct GLTFAttribs
780 {
781 GLTFRendererShaderParameters RenderParameters;
782 GLTF::Material::ShaderAttribs MaterialInfo;
783 static_assert(sizeof(GLTFMaterialShaderInfo) == sizeof(GLTF::Material::ShaderAttribs),
784 "The sizeof(GLTFMaterialShaderInfo) is incosistent with sizeof(GLTF::Material::ShaderAttribs)");
785 };
786 static_assert(sizeof(GLTFAttribs) <= 256, "Size of dynamic GLTFAttribs buffer exceeds 256 bytes. "
787 "It may be worth trying to reduce the size or just live with it.");
788
789 MapHelper<GLTFAttribs> pGLTFAttribs{pCtx, Renderer.m_GLTFAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD};
790
791 pGLTFAttribs->MaterialInfo = material.Attribs;
792
793 auto& ShaderParams = pGLTFAttribs->RenderParameters;
794
795 ShaderParams.DebugViewType = static_cast<int>(Renderer.m_RenderParams.DebugView);
796 ShaderParams.OcclusionStrength = Renderer.m_RenderParams.OcclusionStrength;
797 ShaderParams.EmissionScale = Renderer.m_RenderParams.EmissionScale;
798 ShaderParams.AverageLogLum = Renderer.m_RenderParams.AverageLogLum;
799 ShaderParams.MiddleGray = Renderer.m_RenderParams.MiddleGray;
800 ShaderParams.WhitePoint = Renderer.m_RenderParams.WhitePoint;
801 ShaderParams.IBLScale = Renderer.m_RenderParams.IBLScale;
802 ShaderParams.PrefilteredCubeMipLevels = Renderer.m_Settings.UseIBL ? static_cast<float>(Renderer.m_pPrefilteredEnvMapSRV->GetTexture()->GetDesc().MipLevels) : 0.f;
803 }
804
805 if (primitive.HasIndices())
806 {
807 DrawIndexedAttribs drawAttrs{primitive.IndexCount, VT_UINT32, DRAW_FLAG_VERIFY_ALL};
808 drawAttrs.FirstIndexLocation = FirstIndexLocation + primitive.FirstIndex;
809 drawAttrs.BaseVertex = BaseVertex;
810 pCtx->DrawIndexed(drawAttrs);
811 }
812 else
813 {
814 DrawAttribs drawAttrs{primitive.VertexCount, DRAW_FLAG_VERIFY_ALL};
815 drawAttrs.StartVertexLocation = BaseVertex;
816 pCtx->Draw(drawAttrs);
817 }
779 GLTFRendererShaderParameters RenderParameters;
780 GLTF::Material::ShaderAttribs MaterialInfo;
781 static_assert(sizeof(GLTFMaterialShaderInfo) == sizeof(GLTF::Material::ShaderAttribs),
782 "The sizeof(GLTFMaterialShaderInfo) is incosistent with sizeof(GLTF::Material::ShaderAttribs)");
783 };
784 static_assert(sizeof(GLTFAttribs) <= 256, "Size of dynamic GLTFAttribs buffer exceeds 256 bytes. "
785 "It may be worth trying to reduce the size or just live with it.");
786
787 MapHelper<GLTFAttribs> pGLTFAttribs{pCtx, Renderer.m_GLTFAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD};
788
789 pGLTFAttribs->MaterialInfo = material.Attribs;
790
791 auto& ShaderParams = pGLTFAttribs->RenderParameters;
792
793 ShaderParams.DebugViewType = static_cast<int>(Renderer.m_RenderParams.DebugView);
794 ShaderParams.OcclusionStrength = Renderer.m_RenderParams.OcclusionStrength;
795 ShaderParams.EmissionScale = Renderer.m_RenderParams.EmissionScale;
796 ShaderParams.AverageLogLum = Renderer.m_RenderParams.AverageLogLum;
797 ShaderParams.MiddleGray = Renderer.m_RenderParams.MiddleGray;
798 ShaderParams.WhitePoint = Renderer.m_RenderParams.WhitePoint;
799 ShaderParams.IBLScale = Renderer.m_RenderParams.IBLScale;
800 ShaderParams.PrefilteredCubeMipLevels = Renderer.m_Settings.UseIBL ? static_cast<float>(Renderer.m_pPrefilteredEnvMapSRV->GetTexture()->GetDesc().MipLevels) : 0.f;
801 }
802
803 if (primitive.HasIndices())
804 {
805 DrawIndexedAttribs drawAttrs{primitive.IndexCount, VT_UINT32, DRAW_FLAG_VERIFY_ALL};
806 drawAttrs.FirstIndexLocation = FirstIndexLocation + primitive.FirstIndex;
807 drawAttrs.BaseVertex = BaseVertex;
808 pCtx->DrawIndexed(drawAttrs);
818809 }
819810 else
820811 {
821 GLTFNodeRenderInfo NodeRI;
822 NodeRI.MaterialId = primitive.MaterialId;
823 NodeRI.pTransformData = &Node.Mesh->Transforms;
824 NodeRI.IndexType = primitive.HasIndices() ? VT_UINT32 : VT_UNDEFINED;
825 NodeRI.BaseVertex = BaseVertex;
826
827 if (primitive.HasIndices())
828 {
829 NodeRI.IndexCount = primitive.IndexCount;
830 NodeRI.FirstIndex = FirstIndexLocation + primitive.FirstIndex;
831 }
832 else
833 {
834 NodeRI.VertexCount = primitive.VertexCount;
835 }
836
837 RenderNodeCallback(NodeRI);
812 DrawAttribs drawAttrs{primitive.VertexCount, DRAW_FLAG_VERIFY_ALL};
813 drawAttrs.StartVertexLocation = BaseVertex;
814 pCtx->Draw(drawAttrs);
838815 }
839816 }
840817 }
851828 MapHelper<float4x4> pJoints{pCtx, m_JointsBuffer, MAP_WRITE, MAP_FLAG_DISCARD};
852829 }
853830
854 void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx,
855 GLTF::Model& GLTFModel,
856 const RenderInfo& RenderParams,
857 const ModelResourceBindings& ResourceBindings,
858 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback)
831 void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx,
832 GLTF::Model& GLTFModel,
833 const RenderInfo& RenderParams,
834 const ModelResourceBindings& ResourceBindings)
859835 {
860836 DEV_CHECK_ERR(ResourceBindings.MaterialSRB.size() == GLTFModel.Materials.size(),
861837 "The number of material shader resource bindings is not consistent with the number of materials");
862838
863839 m_RenderParams = RenderParams;
864840
865 if (RenderNodeCallback == nullptr)
866 {
867 std::array<Uint32, 2> Offsets = {};
868 std::array<IBuffer*, 2> pVBs =
869 {
870 GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_VERTEX0, nullptr, nullptr),
871 GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_VERTEX1, nullptr, nullptr) //
872 };
873 pCtx->SetVertexBuffers(0, static_cast<Uint32>(pVBs.size()), pVBs.data(), Offsets.data(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION, SET_VERTEX_BUFFERS_FLAG_RESET);
874
875 if (auto* pIndexBuffer = GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_INDEX, nullptr, nullptr))
876 {
877 pCtx->SetIndexBuffer(pIndexBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
878 }
879 }
880 else
881 {
882 // An application should bind index buffers and PSOs
841 std::array<Uint32, 2> Offsets = {};
842 std::array<IBuffer*, 2> pVBs =
843 {
844 GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_VERTEX0, nullptr, nullptr),
845 GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_VERTEX1, nullptr, nullptr) //
846 };
847 pCtx->SetVertexBuffers(0, static_cast<Uint32>(pVBs.size()), pVBs.data(), Offsets.data(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION, SET_VERTEX_BUFFERS_FLAG_RESET);
848
849 if (auto* pIndexBuffer = GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_INDEX, nullptr, nullptr))
850 {
851 pCtx->SetIndexBuffer(pIndexBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
883852 }
884853
885854 GLTFNodeRenderer NodeRenderer //
889858 GLTFModel,
890859 RenderParams,
891860 ResourceBindings,
892 RenderNodeCallback,
893861 GLTFModel.GetFirstIndexLocation(),
894862 GLTFModel.GetBaseVertex() //
895863 };
896864
897 // Opaque primitives first
898 if (RenderParams.AlphaModes & RenderInfo::ALPHA_MODE_FLAG_OPAQUE)
899 {
900 for (const auto& node : GLTFModel.Nodes)
901 {
902 NodeRenderer.Render(*node, GLTF::Material::ALPHAMODE_OPAQUE);
903 }
904 }
905
906
907 // Alpha masked primitives
908 if (RenderParams.AlphaModes & RenderInfo::ALPHA_MODE_FLAG_MASK)
909 {
910 for (const auto& node : GLTFModel.Nodes)
911 {
912 NodeRenderer.Render(*node, GLTF::Material::ALPHAMODE_MASK);
913 }
914 }
915
916
917 // Transparent primitives
918 // TODO: Correct depth sorting
919 if (RenderParams.AlphaModes & RenderInfo::ALPHA_MODE_FLAG_BLEND)
920 {
921 for (const auto& node : GLTFModel.Nodes)
922 {
923 NodeRenderer.Render(*node, GLTF::Material::ALPHAMODE_BLEND);
865 for (auto AlphaMode : {
866 GLTF::Material::ALPHA_MODE_OPAQUE, // Opaque primitives - first
867 GLTF::Material::ALPHA_MODE_MASK, // Alpha-masked primitives - second
868 GLTF::Material::ALPHA_MODE_BLEND, // Transparent primitives - last (TODO: depth sorting)
869 })
870 {
871 if (RenderParams.AlphaModes & (1 << AlphaMode))
872 {
873 for (const auto& node : GLTFModel.Nodes)
874 {
875 NodeRenderer.Render(*node, AlphaMode);
876 }
924877 }
925878 }
926879 }