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 #if !defined(API_3D_ECS_COMPONENTS_MATERIAL_COMPONENT_H) || defined(IMPLEMENT_MANAGER)
17 #define API_3D_ECS_COMPONENTS_MATERIAL_COMPONENT_H
18 
19 #if !defined(IMPLEMENT_MANAGER)
20 #include <3d/namespace.h>
21 #include <base/containers/vector.h>
22 #include <base/math/vector.h>
23 #include <core/ecs/component_struct_macros.h>
24 #include <core/ecs/entity_reference.h>
25 #include <core/ecs/intf_component_manager.h>
26 
27 CORE3D_BEGIN_NAMESPACE()
28 /** \addtogroup group_material_materialdesc
29  *  @{
30  */
31 #endif
32 
33 /** Material properties.
34  * With full customization one can use custom resources property
35  */
36 BEGIN_COMPONENT(IMaterialComponentManager, MaterialComponent)
37 #if !defined(IMPLEMENT_MANAGER)
38     /** Material type enumeration */
39     enum class Type : uint8_t {
40         /** Enumeration for Metallic roughness workflow */
41         METALLIC_ROUGHNESS = 0,
42         /** Enumumeration for Specular glossiness workflow */
43         SPECULAR_GLOSSINESS = 1,
44         /** Enumumeration for KHR materials unlit workflow */
45         UNLIT = 2,
46         /** Enumumeration for special unlit shadow receiver */
47         UNLIT_SHADOW_ALPHA = 3,
48         /** Custom material. Could be used with custom material model e.g. with shader graph.
49          * Disables automatic factor based modifications for flags.
50          * Note: that base color is always automatically pre-multiplied in all cases
51          */
52         CUSTOM = 4,
53         /** Custom complex material. Could be used with custom material model e.g. with shader graph.
54          * Disables automatic factor based modifications for flags.
55          * Does not use deferred rendering path in any case due to complex material model.
56          * Note: that base color is always automatically pre-multiplied in all cases
57          */
58         CUSTOM_COMPLEX = 5,
59     };
60 
61     /** Material specialization flags */
62     enum LightingFlagBits : uint32_t {
63         /** Defines whether this material receives shadow */
64         SHADOW_RECEIVER_BIT = (1 << 0),
65         /** Defines whether this material is a shadow caster */
66         SHADOW_CASTER_BIT = (1 << 1),
67         /** Defines whether this material will receive light from punctual lights (points, spots, directional) */
68         PUNCTUAL_LIGHT_RECEIVER_BIT = (1 << 2),
69         /** Defines whether this material will receive indirect light from SH and cubemaps */
70         INDIRECT_LIGHT_RECEIVER_BIT = (1 << 3),
71     };
72     /** Container for material flag bits */
73     using LightingFlags = uint32_t;
74 
75     /** Rendering flags (specialized rendering flags) */
76     enum ExtraRenderingFlagBits : uint32_t {
77         /** Is an additional flag which can be used to discard some materials from rendering from render node graph */
78         DISCARD_BIT = (1 << 0),
79         /** Is an additional flag which disables default render system push to render data stores and rendering */
80         DISABLE_BIT = (1 << 1),
81         /** Allow rendering mutiple instances of the same mesh using GPU instancing. materialShader must support
82            instancing. */
83         ALLOW_GPU_INSTANCING_BIT = (1 << 2),
84     };
85     /** Container for extra material rendering flag bits */
86     using ExtraRenderingFlags = uint32_t;
87 
88     /** Needs to match the texture ordering with default material shader pipeline layout. The names are for default
89      * materials.
90      *
91      * For other predefined material shaders included in 3D:
92      *
93      * "core3d_dm_fw_reflection_plane.shader":
94      * CLEARCOAT_ROUGHNESS index has been reserved for reflection image.
95      */
96     enum TextureIndex : uint8_t {
97         /** basecolor texture (expected to be premultiplied alpha) (aka. diffuse for specular-glossiness)*/
98         BASE_COLOR,
99         /** normal map texture */
100         NORMAL,
101         /** metallic-roughness or specular-glossiness texture */
102         MATERIAL,
103         /** emissive texture */
104         EMISSIVE,
105         /** ambient-occlusion texture */
106         AO,
107 
108         /** clearcoat intensity texture */
109         CLEARCOAT,
110         /** clearcoat roughness texture */
111         CLEARCOAT_ROUGHNESS,
112         /** clearcoat normal map texture */
113         CLEARCOAT_NORMAL,
114 
115         /** sheen color texture in rgb, sheen roughness in alpha */
116         SHEEN,
117 
118         /** transmission percentage texture */
119         TRANSMISSION,
120 
121         /** specular color and reflection strength texture */
122         SPECULAR,
123 
124         /** number of textures */
125         TEXTURE_COUNT
126     };
127 
128     /** Channel mapping for materials using Type::METALLIC_ROUGHNESS
129      *  that can be used to access a specific channel in a TextureIndex::MATERIAL texture.
130      */
131     enum MetallicRoughnessChannel : uint8_t {
132         /** Index of the roughness channel in the material texture. */
133         ROUGHNESS = 1,
134 
135         /** Index of the metallic channel in the material texture. */
136         METALLIC,
137     };
138 
139     /** Channel mapping for materials using Type::SPECULAR_GLOSSINESS
140      *  that can be used to access a specific channel in a TextureIndex::MATERIAL texture.
141      */
142     enum SpecularGlossinessChannel : uint8_t {
143         /** Index of the specular red channel in the material texture. */
144         SPECULAR_R = 0,
145 
146         /** Index of the specular green channel in the material texture. */
147         SPECULAR_G,
148 
149         /** Index of the specular blue channel in the material texture. */
150         SPECULAR_B,
151 
152         /** Index of the glossiness channel in the material texture. */
153         GLOSSINESS,
154     };
155 
156     struct TextureTransform {
157         BASE_NS::Math::Vec2 translation { 0.f, 0.f };
158         float rotation { 0.f };
159         BASE_NS::Math::Vec2 scale { 1.f, 1.f };
160     };
161 
162     struct TextureInfo {
163         CORE_NS::EntityReference image;
164         CORE_NS::EntityReference sampler;
165         BASE_NS::Math::Vec4 factor;
166         TextureTransform transform;
167     };
168 
169     /** Default material component shader */
170     struct Shader {
171         /** Shader to be used. (If invalid, a default is chosen by the default material renderer)
172          * NOTE: the material medata and custom properties are updated when the shader is updated.
173          */
174         CORE_NS::EntityReference shader;
175         /** Shader graphics state to be used. (If invalid, a default is chosen by the default material renderer) */
176         CORE_NS::EntityReference graphicsState;
177     };
178 #endif
179     /** Material type which can be one of the following Type::METALLIC_ROUGHNESS, Type::SPECULAR_GLOSSINESS */
180     DEFINE_PROPERTY(Type, type, "Material Type", 0, VALUE(Type::METALLIC_ROUGHNESS))
181 
182     /** Alpha cut off value, set the cutting value for alpha (0.0 - 1.0). Below 1.0 starts to affect.
183      */
184     DEFINE_PROPERTY(float, alphaCutoff, "Alpha Cutoff", 0, VALUE(1.0f))
185 
186     /** Material lighting flags that define the lighting related settings for this material */
187     DEFINE_BITFIELD_PROPERTY(LightingFlags, materialLightingFlags, "Material Lighting Flags",
188         PropertyFlags::IS_BITFIELD,
189         VALUE(MaterialComponent::LightingFlagBits::SHADOW_RECEIVER_BIT |
190               MaterialComponent::LightingFlagBits::SHADOW_CASTER_BIT |
191               MaterialComponent::LightingFlagBits::PUNCTUAL_LIGHT_RECEIVER_BIT |
192               MaterialComponent::LightingFlagBits::INDIRECT_LIGHT_RECEIVER_BIT),
193         MaterialComponent::LightingFlagBits)
194 
195     /** Material shader. Prefer using automatic selection (or editor selection) if no custom shaders.
196      * Needs to match default material layouts and specializations (api/3d/shaders/common).
197      * If no default slot given to shader default material shader slots are used automatically.
198      * Therefore, do not set slots and their graphics states if no special handling is needed.
199      * Use OPAQUE_FW core3d_dm_fw.shader as an example reference.
200      * (I.e. if one wants to things just work, do not specify slots or additional custom graphics states per slots)
201      * NOTE: when material shader is updated the possible material metadata and custom properties are updated
202      * NOTE: one needs to reload the shader file(s) with shader manager to get dynamic updated custom property data
203      */
204     DEFINE_PROPERTY(Shader, materialShader, "Material Shader", 0, )
205 
206     /** Depth shader. Prefer using automatic selection (or editor selection) if no custom shaders.
207      * Needs to match default material layouts and specializations (api/3d/shaders/common).
208      * If no default slot given to shader default material shader slots are used automatically.
209      * (I.e. if one wants to things just work, do not specify slots or additional custom graphics states per slots)
210      */
211     DEFINE_PROPERTY(Shader, depthShader, "Depth Shader", 0, )
212 
213     /** Extra material rendering flags define special rendering hints */
214     DEFINE_BITFIELD_PROPERTY(ExtraRenderingFlags, extraRenderingFlags, "ExtraRenderingFlags",
215         PropertyFlags::IS_BITFIELD, VALUE(0u), MaterialComponent::ExtraRenderingFlagBits)
216 
217     /** Array of texture information. With default shaders TextureIndex is used for identifying texures for different
218      * material properties. Use of TextureInfo::factor depends on the index.
219      *
220      * BASE_COLOR: RGBA, base color, if an image is specified, this value is multiplied with the texel values.
221      * NOTE: the pre-multiplication is done always, i.e. use only for base color with custom materials
222      * NOTE: the built-in default material shaders write out alpha values from 0.0 - 1.0
223      *       opaque flag is enabled to shader is graphics state's blending mode is not active -> alpha 1.0
224      *
225      * NORMAL: R, normal scale, scalar multiplier applied to each normal vector of the texture. (Ignored if image is not
226      * specified, this value is linear).
227      *
228      * MATERIAL: For Type::METALLIC_ROUGHNESS: G roughness (smooth 0.0 - 1.0 rough), B metallic (dielectric 0.0 - 1.0
229      * metallic)., and A reflectance at normal incidence
230      * For Type::SPECULAR_GLOSSINESS: RGB specular color (linear), A glossiness (rough 0.0 - 1.0 glossy). Texel values
231      * are multiplied with the corresponding factors.
232      *
233      * EMISSIVE: RGB, emissive color, A intensity, if an image is specified, this value is multiplied with the texel
234      * values.
235      *
236      * AO: R, ambient occlusion factor, this value is multiplied with the texel values (no ao 0.0 - 1.0 full ao)
237      *
238      * CLEARCOAT: R, clearcoat layer intensity, if an image is specified, this value is multiplied with the texel
239      * values.
240      *
241      * CLEARCOAT_ROUGHNESS: G, clearcoat layer roughness, if an image is specified, this value is multiplied with the
242      * texel values.
243      *
244      * CLEARCOAT_NORMAL: RGB, clearcoat normal scale, scalar multiplier applied to each normal vector of the clearcoat
245      * normal texture.
246      *
247      * SHEEN: RGB, sheen color, if an image is specified, this value is multiplied with the texel values.
248      * SHEEN: A, sheen roughness, if an image is specified, this value is multiplied with the texel values.
249      *
250      * TRANSMISSION: R, Percentage of light that is transmitted through the surface, if an image is specified, this
251      * value is multiplied with the texel values.
252      *
253      * SPECULAR: RGB color of the specular reflection, A strength of the specular reflection, if an image is specified,
254      * this value is multiplied with the texel values.
255      */
256     DEFINE_ARRAY_PROPERTY(TextureInfo, TextureIndex::TEXTURE_COUNT, textures, "", PropertyFlags::IS_HIDDEN,
257         ARRAY_VALUE(                                              //
258             TextureInfo { {}, {}, { 1.f, 1.f, 1.f, 1.f }, {} },   // base color opaque white
259             TextureInfo { {}, {}, { 1.f, 0.f, 0.f, 0.f }, {} },   // normal scale 1
260             TextureInfo { {}, {}, { 0.f, 1.f, 1.f, 0.04f }, {} }, // material (empty, roughness, metallic, reflectance)
261             TextureInfo { {}, {}, { 0.f, 0.f, 0.f, 1.f }, {} },   // emissive 0
262             TextureInfo { {}, {}, { 1.f, 0.f, 0.f, 0.f }, {} },   // ambient occlusion 1
263             TextureInfo { {}, {}, { 0.f, 0.f, 0.f, 0.f }, {} },   // clearcoat intensity 0
264             TextureInfo { {}, {}, { 0.f, 0.f, 0.f, 0.f }, {} },   // clearcoat roughness 0
265             TextureInfo { {}, {}, { 1.f, 0.f, 0.f, 0.f }, {} },   // clearcoat normal scale 1
266             TextureInfo { {}, {}, { 0.f, 0.f, 0.f, 0.f }, {} },   // sheen color black, roughness 0
267             TextureInfo { {}, {}, { 0.f, 0.f, 0.f, 0.f }, {} },   // transmission 0
268             TextureInfo { {}, {}, { 1.f, 1.f, 1.f, 1.f }, {} }    // specular white
269             ))
270 
271     /** Texture coordinates from set 0 or 1. */
272     DEFINE_PROPERTY(uint32_t, useTexcoordSetBit, "Active Texture Coordinate", 0,
273         VALUE(0u)) // if uses set 1 (1 << enum TextureIndex)
274 
275     /** Custom forced render slot id. One can force rendering with e.g. opaque or translucent render slots */
276     DEFINE_PROPERTY(uint32_t, customRenderSlotId, "Custom Render Slot ID", ~0, VALUE(~0u))
277 
278     /** Custom material extension resources. Deprecates and prevents MaterialExtensionComponent usage.
279      * Are automatically bound to custom shader, custom pipeline layout custom descriptor set if they are in order.
280      */
281     DEFINE_PROPERTY(
282         BASE_NS::vector<CORE_NS::EntityReference>, customResources, "Custom Material Extension Resources", 0, )
283 
284     /** Per material additional user property data which is passed to shader UBO.
285      * Max size is 256 bytes.
286      */
287     DEFINE_PROPERTY(CORE_NS::IPropertyHandle*, customProperties, "Custom Properties", 0, VALUE(nullptr))
288 
289 END_COMPONENT(IMaterialComponentManager, MaterialComponent, "56430c14-cb12-4320-80d3-2bef4f86a041")
290 #if !defined(IMPLEMENT_MANAGER)
291 CORE3D_END_NAMESPACE()
292 #endif
293 #endif
294