Blender V4.5
eevee_material.cc
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#include "BLI_time.h"
10#include "DNA_material_types.h"
11
12#include "BKE_lib_id.hh"
13#include "BKE_material.hh"
14#include "BKE_node.hh"
16
17#include "NOD_shader.h"
18
19#include "eevee_instance.hh"
20#include "eevee_material.hh"
21
22namespace blender::eevee {
23
24/* -------------------------------------------------------------------- */
28
30{
31 bNodeTree *ntree = bke::node_tree_add_tree(nullptr, "Shader Nodetree", ntreeType_Shader->idname);
34 bNodeSocket *bsdf_out = bke::node_find_socket(*bsdf, SOCK_OUT, "BSDF");
35 bNodeSocket *output_in = bke::node_find_socket(*output, SOCK_IN, "Surface");
36 bke::node_add_link(*ntree, *bsdf, *bsdf_out, *output, *output_in);
38
39 color_socket_ =
40 (bNodeSocketValueRGBA *)bke::node_find_socket(*bsdf, SOCK_IN, "Base Color")->default_value;
41 metallic_socket_ =
42 (bNodeSocketValueFloat *)bke::node_find_socket(*bsdf, SOCK_IN, "Metallic")->default_value;
43 roughness_socket_ =
44 (bNodeSocketValueFloat *)bke::node_find_socket(*bsdf, SOCK_IN, "Roughness")->default_value;
45 specular_socket_ = (bNodeSocketValueFloat *)bke::node_find_socket(
46 *bsdf, SOCK_IN, "Specular IOR Level")
47 ->default_value;
48 ntree_ = ntree;
49}
50
56
58{
59 /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
60 copy_v3_fl3(color_socket_->value, ma->r, ma->g, ma->b);
61 metallic_socket_->value = ma->metallic;
62 roughness_socket_->value = ma->roughness;
63 specular_socket_->value = ma->spec;
64
65 return ntree_;
66}
67
69
70/* -------------------------------------------------------------------- */
74
76{
77 {
78 diffuse_mat = BKE_id_new_nomain<::Material>("EEVEE default diffuse");
80 nullptr, &diffuse_mat->id, "Shader Nodetree", ntreeType_Shader->idname);
81 diffuse_mat->use_nodes = true;
82 diffuse_mat->surface_render_method = MA_SURFACE_METHOD_FORWARD;
83
84 /* Use 0.18 as it is close to middle gray. Middle gray is typically defined as 18% reflectance
85 * of visible light and commonly used for VFX balls. */
87 bNodeSocket *base_color = bke::node_find_socket(*bsdf, SOCK_IN, "Color");
88 copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.18f);
89
91
92 bke::node_add_link(*ntree,
93 *bsdf,
94 *bke::node_find_socket(*bsdf, SOCK_OUT, "BSDF"),
95 *output,
96 *bke::node_find_socket(*output, SOCK_IN, "Surface"));
97
99 }
100 {
101 metallic_mat = BKE_id_new_nomain<::Material>("EEVEE default metal");
103 nullptr, &metallic_mat->id, "Shader Nodetree", ntreeType_Shader->idname);
104 metallic_mat->use_nodes = true;
105 metallic_mat->surface_render_method = MA_SURFACE_METHOD_FORWARD;
106
107 bNode *bsdf = bke::node_add_static_node(nullptr, *ntree, SH_NODE_BSDF_GLOSSY);
108 bNodeSocket *base_color = bke::node_find_socket(*bsdf, SOCK_IN, "Color");
109 copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f);
110 bNodeSocket *roughness = bke::node_find_socket(*bsdf, SOCK_IN, "Roughness");
111 ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f;
112
114
115 bke::node_add_link(*ntree,
116 *bsdf,
117 *bke::node_find_socket(*bsdf, SOCK_OUT, "BSDF"),
118 *output,
119 *bke::node_find_socket(*output, SOCK_IN, "Surface"));
120
122 }
123 {
124 default_surface = reinterpret_cast<::Material *>(BKE_id_copy_ex(
125 nullptr, &BKE_material_default_surface()->id, nullptr, LIB_ID_COPY_LOCALIZE));
126 default_volume = reinterpret_cast<::Material *>(BKE_id_copy_ex(
127 nullptr, &BKE_material_default_volume()->id, nullptr, LIB_ID_COPY_LOCALIZE));
128 }
129 {
130 error_mat_ = BKE_id_new_nomain<::Material>("EEVEE default error");
132 nullptr, &error_mat_->id, "Shader Nodetree", ntreeType_Shader->idname);
133 error_mat_->use_nodes = true;
134
135 /* Use emission and output material to be compatible with both World and Material. */
136 bNode *bsdf = bke::node_add_static_node(nullptr, *ntree, SH_NODE_EMISSION);
138 copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f);
139
141
142 bke::node_add_link(*ntree,
143 *bsdf,
144 *bke::node_find_socket(*bsdf, SOCK_OUT, "Emission"),
145 *output,
146 *bke::node_find_socket(*output, SOCK_IN, "Surface"));
147
149 }
150}
151
153{
154 BKE_id_free(nullptr, metallic_mat);
155 BKE_id_free(nullptr, diffuse_mat);
157 BKE_id_free(nullptr, default_volume);
158 BKE_id_free(nullptr, error_mat_);
159}
160
162{
166
168 gpu_pass_last_update_ = gpu_pass_next_update_;
169 gpu_pass_next_update_ = next_update;
170
171 texture_loading_queue_.clear();
172 material_map_.clear();
173 shader_map_.clear();
174}
175
176void MaterialModule::queue_texture_loading(GPUMaterial *material)
177{
178 ListBase textures = GPU_material_textures(material);
180 if (tex->ima) {
181 const bool use_tile_mapping = tex->tiled_mapping_name[0];
182 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
184 tex->ima, iuser, use_tile_mapping);
185 if (*gputex.texture == nullptr) {
186 texture_loading_queue_.append(tex);
187 }
188 }
189 }
190}
191
193{
194 if (texture_loading_queue_.is_empty()) {
195 return;
196 }
197
198 if (inst_.is_viewport()) {
199 /* Avoid ghosting of textures. */
200 inst_.sampling.reset();
201 }
202
203 GPU_debug_group_begin("Texture Loading");
204
205 /* Load files from disk in a multithreaded manner. Allow better parallelism. */
206 threading::parallel_for(texture_loading_queue_.index_range(), 1, [&](const IndexRange range) {
207 for (auto i : range) {
208 GPUMaterialTexture *tex = texture_loading_queue_[i];
209 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
210 BKE_image_get_tile(tex->ima, 0);
211 threading::isolate_task([&]() {
212 ImBuf *imbuf = BKE_image_acquire_ibuf(tex->ima, iuser, nullptr);
213 BKE_image_release_ibuf(tex->ima, imbuf, nullptr);
214 });
215 }
216 });
217
218 /* Tag time is not thread-safe. */
219 for (GPUMaterialTexture *tex : texture_loading_queue_) {
220 BKE_image_tag_time(tex->ima);
221 }
222
223 /* Upload to the GPU (create GPUTexture). This part still requires a valid GPU context and
224 * is not easily parallelized. */
225 for (GPUMaterialTexture *tex : texture_loading_queue_) {
226 BLI_assert(tex->ima);
227 GPU_debug_group_begin(tex->ima->id.name);
228
229 const bool use_tile_mapping = tex->tiled_mapping_name[0];
230 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
232 tex->ima, iuser, use_tile_mapping);
233
234 /* Acquire the textures since they were not existing inside `PassBase::material_set()`. */
235 inst_.manager->acquire_texture(*gputex.texture);
236 if (gputex.tile_mapping) {
237 inst_.manager->acquire_texture(*gputex.tile_mapping);
238 }
239
241 }
243 texture_loading_queue_.clear();
244}
245
246MaterialPass MaterialModule::material_pass_get(Object *ob,
247 ::Material *blender_mat,
248 eMaterialPipeline pipeline_type,
249 eMaterialGeometry geometry_type,
250 eMaterialProbe probe_capture)
251{
252 bNodeTree *ntree = (blender_mat->use_nodes && blender_mat->nodetree != nullptr) ?
253 blender_mat->nodetree :
254 default_surface_ntree_.nodetree_get(blender_mat);
255
256 /* We can't defer compilation in viewport image render, since we can't re-sync.(See #130235) */
257 bool use_deferred_compilation = !inst_.is_viewport_image_render;
258
259 const bool is_volume = ELEM(pipeline_type, MAT_PIPE_VOLUME_OCCUPANCY, MAT_PIPE_VOLUME_MATERIAL);
260 ::Material *default_mat = is_volume ? default_volume : default_surface;
261
262 MaterialPass matpass = MaterialPass();
263 matpass.gpumat = inst_.shaders.material_shader_get(
264 blender_mat, ntree, pipeline_type, geometry_type, use_deferred_compilation, default_mat);
265
266 queue_texture_loading(matpass.gpumat);
267
268 const bool is_forward = ELEM(pipeline_type,
269 MAT_PIPE_FORWARD,
270 MAT_PIPE_PREPASS_FORWARD,
271 MAT_PIPE_PREPASS_FORWARD_VELOCITY,
272 MAT_PIPE_PREPASS_OVERLAP);
273
274 switch (GPU_material_status(matpass.gpumat)) {
275 case GPU_MAT_SUCCESS: {
276 /* Determine optimization status for remaining compilations counter. */
277 int optimization_status = GPU_material_optimization_status(matpass.gpumat);
278 if (optimization_status == GPU_MAT_OPTIMIZATION_QUEUED) {
279 queued_optimize_shaders_count++;
280 }
281 break;
282 }
283 case GPU_MAT_QUEUED:
284 queued_shaders_count++;
285 matpass.gpumat = inst_.shaders.material_shader_get(
286 default_mat, default_mat->nodetree, pipeline_type, geometry_type, false, nullptr);
287 break;
288 case GPU_MAT_FAILED:
289 default:
290 matpass.gpumat = inst_.shaders.material_shader_get(
291 error_mat_, error_mat_->nodetree, pipeline_type, geometry_type, false, nullptr);
292 break;
293 }
294 /* Returned material should be ready to be drawn. */
296
297 inst_.manager->register_layer_attributes(matpass.gpumat);
298
299 const bool is_transparent = GPU_material_flag_get(matpass.gpumat, GPU_MATFLAG_TRANSPARENT);
300
301 bool pass_updated = GPU_material_compilation_timestamp(matpass.gpumat) > gpu_pass_last_update_;
302
303 if (inst_.is_viewport() && use_deferred_compilation && pass_updated) {
304 inst_.sampling.reset();
305
306 const bool has_displacement = GPU_material_has_displacement_output(matpass.gpumat) &&
308 const bool has_volume = GPU_material_has_volume_output(matpass.gpumat);
309
310 if (((pipeline_type == MAT_PIPE_SHADOW) && (is_transparent || has_displacement)) || has_volume)
311 {
312 /* WORKAROUND: This is to avoid lingering shadows from default material.
313 * Ideally, we should tag the caster object to update only the needed areas but that's a bit
314 * more involved. */
315 inst_.shadows.reset();
316 }
317 }
318
319 if (is_volume || (is_forward && is_transparent)) {
320 /* Sub pass is generated later. */
321 matpass.sub_pass = nullptr;
322 }
323 else {
324 ShaderKey shader_key(matpass.gpumat, blender_mat, probe_capture);
325
326 PassMain::Sub *shader_sub = shader_map_.lookup_or_add_cb(shader_key, [&]() {
327 /* First time encountering this shader. Create a sub that will contain materials using it. */
328 return inst_.pipelines.material_add(
329 ob, blender_mat, matpass.gpumat, pipeline_type, probe_capture);
330 });
331
332 if (shader_sub != nullptr) {
333 /* Create a sub for this material as `shader_sub` is for sharing shader between materials. */
334 matpass.sub_pass = &shader_sub->sub(GPU_material_get_name(matpass.gpumat));
335 matpass.sub_pass->material_set(*inst_.manager, matpass.gpumat, true);
336 }
337 else {
338 matpass.sub_pass = nullptr;
339 }
340 }
341
342 return matpass;
343}
344
345Material &MaterialModule::material_sync(Object *ob,
346 ::Material *blender_mat,
347 eMaterialGeometry geometry_type,
348 bool has_motion)
349{
350 bool hide_on_camera = ob->visibility_flag & OB_HIDE_CAMERA;
351
352 if (geometry_type == MAT_GEOM_VOLUME) {
353 MaterialKey material_key(
354 blender_mat, geometry_type, MAT_PIPE_VOLUME_MATERIAL, ob->visibility_flag);
355 Material &mat = material_map_.lookup_or_add_cb(material_key, [&]() {
356 Material mat = {};
357 mat.volume_occupancy = material_pass_get(
358 ob, blender_mat, MAT_PIPE_VOLUME_OCCUPANCY, MAT_GEOM_VOLUME);
359 mat.volume_material = material_pass_get(
360 ob, blender_mat, MAT_PIPE_VOLUME_MATERIAL, MAT_GEOM_VOLUME);
361 return mat;
362 });
363
364 /* Volume needs to use one sub pass per object to support layering. */
365 VolumeLayer *layer = hide_on_camera ? nullptr :
366 inst_.pipelines.volume.register_and_get_layer(ob);
367 if (layer) {
368 mat.volume_occupancy.sub_pass = layer->occupancy_add(
369 ob, blender_mat, mat.volume_occupancy.gpumat);
370 mat.volume_material.sub_pass = layer->material_add(
371 ob, blender_mat, mat.volume_material.gpumat);
372 }
373 else {
374 /* Culled volumes. */
375 mat.volume_occupancy.sub_pass = nullptr;
376 mat.volume_material.sub_pass = nullptr;
377 }
378 return mat;
379 }
380
381 const bool use_forward_pipeline = (blender_mat->surface_render_method ==
383 eMaterialPipeline surface_pipe, prepass_pipe;
384 if (use_forward_pipeline) {
385 surface_pipe = MAT_PIPE_FORWARD;
387 }
388 else {
389 surface_pipe = MAT_PIPE_DEFERRED;
391 }
392
393 MaterialKey material_key(blender_mat, geometry_type, surface_pipe, ob->visibility_flag);
394
395 Material &mat = material_map_.lookup_or_add_cb(material_key, [&]() {
396 Material mat;
397 if (inst_.is_baking()) {
399 mat.capture = MaterialPass();
400 }
401 else {
402 mat.capture = material_pass_get(ob, blender_mat, MAT_PIPE_CAPTURE, geometry_type);
403 }
404 mat.prepass = MaterialPass();
405 /* TODO(fclem): Still need the shading pass for correct attribute extraction. Would be better
406 * to avoid this shader compilation in another context. */
407 mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
408 mat.overlap_masking = MaterialPass();
409 mat.lightprobe_sphere_prepass = MaterialPass();
410 mat.lightprobe_sphere_shading = MaterialPass();
411 mat.planar_probe_prepass = MaterialPass();
412 mat.planar_probe_shading = MaterialPass();
413 mat.volume_occupancy = MaterialPass();
414 mat.volume_material = MaterialPass();
415 mat.has_volume = false; /* TODO */
416 mat.has_surface = GPU_material_has_surface_output(mat.shading.gpumat);
417 }
418 else {
419 /* Order is important for transparent. */
420 if (!hide_on_camera) {
421 mat.prepass = material_pass_get(ob, blender_mat, prepass_pipe, geometry_type);
422 }
423 else {
424 mat.prepass = MaterialPass();
425 }
426
427 mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
428 if (hide_on_camera) {
429 /* Only null the sub_pass.
430 * `mat.shading.gpumat` is always needed for using the GPU_material API. */
431 mat.shading.sub_pass = nullptr;
432 }
433
434 mat.overlap_masking = MaterialPass();
435 mat.capture = MaterialPass();
436
437 if (inst_.needs_lightprobe_sphere_passes() && !(ob->visibility_flag & OB_HIDE_PROBE_CUBEMAP))
438 {
439 mat.lightprobe_sphere_prepass = material_pass_get(
440 ob, blender_mat, MAT_PIPE_PREPASS_DEFERRED, geometry_type, MAT_PROBE_REFLECTION);
441 mat.lightprobe_sphere_shading = material_pass_get(
442 ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, MAT_PROBE_REFLECTION);
443 }
444 else {
445 mat.lightprobe_sphere_prepass = MaterialPass();
446 mat.lightprobe_sphere_shading = MaterialPass();
447 }
448
449 if (inst_.needs_planar_probe_passes() && !(ob->visibility_flag & OB_HIDE_PROBE_PLANAR)) {
450 mat.planar_probe_prepass = material_pass_get(
451 ob, blender_mat, MAT_PIPE_PREPASS_PLANAR, geometry_type, MAT_PROBE_PLANAR);
452 mat.planar_probe_shading = material_pass_get(
453 ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, MAT_PROBE_PLANAR);
454 }
455 else {
456 mat.planar_probe_prepass = MaterialPass();
457 mat.planar_probe_shading = MaterialPass();
458 }
459
460 mat.has_surface = GPU_material_has_surface_output(mat.shading.gpumat);
461 mat.has_volume = GPU_material_has_volume_output(mat.shading.gpumat);
462 if (mat.has_volume && !hide_on_camera) {
463 mat.volume_occupancy = material_pass_get(
464 ob, blender_mat, MAT_PIPE_VOLUME_OCCUPANCY, geometry_type);
465 mat.volume_material = material_pass_get(
466 ob, blender_mat, MAT_PIPE_VOLUME_MATERIAL, geometry_type);
467 }
468 else {
469 mat.volume_occupancy = MaterialPass();
470 mat.volume_material = MaterialPass();
471 }
472 }
473
474 if (!(ob->visibility_flag & OB_HIDE_SHADOW)) {
475 mat.shadow = material_pass_get(ob, blender_mat, MAT_PIPE_SHADOW, geometry_type);
476 }
477 else {
478 mat.shadow = MaterialPass();
479 }
480
481 mat.is_alpha_blend_transparent = use_forward_pipeline &&
482 GPU_material_flag_get(mat.shading.gpumat,
484 mat.has_transparent_shadows = blender_mat->blend_flag & MA_BL_TRANSPARENT_SHADOW &&
485 GPU_material_flag_get(mat.shading.gpumat,
487
488 return mat;
489 });
490
491 if (mat.is_alpha_blend_transparent && !hide_on_camera) {
492 /* Transparent needs to use one sub pass per object to support reordering.
493 * NOTE: Pre-pass needs to be created first in order to be sorted first. */
494 mat.overlap_masking.sub_pass = inst_.pipelines.forward.prepass_transparent_add(
495 ob, blender_mat, mat.shading.gpumat);
496 mat.shading.sub_pass = inst_.pipelines.forward.material_transparent_add(
497 ob, blender_mat, mat.shading.gpumat);
498 }
499
500 if (mat.has_volume) {
501 /* Volume needs to use one sub pass per object to support layering. */
502 VolumeLayer *layer = hide_on_camera ? nullptr :
503 inst_.pipelines.volume.register_and_get_layer(ob);
504 if (layer) {
505 mat.volume_occupancy.sub_pass = layer->occupancy_add(
506 ob, blender_mat, mat.volume_occupancy.gpumat);
507 mat.volume_material.sub_pass = layer->material_add(
508 ob, blender_mat, mat.volume_material.gpumat);
509 }
510 else {
511 /* Culled volumes. */
512 mat.volume_occupancy.sub_pass = nullptr;
513 mat.volume_material.sub_pass = nullptr;
514 }
515 }
516 return mat;
517}
518
519::Material *MaterialModule::material_from_slot(Object *ob, int slot)
520{
521 ::Material *ma = BKE_object_material_get_eval(ob, slot + 1);
522 if (ma == nullptr) {
523 if (ob->type == OB_VOLUME) {
525 }
527 }
528 return ma;
529}
530
532{
533 material_array_.materials.clear();
534 material_array_.gpu_materials.clear();
535
536 const int materials_len = BKE_object_material_used_with_fallback_eval(*ob);
537
538 for (auto i : IndexRange(materials_len)) {
539 ::Material *blender_mat = material_from_slot(ob, i);
540 Material &mat = material_sync(ob, blender_mat, to_material_geometry(ob), has_motion);
541 /* \note Perform a whole copy since next material_sync() can move the Material memory location
542 * (i.e: because of its container growing) */
543 material_array_.materials.append(mat);
544 material_array_.gpu_materials.append(mat.shading.gpumat);
545 }
546 return material_array_;
547}
548
550 bool has_motion,
551 int mat_nr,
552 eMaterialGeometry geometry_type)
553{
554 ::Material *blender_mat = material_from_slot(ob, mat_nr);
555 Material &mat = material_sync(ob, blender_mat, geometry_type, has_motion);
556 return mat;
557}
558
559ShaderGroups MaterialModule::default_materials_load(bool block_until_ready)
560{
561 bool shaders_are_ready = true;
562 auto request_shader = [&](::Material *mat, eMaterialPipeline pipeline, eMaterialGeometry geom) {
563 GPUMaterial *gpu_mat = inst_.shaders.material_shader_get(
564 mat, mat->nodetree, pipeline, geom, !block_until_ready, nullptr);
565 shaders_are_ready = shaders_are_ready && GPU_material_status(gpu_mat) == GPU_MAT_SUCCESS;
566 };
567
568 request_shader(default_surface, MAT_PIPE_PREPASS_DEFERRED, MAT_GEOM_MESH);
569 request_shader(default_surface, MAT_PIPE_PREPASS_DEFERRED_VELOCITY, MAT_GEOM_MESH);
570 request_shader(default_surface, MAT_PIPE_DEFERRED, MAT_GEOM_MESH);
571 request_shader(default_surface, MAT_PIPE_SHADOW, MAT_GEOM_MESH);
572
573 return shaders_are_ready ? DEFAULT_MATERIALS : NONE;
574}
575
577
578} // namespace blender::eevee
ImageGPUTextures BKE_image_get_gpu_material_texture_try(Image *image, ImageUser *iuser, const bool use_tile_mapping)
Definition image_gpu.cc:503
void BKE_image_tag_time(Image *ima)
ImageGPUTextures BKE_image_get_gpu_material_texture(Image *image, ImageUser *iuser, const bool use_tile_mapping)
Definition image_gpu.cc:496
void BKE_id_free(Main *bmain, void *idv)
@ LIB_ID_COPY_LOCALIZE
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:767
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1500
General operations, lookup, etc. for materials.
Material * BKE_material_default_surface()
Material * BKE_material_default_volume()
Material * BKE_object_material_get_eval(Object *ob, short act)
int BKE_object_material_used_with_fallback_eval(const Object &ob)
#define SH_NODE_BSDF_PRINCIPLED
#define SH_NODE_EMISSION
#define SH_NODE_BSDF_DIFFUSE
#define SH_NODE_OUTPUT_MATERIAL
#define SH_NODE_BSDF_GLOSSY
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE void copy_v3_fl(float r[3], float f)
Platform independent time functions.
#define ELEM(...)
struct Material Material
@ MA_SURFACE_METHOD_FORWARD
@ MA_BL_TRANSPARENT_SHADOW
@ MA_DISPLACEMENT_BUMP
@ SOCK_OUT
@ SOCK_IN
struct bNodeTree bNodeTree
@ OB_HIDE_PROBE_VOLUME
@ OB_HIDE_CAMERA
@ OB_HIDE_PROBE_PLANAR
@ OB_HIDE_PROBE_CUBEMAP
@ OB_HIDE_SHADOW
@ OB_VOLUME
struct Object Object
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
bool GPU_material_has_surface_output(GPUMaterial *mat)
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
ListBase GPU_material_textures(GPUMaterial *material)
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
@ GPU_MATFLAG_TRANSPARENT
@ GPU_MAT_QUEUED
@ GPU_MAT_FAILED
@ GPU_MAT_SUCCESS
uint64_t GPU_material_compilation_timestamp(GPUMaterial *mat)
@ GPU_MAT_OPTIMIZATION_QUEUED
const char * GPU_material_get_name(GPUMaterial *material)
bool GPU_material_has_displacement_output(GPUMaterial *mat)
bool GPU_material_has_volume_output(GPUMaterial *mat)
eGPUMaterialOptimizationStatus GPU_material_optimization_status(GPUMaterial *mat)
uint64_t GPU_pass_global_compilation_count()
Definition gpu_pass.cc:192
struct blender::bke::bNodeTreeType * ntreeType_Shader
@ NONE
unsigned long long int uint64_t
void append(const T &value)
bNodeTree * nodetree_get(::Material *ma)
A running instance of the engine.
Material & material_get(Object *ob, bool has_motion, int mat_nr, eMaterialGeometry geometry_type)
MaterialArray & material_array_get(Object *ob, bool has_motion)
#define output
#define MEM_SAFE_FREE(v)
bNodeTree * node_tree_add_tree_embedded(Main *bmain, ID *owner_id, StringRefNull name, StringRefNull idname)
Definition node.cc:4375
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2864
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
Definition node.cc:3804
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:4087
bNodeTree * node_tree_add_tree(Main *bmain, StringRef name, StringRef idname)
Definition node.cc:4362
void node_set_active(bNodeTree &ntree, bNode &node)
Definition node.cc:4996
void node_tree_free_embedded_tree(bNodeTree *ntree)
Definition node.cc:4724
static eMaterialGeometry to_material_geometry(const Object *ob)
@ MAT_PIPE_PREPASS_FORWARD_VELOCITY
@ MAT_PIPE_PREPASS_DEFERRED_VELOCITY
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
ListBaseWrapperTemplate< ListBase, T > ListBaseWrapper
GPUTexture ** texture
Definition BKE_image.hh:607
GPUTexture ** tile_mapping
Definition BKE_image.hh:608
struct bNodeTree * nodetree
char surface_render_method
short visibility_flag
void * default_value
i
Definition text_draw.cc:230