C API for GLTF_PBR_Renderer
s-ol
2 years ago
1 | 1 | |
2 | 2 | set(SOURCE |
3 | 3 | "${CMAKE_CURRENT_SOURCE_DIR}/src/GLTF_PBR_Renderer.cpp" |
4 | ) | |
5 | ||
6 | set(INTERFACE | |
7 | "${CMAKE_CURRENT_SOURCE_DIR}/interface/GLTF_PBR_Renderer.h" | |
4 | 8 | ) |
5 | 9 | |
6 | 10 | set(INCLUDE |
7 | "${CMAKE_CURRENT_SOURCE_DIR}/interface/GLTF_PBR_Renderer.hpp" | |
11 | "${CMAKE_CURRENT_SOURCE_DIR}/include/GLTF_PBR_Renderer.hpp" | |
8 | 12 | ) |
9 | 13 | |
10 | target_sources(DiligentFX PRIVATE ${SOURCE} ${INCLUDE}) | |
14 | target_sources(DiligentFX PRIVATE ${SOURCE} ${INCLUDE} ${INTERFACE}) | |
11 | 15 | |
12 | 16 | target_include_directories(DiligentFX |
13 | 17 | PUBLIC |
14 | "${CMAKE_CURRENT_SOURCE_DIR}/interface" | |
18 | interface | |
19 | PRIVATE | |
20 | include | |
15 | 21 | ) |
0 | /* | |
1 | * Copyright 2019-2021 Diligent Graphics LLC | |
2 | * Copyright 2015-2019 Egor Yusov | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | * | |
16 | * In no event and under no legal theory, whether in tort (including negligence), | |
17 | * contract, or otherwise, unless required by applicable law (such as deliberate | |
18 | * and grossly negligent acts) or agreed to in writing, shall any Contributor be | |
19 | * liable for any damages, including any direct, indirect, special, incidental, | |
20 | * or consequential damages of any character arising as a result of this License or | |
21 | * out of the use or inability to use the software (including but not limited to damages | |
22 | * for loss of goodwill, work stoppage, computer failure or malfunction, or any and | |
23 | * all other commercial damages or losses), even if such Contributor has been advised | |
24 | * of the possibility of such damages. | |
25 | */ | |
26 | ||
27 | #pragma once | |
28 | ||
29 | #include <unordered_map> | |
30 | #include <functional> | |
31 | #include <mutex> | |
32 | #include <vector> | |
33 | ||
34 | #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/DeviceContext.h" | |
35 | #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/RenderDevice.h" | |
36 | #include "../../../DiligentCore/Common/interface/HashUtils.hpp" | |
37 | #include "../../../DiligentTools/AssetLoader/include/GLTFLoader.hpp" | |
38 | #include "../interface/GLTF_PBR_Renderer.h" | |
39 | ||
40 | namespace Diligent | |
41 | { | |
42 | ||
43 | /// GLTF Model shader resource binding information | |
44 | struct GLTF_ModelResourceBindings | |
45 | { | |
46 | void Clear() | |
47 | { | |
48 | MaterialSRB.clear(); | |
49 | } | |
50 | ||
51 | GLTF_ModelResourceBindings() : MaterialSRB{} {} | |
52 | GLTF_ModelResourceBindings(const GLTF_ModelResourceBindings& o) : MaterialSRB{o.MaterialSRB} {}; | |
53 | ~GLTF_ModelResourceBindings() { MaterialSRB.~vector(); } | |
54 | ||
55 | union { | |
56 | /// Shader resource binding for every material | |
57 | std::vector<RefCntAutoPtr<IShaderResourceBinding>> MaterialSRB; | |
58 | ||
59 | Uint32 _spacer[8]; | |
60 | }; | |
61 | }; | |
62 | ||
63 | /// GLTF resource cache shader resource binding information | |
64 | struct GLTF_ResourceCacheBindings | |
65 | { | |
66 | /// Resource version | |
67 | Uint32 Version = 0; | |
68 | ||
69 | RefCntAutoPtr<IShaderResourceBinding> pSRB; | |
70 | }; | |
71 | ||
72 | #include "Shaders/GLTF_PBR/public/GLTF_PBR_Structures.fxh" | |
73 | ||
74 | /// Implementation of a GLTF PBR renderer | |
75 | class GLTF_PBR_Renderer : public IGLTF_PBR_Renderer | |
76 | { | |
77 | public: | |
78 | ||
79 | /// Initializes the renderer | |
80 | GLTF_PBR_Renderer(IRenderDevice* pDevice, | |
81 | IDeviceContext* pCtx, | |
82 | const GLTF_RendererCreateInfo& CI); | |
83 | ||
84 | /// Rendering information | |
85 | ||
86 | ||
87 | /// Renders a GLTF model. | |
88 | ||
89 | /// \param [in] pCtx - Device context to record rendering commands to. | |
90 | /// \param [in] GLTFModel - GLTF model to render. | |
91 | /// \param [in] RenderParams - Render parameters. | |
92 | /// \param [in] pModelBindings - The model's shader resource binding information. | |
93 | /// \param [in] pCacheBindings - Shader resource cache binding information, if the | |
94 | /// model has been created using the cache. | |
95 | virtual void Render(IDeviceContext* pCtx, | |
96 | IGLTFModel* GLTFModel, | |
97 | const GLTF_RenderInfo& RenderParams, | |
98 | GLTF_ModelResourceBindings* pModelBindings, | |
99 | GLTF_ResourceCacheBindings* pCacheBindings = nullptr) override final; | |
100 | ||
101 | /// Creates resource bindings for a given GLTF model | |
102 | virtual GLTF_ModelResourceBindings CreateResourceBindings(IGLTFModel* GLTFModel, | |
103 | IBuffer* pCameraAttribs, | |
104 | IBuffer* pLightAttribs) override final; | |
105 | ||
106 | /// Precompute cubemaps used by IBL. | |
107 | virtual void PrecomputeCubemaps(IRenderDevice* pDevice, | |
108 | IDeviceContext* pCtx, | |
109 | ITextureView* pEnvironmentMap) override final; | |
110 | ||
111 | // clang-format off | |
112 | virtual ITextureView* GetIrradianceCubeSRV() override final { return m_pIrradianceCubeSRV; } | |
113 | virtual ITextureView* GetPrefilteredEnvMapSRV() override final { return m_pPrefilteredEnvMapSRV; } | |
114 | virtual ITextureView* GetWhiteTexSRV() override final { return m_pWhiteTexSRV; } | |
115 | virtual ITextureView* GetBlackTexSRV() override final { return m_pBlackTexSRV; } | |
116 | virtual ITextureView* GetDefaultNormalMapSRV() override final { return m_pDefaultNormalMapSRV; } | |
117 | // clang-format on | |
118 | ||
119 | /// Creates a shader resource binding for the given material. | |
120 | ||
121 | /// \param [in] Model - GLTF model that keeps material textures. | |
122 | /// \param [in] Material - GLTF material to create SRB for. | |
123 | /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB. | |
124 | /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB. | |
125 | /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the | |
126 | /// default PSO. Can be null | |
127 | /// \param [out] ppMaterialSRB - Pointer to memory location where the pointer to the SRB object | |
128 | /// will be written. | |
129 | virtual void CreateMaterialSRB(IGLTFModel* Model, | |
130 | GLTF::Material& Material, | |
131 | IBuffer* pCameraAttribs, | |
132 | IBuffer* pLightAttribs, | |
133 | IPipelineState* pPSO, | |
134 | IShaderResourceBinding** ppMaterialSRB); // override final; | |
135 | ||
136 | ||
137 | /// Creates a shader resource binding for a GTLF resource cache. | |
138 | ||
139 | /// \param [in] pDevice - Render device that may be needed by the resource cache to create | |
140 | /// internal objects. | |
141 | /// \param [in] pCtx - Device context that may be needed by the resource cache to initialize | |
142 | /// internal objects. | |
143 | /// \param [in] CacheUseInfo - GLTF resource cache usage information. | |
144 | /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB. | |
145 | /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB. | |
146 | /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the | |
147 | /// default PSO. Can be null | |
148 | /// \param [out] ppCacheSRB - Pointer to memory location where the pointer to the SRB object | |
149 | /// will be written. | |
150 | virtual void CreateResourceCacheSRB(IRenderDevice* pDevice, | |
151 | IDeviceContext* pCtx, | |
152 | GLTF_ResourceCacheUseInfo& CacheUseInfo, | |
153 | IBuffer* pCameraAttribs, | |
154 | IBuffer* pLightAttribs, | |
155 | IPipelineState* pPSO, | |
156 | IShaderResourceBinding** ppCacheSRB) override final; | |
157 | ||
158 | /// Prepares the renderer for rendering objects. | |
159 | /// This method must be called at least once per frame. | |
160 | virtual void Begin(IDeviceContext* pCtx) override final; | |
161 | ||
162 | ||
163 | /// Prepares the renderer for rendering objects from the resource cache. | |
164 | /// This method must be called at least once per frame before the first object | |
165 | /// from the cache is rendered. | |
166 | virtual void BeginPSO(IRenderDevice* pDevice, | |
167 | IDeviceContext* pCtx, | |
168 | GLTF_ResourceCacheUseInfo& CacheUseInfo, | |
169 | GLTF_ResourceCacheBindings& Bindings, | |
170 | IBuffer* pCameraAttribs, | |
171 | IBuffer* pLightAttribs, | |
172 | IPipelineState* pPSO = nullptr) override final; | |
173 | ||
174 | private: | |
175 | void PrecomputeBRDF(IRenderDevice* pDevice, | |
176 | IDeviceContext* pCtx); | |
177 | ||
178 | void CreatePSO(IRenderDevice* pDevice); | |
179 | ||
180 | void InitCommonSRBVars(IShaderResourceBinding* pSRB, | |
181 | IBuffer* pCameraAttribs, | |
182 | IBuffer* pLightAttribs); | |
183 | ||
184 | struct PSOKey | |
185 | { | |
186 | PSOKey() noexcept {}; | |
187 | PSOKey(GLTF_MAT_ALPHA_MODE _AlphaMode, bool _DoubleSided) : | |
188 | AlphaMode{_AlphaMode}, | |
189 | DoubleSided{_DoubleSided} | |
190 | {} | |
191 | ||
192 | bool operator==(const PSOKey& rhs) const | |
193 | { | |
194 | return AlphaMode == rhs.AlphaMode && DoubleSided == rhs.DoubleSided; | |
195 | } | |
196 | bool operator!=(const PSOKey& rhs) const | |
197 | { | |
198 | return AlphaMode != rhs.AlphaMode || DoubleSided != rhs.DoubleSided; | |
199 | } | |
200 | ||
201 | GLTF_MAT_ALPHA_MODE AlphaMode = GLTF_MAT_ALPHA_MODE_OPAQUE; | |
202 | bool DoubleSided = false; | |
203 | }; | |
204 | ||
205 | static size_t GetPSOIdx(const PSOKey& Key) | |
206 | { | |
207 | size_t PSOIdx; | |
208 | ||
209 | PSOIdx = Key.AlphaMode == GLTF_MAT_ALPHA_MODE_BLEND ? 1 : 0; | |
210 | PSOIdx = PSOIdx * 2 + (Key.DoubleSided ? 1 : 0); | |
211 | return PSOIdx; | |
212 | } | |
213 | ||
214 | void AddPSO(const PSOKey& Key, RefCntAutoPtr<IPipelineState> pPSO) | |
215 | { | |
216 | auto Idx = GetPSOIdx(Key); | |
217 | if (Idx >= m_PSOCache.size()) | |
218 | m_PSOCache.resize(Idx + 1); | |
219 | VERIFY_EXPR(!m_PSOCache[Idx]); | |
220 | m_PSOCache[Idx] = std::move(pPSO); | |
221 | } | |
222 | ||
223 | IPipelineState* GetPSO(const PSOKey& Key) | |
224 | { | |
225 | auto Idx = GetPSOIdx(Key); | |
226 | VERIFY_EXPR(Idx < m_PSOCache.size()); | |
227 | return Idx < m_PSOCache.size() ? m_PSOCache[Idx].RawPtr() : nullptr; | |
228 | } | |
229 | ||
230 | const GLTF_RendererCreateInfo m_Settings; | |
231 | ||
232 | static constexpr Uint32 BRDF_LUT_Dim = 512; | |
233 | RefCntAutoPtr<ITextureView> m_pBRDF_LUT_SRV; | |
234 | ||
235 | std::vector<RefCntAutoPtr<IPipelineState>> m_PSOCache; | |
236 | ||
237 | RefCntAutoPtr<ITextureView> m_pWhiteTexSRV; | |
238 | RefCntAutoPtr<ITextureView> m_pBlackTexSRV; | |
239 | RefCntAutoPtr<ITextureView> m_pDefaultNormalMapSRV; | |
240 | RefCntAutoPtr<ITextureView> m_pDefaultPhysDescSRV; | |
241 | ||
242 | ||
243 | static constexpr TEXTURE_FORMAT IrradianceCubeFmt = TEX_FORMAT_RGBA32_FLOAT; | |
244 | static constexpr TEXTURE_FORMAT PrefilteredEnvMapFmt = TEX_FORMAT_RGBA16_FLOAT; | |
245 | static constexpr Uint32 IrradianceCubeDim = 64; | |
246 | static constexpr Uint32 PrefilteredEnvMapDim = 256; | |
247 | ||
248 | RefCntAutoPtr<ITextureView> m_pIrradianceCubeSRV; | |
249 | RefCntAutoPtr<ITextureView> m_pPrefilteredEnvMapSRV; | |
250 | RefCntAutoPtr<IPipelineState> m_pPrecomputeIrradianceCubePSO; | |
251 | RefCntAutoPtr<IPipelineState> m_pPrefilterEnvMapPSO; | |
252 | RefCntAutoPtr<IShaderResourceBinding> m_pPrecomputeIrradianceCubeSRB; | |
253 | RefCntAutoPtr<IShaderResourceBinding> m_pPrefilterEnvMapSRB; | |
254 | ||
255 | GLTF_RenderInfo m_RenderParams; | |
256 | ||
257 | RefCntAutoPtr<IBuffer> m_TransformsCB; | |
258 | RefCntAutoPtr<IBuffer> m_GLTFAttribsCB; | |
259 | RefCntAutoPtr<IBuffer> m_PrecomputeEnvMapAttribsCB; | |
260 | RefCntAutoPtr<IBuffer> m_JointsBuffer; | |
261 | }; | |
262 | ||
263 | DEFINE_FLAG_ENUM_OPERATORS(ALPHA_MODE_FLAGS) | |
264 | ||
265 | } // namespace Diligent |
0 | /* | |
1 | * Copyright 2019-2021 Diligent Graphics LLC | |
2 | * Copyright 2015-2019 Egor Yusov | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | * | |
16 | * In no event and under no legal theory, whether in tort (including negligence), | |
17 | * contract, or otherwise, unless required by applicable law (such as deliberate | |
18 | * and grossly negligent acts) or agreed to in writing, shall any Contributor be | |
19 | * liable for any damages, including any direct, indirect, special, incidental, | |
20 | * or consequential damages of any character arising as a result of this License or | |
21 | * out of the use or inability to use the software (including but not limited to damages | |
22 | * for loss of goodwill, work stoppage, computer failure or malfunction, or any and | |
23 | * all other commercial damages or losses), even if such Contributor has been advised | |
24 | * of the possibility of such damages. | |
25 | */ | |
26 | ||
27 | #pragma once | |
28 | ||
29 | #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/DeviceContext.h" | |
30 | #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/RenderDevice.h" | |
31 | #include "../../../DiligentTools/AssetLoader/interface/GLTFLoader.h" | |
32 | ||
33 | DILIGENT_BEGIN_NAMESPACE(Diligent) | |
34 | ||
35 | #if DILIGENT_CPP_INTERFACE | |
36 | using namespace Diligent::GLTF; | |
37 | #endif | |
38 | ||
39 | /// Renderer create info | |
40 | struct GLTF_RendererCreateInfo | |
41 | { | |
42 | /// Render target format. | |
43 | TEXTURE_FORMAT RTVFmt DEFAULT_INITIALIZER(TEX_FORMAT_UNKNOWN); | |
44 | ||
45 | /// Depth-buffer format. | |
46 | ||
47 | /// \note If both RTV and DSV formats are TEX_FORMAT_UNKNOWN, | |
48 | /// the renderer will not initialize PSO, uniform buffers and other | |
49 | /// resources. It is expected that an application will use custom | |
50 | /// render callback function. | |
51 | TEXTURE_FORMAT DSVFmt DEFAULT_INITIALIZER(TEX_FORMAT_UNKNOWN); | |
52 | ||
53 | /// Indicates if front face is CCW. | |
54 | bool FrontCCW DEFAULT_INITIALIZER(false); | |
55 | ||
56 | /// Indicates if the renderer should allow debug views. | |
57 | /// Rendering with debug views disabled is more efficient. | |
58 | bool AllowDebugView DEFAULT_INITIALIZER(false); | |
59 | ||
60 | /// Indicates whether to use IBL. | |
61 | bool UseIBL DEFAULT_INITIALIZER(false); | |
62 | ||
63 | /// Whether to use ambient occlusion texture. | |
64 | bool UseAO DEFAULT_INITIALIZER(true); | |
65 | ||
66 | /// Whether to use emissive texture. | |
67 | bool UseEmissive DEFAULT_INITIALIZER(true); | |
68 | ||
69 | /// When set to true, pipeline state will be compiled with immutable samplers. | |
70 | /// When set to false, samplers from the texture views will be used. | |
71 | bool UseImmutableSamplers DEFAULT_INITIALIZER(true); | |
72 | ||
73 | /// Whether to use texture atlas (e.g. apply UV transforms when sampling textures). | |
74 | bool UseTextureAtals DEFAULT_INITIALIZER(false); | |
75 | ||
76 | #if DILIGENT_CPP_INTERFACE | |
77 | static const SamplerDesc DefaultSampler; | |
78 | #endif | |
79 | ||
80 | /// Immutable sampler for color map texture. | |
81 | SamplerDesc ColorMapImmutableSampler DEFAULT_INITIALIZER(DefaultSampler); | |
82 | ||
83 | /// Immutable sampler for physical description map texture. | |
84 | SamplerDesc PhysDescMapImmutableSampler DEFAULT_INITIALIZER(DefaultSampler); | |
85 | ||
86 | /// Immutable sampler for normal map texture. | |
87 | SamplerDesc NormalMapImmutableSampler DEFAULT_INITIALIZER(DefaultSampler); | |
88 | ||
89 | /// Immutable sampler for AO texture. | |
90 | SamplerDesc AOMapImmutableSampler DEFAULT_INITIALIZER(DefaultSampler); | |
91 | ||
92 | /// Immutable sampler for emissive map texture. | |
93 | SamplerDesc EmissiveMapImmutableSampler DEFAULT_INITIALIZER(DefaultSampler); | |
94 | ||
95 | /// Maximum number of joints | |
96 | Uint32 MaxJointCount DEFAULT_INITIALIZER(64); | |
97 | ||
98 | // Geometry Shader | |
99 | IShader* pGS DEFAULT_INITIALIZER(nullptr); | |
100 | }; | |
101 | typedef struct GLTF_RendererCreateInfo GLTF_RendererCreateInfo; | |
102 | ||
103 | /// Alpha mode flags | |
104 | DILIGENT_TYPED_ENUM(ALPHA_MODE_FLAGS, Uint32) | |
105 | { | |
106 | /// Render nothing | |
107 | ALPHA_MODE_FLAG_NONE = 0, | |
108 | ||
109 | /// Render opaque matetrials | |
110 | ALPHA_MODE_FLAG_OPAQUE = 1 << GLTF_MAT_ALPHA_MODE_OPAQUE, | |
111 | ||
112 | /// Render alpha-masked matetrials | |
113 | ALPHA_MODE_FLAG_MASK = 1 << GLTF_MAT_ALPHA_MODE_MASK, | |
114 | ||
115 | /// Render alpha-blended matetrials | |
116 | ALPHA_MODE_FLAG_BLEND = 1 << GLTF_MAT_ALPHA_MODE_BLEND, | |
117 | ||
118 | /// Render all materials | |
119 | ALPHA_MODE_FLAG_ALL = ALPHA_MODE_FLAG_OPAQUE | ALPHA_MODE_FLAG_MASK | ALPHA_MODE_FLAG_BLEND | |
120 | }; | |
121 | ||
122 | /// Debug view type | |
123 | DILIGENT_TYPED_ENUM(DEBUG_VIEW_TYPE, int) | |
124 | { | |
125 | DEBUG_VIEW_TYPE_NONE = 0, | |
126 | DEBUG_VIEW_TYPE_BASE_COLOR = 1, | |
127 | DEBUG_VIEW_TYPE_TRANSPARENCY = 2, | |
128 | DEBUG_VIEW_TYPE_NORMAL_MAP = 3, | |
129 | DEBUG_VIEW_TYPE_OCCLUSION = 4, | |
130 | DEBUG_VIEW_TYPE_EMISSIVE = 5, | |
131 | DEBUG_VIEW_TYPE_METALLIC = 6, | |
132 | DEBUG_VIEW_TYPE_ROUGHNESS = 7, | |
133 | DEBUG_VIEW_TYPE_DIFFUSE_COLOR = 8, | |
134 | DEBUG_VIEW_TYPE_SPECULAR_COLOR = 9, | |
135 | DEBUG_VIEW_TYPE_REFLECTANCE_90 = 10, | |
136 | DEBUG_VIEW_TYPE_MESH_NORMAL = 11, | |
137 | DEBUG_VIEW_TYPE_PERTURBED_NORMAL = 12, | |
138 | DEBUG_VIEW_TYPE_N_DOT_V = 13, | |
139 | DEBUG_VIEW_TYPE_DIFFUSE_IBL = 14, | |
140 | DEBUG_VIEW_TYPE_SPECULAR_IBL = 15, | |
141 | DEBUG_VIEW_TYPE_NUM, | |
142 | }; | |
143 | ||
144 | /// Rendering information | |
145 | struct GLTF_RenderInfo | |
146 | { | |
147 | /// Model transform matrix | |
148 | float ModelTransform[16] | |
149 | #if DILIGENT_CPP_INTERFACE | |
150 | = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 } | |
151 | #endif | |
152 | ; | |
153 | ||
154 | /// Flag indicating which alpha modes to render | |
155 | ALPHA_MODE_FLAGS AlphaModes DEFAULT_INITIALIZER(ALPHA_MODE_FLAG_ALL); | |
156 | ||
157 | DEBUG_VIEW_TYPE DebugView DEFAULT_INITIALIZER(DEBUG_VIEW_TYPE_NONE); | |
158 | ||
159 | /// Ambient occlusion strength | |
160 | float OcclusionStrength DEFAULT_INITIALIZER(1); | |
161 | ||
162 | /// Emission scale | |
163 | float EmissionScale DEFAULT_INITIALIZER(1); | |
164 | ||
165 | /// IBL scale | |
166 | float IBLScale DEFAULT_INITIALIZER(1); | |
167 | ||
168 | /// Average log luminance used by tone mapping | |
169 | float AverageLogLum DEFAULT_INITIALIZER(0.3f); | |
170 | ||
171 | /// Middle gray value used by tone mapping | |
172 | float MiddleGray DEFAULT_INITIALIZER(0.18f); | |
173 | ||
174 | /// White point value used by tone mapping | |
175 | float WhitePoint DEFAULT_INITIALIZER(3.f); | |
176 | }; | |
177 | typedef struct GLTF_RenderInfo GLTF_RenderInfo; | |
178 | ||
179 | struct GLTF_ModelResourceBindings; | |
180 | typedef struct GLTF_ModelResourceBindings GLTF_ModelResourceBindings; | |
181 | ||
182 | #if DILIGENT_C_INTERFACE | |
183 | struct GLTF_ModelResourceBindings { | |
184 | Uint32 _spacer[8]; | |
185 | }; | |
186 | #endif | |
187 | ||
188 | struct GLTF_ResourceCacheBindings; | |
189 | typedef struct GLTF_ResourceCacheBindings GLTF_ResourceCacheBindings; | |
190 | ||
191 | #define DILIGENT_INTERFACE_NAME IGLTF_PBR_Renderer | |
192 | #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" | |
193 | ||
194 | #define IGLTF_PBR_RendererInclusiveMethods \ | |
195 | IGLTF_PBR_RendererMethods GLTF_PBR_Renderer | |
196 | ||
197 | // clang-format off | |
198 | ||
199 | /// Implementation of a GLTF PBR renderer | |
200 | DILIGENT_BEGIN_INTERFACE1(IGLTF_PBR_Renderer) | |
201 | { | |
202 | /// Renders a GLTF model. | |
203 | ||
204 | /// \param [in] pCtx - Device context to record rendering commands to. | |
205 | /// \param [in] GLTFModel - GLTF model to render. | |
206 | /// \param [in] RenderParams - Render parameters. | |
207 | /// \param [in] pModelBindings - The model's shader resource binding information. | |
208 | /// \param [in] pCacheBindings - Shader resource cache binding information, if the | |
209 | /// model has been created using the cache. | |
210 | VIRTUAL void METHOD(Render)(THIS_ | |
211 | IDeviceContext* pCtx, | |
212 | IGLTFModel* GLTFModel, | |
213 | const GLTF_RenderInfo REF RenderParams, | |
214 | GLTF_ModelResourceBindings* pModelBindings, | |
215 | GLTF_ResourceCacheBindings* pCacheBindings) PURE; | |
216 | ||
217 | /// Creates resource bindings for a given GLTF model | |
218 | VIRTUAL GLTF_ModelResourceBindings METHOD(CreateResourceBindings)(THIS_ | |
219 | IGLTFModel* GLTFModel, | |
220 | IBuffer* pCameraAttribs, | |
221 | IBuffer* pLightAttribs) PURE; | |
222 | ||
223 | /// Precompute cubemaps used by IBL. | |
224 | VIRTUAL void METHOD(PrecomputeCubemaps)(THIS_ | |
225 | IRenderDevice* pDevice, | |
226 | IDeviceContext* pCtx, | |
227 | ITextureView* pEnvironmentMap) PURE; | |
228 | ||
229 | // clang-format off | |
230 | VIRTUAL ITextureView* METHOD(GetIrradianceCubeSRV)(THIS) PURE; | |
231 | VIRTUAL ITextureView* METHOD(GetPrefilteredEnvMapSRV)(THIS) PURE; | |
232 | VIRTUAL ITextureView* METHOD(GetWhiteTexSRV)(THIS) PURE; | |
233 | VIRTUAL ITextureView* METHOD(GetBlackTexSRV)(THIS) PURE; | |
234 | VIRTUAL ITextureView* METHOD(GetDefaultNormalMapSRV)(THIS) PURE; | |
235 | // clang-format on | |
236 | ||
237 | /* | |
238 | /// Creates a shader resource binding for the given material. | |
239 | ||
240 | /// \param [in] Model - GLTF model that keeps material textures. | |
241 | /// \param [in] Material - GLTF material to create SRB for. | |
242 | /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB. | |
243 | /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB. | |
244 | /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the | |
245 | /// default PSO. Can be null | |
246 | /// \param [out] ppMaterialSRB - Pointer to memory location where the pointer to the SRB object | |
247 | /// will be written. | |
248 | VIRTUAL void METHOD(CreateMaterialSRB)(THIS_ | |
249 | IGLTFModel* Model, | |
250 | GLTF_Material REF Material, | |
251 | IBuffer* pCameraAttribs, | |
252 | IBuffer* pLightAttribs, | |
253 | IPipelineState* pPSO, | |
254 | IShaderResourceBinding** ppMaterialSRB) PURE; | |
255 | */ | |
256 | ||
257 | ||
258 | /// Creates a shader resource binding for a GTLF resource cache. | |
259 | ||
260 | /// \param [in] pDevice - Render device that may be needed by the resource cache to create | |
261 | /// internal objects. | |
262 | /// \param [in] pCtx - Device context that may be needed by the resource cache to initialize | |
263 | /// internal objects. | |
264 | /// \param [in] CacheUseInfo - GLTF resource cache usage information. | |
265 | /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB. | |
266 | /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB. | |
267 | /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the | |
268 | /// default PSO. Can be null | |
269 | /// \param [out] ppCacheSRB - Pointer to memory location where the pointer to the SRB object | |
270 | /// will be written. | |
271 | VIRTUAL void METHOD(CreateResourceCacheSRB)(THIS_ | |
272 | IRenderDevice* pDevice, | |
273 | IDeviceContext* pCtx, | |
274 | GLTF_ResourceCacheUseInfo REF CacheUseInfo, | |
275 | IBuffer* pCameraAttribs, | |
276 | IBuffer* pLightAttribs, | |
277 | IPipelineState* pPSO, | |
278 | IShaderResourceBinding** ppCacheSRB) PURE; | |
279 | ||
280 | /// Prepares the renderer for rendering objects. | |
281 | /// This method must be called at least once per frame. | |
282 | VIRTUAL void METHOD(Begin)(THIS_ | |
283 | IDeviceContext* pCtx) PURE; | |
284 | ||
285 | ||
286 | /// Prepares the renderer for rendering objects from the resource cache. | |
287 | /// This method must be called at least once per frame before the first object | |
288 | /// from the cache is rendered. | |
289 | VIRTUAL void METHOD(BeginPSO)(THIS_ | |
290 | IRenderDevice* pDevice, | |
291 | IDeviceContext* pCtx, | |
292 | GLTF_ResourceCacheUseInfo REF CacheUseInfo, | |
293 | GLTF_ResourceCacheBindings REF Bindings, | |
294 | IBuffer* pCameraAttribs, | |
295 | IBuffer* pLightAttribs, | |
296 | IPipelineState* pPSO) PURE; | |
297 | }; | |
298 | DILIGENT_END_INTERFACE | |
299 | ||
300 | #include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" | |
301 | ||
302 | #if DILIGENT_C_INTERFACE | |
303 | ||
304 | # define IGLTF_PBR_Renderer_Render(This, ...) CALL_IFACE_METHOD(GLTF_PBR_Renderer, Render, This, __VA_ARGS__) | |
305 | # define IGLTF_PBR_Renderer_CreateResourceBindings(This, ...) CALL_IFACE_METHOD(GLTF_PBR_Renderer, CreateResourceBindings, This, __VA_ARGS__) | |
306 | # define IGLTF_PBR_Renderer_PrecomputeCubemaps(This, ...) CALL_IFACE_METHOD(GLTF_PBR_Renderer, PrecomputeCubemaps, This, __VA_ARGS__) | |
307 | # define IGLTF_PBR_Renderer_GetIrradianceCubeSRV(This) CALL_IFACE_METHOD(GLTF_PBR_Renderer, GetIrradianceCubeSRV, This) | |
308 | # define IGLTF_PBR_Renderer_GetPrefilteredEnvMapSRV(This) CALL_IFACE_METHOD(GLTF_PBR_Renderer, GetPrefilteredEnvMapSRV, This) | |
309 | # define IGLTF_PBR_Renderer_GetWhiteTexSRV(This) CALL_IFACE_METHOD(GLTF_PBR_Renderer, GetWhiteTexSRV, This) | |
310 | # define IGLTF_PBR_Renderer_GetBlackTexSRV(This) CALL_IFACE_METHOD(GLTF_PBR_Renderer, GetBlackTexSRV, This) | |
311 | # define IGLTF_PBR_Renderer_GetDefaultNormalMapSRV(This) CALL_IFACE_METHOD(GLTF_PBR_Renderer, GetDefaultNormalMapSRV, This) | |
312 | # define IGLTF_PBR_Renderer_CreateMaterialSRB(This, ...) CALL_IFACE_METHOD(GLTF_PBR_Renderer, CreateMaterialSRB, This, __VA_ARGS__) | |
313 | # define IGLTF_PBR_Renderer_CreateResourceCacheSRB(This, ...) CALL_IFACE_METHOD(GLTF_PBR_Renderer, CreateResourceCacheSRB, This, __VA_ARGS__) | |
314 | # define IGLTF_PBR_Renderer_Begin(This, ...) CALL_IFACE_METHOD(GLTF_PBR_Renderer, Begin, This, __VA_ARGS__) | |
315 | # define IGLTF_PBR_Renderer_BeginPSO(This, ...) CALL_IFACE_METHOD(GLTF_PBR_Renderer, BeginPSO, This, __VA_ARGS__) | |
316 | ||
317 | #endif | |
318 | ||
319 | // clang-format on | |
320 | ||
321 | /// Initializes the renderer | |
322 | API_QUALIFIER | |
323 | struct IGLTF_PBR_Renderer* DILIGENT_GLOBAL_FUNCTION(IGLTF_PBR_Renderer_Create)(IRenderDevice* pDevice, | |
324 | IDeviceContext* pCtx, | |
325 | const GLTF_RendererCreateInfo* CI); | |
326 | ||
327 | DILIGENT_END_NAMESPACE // namespace Diligent |
0 | /* | |
1 | * Copyright 2019-2021 Diligent Graphics LLC | |
2 | * Copyright 2015-2019 Egor Yusov | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | * | |
16 | * In no event and under no legal theory, whether in tort (including negligence), | |
17 | * contract, or otherwise, unless required by applicable law (such as deliberate | |
18 | * and grossly negligent acts) or agreed to in writing, shall any Contributor be | |
19 | * liable for any damages, including any direct, indirect, special, incidental, | |
20 | * or consequential damages of any character arising as a result of this License or | |
21 | * out of the use or inability to use the software (including but not limited to damages | |
22 | * for loss of goodwill, work stoppage, computer failure or malfunction, or any and | |
23 | * all other commercial damages or losses), even if such Contributor has been advised | |
24 | * of the possibility of such damages. | |
25 | */ | |
26 | ||
27 | #pragma once | |
28 | ||
29 | #include <unordered_map> | |
30 | #include <functional> | |
31 | #include <mutex> | |
32 | #include <vector> | |
33 | ||
34 | #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/DeviceContext.h" | |
35 | #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/RenderDevice.h" | |
36 | #include "../../../DiligentCore/Common/interface/HashUtils.hpp" | |
37 | #include "../../../DiligentTools/AssetLoader/interface/GLTFLoader.hpp" | |
38 | ||
39 | namespace Diligent | |
40 | { | |
41 | ||
42 | #include "Shaders/GLTF_PBR/public/GLTF_PBR_Structures.fxh" | |
43 | ||
44 | /// Implementation of a GLTF PBR renderer | |
45 | class GLTF_PBR_Renderer | |
46 | { | |
47 | public: | |
48 | /// Renderer create info | |
49 | struct CreateInfo | |
50 | { | |
51 | /// Render target format. | |
52 | TEXTURE_FORMAT RTVFmt = TEX_FORMAT_UNKNOWN; | |
53 | ||
54 | /// Depth-buffer format. | |
55 | ||
56 | /// \note If both RTV and DSV formats are TEX_FORMAT_UNKNOWN, | |
57 | /// the renderer will not initialize PSO, uniform buffers and other | |
58 | /// resources. It is expected that an application will use custom | |
59 | /// render callback function. | |
60 | TEXTURE_FORMAT DSVFmt = TEX_FORMAT_UNKNOWN; | |
61 | ||
62 | /// Indicates if front face is CCW. | |
63 | bool FrontCCW = false; | |
64 | ||
65 | /// Indicates if the renderer should allow debug views. | |
66 | /// Rendering with debug views disabled is more efficient. | |
67 | bool AllowDebugView = false; | |
68 | ||
69 | /// Indicates whether to use IBL. | |
70 | bool UseIBL = false; | |
71 | ||
72 | /// Whether to use ambient occlusion texture. | |
73 | bool UseAO = true; | |
74 | ||
75 | /// Whether to use emissive texture. | |
76 | bool UseEmissive = true; | |
77 | ||
78 | /// When set to true, pipeline state will be compiled with immutable samplers. | |
79 | /// When set to false, samplers from the texture views will be used. | |
80 | bool UseImmutableSamplers = true; | |
81 | ||
82 | /// Whether to use texture atlas (e.g. apply UV transforms when sampling textures). | |
83 | bool UseTextureAtals = false; | |
84 | ||
85 | static const SamplerDesc DefaultSampler; | |
86 | ||
87 | /// Immutable sampler for color map texture. | |
88 | SamplerDesc ColorMapImmutableSampler = DefaultSampler; | |
89 | ||
90 | /// Immutable sampler for physical description map texture. | |
91 | SamplerDesc PhysDescMapImmutableSampler = DefaultSampler; | |
92 | ||
93 | /// Immutable sampler for normal map texture. | |
94 | SamplerDesc NormalMapImmutableSampler = DefaultSampler; | |
95 | ||
96 | /// Immutable sampler for AO texture. | |
97 | SamplerDesc AOMapImmutableSampler = DefaultSampler; | |
98 | ||
99 | /// Immutable sampler for emissive map texture. | |
100 | SamplerDesc EmissiveMapImmutableSampler = DefaultSampler; | |
101 | ||
102 | /// Maximum number of joints | |
103 | Uint32 MaxJointCount = 64; | |
104 | }; | |
105 | ||
106 | /// Initializes the renderer | |
107 | GLTF_PBR_Renderer(IRenderDevice* pDevice, | |
108 | IDeviceContext* pCtx, | |
109 | const CreateInfo& CI); | |
110 | ||
111 | /// Rendering information | |
112 | struct RenderInfo | |
113 | { | |
114 | /// Model transform matrix | |
115 | float4x4 ModelTransform = float4x4::Identity(); | |
116 | ||
117 | /// Alpha mode flags | |
118 | enum ALPHA_MODE_FLAGS : Uint32 | |
119 | { | |
120 | /// Render nothing | |
121 | ALPHA_MODE_FLAG_NONE = 0, | |
122 | ||
123 | /// Render opaque matetrials | |
124 | ALPHA_MODE_FLAG_OPAQUE = 1 << GLTF::Material::ALPHA_MODE_OPAQUE, | |
125 | ||
126 | /// Render alpha-masked matetrials | |
127 | ALPHA_MODE_FLAG_MASK = 1 << GLTF::Material::ALPHA_MODE_MASK, | |
128 | ||
129 | /// Render alpha-blended matetrials | |
130 | ALPHA_MODE_FLAG_BLEND = 1 << GLTF::Material::ALPHA_MODE_BLEND, | |
131 | ||
132 | /// Render all materials | |
133 | ALPHA_MODE_FLAG_ALL = ALPHA_MODE_FLAG_OPAQUE | ALPHA_MODE_FLAG_MASK | ALPHA_MODE_FLAG_BLEND | |
134 | }; | |
135 | /// Flag indicating which alpha modes to render | |
136 | ALPHA_MODE_FLAGS AlphaModes = ALPHA_MODE_FLAG_ALL; | |
137 | ||
138 | /// Debug view type | |
139 | enum class DebugViewType : int | |
140 | { | |
141 | None = 0, | |
142 | BaseColor = 1, | |
143 | Transparency = 2, | |
144 | NormalMap = 3, | |
145 | Occlusion = 4, | |
146 | Emissive = 5, | |
147 | Metallic = 6, | |
148 | Roughness = 7, | |
149 | DiffuseColor = 8, | |
150 | SpecularColor = 9, | |
151 | Reflectance90 = 10, | |
152 | MeshNormal = 11, | |
153 | PerturbedNormal = 12, | |
154 | NdotV = 13, | |
155 | DiffuseIBL = 14, | |
156 | SpecularIBL = 15, | |
157 | NumDebugViews | |
158 | }; | |
159 | DebugViewType DebugView = DebugViewType::None; | |
160 | ||
161 | /// Ambient occlusion strength | |
162 | float OcclusionStrength = 1; | |
163 | ||
164 | /// Emission scale | |
165 | float EmissionScale = 1; | |
166 | ||
167 | /// IBL scale | |
168 | float IBLScale = 1; | |
169 | ||
170 | /// Average log luminance used by tone mapping | |
171 | float AverageLogLum = 0.3f; | |
172 | ||
173 | /// Middle gray value used by tone mapping | |
174 | float MiddleGray = 0.18f; | |
175 | ||
176 | /// White point value used by tone mapping | |
177 | float WhitePoint = 3.f; | |
178 | }; | |
179 | ||
180 | /// GLTF Model shader resource binding information | |
181 | struct ModelResourceBindings | |
182 | { | |
183 | void Clear() | |
184 | { | |
185 | MaterialSRB.clear(); | |
186 | } | |
187 | /// Shader resource binding for every material | |
188 | std::vector<RefCntAutoPtr<IShaderResourceBinding>> MaterialSRB; | |
189 | }; | |
190 | ||
191 | /// GLTF resource cache shader resource binding information | |
192 | struct ResourceCacheBindings | |
193 | { | |
194 | /// Resource version | |
195 | Uint32 Version = 0; | |
196 | ||
197 | RefCntAutoPtr<IShaderResourceBinding> pSRB; | |
198 | }; | |
199 | ||
200 | /// Renders a GLTF model. | |
201 | ||
202 | /// \param [in] pCtx - Device context to record rendering commands to. | |
203 | /// \param [in] GLTFModel - GLTF model to render. | |
204 | /// \param [in] RenderParams - Render parameters. | |
205 | /// \param [in] pModelBindings - The model's shader resource binding information. | |
206 | /// \param [in] pCacheBindings - Shader resource cache binding information, if the | |
207 | /// model has been created using the cache. | |
208 | void Render(IDeviceContext* pCtx, | |
209 | GLTF::Model& GLTFModel, | |
210 | const RenderInfo& RenderParams, | |
211 | ModelResourceBindings* pModelBindings, | |
212 | ResourceCacheBindings* pCacheBindings = nullptr); | |
213 | ||
214 | /// Creates resource bindings for a given GLTF model | |
215 | ModelResourceBindings CreateResourceBindings(GLTF::Model& GLTFModel, | |
216 | IBuffer* pCameraAttribs, | |
217 | IBuffer* pLightAttribs); | |
218 | ||
219 | /// Precompute cubemaps used by IBL. | |
220 | void PrecomputeCubemaps(IRenderDevice* pDevice, | |
221 | IDeviceContext* pCtx, | |
222 | ITextureView* pEnvironmentMap); | |
223 | ||
224 | // clang-format off | |
225 | ITextureView* GetIrradianceCubeSRV() { return m_pIrradianceCubeSRV; } | |
226 | ITextureView* GetPrefilteredEnvMapSRV() { return m_pPrefilteredEnvMapSRV; } | |
227 | ITextureView* GetWhiteTexSRV() { return m_pWhiteTexSRV; } | |
228 | ITextureView* GetBlackTexSRV() { return m_pBlackTexSRV; } | |
229 | ITextureView* GetDefaultNormalMapSRV() { return m_pDefaultNormalMapSRV; } | |
230 | // clang-format on | |
231 | ||
232 | /// Creates a shader resource binding for the given material. | |
233 | ||
234 | /// \param [in] Model - GLTF model that keeps material textures. | |
235 | /// \param [in] Material - GLTF material to create SRB for. | |
236 | /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB. | |
237 | /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB. | |
238 | /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the | |
239 | /// default PSO. Can be null | |
240 | /// \param [out] ppMaterialSRB - Pointer to memory location where the pointer to the SRB object | |
241 | /// will be written. | |
242 | void CreateMaterialSRB(GLTF::Model& Model, | |
243 | GLTF::Material& Material, | |
244 | IBuffer* pCameraAttribs, | |
245 | IBuffer* pLightAttribs, | |
246 | IPipelineState* pPSO, | |
247 | IShaderResourceBinding** ppMaterialSRB); | |
248 | ||
249 | ||
250 | /// Creates a shader resource binding for a GTLF resource cache. | |
251 | ||
252 | /// \param [in] pDevice - Render device that may be needed by the resource cache to create | |
253 | /// internal objects. | |
254 | /// \param [in] pCtx - Device context that may be needed by the resource cache to initialize | |
255 | /// internal objects. | |
256 | /// \param [in] CacheUseInfo - GLTF resource cache usage information. | |
257 | /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB. | |
258 | /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB. | |
259 | /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the | |
260 | /// default PSO. Can be null | |
261 | /// \param [out] ppCacheSRB - Pointer to memory location where the pointer to the SRB object | |
262 | /// will be written. | |
263 | void CreateResourceCacheSRB(IRenderDevice* pDevice, | |
264 | IDeviceContext* pCtx, | |
265 | GLTF::ResourceCacheUseInfo& CacheUseInfo, | |
266 | IBuffer* pCameraAttribs, | |
267 | IBuffer* pLightAttribs, | |
268 | IPipelineState* pPSO, | |
269 | IShaderResourceBinding** ppCacheSRB); | |
270 | ||
271 | /// Prepares the renderer for rendering objects. | |
272 | /// This method must be called at least once per frame. | |
273 | void Begin(IDeviceContext* pCtx); | |
274 | ||
275 | ||
276 | /// Prepares the renderer for rendering objects from the resource cache. | |
277 | /// This method must be called at least once per frame before the first object | |
278 | /// from the cache is rendered. | |
279 | void Begin(IRenderDevice* pDevice, | |
280 | IDeviceContext* pCtx, | |
281 | GLTF::ResourceCacheUseInfo& CacheUseInfo, | |
282 | ResourceCacheBindings& Bindings, | |
283 | IBuffer* pCameraAttribs, | |
284 | IBuffer* pLightAttribs, | |
285 | IPipelineState* pPSO = nullptr); | |
286 | ||
287 | private: | |
288 | void PrecomputeBRDF(IRenderDevice* pDevice, | |
289 | IDeviceContext* pCtx); | |
290 | ||
291 | void CreatePSO(IRenderDevice* pDevice); | |
292 | ||
293 | void InitCommonSRBVars(IShaderResourceBinding* pSRB, | |
294 | IBuffer* pCameraAttribs, | |
295 | IBuffer* pLightAttribs); | |
296 | ||
297 | struct PSOKey | |
298 | { | |
299 | PSOKey() noexcept {}; | |
300 | PSOKey(GLTF::Material::ALPHA_MODE _AlphaMode, bool _DoubleSided) : | |
301 | AlphaMode{_AlphaMode}, | |
302 | DoubleSided{_DoubleSided} | |
303 | {} | |
304 | ||
305 | bool operator==(const PSOKey& rhs) const | |
306 | { | |
307 | return AlphaMode == rhs.AlphaMode && DoubleSided == rhs.DoubleSided; | |
308 | } | |
309 | bool operator!=(const PSOKey& rhs) const | |
310 | { | |
311 | return AlphaMode != rhs.AlphaMode || DoubleSided != rhs.DoubleSided; | |
312 | } | |
313 | ||
314 | GLTF::Material::ALPHA_MODE AlphaMode = GLTF::Material::ALPHA_MODE_OPAQUE; | |
315 | bool DoubleSided = false; | |
316 | }; | |
317 | ||
318 | static size_t GetPSOIdx(const PSOKey& Key) | |
319 | { | |
320 | size_t PSOIdx; | |
321 | ||
322 | PSOIdx = Key.AlphaMode == GLTF::Material::ALPHA_MODE_BLEND ? 1 : 0; | |
323 | PSOIdx = PSOIdx * 2 + (Key.DoubleSided ? 1 : 0); | |
324 | return PSOIdx; | |
325 | } | |
326 | ||
327 | void AddPSO(const PSOKey& Key, RefCntAutoPtr<IPipelineState> pPSO) | |
328 | { | |
329 | auto Idx = GetPSOIdx(Key); | |
330 | if (Idx >= m_PSOCache.size()) | |
331 | m_PSOCache.resize(Idx + 1); | |
332 | VERIFY_EXPR(!m_PSOCache[Idx]); | |
333 | m_PSOCache[Idx] = std::move(pPSO); | |
334 | } | |
335 | ||
336 | IPipelineState* GetPSO(const PSOKey& Key) | |
337 | { | |
338 | auto Idx = GetPSOIdx(Key); | |
339 | VERIFY_EXPR(Idx < m_PSOCache.size()); | |
340 | return Idx < m_PSOCache.size() ? m_PSOCache[Idx].RawPtr() : nullptr; | |
341 | } | |
342 | ||
343 | const CreateInfo m_Settings; | |
344 | ||
345 | static constexpr Uint32 BRDF_LUT_Dim = 512; | |
346 | RefCntAutoPtr<ITextureView> m_pBRDF_LUT_SRV; | |
347 | ||
348 | std::vector<RefCntAutoPtr<IPipelineState>> m_PSOCache; | |
349 | ||
350 | RefCntAutoPtr<ITextureView> m_pWhiteTexSRV; | |
351 | RefCntAutoPtr<ITextureView> m_pBlackTexSRV; | |
352 | RefCntAutoPtr<ITextureView> m_pDefaultNormalMapSRV; | |
353 | RefCntAutoPtr<ITextureView> m_pDefaultPhysDescSRV; | |
354 | ||
355 | ||
356 | static constexpr TEXTURE_FORMAT IrradianceCubeFmt = TEX_FORMAT_RGBA32_FLOAT; | |
357 | static constexpr TEXTURE_FORMAT PrefilteredEnvMapFmt = TEX_FORMAT_RGBA16_FLOAT; | |
358 | static constexpr Uint32 IrradianceCubeDim = 64; | |
359 | static constexpr Uint32 PrefilteredEnvMapDim = 256; | |
360 | ||
361 | RefCntAutoPtr<ITextureView> m_pIrradianceCubeSRV; | |
362 | RefCntAutoPtr<ITextureView> m_pPrefilteredEnvMapSRV; | |
363 | RefCntAutoPtr<IPipelineState> m_pPrecomputeIrradianceCubePSO; | |
364 | RefCntAutoPtr<IPipelineState> m_pPrefilterEnvMapPSO; | |
365 | RefCntAutoPtr<IShaderResourceBinding> m_pPrecomputeIrradianceCubeSRB; | |
366 | RefCntAutoPtr<IShaderResourceBinding> m_pPrefilterEnvMapSRB; | |
367 | ||
368 | RenderInfo m_RenderParams; | |
369 | ||
370 | RefCntAutoPtr<IBuffer> m_TransformsCB; | |
371 | RefCntAutoPtr<IBuffer> m_GLTFAttribsCB; | |
372 | RefCntAutoPtr<IBuffer> m_PrecomputeEnvMapAttribsCB; | |
373 | RefCntAutoPtr<IBuffer> m_JointsBuffer; | |
374 | }; | |
375 | ||
376 | DEFINE_FLAG_ENUM_OPERATORS(GLTF_PBR_Renderer::RenderInfo::ALPHA_MODE_FLAGS) | |
377 | ||
378 | } // namespace Diligent |
40 | 40 | namespace Diligent |
41 | 41 | { |
42 | 42 | |
43 | const SamplerDesc GLTF_PBR_Renderer::CreateInfo::DefaultSampler = Sam_LinearWrap; | |
43 | const SamplerDesc GLTF_RendererCreateInfo::DefaultSampler = Sam_LinearWrap; | |
44 | 44 | |
45 | 45 | GLTF_PBR_Renderer::GLTF_PBR_Renderer(IRenderDevice* pDevice, |
46 | 46 | IDeviceContext* pCtx, |
47 | const CreateInfo& CI) : | |
47 | const GLTF_RendererCreateInfo& CI) : | |
48 | 48 | m_Settings{CI} |
49 | 49 | { |
50 | 50 | if (m_Settings.UseIBL) |
207 | 207 | // Finally, create the pipeline state |
208 | 208 | PSOCreateInfo.pVS = pVS; |
209 | 209 | PSOCreateInfo.pPS = pPS; |
210 | ||
210 | 211 | pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &PrecomputeBRDF_PSO); |
211 | 212 | } |
212 | 213 | pCtx->SetPipelineState(PrecomputeBRDF_PSO); |
256 | 257 | Macros.AddShaderMacro("USE_TEXTURE_ATLAS", m_Settings.UseTextureAtals); |
257 | 258 | Macros.AddShaderMacro("PBR_WORKFLOW_METALLIC_ROUGHNESS", GLTF::Material::PBR_WORKFLOW_METALL_ROUGH); |
258 | 259 | Macros.AddShaderMacro("PBR_WORKFLOW_SPECULAR_GLOSINESS", GLTF::Material::PBR_WORKFLOW_SPEC_GLOSS); |
259 | Macros.AddShaderMacro("GLTF_ALPHA_MODE_OPAQUE", GLTF::Material::ALPHA_MODE_OPAQUE); | |
260 | Macros.AddShaderMacro("GLTF_ALPHA_MODE_MASK", GLTF::Material::ALPHA_MODE_MASK); | |
261 | Macros.AddShaderMacro("GLTF_ALPHA_MODE_BLEND", GLTF::Material::ALPHA_MODE_BLEND); | |
260 | Macros.AddShaderMacro("GLTF_ALPHA_MODE_OPAQUE", GLTF_MAT_ALPHA_MODE_OPAQUE); | |
261 | Macros.AddShaderMacro("GLTF_ALPHA_MODE_MASK", GLTF_MAT_ALPHA_MODE_MASK); | |
262 | Macros.AddShaderMacro("GLTF_ALPHA_MODE_BLEND", GLTF_MAT_ALPHA_MODE_BLEND); | |
262 | 263 | ShaderCI.Macros = Macros; |
263 | 264 | RefCntAutoPtr<IShader> pVS; |
264 | 265 | { |
342 | 343 | PSOCreateInfo.pVS = pVS; |
343 | 344 | PSOCreateInfo.pPS = pPS; |
344 | 345 | |
345 | { | |
346 | PSOKey Key{GLTF::Material::ALPHA_MODE_OPAQUE, false}; | |
346 | if (m_Settings.pGS) | |
347 | PSOCreateInfo.pGS = m_Settings.pGS; | |
348 | ||
349 | { | |
350 | PSOKey Key{GLTF_MAT_ALPHA_MODE_OPAQUE, false}; | |
347 | 351 | |
348 | 352 | RefCntAutoPtr<IPipelineState> pSingleSidedOpaquePSO; |
349 | 353 | pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pSingleSidedOpaquePSO); |
370 | 374 | RT0.BlendOpAlpha = BLEND_OPERATION_ADD; |
371 | 375 | |
372 | 376 | { |
373 | PSOKey Key{GLTF::Material::ALPHA_MODE_BLEND, false}; | |
377 | PSOKey Key{GLTF_MAT_ALPHA_MODE_BLEND, false}; | |
374 | 378 | |
375 | 379 | RefCntAutoPtr<IPipelineState> pSingleSidedBlendPSO; |
376 | 380 | pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &pSingleSidedBlendPSO); |
431 | 435 | } |
432 | 436 | |
433 | 437 | |
434 | void GLTF_PBR_Renderer::CreateMaterialSRB(GLTF::Model& Model, | |
438 | void GLTF_PBR_Renderer::CreateMaterialSRB(IGLTFModel* _Model, | |
435 | 439 | GLTF::Material& Material, |
436 | 440 | IBuffer* pCameraAttribs, |
437 | 441 | IBuffer* pLightAttribs, |
438 | 442 | IPipelineState* pPSO, |
439 | 443 | IShaderResourceBinding** ppMaterialSRB) |
440 | 444 | { |
445 | auto& Model = *static_cast<GLTF::Model*>(_Model); | |
446 | ||
441 | 447 | if (pPSO == nullptr) |
442 | 448 | pPSO = GetPSO(PSOKey{}); |
443 | 449 | |
494 | 500 | |
495 | 501 | void GLTF_PBR_Renderer::CreateResourceCacheSRB(IRenderDevice* pDevice, |
496 | 502 | IDeviceContext* pCtx, |
497 | GLTF::ResourceCacheUseInfo& CacheUseInfo, | |
503 | GLTF_ResourceCacheUseInfo& CacheUseInfo, | |
498 | 504 | IBuffer* pCameraAttribs, |
499 | 505 | IBuffer* pLightAttribs, |
500 | 506 | IPipelineState* pPSO, |
704 | 710 | |
705 | 711 | |
706 | 712 | // clang-format off |
707 | const std::array<float4x4, 6> Matrices = | |
713 | const std::array<float4x4, 6> Matrices = | |
708 | 714 | { |
709 | 715 | /* +X */ float4x4::RotationY(+PI_F / 2.f), |
710 | 716 | /* -X */ float4x4::RotationY(-PI_F / 2.f), |
712 | 718 | /* -Y */ float4x4::RotationX(+PI_F / 2.f), |
713 | 719 | /* +Z */ float4x4::Identity(), |
714 | 720 | /* -Z */ float4x4::RotationY(PI_F) |
715 | }; | |
721 | }; | |
716 | 722 | // clang-format on |
717 | 723 | |
718 | 724 | pCtx->SetPipelineState(m_pPrecomputeIrradianceCubePSO); |
785 | 791 | } |
786 | 792 | |
787 | 793 | |
788 | GLTF_PBR_Renderer::ModelResourceBindings GLTF_PBR_Renderer::CreateResourceBindings( | |
789 | GLTF::Model& GLTFModel, | |
794 | GLTF_ModelResourceBindings GLTF_PBR_Renderer::CreateResourceBindings( | |
795 | IGLTFModel* _GLTFModel, | |
790 | 796 | IBuffer* pCameraAttribs, |
791 | 797 | IBuffer* pLightAttribs) |
792 | 798 | { |
793 | ModelResourceBindings ResourceBindings; | |
799 | auto& GLTFModel = *static_cast<GLTF::Model*>(_GLTFModel); | |
800 | GLTF_ModelResourceBindings ResourceBindings; | |
794 | 801 | ResourceBindings.MaterialSRB.resize(GLTFModel.Materials.size()); |
795 | 802 | for (size_t mat = 0; mat < GLTFModel.Materials.size(); ++mat) |
796 | 803 | { |
797 | CreateMaterialSRB(GLTFModel, GLTFModel.Materials[mat], pCameraAttribs, pLightAttribs, nullptr, &ResourceBindings.MaterialSRB[mat]); | |
804 | CreateMaterialSRB(_GLTFModel, GLTFModel.Materials[mat], pCameraAttribs, pLightAttribs, nullptr, &ResourceBindings.MaterialSRB[mat]); | |
798 | 805 | } |
799 | 806 | return ResourceBindings; |
800 | 807 | } |
808 | 815 | } |
809 | 816 | } |
810 | 817 | |
811 | void GLTF_PBR_Renderer::Begin(IRenderDevice* pDevice, | |
812 | IDeviceContext* pCtx, | |
813 | GLTF::ResourceCacheUseInfo& CacheUseInfo, | |
814 | ResourceCacheBindings& Bindings, | |
815 | IBuffer* pCameraAttribs, | |
816 | IBuffer* pLightAttribs, | |
817 | IPipelineState* pPSO) | |
818 | void GLTF_PBR_Renderer::BeginPSO(IRenderDevice* pDevice, | |
819 | IDeviceContext* pCtx, | |
820 | GLTF_ResourceCacheUseInfo& CacheUseInfo, | |
821 | GLTF_ResourceCacheBindings& Bindings, | |
822 | IBuffer* pCameraAttribs, | |
823 | IBuffer* pLightAttribs, | |
824 | IPipelineState* pPSO) | |
818 | 825 | { |
819 | 826 | VERIFY_EXPR(CacheUseInfo.pResourceMgr != nullptr); |
820 | 827 | |
850 | 857 | pCtx->SetIndexBuffer(pIndexBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); |
851 | 858 | } |
852 | 859 | |
853 | void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, | |
854 | GLTF::Model& GLTFModel, | |
855 | const RenderInfo& RenderParams, | |
856 | ModelResourceBindings* pModelBindings, | |
857 | ResourceCacheBindings* pCacheBindings) | |
858 | { | |
860 | void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, | |
861 | IGLTFModel* _GLTFModel, | |
862 | const GLTF_RenderInfo& RenderParams, | |
863 | GLTF_ModelResourceBindings* pModelBindings, | |
864 | GLTF_ResourceCacheBindings* pCacheBindings) | |
865 | { | |
866 | auto& GLTFModel = *static_cast<GLTF::Model*>(_GLTFModel); | |
867 | ||
859 | 868 | DEV_CHECK_ERR((pModelBindings != nullptr) ^ (pCacheBindings != nullptr), "Either model bindings or cache bindings must not be null"); |
860 | 869 | DEV_CHECK_ERR(pModelBindings == nullptr || pModelBindings->MaterialSRB.size() == GLTFModel.Materials.size(), |
861 | 870 | "The number of material shader resource bindings is not consistent with the number of materials"); |
867 | 876 | std::array<Uint32, 2> Offsets = {}; |
868 | 877 | std::array<IBuffer*, 2> pVBs = |
869 | 878 | { |
870 | GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_VERTEX_BASIC_ATTRIBS), | |
871 | GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_VERTEX_SKIN_ATTRIBS) // | |
879 | GLTFModel.GetBuffer(GLTF_BUFFER_ID_VERTEX_BASIC_ATTRIBS), | |
880 | GLTFModel.GetBuffer(GLTF_BUFFER_ID_VERTEX_SKIN_ATTRIBS) // | |
872 | 881 | }; |
873 | 882 | pCtx->SetVertexBuffers(0, static_cast<Uint32>(pVBs.size()), pVBs.data(), Offsets.data(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION, SET_VERTEX_BUFFERS_FLAG_RESET); |
874 | 883 | |
875 | if (auto* pIndexBuffer = GLTFModel.GetBuffer(GLTF::Model::BUFFER_ID_INDEX)) | |
884 | if (auto* pIndexBuffer = GLTFModel.GetBuffer(GLTF_BUFFER_ID_INDEX)) | |
876 | 885 | { |
877 | 886 | pCtx->SetIndexBuffer(pIndexBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); |
878 | 887 | } |
881 | 890 | const auto FirstIndexLocation = GLTFModel.GetFirstIndexLocation(); |
882 | 891 | const auto BaseVertex = GLTFModel.GetBaseVertex(); |
883 | 892 | |
884 | const std::array<GLTF::Material::ALPHA_MODE, 3> AlphaModes // | |
885 | { | |
886 | GLTF::Material::ALPHA_MODE_OPAQUE, // Opaque primitives - first | |
887 | GLTF::Material::ALPHA_MODE_MASK, // Alpha-masked primitives - second | |
888 | GLTF::Material::ALPHA_MODE_BLEND, // Transparent primitives - last (TODO: depth sorting) | |
893 | const std::array<GLTF_MAT_ALPHA_MODE, 3> AlphaModes // | |
894 | { | |
895 | GLTF_MAT_ALPHA_MODE_OPAQUE, // Opaque primitives - first | |
896 | GLTF_MAT_ALPHA_MODE_MASK, // Alpha-masked primitives - second | |
897 | GLTF_MAT_ALPHA_MODE_BLEND, // Transparent primitives - last (TODO: depth sorting) | |
889 | 898 | }; |
890 | 899 | |
891 | 900 | const GLTF::Mesh* pLastAnimatedMesh = nullptr; |
960 | 969 | |
961 | 970 | { |
962 | 971 | MapHelper<GLTFNodeShaderTransforms> pTransforms{pCtx, m_TransformsCB, MAP_WRITE, MAP_FLAG_DISCARD}; |
963 | pTransforms->NodeMatrix = Mesh.Transforms.matrix * RenderParams.ModelTransform; | |
972 | pTransforms->NodeMatrix = Mesh.Transforms.matrix * float4x4::MakeMatrix(RenderParams.ModelTransform); | |
964 | 973 | pTransforms->JointCount = static_cast<int>(JointCount); |
965 | 974 | } |
966 | 975 | |
1016 | 1025 | } |
1017 | 1026 | } |
1018 | 1027 | |
1028 | API_QUALIFIER | |
1029 | IGLTF_PBR_Renderer* IGLTF_PBR_Renderer_Create(IRenderDevice* pDevice, | |
1030 | IDeviceContext* pCtx, | |
1031 | const GLTF_RendererCreateInfo* CI) { | |
1032 | return new GLTF_PBR_Renderer(pDevice, pCtx, *CI); | |
1033 | } | |
1034 | ||
1019 | 1035 | } // namespace Diligent |
1036 | ||
1037 | extern "C" | |
1038 | { | |
1039 | API_QUALIFIER | |
1040 | Diligent::IGLTF_PBR_Renderer* Diligent_IGLTF_PBR_Renderer_Create(Diligent::IRenderDevice* pDevice, | |
1041 | Diligent::IDeviceContext* pCtx, | |
1042 | const Diligent::GLTF_RendererCreateInfo* CI) { | |
1043 | return Diligent::IGLTF_PBR_Renderer_Create(pDevice, pCtx, CI); | |
1044 | } | |
1045 | } |