git.s-ol.nu ~forks/DiligentFX / 5521f3f
GLTF PBR renderer: updates to match refactored material textures handling assiduous 10 months ago
2 changed file(s) with 131 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
241241
242242 /// Creates a shader resource binding for the given material.
243243
244 /// \param [in] Model - GLTF model that keeps material textures.
244245 /// \param [in] Material - GLTF material to create SRB for.
245246 /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB.
246247 /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB.
252253 /// An application may use this type to differentiate e.g. shadow-pass SRBs
253254 /// from color-pass SRBs.
254255 /// \return Created shader resource binding.
255 IShaderResourceBinding* CreateMaterialSRB(GLTF::Material& Material,
256 IShaderResourceBinding* CreateMaterialSRB(GLTF::Model& Model,
257 GLTF::Material& Material,
256258 IBuffer* pCameraAttribs,
257259 IBuffer* pLightAttribs,
258260 IPipelineState* pPSO = nullptr,
374376 RefCntAutoPtr<IBuffer> m_TransformsCB;
375377 RefCntAutoPtr<IBuffer> m_GLTFAttribsCB;
376378 RefCntAutoPtr<IBuffer> m_PrecomputeEnvMapAttribsCB;
379
380 struct GLTFNodeRenderer
381 {
382 GLTF_PBR_Renderer& Renderer;
383 IDeviceContext* const pCtx;
384 GLTF::Model& GLTFModel;
385 const RenderInfo& RenderParams;
386 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback;
387 const size_t SRBTypeId;
388
389 void Render(const GLTF::Node& Node,
390 GLTF::Material::ALPHA_MODE AlphaMode);
391 };
377392 };
378393
379394 DEFINE_FLAG_ENUM_OPERATORS(GLTF_PBR_Renderer::RenderInfo::ALPHA_MODE_FLAGS);
383383 }
384384 }
385385
386 IShaderResourceBinding* GLTF_PBR_Renderer::CreateMaterialSRB(GLTF::Material& Material,
386 IShaderResourceBinding* GLTF_PBR_Renderer::CreateMaterialSRB(GLTF::Model& Model,
387 GLTF::Material& Material,
387388 IBuffer* pCameraAttribs,
388389 IBuffer* pLightAttribs,
389390 IPipelineState* pPSO,
419420 pPrefilteredEnvMap->Set(m_pPrefilteredEnvMapSRV);
420421 }
421422
422 auto SetTexture = [&](ITexture* pTexture, ITextureView* pDefaultTexSRV, const char* VarName) //
423 {
424 ITextureView* pTexSRV = pTexture != nullptr ? pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE) : pDefaultTexSRV;
423 auto SetTexture = [&](GLTF::Material::TEXTURE_ID TexId, ITextureView* pDefaultTexSRV, const char* VarName) //
424 {
425 ITextureView* pTexSRV = nullptr;
426
427 auto TexIdx = Material.Textures[TexId].Index;
428 if (TexIdx >= 0)
429 {
430 if (auto* pTexture = Model.GetTexture(TexIdx))
431 pTexSRV = pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
432 }
433
434 if (pTexSRV == nullptr)
435 pTexSRV = pDefaultTexSRV;
436
425437 if (auto* pVar = pSRB->GetVariableByName(SHADER_TYPE_PIXEL, VarName))
426438 pVar->Set(pTexSRV);
427439 };
428440
429 ITexture* pBaseColorTex = nullptr;
430 ITexture* pPhysDescTex = nullptr;
441 GLTF::Material::TEXTURE_ID BaseColorTexId = GLTF::Material::TEXTURE_ID_BASE_COLOR;
442 GLTF::Material::TEXTURE_ID PhysDescTexId = GLTF::Material::TEXTURE_ID_METALL_ROUGHNESS;
431443 if (Material.workflow == GLTF::Material::PbrWorkflow::MetallicRoughness)
432444 {
433 pBaseColorTex = Material.pBaseColorTexture;
434 pPhysDescTex = Material.pMetallicRoughnessTexture;
435445 }
436446 else if (Material.workflow == GLTF::Material::PbrWorkflow::SpecularGlossiness)
437447 {
438 pBaseColorTex = Material.extension.pDiffuseTexture;
439 pPhysDescTex = Material.extension.pSpecularGlossinessTexture;
440 }
441
442 // clang-format off
443 SetTexture(pBaseColorTex, m_pWhiteTexSRV, "g_ColorMap");
444 SetTexture(pPhysDescTex , m_pWhiteTexSRV, "g_PhysicalDescriptorMap");
445 SetTexture(Material.pNormalTexture, m_pDefaultNormalMapSRV, "g_NormalMap");
446 // clang-format on
448 BaseColorTexId = GLTF::Material::TEXTURE_ID_DIFFUSE;
449 PhysDescTexId = GLTF::Material::TEXTURE_ID_SPEC_GLOSS;
450 }
451 else
452 {
453 UNEXPECTED("Unexpected workflow");
454 }
455
456 SetTexture(BaseColorTexId, m_pWhiteTexSRV, "g_ColorMap");
457 SetTexture(PhysDescTexId, m_pWhiteTexSRV, "g_PhysicalDescriptorMap");
458 SetTexture(GLTF::Material::TEXTURE_ID_NORMAL_MAP, m_pDefaultNormalMapSRV, "g_NormalMap");
447459 if (m_Settings.UseAO)
448460 {
449 SetTexture(Material.pOcclusionTexture, m_pWhiteTexSRV, "g_AOMap");
461 SetTexture(GLTF::Material::TEXTURE_ID_OCCLUSION, m_pWhiteTexSRV, "g_AOMap");
450462 }
451463 if (m_Settings.UseEmissive)
452464 {
453 SetTexture(Material.pEmissiveTexture, m_pBlackTexSRV, "g_EmissiveMap");
465 SetTexture(GLTF::Material::TEXTURE_ID_EMISSIVE, m_pBlackTexSRV, "g_EmissiveMap");
454466 }
455467
456468
729741 {
730742 for (auto& mat : GLTFModel.Materials)
731743 {
732 CreateMaterialSRB(mat, pCameraAttribs, pLightAttribs);
744 CreateMaterialSRB(GLTFModel, mat, pCameraAttribs, pLightAttribs);
733745 }
734746 }
735747
743755 }
744756
745757
746 void GLTF_PBR_Renderer::RenderGLTFNode(IDeviceContext* pCtx,
747 const GLTF::Node* node,
748 GLTF::Material::ALPHA_MODE AlphaMode,
749 const float4x4& ModelTransform,
750 std::function<void(const GLTFNodeRenderInfo&)> RenderNodeCallback,
751 size_t SRBTypeId)
758 void GLTF_PBR_Renderer::GLTFNodeRenderer::Render(const GLTF::Node& Node,
759 GLTF::Material::ALPHA_MODE AlphaMode)
752760 {
753 if (node->_Mesh)
761 if (Node._Mesh)
754762 {
755763 // Render mesh primitives
756 for (const auto& primitive : node->_Mesh->Primitives)
764 for (const auto& primitive : Node._Mesh->Primitives)
757765 {
758766 if (primitive->material.AlphaMode != AlphaMode)
759767 continue;
765773 const auto& material = primitive->material;
766774 if (RenderNodeCallback == nullptr)
767775 {
768 auto* pPSO = GetPSO(PSOKey{AlphaMode, material.DoubleSided});
776 auto* pPSO = Renderer.GetPSO(PSOKey{AlphaMode, material.DoubleSided});
769777 VERIFY_EXPR(pPSO != nullptr);
770778 pCtx->SetPipelineState(pPSO);
771779
772 pSRB = GetMaterialSRB(&material, SRBTypeId);
780 pSRB = Renderer.GetMaterialSRB(&material, SRBTypeId);
773781 if (pSRB == nullptr)
774782 {
775783 LOG_ERROR_MESSAGE("Unable to find SRB for GLTF material. Please call GLTF_PBR_Renderer::InitializeResourceBindings()");
786794 GLTFNodeShaderTransforms* pTransforms = nullptr;
787795 if (RenderNodeCallback == nullptr)
788796 {
789 pCtx->MapBuffer(m_TransformsCB, MAP_WRITE, MAP_FLAG_DISCARD, reinterpret_cast<PVoid&>(pTransforms));
797 pCtx->MapBuffer(Renderer.m_TransformsCB, MAP_WRITE, MAP_FLAG_DISCARD, reinterpret_cast<PVoid&>(pTransforms));
790798 }
791799 else
792800 {
793801 pTransforms = &NodeRI.ShaderTransforms;
794802 }
795803
796 pTransforms->NodeMatrix = node->_Mesh->Transforms.matrix * ModelTransform;
797 pTransforms->JointCount = node->_Mesh->Transforms.jointcount;
798 if (node->_Mesh->Transforms.jointcount != 0)
799 {
800 static_assert(sizeof(pTransforms->JointMatrix) == sizeof(node->_Mesh->Transforms.jointMatrix), "Incosistent sizes");
801 memcpy(pTransforms->JointMatrix, node->_Mesh->Transforms.jointMatrix, sizeof(node->_Mesh->Transforms.jointMatrix));
804 pTransforms->NodeMatrix = Node._Mesh->Transforms.matrix * RenderParams.ModelTransform;
805 pTransforms->JointCount = Node._Mesh->Transforms.jointcount;
806 if (Node._Mesh->Transforms.jointcount != 0)
807 {
808 static_assert(sizeof(pTransforms->JointMatrix) == sizeof(Node._Mesh->Transforms.jointMatrix), "Incosistent sizes");
809 memcpy(pTransforms->JointMatrix, Node._Mesh->Transforms.jointMatrix, sizeof(Node._Mesh->Transforms.jointMatrix));
802810 }
803811
804812 if (RenderNodeCallback == nullptr)
805813 {
806 pCtx->UnmapBuffer(m_TransformsCB, MAP_WRITE);
814 pCtx->UnmapBuffer(Renderer.m_TransformsCB, MAP_WRITE);
807815 }
808816 }
809817
816824 GLTFRendererShaderParameters RenderParameters;
817825 GLTFMaterialShaderInfo MaterialInfo;
818826 };
827 static_assert(sizeof(GLTFAttribs) <= 256, "Size of dynamic GLTFAttribs buffer exceeds 256 bytes. "
828 "It may be worth trying to reduce the size or just live with it.");
829
819830 GLTFAttribs* pGLTFAttribs = nullptr;
820 pCtx->MapBuffer(m_GLTFAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD, reinterpret_cast<PVoid&>(pGLTFAttribs));
831 pCtx->MapBuffer(Renderer.m_GLTFAttribsCB, MAP_WRITE, MAP_FLAG_DISCARD, reinterpret_cast<PVoid&>(pGLTFAttribs));
821832 pMaterialInfo = &pGLTFAttribs->MaterialInfo;
822833
823 auto& RenderParams = pGLTFAttribs->RenderParameters;
824
825 RenderParams.DebugViewType = static_cast<int>(m_RenderParams.DebugView);
826 RenderParams.OcclusionStrength = m_RenderParams.OcclusionStrength;
827 RenderParams.EmissionScale = m_RenderParams.EmissionScale;
828 RenderParams.AverageLogLum = m_RenderParams.AverageLogLum;
829 RenderParams.MiddleGray = m_RenderParams.MiddleGray;
830 RenderParams.WhitePoint = m_RenderParams.WhitePoint;
831 RenderParams.IBLScale = m_RenderParams.IBLScale;
832 RenderParams.PrefilteredCubeMipLevels = m_Settings.UseIBL ? static_cast<float>(m_pPrefilteredEnvMapSRV->GetTexture()->GetDesc().MipLevels) : 0.f;
834 auto& ShaderParams = pGLTFAttribs->RenderParameters;
835
836 ShaderParams.DebugViewType = static_cast<int>(Renderer.m_RenderParams.DebugView);
837 ShaderParams.OcclusionStrength = Renderer.m_RenderParams.OcclusionStrength;
838 ShaderParams.EmissionScale = Renderer.m_RenderParams.EmissionScale;
839 ShaderParams.AverageLogLum = Renderer.m_RenderParams.AverageLogLum;
840 ShaderParams.MiddleGray = Renderer.m_RenderParams.MiddleGray;
841 ShaderParams.WhitePoint = Renderer.m_RenderParams.WhitePoint;
842 ShaderParams.IBLScale = Renderer.m_RenderParams.IBLScale;
843 ShaderParams.PrefilteredCubeMipLevels = Renderer.m_Settings.UseIBL ? static_cast<float>(Renderer.m_pPrefilteredEnvMapSRV->GetTexture()->GetDesc().MipLevels) : 0.f;
833844 }
834845 else
835846 {
838849
839850 pMaterialInfo->EmissiveFactor = material.EmissiveFactor;
840851
841 auto GetUVSelector = [](const ITexture* pTexture, Uint8 TexCoordSet) {
842 return pTexture != nullptr ? static_cast<float>(TexCoordSet) : -1;
852 pMaterialInfo->NormalTextureUVSelector = material.Textures[GLTF::Material::TEXTURE_ID_NORMAL_MAP].CoordSet;
853 pMaterialInfo->OcclusionTextureUVSelector = material.Textures[GLTF::Material::TEXTURE_ID_OCCLUSION].CoordSet;
854 pMaterialInfo->EmissiveTextureUVSelector = material.Textures[GLTF::Material::TEXTURE_ID_EMISSIVE].CoordSet;
855
856 pMaterialInfo->UseAlphaMask = material.AlphaMode == GLTF::Material::ALPHAMODE_MASK ? 1 : 0;
857 pMaterialInfo->AlphaMaskCutoff = material.AlphaCutoff;
858
859 auto GetUVScaleBias = [&](GLTF::Material::TEXTURE_ID TexId) //
860 {
861 auto TexIndex = material.Textures[TexId].Index;
862 return (TexIndex >= 0) ?
863 GLTFModel.Textures[TexIndex].UVScaleBias :
864 float4{1, 1, 0, 0};
843865 };
844866
845 pMaterialInfo->BaseColorTextureUVSelector = GetUVSelector(material.pBaseColorTexture, material.TexCoordSets.BaseColor);
846 pMaterialInfo->NormalTextureUVSelector = GetUVSelector(material.pNormalTexture, material.TexCoordSets.Normal);
847 pMaterialInfo->OcclusionTextureUVSelector = GetUVSelector(material.pOcclusionTexture, material.TexCoordSets.Occlusion);
848 pMaterialInfo->EmissiveTextureUVSelector = GetUVSelector(material.pEmissiveTexture, material.TexCoordSets.Emissive);
849 pMaterialInfo->UseAlphaMask = material.AlphaMode == GLTF::Material::ALPHAMODE_MASK ? 1 : 0;
850 pMaterialInfo->AlphaMaskCutoff = material.AlphaCutoff;
851
852 pMaterialInfo->BaseColorUVScaleBias = material.TexCoordSets.BaseColorScaleBias;
853 pMaterialInfo->NormalMapUVScaleBias = material.TexCoordSets.NormalScaleBias;
854 pMaterialInfo->OcclusionUVScaleBias = material.TexCoordSets.OcclusionScaleBias;
855 pMaterialInfo->EmissiveUVScaleBias = material.TexCoordSets.EmissiveScaleBias;
856
867 pMaterialInfo->NormalMapUVScaleBias = GetUVScaleBias(GLTF::Material::TEXTURE_ID_NORMAL_MAP);
868 pMaterialInfo->OcclusionUVScaleBias = GetUVScaleBias(GLTF::Material::TEXTURE_ID_OCCLUSION);
869 pMaterialInfo->EmissiveUVScaleBias = GetUVScaleBias(GLTF::Material::TEXTURE_ID_EMISSIVE);
870
871 GLTF::Material::TEXTURE_ID BaseColorTexId = GLTF::Material::TEXTURE_ID_BASE_COLOR;
872 GLTF::Material::TEXTURE_ID PhysDescTexId = GLTF::Material::TEXTURE_ID_METALL_ROUGHNESS;
857873 // TODO: glTF specs states that metallic roughness should be preferred, even if specular glosiness is present
858874 if (material.workflow == GLTF::Material::PbrWorkflow::MetallicRoughness)
859875 {
860876 // Metallic roughness workflow
861 pMaterialInfo->Workflow = PBR_WORKFLOW_METALLIC_ROUGHNESS;
862 pMaterialInfo->BaseColorFactor = material.BaseColorFactor;
863 pMaterialInfo->MetallicFactor = material.MetallicFactor;
864 pMaterialInfo->RoughnessFactor = material.RoughnessFactor;
865 pMaterialInfo->PhysicalDescriptorTextureUVSelector = GetUVSelector(material.pMetallicRoughnessTexture, material.TexCoordSets.MetallicRoughness);
866 pMaterialInfo->BaseColorTextureUVSelector = GetUVSelector(material.pBaseColorTexture, material.TexCoordSets.BaseColor);
867 pMaterialInfo->PhysicalDescriptorUVScaleBias = material.TexCoordSets.MetallicRoughnessScaleBias;
877 pMaterialInfo->Workflow = PBR_WORKFLOW_METALLIC_ROUGHNESS;
878 pMaterialInfo->MetallicFactor = material.MetallicFactor;
879 pMaterialInfo->RoughnessFactor = material.RoughnessFactor;
880 pMaterialInfo->BaseColorFactor = material.BaseColorFactor;
868881 }
869882 else if (material.workflow == GLTF::Material::PbrWorkflow::SpecularGlossiness)
870883 {
871884 // Specular glossiness workflow
872 pMaterialInfo->Workflow = PBR_WORKFLOW_SPECULAR_GLOSINESS;
873 pMaterialInfo->PhysicalDescriptorTextureUVSelector = GetUVSelector(material.extension.pSpecularGlossinessTexture, material.TexCoordSets.SpecularGlossiness);
874 pMaterialInfo->BaseColorTextureUVSelector = GetUVSelector(material.extension.pDiffuseTexture, material.TexCoordSets.BaseColor);
875 pMaterialInfo->BaseColorFactor = material.extension.DiffuseFactor;
876 pMaterialInfo->SpecularFactor = float4(material.extension.SpecularFactor, 1.0f);
877 pMaterialInfo->PhysicalDescriptorUVScaleBias = material.TexCoordSets.SpecularGlossinessScaleBias;
878 }
885 pMaterialInfo->Workflow = PBR_WORKFLOW_SPECULAR_GLOSINESS;
886 pMaterialInfo->SpecularFactor = material.SpecularFactor;
887 pMaterialInfo->BaseColorFactor = material.DiffuseFactor;
888
889 BaseColorTexId = GLTF::Material::TEXTURE_ID_DIFFUSE;
890 PhysDescTexId = GLTF::Material::TEXTURE_ID_SPEC_GLOSS;
891 }
892 else
893 {
894 UNEXPECTED("Unexpected workflow");
895 }
896
897 pMaterialInfo->BaseColorTextureUVSelector = material.Textures[BaseColorTexId].CoordSet;
898 pMaterialInfo->PhysicalDescriptorTextureUVSelector = material.Textures[PhysDescTexId].CoordSet;
899 pMaterialInfo->BaseColorUVScaleBias = GetUVScaleBias(BaseColorTexId);
900 pMaterialInfo->PhysicalDescriptorUVScaleBias = GetUVScaleBias(PhysDescTexId);
879901
880902 if (RenderNodeCallback == nullptr)
881903 {
882 pCtx->UnmapBuffer(m_GLTFAttribsCB, MAP_WRITE);
904 pCtx->UnmapBuffer(Renderer.m_GLTFAttribsCB, MAP_WRITE);
883905 }
884906 }
885907
917939 }
918940 }
919941
920 for (const auto& child : node->Children)
921 {
922 RenderGLTFNode(pCtx, child.get(), AlphaMode, ModelTransform, RenderNodeCallback, SRBTypeId);
942 for (const auto& child : Node.Children)
943 {
944 Render(*child, AlphaMode);
923945 }
924946 }
925947
946968 // An application should bind index buffers and PSOs
947969 }
948970
971 GLTFNodeRenderer NodeRenderer //
972 {
973 *this,
974 pCtx,
975 GLTFModel,
976 RenderParams,
977 RenderNodeCallback,
978 SRBTypeId //
979 };
949980
950981 // Opaque primitives first
951982 if (RenderParams.AlphaModes & RenderInfo::ALPHA_MODE_FLAG_OPAQUE)
952983 {
953984 for (const auto& node : GLTFModel.Nodes)
954985 {
955 RenderGLTFNode(pCtx, node.get(), GLTF::Material::ALPHAMODE_OPAQUE, RenderParams.ModelTransform, RenderNodeCallback, SRBTypeId);
986 NodeRenderer.Render(*node, GLTF::Material::ALPHAMODE_OPAQUE);
956987 }
957988 }
958989
962993 {
963994 for (const auto& node : GLTFModel.Nodes)
964995 {
965 RenderGLTFNode(pCtx, node.get(), GLTF::Material::ALPHAMODE_MASK, RenderParams.ModelTransform, RenderNodeCallback, SRBTypeId);
996 NodeRenderer.Render(*node, GLTF::Material::ALPHAMODE_MASK);
966997 }
967998 }
968999
9731004 {
9741005 for (const auto& node : GLTFModel.Nodes)
9751006 {
976 RenderGLTFNode(pCtx, node.get(), GLTF::Material::ALPHAMODE_BLEND, RenderParams.ModelTransform, RenderNodeCallback, SRBTypeId);
1007 NodeRenderer.Render(*node, GLTF::Material::ALPHAMODE_BLEND);
9771008 }
9781009 }
9791010 }