46 *bsdf,
SOCK_IN,
"Specular IOR Level")
61 metallic_socket_->value = ma->
metallic;
63 specular_socket_->value = ma->
spec;
133 error_mat_->use_nodes =
true;
168 gpu_pass_last_update_ = gpu_pass_next_update_;
169 gpu_pass_next_update_ = next_update;
171 texture_loading_queue_.clear();
172 material_map_.clear();
176void MaterialModule::queue_texture_loading(
GPUMaterial *material)
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);
194 if (texture_loading_queue_.is_empty()) {
198 if (inst_.is_viewport()) {
200 inst_.sampling.reset();
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);
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);
235 inst_.manager->acquire_texture(*gputex.
texture);
243 texture_loading_queue_.clear();
246MaterialPass MaterialModule::material_pass_get(
Object *ob,
248 eMaterialPipeline pipeline_type,
249 eMaterialGeometry geometry_type,
250 eMaterialProbe probe_capture)
254 default_surface_ntree_.nodetree_get(blender_mat);
257 bool use_deferred_compilation = !inst_.is_viewport_image_render;
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;
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);
266 queue_texture_loading(matpass.gpumat);
268 const bool is_forward =
ELEM(pipeline_type,
270 MAT_PIPE_PREPASS_FORWARD,
271 MAT_PIPE_PREPASS_FORWARD_VELOCITY,
272 MAT_PIPE_PREPASS_OVERLAP);
279 queued_optimize_shaders_count++;
284 queued_shaders_count++;
285 matpass.gpumat = inst_.shaders.material_shader_get(
286 default_mat, default_mat->
nodetree, pipeline_type, geometry_type,
false,
nullptr);
290 matpass.gpumat = inst_.shaders.material_shader_get(
291 error_mat_, error_mat_->nodetree, pipeline_type, geometry_type,
false,
nullptr);
297 inst_.manager->register_layer_attributes(matpass.gpumat);
303 if (inst_.is_viewport() && use_deferred_compilation && pass_updated) {
304 inst_.sampling.reset();
310 if (((pipeline_type == MAT_PIPE_SHADOW) && (is_transparent || has_displacement)) || has_volume)
315 inst_.shadows.reset();
319 if (is_volume || (is_forward && is_transparent)) {
321 matpass.sub_pass =
nullptr;
324 ShaderKey shader_key(matpass.gpumat, blender_mat, probe_capture);
326 PassMain::Sub *shader_sub = shader_map_.lookup_or_add_cb(shader_key, [&]() {
328 return inst_.pipelines.material_add(
329 ob, blender_mat, matpass.gpumat, pipeline_type, probe_capture);
332 if (shader_sub !=
nullptr) {
335 matpass.sub_pass->material_set(*inst_.manager, matpass.gpumat,
true);
338 matpass.sub_pass =
nullptr;
347 eMaterialGeometry geometry_type,
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, [&]() {
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);
365 VolumeLayer *layer = hide_on_camera ?
nullptr :
366 inst_.pipelines.volume.register_and_get_layer(ob);
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);
375 mat.volume_occupancy.sub_pass =
nullptr;
376 mat.volume_material.sub_pass =
nullptr;
384 if (use_forward_pipeline) {
393 MaterialKey material_key(blender_mat, geometry_type, surface_pipe, ob->
visibility_flag);
395 Material &mat = material_map_.lookup_or_add_cb(material_key, [&]() {
397 if (inst_.is_baking()) {
399 mat.capture = MaterialPass();
402 mat.capture = material_pass_get(ob, blender_mat, MAT_PIPE_CAPTURE, geometry_type);
404 mat.prepass = MaterialPass();
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;
420 if (!hide_on_camera) {
421 mat.prepass = material_pass_get(ob, blender_mat, prepass_pipe, geometry_type);
424 mat.prepass = MaterialPass();
427 mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
428 if (hide_on_camera) {
431 mat.shading.sub_pass =
nullptr;
434 mat.overlap_masking = MaterialPass();
435 mat.capture = MaterialPass();
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);
445 mat.lightprobe_sphere_prepass = MaterialPass();
446 mat.lightprobe_sphere_shading = MaterialPass();
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);
456 mat.planar_probe_prepass = MaterialPass();
457 mat.planar_probe_shading = MaterialPass();
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);
469 mat.volume_occupancy = MaterialPass();
470 mat.volume_material = MaterialPass();
475 mat.shadow = material_pass_get(ob, blender_mat, MAT_PIPE_SHADOW, geometry_type);
478 mat.shadow = MaterialPass();
481 mat.is_alpha_blend_transparent = use_forward_pipeline &&
491 if (mat.is_alpha_blend_transparent && !hide_on_camera) {
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);
500 if (mat.has_volume) {
502 VolumeLayer *layer = hide_on_camera ?
nullptr :
503 inst_.pipelines.volume.register_and_get_layer(ob);
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);
512 mat.volume_occupancy.sub_pass =
nullptr;
513 mat.volume_material.sub_pass =
nullptr;
533 material_array_.materials.clear();
534 material_array_.gpu_materials.clear();
539 ::Material *blender_mat = material_from_slot(ob,
i);
543 material_array_.materials.append(mat);
546 return material_array_;
554 ::Material *blender_mat = material_from_slot(ob, mat_nr);
555 Material &mat = material_sync(ob, blender_mat, geometry_type, has_motion);
559ShaderGroups MaterialModule::default_materials_load(
bool block_until_ready)
561 bool shaders_are_ready =
true;
563 GPUMaterial *gpu_mat = inst_.shaders.material_shader_get(
564 mat, mat->
nodetree, pipeline, geom, !block_until_ready,
nullptr);
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);
573 return shaders_are_ready ? DEFAULT_MATERIALS :
NONE;
ImageGPUTextures BKE_image_get_gpu_material_texture_try(Image *image, ImageUser *iuser, const bool use_tile_mapping)
void BKE_image_tag_time(Image *ima)
ImageGPUTextures BKE_image_get_gpu_material_texture(Image *image, ImageUser *iuser, const bool use_tile_mapping)
void BKE_id_free(Main *bmain, void *idv)
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
void * BKE_id_new_nomain(short type, const char *name)
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_BSDF_DIFFUSE
#define SH_NODE_OUTPUT_MATERIAL
#define SH_NODE_BSDF_GLOSSY
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.
@ MA_SURFACE_METHOD_FORWARD
@ MA_BL_TRANSPARENT_SHADOW
struct bNodeTree bNodeTree
void GPU_debug_group_end()
void GPU_debug_group_begin(const char *name)
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
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()
struct blender::bke::bNodeTreeType * ntreeType_Shader
unsigned long long int uint64_t
void append(const T &value)
bNodeTree * nodetree_get(::Material *ma)
~DefaultSurfaceNodeTree()
A running instance of the engine.
MaterialModule(Instance &inst)
::Material * default_volume
Material & material_get(Object *ob, bool has_motion, int mat_nr, eMaterialGeometry geometry_type)
::Material * metallic_mat
int64_t queued_textures_count
MaterialArray & material_array_get(Object *ob, bool has_motion)
::Material * default_surface
int64_t queued_optimize_shaders_count
int64_t queued_shaders_count
bNodeTree * node_tree_add_tree_embedded(Main *bmain, ID *owner_id, StringRefNull name, StringRefNull idname)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
bNode * node_add_static_node(const bContext *C, bNodeTree &ntree, int type)
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
bNodeTree * node_tree_add_tree(Main *bmain, StringRef name, StringRef idname)
void node_set_active(bNodeTree &ntree, bNode &node)
void node_tree_free_embedded_tree(bNodeTree *ntree)
static eMaterialGeometry to_material_geometry(const Object *ob)
@ MAT_PIPE_PREPASS_FORWARD_VELOCITY
@ MAT_PIPE_PREPASS_DEFERRED
@ MAT_PIPE_PREPASS_DEFERRED_VELOCITY
@ MAT_PIPE_PREPASS_FORWARD
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
ListBaseWrapperTemplate< ListBase, T > ListBaseWrapper
GPUTexture ** tile_mapping
struct bNodeTree * nodetree
char surface_render_method