1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef API_3D_RENDER_IRENDER_DATA_STORE_DEFAULT_MATERIAL_H 17 #define API_3D_RENDER_IRENDER_DATA_STORE_DEFAULT_MATERIAL_H 18 19 #include <cstdint> 20 21 #include <3d/ecs/components/material_component.h> 22 #include <3d/render/render_data_defines_3d.h> 23 #include <base/containers/array_view.h> 24 #include <base/math/matrix.h> 25 #include <base/math/vector.h> 26 #include <core/namespace.h> 27 #include <render/datastore/intf_render_data_store.h> 28 #include <render/device/intf_shader_manager.h> 29 #include <render/resource_handle.h> 30 31 CORE3D_BEGIN_NAMESPACE() 32 /** @ingroup group_render_irenderdatastoredefaultmaterial */ 33 /** RenderDataDefaultMaterial. 34 */ 35 struct RenderDataDefaultMaterial { 36 /** min supported roughness value. clamped to this - 1.0. 37 Avoids division with zero in shader BRDF calculations and prevents "zero" size speculars. */ 38 static constexpr float MIN_ROUGHNESS { 0.089f }; 39 /** max supported skin matrix count */ 40 static constexpr uint32_t MAX_SKIN_MATRIX_COUNT { 128u }; 41 42 /** Count of uvec4 variables for material uniforms (must match 3d_dm_structure_common.h) 43 * Aligned for 256 bytes with indices. 44 */ 45 static constexpr uint32_t MATERIAL_FACTOR_UNIFORM_VEC4_COUNT { 15u }; 46 static constexpr uint32_t MATERIAL_PACKED_UNIFORM_UVEC4_COUNT { 15u }; 47 48 /** Count of uvec4 variables for material uniforms (must match 3d_dm_structure_common.h) */ 49 static constexpr uint32_t MATERIAL_TEXTURE_COUNT { 11u }; 50 51 /** max default material custom resources */ 52 static constexpr uint32_t MAX_MATERIAL_CUSTOM_RESOURCE_COUNT { 4u }; 53 54 /** max default material custom resources */ 55 static constexpr uint32_t MAX_MESH_USER_VEC4_COUNT { 8u }; 56 57 /** max default material custom resources */ 58 static constexpr uint32_t MAX_MATERIAL_CUSTOM_PROPERTY_BYTE_SIZE { 256u }; 59 60 /** Input material uniforms 61 * There's no conversion happening to these, so pre-multiplications etc needs to happen prior 62 */ 63 struct InputMaterialUniforms { 64 struct TextureData { 65 BASE_NS::Math::Vec4 factor { 0.0f, 0.0f, 0.0f, 0.0f }; 66 BASE_NS::Math::Vec2 translation { 0.0f, 0.0f }; 67 float rotation { 0.0f }; 68 BASE_NS::Math::Vec2 scale { 1.0f, 1.0f }; 69 }; 70 TextureData textureData[MATERIAL_TEXTURE_COUNT]; 71 // separate values which is pushed to shader 72 // alpha cutoff 73 float alphaCutoff { 0.5f }; 74 // texcoord set bits, selection for uv0 or uv1 75 uint32_t texCoordSetBits { 0u }; 76 // texcoord transform set bits 77 uint32_t texTransformSetBits { 0u }; 78 /** material id */ 79 uint64_t id { 0 }; 80 }; 81 82 /** Material uniforms (NOTE: rotScaleTrans could be packed more) 83 */ 84 struct MaterialUniforms { 85 // Factors as half4 86 // 0: baseColor 87 // 1: normal 88 // 2: material 89 // 3: emissive 90 // 4: ao 91 // 5: clearcoat 92 // 6: clearcoat roughness 93 // 7: clearcoat normal 94 // 8: sheen 95 // 9: transmission 96 // 10: specular 97 // 11: alpha cutoff 98 99 BASE_NS::Math::Vec4 factors[MATERIAL_FACTOR_UNIFORM_VEC4_COUNT]; 100 101 // unpacked, .xy material id, 102 BASE_NS::Math::UVec4 indices { 0u, 0u, 0u, 0u }; 103 }; 104 105 struct MaterialPackedUniforms { 106 // Texture transforms as half4 ({2x2 mat}, {2d offset, unused}) 107 // 0: rotScaleTrans baseColor 108 // 1: rotScaleTrans normal 109 // 2: rotScaleTrans material 110 // 3: rotScaleTrans emissive 111 // 4: rotScaleTrans ao 112 // 5: rotScaleTrans clearcoat 113 // 6: rotScaleTrans clearcoat roughness 114 // 7: rotScaleTrans clearcoat normal 115 // 8: rotScaleTrans sheen 116 // 9: rotScaleTrans transmission 117 // 10: rotScaleTrans specular 118 119 // 120 // 12: alphaCutoff, unused, useTexcoord | hasTransform 121 BASE_NS::Math::UVec4 packed[MATERIAL_PACKED_UNIFORM_UVEC4_COUNT]; 122 123 // unpacked, .xy material id, 124 BASE_NS::Math::UVec4 indices { 0u, 0u, 0u, 0u }; 125 }; 126 127 /* 128 * Combined uniforms for factors and packed transforms 129 **/ 130 struct AllMaterialUniforms { 131 /** Material factor uniforms */ 132 MaterialUniforms factors; 133 /** Material packed transforms */ 134 MaterialPackedUniforms transforms; 135 }; 136 137 /** Material handles 138 */ 139 struct MaterialHandles { 140 /** Source images for different texture types */ 141 RENDER_NS::RenderHandleReference images[MATERIAL_TEXTURE_COUNT]; 142 /** Samplers for different texture types */ 143 RENDER_NS::RenderHandleReference samplers[MATERIAL_TEXTURE_COUNT]; 144 }; 145 146 /** Material shader 147 */ 148 struct MaterialShader { 149 /** Shader to be used. (If invalid, a default is chosen by the default material renderer) */ 150 RENDER_NS::RenderHandleReference shader; 151 /** Shader graphics state to be used. (If invalid, a default is chosen by the default material renderer) */ 152 RENDER_NS::RenderHandleReference graphicsState; 153 }; 154 155 /** Material data 156 */ 157 struct MaterialData { 158 /** Render material type */ 159 RenderMaterialType materialType { RenderMaterialType::METALLIC_ROUGHNESS }; 160 /** Render extra rendering flags */ 161 RenderExtraRenderingFlags extraMaterialRenderingFlags { 0u }; 162 /** Render material flags */ 163 RenderMaterialFlags renderMaterialFlags { 0u }; 164 165 /** Custom render slot id */ 166 uint32_t customRenderSlotId { ~0u }; 167 /** Material shader */ 168 MaterialShader materialShader; 169 /** Depth shader */ 170 MaterialShader depthShader; 171 }; 172 173 /** Submesh material flags 174 */ 175 struct SubmeshMaterialFlags { 176 /** Material type */ 177 RenderMaterialType materialType { RenderMaterialType::METALLIC_ROUGHNESS }; 178 /* Render submesh's submesh flags, dublicated here for convenience */ 179 RenderSubmeshFlags submeshFlags { 0u }; 180 /** Extra material rendering flags */ 181 RenderExtraRenderingFlags extraMaterialRenderingFlags { 0u }; 182 183 /** Render material flags */ 184 RenderMaterialFlags renderMaterialFlags { 0u }; 185 186 /** 32 bit hash based on the variables above */ 187 uint32_t renderHash { 0u }; 188 }; 189 190 struct SlotMaterialData { 191 /** Combined sort layer from render submesh */ 192 uint16_t combinedRenderSortLayer { 0u }; 193 /** Combined of render materials flags hash, material idx, shader id */ 194 uint32_t renderSortHash { 0u }; 195 /** Render material flags */ 196 RenderMaterialFlags renderMaterialFlags { 0u }; 197 /** Custom shader handle or invalid handle */ 198 RENDER_NS::RenderHandleReference shader; 199 /** Custom graphics state handle or invalid handle */ 200 RENDER_NS::RenderHandleReference gfxState; 201 }; 202 203 /** Object counts for rendering. 204 */ 205 struct ObjectCounts { 206 /** Mesh count, NOTE: is currently global */ 207 uint32_t meshCount { 0u }; 208 /** Submesh count */ 209 uint32_t submeshCount { 0u }; 210 /** Skin count */ 211 uint32_t skinCount { 0u }; 212 /** Material count */ 213 uint32_t materialCount { 0u }; 214 }; 215 216 /** Per mesh skin joint matrices. 217 */ 218 struct JointMatrixData { 219 /** Matrices */ 220 BASE_NS::Math::Mat4X4* data { nullptr }; 221 /** Matrix count */ 222 uint32_t count { 0 }; 223 }; 224 225 /** Material custom resources. 226 */ 227 struct CustomResourceData { 228 /** invalid handle if custom material shader not given. 229 * With default material build-in render nodes must have compatible pipeline layout. 230 * With custom render slots and custom render nodes can be anything. 231 */ 232 RENDER_NS::RenderHandleReference shaderHandle; 233 234 /** handle count */ 235 uint32_t resourceHandleCount { 0u }; 236 /** invalid handles if not given */ 237 RENDER_NS::RenderHandleReference resourceHandles[MAX_MATERIAL_CUSTOM_RESOURCE_COUNT]; 238 }; 239 240 /** Material slot types. Where 241 */ 242 enum class MaterialSlotType : uint32_t { 243 /** Basic opaque slot */ 244 SLOT_TYPE_OPAQUE = 0, 245 /** Basic translucent slot */ 246 SLOT_TYPE_TRANSLUCENT = 1, 247 /** Basic depth slot for shadows and depth pre-pass */ 248 SLOT_TYPE_DEPTH = 2, 249 }; 250 251 /** Material indices. 252 */ 253 struct MaterialIndices { 254 /** Material index */ 255 uint32_t materialIndex { ~0u }; 256 /** Material custom resource index */ 257 uint32_t materialCustomResourceIndex { ~0u }; 258 }; 259 }; 260 261 /** @ingroup group_render_irenderdatastoredefaultmaterial */ 262 /** RenderDataStoreDefaultMaterial interface. 263 * Not internally syncronized. 264 */ 265 class IRenderDataStoreDefaultMaterial : public RENDER_NS::IRenderDataStore { 266 public: 267 static constexpr BASE_NS::Uid UID { "fdd9f86b-f5fc-45da-8832-41cbd649ed49" }; 268 269 ~IRenderDataStoreDefaultMaterial() override = default; 270 271 /** Add mesh data. 272 * @param meshData All mesh data. 273 * @return Mesh index for submesh to use. 274 */ 275 virtual uint32_t AddMeshData(const RenderMeshData& meshData) = 0; 276 277 /** Add material and get material index. 278 * @param materialUniforms input uniform data. 279 * @param materialHandles raw GPU resource handles. 280 * @param materialData Material data. 281 * @param customPropertyData Custom property data per material. 282 * @return Material index for submesh to use. 283 */ 284 virtual uint32_t AddMaterialData(const RenderDataDefaultMaterial::InputMaterialUniforms& materialUniforms, 285 const RenderDataDefaultMaterial::MaterialHandles& materialHandles, 286 const RenderDataDefaultMaterial::MaterialData& materialData, 287 const BASE_NS::array_view<const uint8_t> customPropertyData) = 0; 288 289 /** Add material and get material index. 290 * Automatic hashing with id. (E.g. material entity id) 291 * Final rendering material flags are per submesh (RenderDataDefaultMaterial::SubmeshMaterialFlags) 292 * @param id Material component id. In typical ECS usage material entity id. 293 * @param materialUniforms input material uniforms. 294 * @param materialHandles raw GPU resource handles. 295 * @param materialData Material data. 296 * @param customPropertyData Custom property data per material. 297 * @return Material index for submesh to use. 298 */ 299 virtual uint32_t AddMaterialData(const uint64_t id, 300 const RenderDataDefaultMaterial::InputMaterialUniforms& materialUniforms, 301 const RenderDataDefaultMaterial::MaterialHandles& materialHandles, 302 const RenderDataDefaultMaterial::MaterialData& materialData, 303 const BASE_NS::array_view<const uint8_t> customPropertyData) = 0; 304 305 /** Reserve space for instanceCount materials. 306 * @param id Material component id. In typical ECS usage material entity id. 307 * @param instanceCount How many submesh instances will be will be draw. 308 * @return Material index for the first submesh instance. 309 */ 310 virtual uint32_t AllocateMaterials(uint64_t id, uint32_t instanceCount) = 0; 311 312 /** Add material with preallocated index. 313 * @param materialIndex Index to first submesh material (from AllocateMaterials). 314 * @param materialInstanceIndex Offset to submesh instance's material. 315 * @param materialInstanceCount How many times is the material data duplicated. 316 * @param materialUniforms input material uniforms. 317 * @param materialHandles raw GPU resource handles. 318 * @param materialData Material data. 319 * @param customPropertyData Custom property data per material. 320 */ 321 virtual void AddInstanceMaterialData(uint32_t materialIndex, uint32_t materialInstanceIndex, 322 uint32_t materialInstanceCount, const RenderDataDefaultMaterial::InputMaterialUniforms& materialUniforms, 323 const RenderDataDefaultMaterial::MaterialHandles& materialHandles, 324 const RenderDataDefaultMaterial::MaterialData& materialData, 325 const BASE_NS::array_view<const uint8_t> customPropertyData) = 0; 326 327 /** Add material with preallocated index. Material handles and material data is not passed as inputs. 328 * Use for inputting material GPU instances (the shader data and material GPU image handles cannot change) 329 * @param materialIndex Index to first submesh material (from AllocateMaterials). 330 * @param materialInstanceIndex Offset to submesh instance's material. 331 * @param materialInstanceCount How many times is the material data duplicated. 332 * @param materialUniforms input material uniforms. 333 * @param customPropertyData Custom property data per material. 334 */ 335 virtual void AddInstanceMaterialData(uint32_t materialIndex, uint32_t materialInstanceIndex, 336 uint32_t materialInstanceCount, const RenderDataDefaultMaterial::InputMaterialUniforms& materialUniforms, 337 const BASE_NS::array_view<const uint8_t> customPropertyData) = 0; 338 339 /** Get material index if already created with the same id. 340 * It's beneficial to use unique materials and use as few of them as possible (there will be copying and such). 341 * @param id Material component id. In typical ECS usage material entity id. 342 * @return Material index for submesh to use. (if no material created with the id 343 * RenderSceneDataConstants::INVALID_INDEX is returned) 344 */ 345 virtual uint32_t GetMaterialIndex(const uint64_t id) const = 0; 346 347 /** Get material custom resource index if already created for the same material. 348 * @param id Material component id. In typical ECS usage material entity id. 349 * @return Material custom resource index for submesh to use. (if no material custorm resource created with the id 350 * RenderSceneDataConstants::INVALID_INDEX is returned) 351 */ 352 virtual uint32_t GetMaterialCustomResourceIndex(const uint64_t id) const = 0; 353 354 /** Get material indices. 355 * @param id Material component id. In typical ECS usage material entity id. 356 * @return Material indices. 357 */ 358 virtual RenderDataDefaultMaterial::MaterialIndices GetMaterialIndices(const uint64_t id) const = 0; 359 360 /** Get material indices. 361 * @param id Material component id. In typical ECS usage material entity id. 362 * @paran instanceCount Expected instance count for the material id. 363 * @return Material indices. 364 */ 365 virtual RenderDataDefaultMaterial::MaterialIndices GetMaterialIndices( 366 uint64_t id, uint32_t instanceCount) const = 0; 367 368 /** Add skin joint matrices and get an index for render submesh. 369 * If skinJointMatrices.size() != previousSkinJointMatrices.size() 370 * The skinJointMatrices are copied to previous frame buffer. 371 * @param skinJointMatrices All skin joint matrices. 372 * @param prevSkinJointMatrices All skin joint matrices for previous frame. 373 * @return Skin joint matrices index for submesh to use. (if no skin joints are given 374 * RenderSceneDataConstants::INVALID_INDEX is returned) 375 */ 376 virtual uint32_t AddSkinJointMatrices(const BASE_NS::array_view<const BASE_NS::Math::Mat4X4> skinJointMatrices, 377 const BASE_NS::array_view<const BASE_NS::Math::Mat4X4> prevSkinJointMatrices) = 0; 378 379 /** Add custom material resources. (Extra resources on top of default material resources) 380 * With built-in default material render nodes, the resources are mapped to user 381 * defined custom pipeline layout to the single descriptor set which is after default material descriptor sets. 382 * The pipeline layout must be compatible. 383 * Invalid GPU resource handles are ignored. 384 * Automatic hashing with id. (E.g. material entity id) 385 * @param bindings Valid GPU resource handles. (<= MAX_MATERIAL_CUSTOM_RESOURCE_COUNT) 386 * @param id Material component id. In typical ECS usage material entity id. 387 * @return Index for custom material resources. (if no bindings are given 388 * RenderSceneDataConstants::INVALID_INDEX is returned) 389 */ 390 virtual uint32_t AddMaterialCustomResources( 391 const uint64_t id, const BASE_NS::array_view<const RENDER_NS::RenderHandleReference> bindings) = 0; 392 393 /** Add submeshes safely with default material to rendering. Render slots are evaluated automatically. 394 * @param submesh Submesh. 395 */ 396 virtual void AddSubmesh(const RenderSubmesh& submesh) = 0; 397 398 /** Add submeshes safely with default material to rendering. 399 * @param submesh Submesh. 400 * @param renderSlotAndShaders All the render slots where the submesh is handled. 401 */ 402 virtual void AddSubmesh(const RenderSubmesh& submesh, 403 const BASE_NS::array_view<const RENDER_NS::IShaderManager::RenderSlotData> renderSlotAndShaders) = 0; 404 405 /** Set render slots for material types. 406 * @param materialSlotType Material slot type. 407 * @param renderSlotIds All render slot ids. 408 */ 409 virtual void SetRenderSlots(const RenderDataDefaultMaterial::MaterialSlotType materialSlotType, 410 const BASE_NS::array_view<const uint32_t> renderSlotIds) = 0; 411 412 /** Get render slot mask for material type. 413 * @param materialSlotType Material slot type. 414 * @return Mask of render slot ids. 415 */ 416 virtual uint64_t GetRenderSlotMask(const RenderDataDefaultMaterial::MaterialSlotType materialSlotType) const = 0; 417 418 /** Get all object count which were send to rendering 419 * @return ObjectCounts 420 */ 421 virtual RenderDataDefaultMaterial::ObjectCounts GetObjectCounts() const = 0; 422 423 /** Get list of mesh data 424 */ 425 virtual BASE_NS::array_view<const RenderMeshData> GetMeshData() const = 0; 426 427 /** Get list of mesh skin joint matrices 428 */ 429 virtual BASE_NS::array_view<const RenderDataDefaultMaterial::JointMatrixData> GetMeshJointMatrices() const = 0; 430 431 /** Get slot submesh indices 432 * @param renderSlotId Index 433 */ 434 virtual BASE_NS::array_view<const uint32_t> GetSlotSubmeshIndices(const uint32_t renderSlotId) const = 0; 435 436 /** Get slot submesh shader handles 437 * @param renderSlotId Index 438 */ 439 virtual BASE_NS::array_view<const RenderDataDefaultMaterial::SlotMaterialData> GetSlotSubmeshMaterialData( 440 const uint32_t renderSlotId) const = 0; 441 442 /** Get object counts per render slot 443 * @param renderSlotId Index 444 */ 445 virtual RenderDataDefaultMaterial::ObjectCounts GetSlotObjectCounts(const uint32_t renderSlotId) const = 0; 446 447 /** Get list of render submeshes 448 */ 449 virtual BASE_NS::array_view<const RenderSubmesh> GetSubmeshes() const = 0; 450 451 /** Get submesh joint matrix data 452 * @param skinJointIndex Skin joint index from RenderSubmesh got from AddSkinJointMatrices(). 453 */ 454 virtual BASE_NS::array_view<const BASE_NS::Math::Mat4X4> GetSubmeshJointMatrixData( 455 const uint32_t skinJointIndex) const = 0; 456 457 /** Get material uniforms (per material) */ 458 virtual BASE_NS::array_view<const RenderDataDefaultMaterial::AllMaterialUniforms> GetMaterialUniforms() const = 0; 459 /** Get material handles (per material) */ 460 virtual BASE_NS::array_view<const RenderDataDefaultMaterial::MaterialHandles> GetMaterialHandles() const = 0; 461 /** Get material custom property data with material index. 462 * @param materialIndex Index of material from RenderSubmesh and an index if going through e.g. material unforms 463 */ 464 virtual BASE_NS::array_view<const uint8_t> GetMaterialCustomPropertyData(const uint32_t materialIndex) const = 0; 465 /** Get submesh material flags (per submesh) */ 466 virtual BASE_NS::array_view<const RenderDataDefaultMaterial::SubmeshMaterialFlags> 467 GetSubmeshMaterialFlags() const = 0; 468 469 /** Get custom resource handles */ 470 virtual BASE_NS::array_view<const RenderDataDefaultMaterial::CustomResourceData> 471 GetCustomResourceHandles() const = 0; 472 473 /** Generate render hash (32 bits as RenderDataDefaultMaterial::SubmeshMaterialFlags::renderHash) */ 474 virtual uint32_t GenerateRenderHash(const RenderDataDefaultMaterial::SubmeshMaterialFlags& flags) const = 0; 475 476 protected: 477 IRenderDataStoreDefaultMaterial() = default; 478 }; 479 CORE3D_END_NAMESPACE() 480 481 #endif // API_3D_RENDER_IRENDER_DATA_STORE_DEFAULT_MATERIAL_H 482