Blender V5.0
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 {
32 diffuse_mat = BKE_id_new_nomain<::Material>("EEVEE default diffuse");
34 nullptr, &diffuse_mat->id, "Shader Nodetree", ntreeType_Shader->idname);
35 diffuse_mat->surface_render_method = MA_SURFACE_METHOD_FORWARD;
36
37 /* Use 0.18 as it is close to middle gray. Middle gray is typically defined as 18% reflectance
38 * of visible light and commonly used for VFX balls. */
40 bNodeSocket *base_color = bke::node_find_socket(*bsdf, SOCK_IN, "Color");
41 copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.18f);
42
44
45 bke::node_add_link(*ntree,
46 *bsdf,
47 *bke::node_find_socket(*bsdf, SOCK_OUT, "BSDF"),
48 *output,
49 *bke::node_find_socket(*output, SOCK_IN, "Surface"));
50
52 }
53 {
54 metallic_mat = BKE_id_new_nomain<::Material>("EEVEE default metal");
56 nullptr, &metallic_mat->id, "Shader Nodetree", ntreeType_Shader->idname);
57 metallic_mat->surface_render_method = MA_SURFACE_METHOD_FORWARD;
58
59 bNode *bsdf = bke::node_add_static_node(nullptr, *ntree, SH_NODE_BSDF_GLOSSY);
60 bNodeSocket *base_color = bke::node_find_socket(*bsdf, SOCK_IN, "Color");
61 copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f);
62 bNodeSocket *roughness = bke::node_find_socket(*bsdf, SOCK_IN, "Roughness");
63 ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f;
64
66
67 bke::node_add_link(*ntree,
68 *bsdf,
69 *bke::node_find_socket(*bsdf, SOCK_OUT, "BSDF"),
70 *output,
71 *bke::node_find_socket(*output, SOCK_IN, "Surface"));
72
74 }
75 {
76 default_surface = reinterpret_cast<::Material *>(BKE_id_copy_ex(
77 nullptr, &BKE_material_default_surface()->id, nullptr, LIB_ID_COPY_LOCALIZE));
78 default_volume = reinterpret_cast<::Material *>(BKE_id_copy_ex(
79 nullptr, &BKE_material_default_volume()->id, nullptr, LIB_ID_COPY_LOCALIZE));
80 }
81 {
82 error_mat_ = BKE_id_new_nomain<::Material>("EEVEE default error");
84 nullptr, &error_mat_->id, "Shader Nodetree", ntreeType_Shader->idname);
85
86 /* Use emission and output material to be compatible with both World and Material. */
87 bNode *bsdf = bke::node_add_static_node(nullptr, *ntree, SH_NODE_EMISSION);
89 copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f);
90
92
93 bke::node_add_link(*ntree,
94 *bsdf,
95 *bke::node_find_socket(*bsdf, SOCK_OUT, "Emission"),
96 *output,
97 *bke::node_find_socket(*output, SOCK_IN, "Surface"));
98
100 }
101}
102
104{
105 BKE_id_free(nullptr, metallic_mat);
106 BKE_id_free(nullptr, diffuse_mat);
108 BKE_id_free(nullptr, default_volume);
109 BKE_id_free(nullptr, error_mat_);
110}
111
113{
117
118 material_override = DEG_get_evaluated(inst_.depsgraph, inst_.view_layer->mat_override);
119
121 gpu_pass_last_update_ = gpu_pass_next_update_;
122 gpu_pass_next_update_ = next_update;
123
124 texture_loading_queue_.clear();
125 material_map_.clear();
126 shader_map_.clear();
127}
128
129void MaterialModule::queue_texture_loading(GPUMaterial *material)
130{
131 ListBase textures = GPU_material_textures(material);
133 if (tex->ima) {
134 const bool use_tile_mapping = tex->tiled_mapping_name[0];
135 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
137 tex->ima, iuser, use_tile_mapping);
138 if (*gputex.texture == nullptr) {
139 texture_loading_queue_.append(tex);
140 }
141 }
142 }
143}
144
146{
147 if (texture_loading_queue_.is_empty()) {
148 return;
149 }
150
151 if (inst_.is_viewport()) {
152 /* Avoid ghosting of textures. */
153 inst_.sampling.reset();
154 }
155
156 GPU_debug_group_begin("Texture Loading");
157
158 /* Load files from disk in a multithreaded manner. Allow better parallelism. */
159 threading::parallel_for(texture_loading_queue_.index_range(), 1, [&](const IndexRange range) {
160 for (auto i : range) {
161 GPUMaterialTexture *tex = texture_loading_queue_[i];
162 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
163 BKE_image_get_tile(tex->ima, 0);
164 threading::isolate_task([&]() {
165 ImBuf *imbuf = BKE_image_acquire_ibuf(tex->ima, iuser, nullptr);
166 BKE_image_release_ibuf(tex->ima, imbuf, nullptr);
167 });
168 }
169 });
170
171 /* Tag time is not thread-safe. */
172 for (GPUMaterialTexture *tex : texture_loading_queue_) {
173 BKE_image_tag_time(tex->ima);
174 }
175
176 /* Upload to the GPU (create gpu::Texture). This part still requires a valid GPU context and
177 * is not easily parallelized. */
178 for (GPUMaterialTexture *tex : texture_loading_queue_) {
179 BLI_assert(tex->ima);
180 GPU_debug_group_begin(tex->ima->id.name);
181
182 const bool use_tile_mapping = tex->tiled_mapping_name[0];
183 ImageUser *iuser = tex->iuser_available ? &tex->iuser : nullptr;
185 tex->ima, iuser, use_tile_mapping);
186
187 /* Acquire the textures since they were not existing inside `PassBase::material_set()`. */
188 inst_.manager->acquire_texture(*gputex.texture);
189 if (gputex.tile_mapping) {
190 inst_.manager->acquire_texture(*gputex.tile_mapping);
191 }
192
194 }
196 texture_loading_queue_.clear();
197}
198
199MaterialPass MaterialModule::material_pass_get(Object *ob,
200 ::Material *blender_mat,
201 eMaterialPipeline pipeline_type,
202 eMaterialGeometry geometry_type,
203 eMaterialProbe probe_capture)
204{
205 bNodeTree *ntree = (blender_mat->nodetree != nullptr) ? blender_mat->nodetree :
206 default_surface->nodetree;
207
208 /* We can't defer compilation in viewport image render, since we can't re-sync.(See #130235) */
209 bool use_deferred_compilation = !inst_.is_viewport_image_render;
210
211 const bool is_volume = ELEM(pipeline_type, MAT_PIPE_VOLUME_OCCUPANCY, MAT_PIPE_VOLUME_MATERIAL);
212 ::Material *default_mat = is_volume ? default_volume : default_surface;
213
214 MaterialPass matpass = MaterialPass();
215 matpass.gpumat = inst_.shaders.material_shader_get(
216 blender_mat, ntree, pipeline_type, geometry_type, use_deferred_compilation, default_mat);
217
218 queue_texture_loading(matpass.gpumat);
219
220 const bool is_forward = ELEM(pipeline_type,
221 MAT_PIPE_FORWARD,
222 MAT_PIPE_PREPASS_FORWARD,
223 MAT_PIPE_PREPASS_FORWARD_VELOCITY,
224 MAT_PIPE_PREPASS_OVERLAP);
225
226 switch (GPU_material_status(matpass.gpumat)) {
227 case GPU_MAT_SUCCESS: {
228 /* Determine optimization status for remaining compilations counter. */
229 int optimization_status = GPU_material_optimization_status(matpass.gpumat);
230 if (optimization_status == GPU_MAT_OPTIMIZATION_QUEUED) {
231 queued_optimize_shaders_count++;
232 }
233 break;
234 }
235 case GPU_MAT_QUEUED:
236 queued_shaders_count++;
237 matpass.gpumat = inst_.shaders.material_shader_get(
238 default_mat, default_mat->nodetree, pipeline_type, geometry_type, false, nullptr);
239 break;
240 case GPU_MAT_FAILED:
241 default:
242 matpass.gpumat = inst_.shaders.material_shader_get(
243 error_mat_, error_mat_->nodetree, pipeline_type, geometry_type, false, nullptr);
244 break;
245 }
246 /* Returned material should be ready to be drawn. */
248
249 inst_.manager->register_layer_attributes(matpass.gpumat);
250
251 const bool is_transparent = GPU_material_flag_get(matpass.gpumat, GPU_MATFLAG_TRANSPARENT);
252
253 bool pass_updated = GPU_material_compilation_timestamp(matpass.gpumat) > gpu_pass_last_update_;
254
255 if (inst_.is_viewport() && use_deferred_compilation && pass_updated) {
256 inst_.sampling.reset();
257
258 const bool has_displacement = GPU_material_has_displacement_output(matpass.gpumat) &&
260 const bool has_volume = GPU_material_has_volume_output(matpass.gpumat);
261
262 if (((pipeline_type == MAT_PIPE_SHADOW) && (is_transparent || has_displacement)) || has_volume)
263 {
264 /* WORKAROUND: This is to avoid lingering shadows from default material.
265 * Ideally, we should tag the caster object to update only the needed areas but that's a bit
266 * more involved. */
267 inst_.shadows.reset();
268 }
269 }
270
271 if (is_volume || (is_forward && is_transparent)) {
272 /* Sub pass is generated later. */
273 matpass.sub_pass = nullptr;
274 }
275 else {
276 ShaderKey shader_key(matpass.gpumat, blender_mat, probe_capture);
277
278 PassMain::Sub *shader_sub = shader_map_.lookup_or_add_cb(shader_key, [&]() {
279 /* First time encountering this shader. Create a sub that will contain materials using it. */
280 return inst_.pipelines.material_add(
281 ob, blender_mat, matpass.gpumat, pipeline_type, probe_capture);
282 });
283
284 if (shader_sub != nullptr) {
285 /* Create a sub for this material as `shader_sub` is for sharing shader between materials. */
286 matpass.sub_pass = &shader_sub->sub(GPU_material_get_name(matpass.gpumat));
287 matpass.sub_pass->material_set(*inst_.manager, matpass.gpumat, true);
288 }
289 else {
290 matpass.sub_pass = nullptr;
291 }
292 }
293
294 return matpass;
295}
296
297Material &MaterialModule::material_sync(Object *ob,
298 ::Material *blender_mat,
299 eMaterialGeometry geometry_type,
300 bool has_motion)
301{
302 bool hide_on_camera = ob->visibility_flag & OB_HIDE_CAMERA;
303
304 if (geometry_type == MAT_GEOM_VOLUME) {
305 MaterialKey material_key(
306 blender_mat, geometry_type, MAT_PIPE_VOLUME_MATERIAL, ob->visibility_flag);
307 Material &mat = material_map_.lookup_or_add_cb(material_key, [&]() {
308 Material mat = {};
309 mat.volume_occupancy = material_pass_get(
310 ob, blender_mat, MAT_PIPE_VOLUME_OCCUPANCY, MAT_GEOM_VOLUME);
311 mat.volume_material = material_pass_get(
312 ob, blender_mat, MAT_PIPE_VOLUME_MATERIAL, MAT_GEOM_VOLUME);
313 return mat;
314 });
315
316 /* Volume needs to use one sub pass per object to support layering. */
317 VolumeLayer *layer = hide_on_camera ? nullptr :
318 inst_.pipelines.volume.register_and_get_layer(ob);
319 if (layer) {
320 mat.volume_occupancy.sub_pass = layer->occupancy_add(
321 ob, blender_mat, mat.volume_occupancy.gpumat);
322 mat.volume_material.sub_pass = layer->material_add(
323 ob, blender_mat, mat.volume_material.gpumat);
324 }
325 else {
326 /* Culled volumes. */
327 mat.volume_occupancy.sub_pass = nullptr;
328 mat.volume_material.sub_pass = nullptr;
329 }
330 return mat;
331 }
332
333 const bool use_forward_pipeline = (blender_mat->surface_render_method ==
335 eMaterialPipeline surface_pipe, prepass_pipe;
336 if (use_forward_pipeline) {
337 surface_pipe = MAT_PIPE_FORWARD;
339 }
340 else {
341 surface_pipe = MAT_PIPE_DEFERRED;
343 }
344
345 MaterialKey material_key(blender_mat, geometry_type, surface_pipe, ob->visibility_flag);
346
347 Material &mat = material_map_.lookup_or_add_cb(material_key, [&]() {
348 Material mat;
349 if (inst_.is_baking()) {
351 mat.capture = MaterialPass();
352 }
353 else {
354 mat.capture = material_pass_get(ob, blender_mat, MAT_PIPE_CAPTURE, geometry_type);
355 }
356 mat.prepass = MaterialPass();
357 /* TODO(fclem): Still need the shading pass for correct attribute extraction. Would be better
358 * to avoid this shader compilation in another context. */
359 mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
360 mat.overlap_masking = MaterialPass();
361 mat.lightprobe_sphere_prepass = MaterialPass();
362 mat.lightprobe_sphere_shading = MaterialPass();
363 mat.planar_probe_prepass = MaterialPass();
364 mat.planar_probe_shading = MaterialPass();
365 mat.volume_occupancy = MaterialPass();
366 mat.volume_material = MaterialPass();
367 mat.has_volume = false; /* TODO */
368 mat.has_surface = GPU_material_has_surface_output(mat.shading.gpumat);
369 }
370 else {
371 /* Order is important for transparent. */
372 if (!hide_on_camera) {
373 mat.prepass = material_pass_get(ob, blender_mat, prepass_pipe, geometry_type);
374 }
375 else {
376 mat.prepass = MaterialPass();
377 }
378
379 mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
380 if (hide_on_camera) {
381 /* Only null the sub_pass.
382 * `mat.shading.gpumat` is always needed for using the GPU_material API. */
383 mat.shading.sub_pass = nullptr;
384 }
385
386 mat.overlap_masking = MaterialPass();
387 mat.capture = MaterialPass();
388
389 if (inst_.needs_lightprobe_sphere_passes() && !(ob->visibility_flag & OB_HIDE_PROBE_CUBEMAP))
390 {
391 mat.lightprobe_sphere_prepass = material_pass_get(
392 ob, blender_mat, MAT_PIPE_PREPASS_DEFERRED, geometry_type, MAT_PROBE_REFLECTION);
393 mat.lightprobe_sphere_shading = material_pass_get(
394 ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, MAT_PROBE_REFLECTION);
395 }
396 else {
397 mat.lightprobe_sphere_prepass = MaterialPass();
398 mat.lightprobe_sphere_shading = MaterialPass();
399 }
400
401 if (inst_.needs_planar_probe_passes() && !(ob->visibility_flag & OB_HIDE_PROBE_PLANAR)) {
402 mat.planar_probe_prepass = material_pass_get(
403 ob, blender_mat, MAT_PIPE_PREPASS_PLANAR, geometry_type, MAT_PROBE_PLANAR);
404 mat.planar_probe_shading = material_pass_get(
405 ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, MAT_PROBE_PLANAR);
406 }
407 else {
408 mat.planar_probe_prepass = MaterialPass();
409 mat.planar_probe_shading = MaterialPass();
410 }
411
412 mat.has_surface = GPU_material_has_surface_output(mat.shading.gpumat);
413 mat.has_volume = GPU_material_has_volume_output(mat.shading.gpumat);
414 if (mat.has_volume && !hide_on_camera) {
415 mat.volume_occupancy = material_pass_get(
416 ob, blender_mat, MAT_PIPE_VOLUME_OCCUPANCY, geometry_type);
417 mat.volume_material = material_pass_get(
418 ob, blender_mat, MAT_PIPE_VOLUME_MATERIAL, geometry_type);
419 }
420 else {
421 mat.volume_occupancy = MaterialPass();
422 mat.volume_material = MaterialPass();
423 }
424 }
425
426 if (!(ob->visibility_flag & OB_HIDE_SHADOW)) {
427 mat.shadow = material_pass_get(ob, blender_mat, MAT_PIPE_SHADOW, geometry_type);
428 }
429 else {
430 mat.shadow = MaterialPass();
431 }
432
433 mat.is_alpha_blend_transparent = use_forward_pipeline &&
434 GPU_material_flag_get(mat.shading.gpumat,
436 mat.has_transparent_shadows = blender_mat->blend_flag & MA_BL_TRANSPARENT_SHADOW &&
437 GPU_material_flag_get(mat.shading.gpumat,
439
440 return mat;
441 });
442
443 if (mat.is_alpha_blend_transparent && !hide_on_camera) {
444 /* Transparent needs to use one sub pass per object to support reordering.
445 * NOTE: Pre-pass needs to be created first in order to be sorted first. */
446 mat.overlap_masking.sub_pass = inst_.pipelines.forward.prepass_transparent_add(
447 ob, blender_mat, mat.shading.gpumat);
448 mat.shading.sub_pass = inst_.pipelines.forward.material_transparent_add(
449 ob, blender_mat, mat.shading.gpumat);
450 }
451
452 if (mat.has_volume) {
453 /* Volume needs to use one sub pass per object to support layering. */
454 VolumeLayer *layer = hide_on_camera ? nullptr :
455 inst_.pipelines.volume.register_and_get_layer(ob);
456 if (layer) {
457 mat.volume_occupancy.sub_pass = layer->occupancy_add(
458 ob, blender_mat, mat.volume_occupancy.gpumat);
459 mat.volume_material.sub_pass = layer->material_add(
460 ob, blender_mat, mat.volume_material.gpumat);
461 }
462 else {
463 /* Culled volumes. */
464 mat.volume_occupancy.sub_pass = nullptr;
465 mat.volume_material.sub_pass = nullptr;
466 }
467 }
468 return mat;
469}
470
471::Material *MaterialModule::material_from_slot(Object *ob, int slot)
472{
473 ::Material *ma = BKE_object_material_get_eval(ob, slot + 1);
474 if (ma == nullptr) {
475 if (ob->type == OB_VOLUME) {
477 }
479 }
480 return ma;
481}
482
484{
485 material_array_.materials.clear();
486 material_array_.gpu_materials.clear();
487
488 const int materials_len = BKE_object_material_used_with_fallback_eval(*ob);
489
490 for (auto i : IndexRange(materials_len)) {
491 ::Material *blender_mat = (material_override) ? material_override : material_from_slot(ob, i);
492 Material &mat = material_sync(ob, blender_mat, to_material_geometry(ob), has_motion);
493 /* \note Perform a whole copy since next material_sync() can move the Material memory location
494 * (i.e: because of its container growing) */
495 material_array_.materials.append(mat);
496 material_array_.gpu_materials.append(mat.shading.gpumat);
497 }
498 return material_array_;
499}
500
502 bool has_motion,
503 int mat_nr,
504 eMaterialGeometry geometry_type)
505{
507 material_from_slot(ob, mat_nr);
508 Material &mat = material_sync(ob, blender_mat, geometry_type, has_motion);
509 return mat;
510}
511
512ShaderGroups MaterialModule::default_materials_load(bool block_until_ready)
513{
514 bool shaders_are_ready = true;
515 auto request_shader = [&](::Material *mat, eMaterialPipeline pipeline, eMaterialGeometry geom) {
516 GPUMaterial *gpu_mat = inst_.shaders.material_shader_get(
517 mat, mat->nodetree, pipeline, geom, !block_until_ready, nullptr);
518 shaders_are_ready = shaders_are_ready && GPU_material_status(gpu_mat) == GPU_MAT_SUCCESS;
519 };
520
521 request_shader(default_surface, MAT_PIPE_PREPASS_DEFERRED, MAT_GEOM_MESH);
522 request_shader(default_surface, MAT_PIPE_PREPASS_DEFERRED_VELOCITY, MAT_GEOM_MESH);
523 request_shader(default_surface, MAT_PIPE_DEFERRED, MAT_GEOM_MESH);
524 request_shader(default_surface, MAT_PIPE_SHADOW, MAT_GEOM_MESH);
525
526 return shaders_are_ready ? DEFAULT_MATERIALS : NONE;
527}
528
530
531} // namespace blender::eevee
ImageGPUTextures BKE_image_get_gpu_material_texture_try(Image *image, ImageUser *iuser, const bool use_tile_mapping)
Definition image_gpu.cc:513
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:506
void BKE_id_free(Main *bmain, void *idv)
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
@ LIB_ID_COPY_LOCALIZE
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1519
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_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(...)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ MA_BL_TRANSPARENT_SHADOW
@ MA_SURFACE_METHOD_FORWARD
struct Material Material
@ 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)
@ GPU_MAT_QUEUED
@ GPU_MAT_FAILED
@ GPU_MAT_SUCCESS
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
ListBase GPU_material_textures(GPUMaterial *material)
GPUMaterialStatus GPU_material_status(GPUMaterial *mat)
@ GPU_MATFLAG_TRANSPARENT
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:194
struct blender::bke::bNodeTreeType * ntreeType_Shader
@ NONE
unsigned long long int uint64_t
void append(const T &value)
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
bNodeTree * node_tree_add_tree_embedded(Main *bmain, ID *owner_id, StringRefNull name, StringRefNull idname)
Definition node.cc:4098
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2532
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
Definition node.cc:3500
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:3810
void node_set_active(bNodeTree &ntree, bNode &node)
Definition node.cc:4724
static eMaterialGeometry to_material_geometry(const Object *ob)
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
blender::gpu::Texture ** tile_mapping
Definition BKE_image.hh:615
blender::gpu::Texture ** texture
Definition BKE_image.hh:614
struct bNodeTree * nodetree
char surface_render_method
short visibility_flag
void * default_value
i
Definition text_draw.cc:230