Blender V5.0
eevee_material.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "DNA_material_types.h"
12
13#include "DRW_render.hh"
14
15#include "BLI_map.hh"
16#include "BLI_vector.hh"
17#include "GPU_material.hh"
18
19#include "draw_pass.hh"
20
22#include "eevee_shader.hh"
23#include "eevee_sync.hh"
24
27
28namespace blender::eevee {
29
30class Instance;
31
32/* -------------------------------------------------------------------- */
36
37static inline bool geometry_type_has_surface(eMaterialGeometry geometry_type)
38{
39 return geometry_type < MAT_GEOM_VOLUME;
40}
41
46
47static inline eMaterialDisplacement to_displacement_type(int displacement_method)
48{
49 switch (displacement_method) {
51 /* Currently unsupported. Revert to vertex displacement + bump. */
55 default:
57 }
58}
59
61 /* These maps directly to thickness mode. */
64};
65
66static inline eMaterialThickness to_thickness_type(int thickness_mode)
67{
68 switch (thickness_mode) {
70 return MAT_THICKNESS_SLAB;
71 default:
73 }
74}
75
81
82static inline void material_type_from_shader_uuid(uint64_t shader_uuid,
83 eMaterialPipeline &pipeline_type,
84 eMaterialGeometry &geometry_type,
85 eMaterialDisplacement &displacement_type,
86 eMaterialThickness &thickness_type,
87 bool &transparent_shadows)
88{
89 const uint64_t geometry_mask = ((1u << 4u) - 1u);
90 const uint64_t pipeline_mask = ((1u << 4u) - 1u);
91 const uint64_t thickness_mask = ((1u << 1u) - 1u);
92 const uint64_t displacement_mask = ((1u << 1u) - 1u);
93 geometry_type = static_cast<eMaterialGeometry>(shader_uuid & geometry_mask);
94 pipeline_type = static_cast<eMaterialPipeline>((shader_uuid >> 4u) & pipeline_mask);
95 displacement_type = static_cast<eMaterialDisplacement>((shader_uuid >> 8u) & displacement_mask);
96 thickness_type = static_cast<eMaterialThickness>((shader_uuid >> 9u) & thickness_mask);
97 transparent_shadows = (shader_uuid >> 10u) & 1u;
98}
99
101 eMaterialPipeline pipeline_type,
102 eMaterialGeometry geometry_type,
105 char blend_flags = 0)
106{
107 BLI_assert(int64_t(displacement_type) < (1 << 1));
108 BLI_assert(int64_t(thickness_type) < (1 << 1));
109 BLI_assert(int64_t(geometry_type) < (1 << 4));
110 BLI_assert(int64_t(pipeline_type) < (1 << 4));
111 uint64_t transparent_shadows = blend_flags & MA_BL_TRANSPARENT_SHADOW ? 1 : 0;
112
113 uint64_t uuid;
114 uuid = geometry_type;
115 uuid |= pipeline_type << 4;
116 uuid |= displacement_type << 8;
117 uuid |= thickness_type << 9;
118 uuid |= transparent_shadows << 10;
119 return uuid;
120}
121
140
142{
143 eClosureBits closure_bits = eClosureBits(0);
145 closure_bits |= CLOSURE_DIFFUSE;
146 }
148 closure_bits |= CLOSURE_TRANSPARENCY;
149 }
151 closure_bits |= CLOSURE_TRANSLUCENT;
152 }
154 closure_bits |= CLOSURE_EMISSION;
155 }
157 closure_bits |= CLOSURE_REFLECTION;
158 }
160 closure_bits |= CLOSURE_CLEARCOAT;
161 }
163 closure_bits |= CLOSURE_SSS;
164 }
166 closure_bits |= CLOSURE_REFRACTION;
167 }
169 closure_bits |= CLOSURE_HOLDOUT;
170 }
172 closure_bits |= CLOSURE_AMBIENT_OCCLUSION;
173 }
175 closure_bits |= CLOSURE_SHADER_TO_RGBA;
176 }
177 return closure_bits;
178}
179
180/* Count the number of closure bins required for the given combination of closure types. */
181static inline int to_gbuffer_bin_count(const eClosureBits closure_bits)
182{
183 int closure_data_slots = 0;
184 if (closure_bits & CLOSURE_DIFFUSE) {
185 if ((closure_bits & CLOSURE_TRANSLUCENT) && !(closure_bits & CLOSURE_CLEARCOAT)) {
186 /* Special case to allow translucent with diffuse without noise.
187 * Revert back to noise if clear coat is present. */
188 closure_data_slots |= (1 << 2);
189 }
190 else {
191 closure_data_slots |= (1 << 0);
192 }
193 }
194 if (closure_bits & CLOSURE_SSS) {
195 closure_data_slots |= (1 << 0);
196 }
197 if (closure_bits & CLOSURE_REFRACTION) {
198 closure_data_slots |= (1 << 0);
199 }
200 if (closure_bits & CLOSURE_TRANSLUCENT) {
201 closure_data_slots |= (1 << 0);
202 }
203 if (closure_bits & CLOSURE_REFLECTION) {
204 closure_data_slots |= (1 << 1);
205 }
206 if (closure_bits & CLOSURE_CLEARCOAT) {
207 closure_data_slots |= (1 << 2);
208 }
209 return count_bits_i(closure_data_slots);
210};
211
213{
214 switch (ob->type) {
215 case OB_CURVES:
216 return MAT_GEOM_CURVES;
217 case OB_VOLUME:
218 return MAT_GEOM_VOLUME;
219 case OB_POINTCLOUD:
220 return MAT_GEOM_POINTCLOUD;
221 default:
222 return MAT_GEOM_MESH;
223 }
224}
225
233
236 eMaterialPipeline pipeline,
237 short visibility_flags)
238 : mat(mat_)
239 {
241 geometry,
244 mat_->blend_flag);
245 options = (options << 1) | (visibility_flags & OB_HIDE_CAMERA ? 0 : 1);
246 options = (options << 1) | (visibility_flags & OB_HIDE_SHADOW ? 0 : 1);
247 options = (options << 1) | (visibility_flags & OB_HIDE_PROBE_CUBEMAP ? 0 : 1);
248 options = (options << 1) | (visibility_flags & OB_HIDE_PROBE_PLANAR ? 0 : 1);
249 }
250
252 {
253 return uint64_t(mat) + options;
254 }
255
256 bool operator==(const MaterialKey &k) const
257 {
258 return (mat == k.mat) && (options == k.options);
259 }
260};
261
263
264/* -------------------------------------------------------------------- */
268
275struct ShaderKey {
278
279 ShaderKey(GPUMaterial *gpumat, ::Material *blender_mat, eMaterialProbe probe_capture)
280 {
283 options = (options << 8) | blender_mat->blend_flag;
284 options = (options << 2) | uint64_t(probe_capture);
285 }
286
288 {
289 return uint64_t(shader) + options;
290 }
291
292 bool operator==(const ShaderKey &k) const
293 {
294 return (shader == k.shader) && (options == k.options);
295 }
296};
297
299
300/* -------------------------------------------------------------------- */
304
309
327
332
334 public:
339
341
345
346 private:
347 Instance &inst_;
348
349 Map<MaterialKey, Material> material_map_;
351
352 MaterialArray material_array_;
353
354 ::Material *error_mat_;
355
356 uint64_t gpu_pass_last_update_ = 0;
357 uint64_t gpu_pass_next_update_ = 0;
358
359 Vector<GPUMaterialTexture *> texture_loading_queue_;
360
361 public:
364
365 void begin_sync();
366 void end_sync();
367
371 MaterialArray &material_array_get(Object *ob, bool has_motion);
376 Material &material_get(Object *ob, bool has_motion, int mat_nr, eMaterialGeometry geometry_type);
377
378 /* Request default materials and return DEFAULT_MATERIALS if they are compiled. */
380 {
381 return default_materials_load(false);
382 }
384 {
385 return default_materials_load(true);
386 }
387
388 private:
389 Material &material_sync(Object *ob,
390 ::Material *blender_mat,
391 eMaterialGeometry geometry_type,
392 bool has_motion);
393
395 ::Material *material_from_slot(Object *ob, int slot);
396 MaterialPass material_pass_get(Object *ob,
397 ::Material *blender_mat,
398 eMaterialPipeline pipeline_type,
399 eMaterialGeometry geometry_type,
400 eMaterialProbe probe_capture = MAT_PROBE_NONE);
401
402 /* Push unloaded texture used by this material to the texture loading queue. */
403 void queue_texture_loading(GPUMaterial *material);
404
405 ShaderGroups default_materials_load(bool block_until_ready = false);
406};
407
409
410} // namespace blender::eevee
#define BLI_assert(a)
Definition BLI_assert.h:46
#define ATTR_FALLTHROUGH
MINLINE int count_bits_i(unsigned int n)
#define ENUM_OPERATORS(_type, _max)
@ MA_BL_TRANSPARENT_SHADOW
@ MA_THICKNESS_SLAB
@ MA_DISPLACEMENT_BOTH
@ MA_DISPLACEMENT_DISPLACE
@ OB_HIDE_CAMERA
@ OB_HIDE_PROBE_PLANAR
@ OB_HIDE_PROBE_CUBEMAP
@ OB_HIDE_SHADOW
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES
blender::gpu::Shader * GPU_material_get_shader(GPUMaterial *material)
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
@ GPU_MATFLAG_SHADER_TO_RGBA
@ GPU_MATFLAG_EMISSION
@ GPU_MATFLAG_GLOSSY
@ GPU_MATFLAG_COAT
@ GPU_MATFLAG_AO
@ GPU_MATFLAG_REFRACT
@ GPU_MATFLAG_TRANSLUCENT
@ GPU_MATFLAG_HOLDOUT
@ GPU_MATFLAG_DIFFUSE
@ GPU_MATFLAG_TRANSPARENT
@ GPU_MATFLAG_SUBSURFACE
long long int int64_t
unsigned long long int uint64_t
detail::PassBase< command::DrawMultiBuf > Sub
Definition draw_pass.hh:499
A running instance of the engine.
ShaderGroups default_materials_load_async()
Material & material_get(Object *ob, bool has_motion, int mat_nr, eMaterialGeometry geometry_type)
MaterialArray & material_array_get(Object *ob, bool has_motion)
ShaderGroups default_materials_wait_ready()
static eMaterialDisplacement to_displacement_type(int displacement_method)
static bool geometry_type_has_surface(eMaterialGeometry geometry_type)
static eMaterialGeometry to_material_geometry(const Object *ob)
static eClosureBits shader_closure_bits_from_flag(const GPUMaterial *gpumat)
static void material_type_from_shader_uuid(uint64_t shader_uuid, eMaterialPipeline &pipeline_type, eMaterialGeometry &geometry_type, eMaterialDisplacement &displacement_type, eMaterialThickness &thickness_type, bool &transparent_shadows)
static uint64_t shader_uuid_from_material_type(eMaterialPipeline pipeline_type, eMaterialGeometry geometry_type, eMaterialDisplacement displacement_type=MAT_DISPLACEMENT_BUMP, eMaterialThickness thickness_type=MAT_THICKNESS_SPHERE, char blend_flags=0)
static int to_gbuffer_bin_count(const eClosureBits closure_bits)
static eMaterialThickness to_thickness_type(int thickness_mode)
@ MAT_DISPLACEMENT_VERTEX_WITH_BUMP
Vector< GPUMaterial * > gpu_materials
MaterialKey(::Material *mat_, eMaterialGeometry geometry, eMaterialPipeline pipeline, short visibility_flags)
bool operator==(const MaterialKey &k) const
MaterialPass lightprobe_sphere_shading
MaterialPass lightprobe_sphere_prepass
ShaderKey(GPUMaterial *gpumat, ::Material *blender_mat, eMaterialProbe probe_capture)
bool operator==(const ShaderKey &k) const