Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/shader.cpp
| Show First 20 Lines • Show All 223 Lines • ▼ Show 20 Lines | |||||
| Shader::~Shader() | Shader::~Shader() | ||||
| { | { | ||||
| delete graph; | delete graph; | ||||
| } | } | ||||
| bool Shader::is_constant_emission(float3 *emission) | bool Shader::is_constant_emission(float3 *emission) | ||||
| { | { | ||||
| /* If the shader has AOVs, they need to be evaluated, so we can't skip the shader. */ | /* If the shader has AOVs, they need to be evaluated, so we can't skip the shader. */ | ||||
| foreach (ShaderNode *node, graph->nodes) { | foreach (ShaderNode *node, graph->get_nodes()) { | ||||
| if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT_AOV) { | if (node->get_special_type() == SHADER_SPECIAL_TYPE_OUTPUT_AOV) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| ShaderInput *surf = graph->output()->input("Surface"); | ShaderInput *surf = graph->output()->input("Surface"); | ||||
| if (surf->link == NULL) { | if (surf->get_link() == NULL) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (surf->link->parent->type == EmissionNode::node_type) { | if (surf->get_link()->get_parent()->get_type() == EmissionNode::node_type) { | ||||
| EmissionNode *node = (EmissionNode *)surf->link->parent; | EmissionNode *node = (EmissionNode *)surf->get_link()->get_parent(); | ||||
| assert(node->input("Color")); | assert(node->input("Color")); | ||||
| assert(node->input("Strength")); | assert(node->input("Strength")); | ||||
| if (node->input("Color")->link || node->input("Strength")->link) { | if (node->input("Color")->get_link() || node->input("Strength")->get_link()) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| *emission = node->get_color() * node->get_strength(); | *emission = node->get_color() * node->get_strength(); | ||||
| } | } | ||||
| else if (surf->link->parent->type == BackgroundNode::node_type) { | else if (surf->get_link()->get_parent()->get_type() == BackgroundNode::node_type) { | ||||
| BackgroundNode *node = (BackgroundNode *)surf->link->parent; | BackgroundNode *node = (BackgroundNode *)surf->get_link()->get_parent(); | ||||
| assert(node->input("Color")); | assert(node->input("Color")); | ||||
| assert(node->input("Strength")); | assert(node->input("Strength")); | ||||
| if (node->input("Color")->link || node->input("Strength")->link) { | if (node->input("Color")->get_link() || node->input("Strength")->get_link()) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| *emission = node->get_color() * node->get_strength(); | *emission = node->get_color() * node->get_strength(); | ||||
| } | } | ||||
| else { | else { | ||||
| return false; | return false; | ||||
| } | } | ||||
| Show All 25 Lines | void Shader::set_graph(ShaderGraph *graph_) | ||||
| } | } | ||||
| /* assign graph */ | /* assign graph */ | ||||
| delete graph; | delete graph; | ||||
| graph = graph_; | graph = graph_; | ||||
| /* Store info here before graph optimization to make sure that | /* Store info here before graph optimization to make sure that | ||||
| * nodes that get optimized away still count. */ | * nodes that get optimized away still count. */ | ||||
| has_volume_connected = (graph->output()->input("Volume")->link != NULL); | has_volume_connected = (graph->output()->input("Volume")->get_link() != NULL); | ||||
| } | } | ||||
| void Shader::tag_update(Scene *scene) | void Shader::tag_update(Scene *scene) | ||||
| { | { | ||||
| /* update tag */ | /* update tag */ | ||||
| tag_modified(); | tag_modified(); | ||||
| scene->shader_manager->need_update = true; | scene->get_shader_manager()->need_update = true; | ||||
| /* if the shader previously was emissive, update light distribution, | /* if the shader previously was emissive, update light distribution, | ||||
| * if the new shader is emissive, a light manager update tag will be | * if the new shader is emissive, a light manager update tag will be | ||||
| * done in the shader manager device update. */ | * done in the shader manager device update. */ | ||||
| if (use_mis && has_surface_emission) | if (use_mis && has_surface_emission) | ||||
| scene->light_manager->need_update = true; | scene->get_light_manager()->need_update = true; | ||||
| /* Special handle of background MIS light for now: for some reason it | /* Special handle of background MIS light for now: for some reason it | ||||
| * has use_mis set to false. We are quite close to release now, so | * has use_mis set to false. We are quite close to release now, so | ||||
| * better to be safe. | * better to be safe. | ||||
| */ | */ | ||||
| if (this == scene->background->get_shader(scene)) { | if (this == scene->get_background()->get_shader(scene)) { | ||||
| scene->light_manager->need_update_background = true; | scene->get_light_manager()->need_update_background = true; | ||||
| if (scene->light_manager->has_background_light(scene)) { | if (scene->get_light_manager()->has_background_light(scene)) { | ||||
| scene->light_manager->need_update = true; | scene->get_light_manager()->need_update = true; | ||||
| } | } | ||||
| } | } | ||||
| /* quick detection of which kind of shaders we have to avoid loading | /* quick detection of which kind of shaders we have to avoid loading | ||||
| * e.g. surface attributes when there is only a volume shader. this could | * e.g. surface attributes when there is only a volume shader. this could | ||||
| * be more fine grained but it's better than nothing */ | * be more fine grained but it's better than nothing */ | ||||
| OutputNode *output = graph->output(); | OutputNode *output = graph->output(); | ||||
| bool prev_has_volume = has_volume; | bool prev_has_volume = has_volume; | ||||
| has_surface = has_surface || output->input("Surface")->link; | has_surface = has_surface || output->input("Surface")->get_link(); | ||||
| has_volume = has_volume || output->input("Volume")->link; | has_volume = has_volume || output->input("Volume")->get_link(); | ||||
| has_displacement = has_displacement || output->input("Displacement")->link; | has_displacement = has_displacement || output->input("Displacement")->get_link(); | ||||
| /* get requested attributes. this could be optimized by pruning unused | /* get requested attributes. this could be optimized by pruning unused | ||||
| * nodes here already, but that's the job of the shader manager currently, | * nodes here already, but that's the job of the shader manager currently, | ||||
| * and may not be so great for interactive rendering where you temporarily | * and may not be so great for interactive rendering where you temporarily | ||||
| * disconnect a node */ | * disconnect a node */ | ||||
| AttributeRequestSet prev_attributes = attributes; | AttributeRequestSet prev_attributes = attributes; | ||||
| attributes.clear(); | attributes.clear(); | ||||
| foreach (ShaderNode *node, graph->nodes) | foreach (ShaderNode *node, graph->get_nodes()) | ||||
| node->attributes(this, &attributes); | node->attributes(this, &attributes); | ||||
| if (has_displacement) { | if (has_displacement) { | ||||
| if (displacement_method == DISPLACE_BOTH) { | if (displacement_method == DISPLACE_BOTH) { | ||||
| attributes.add(ATTR_STD_POSITION_UNDISPLACED); | attributes.add(ATTR_STD_POSITION_UNDISPLACED); | ||||
| } | } | ||||
| if (displacement_method_is_modified()) { | if (displacement_method_is_modified()) { | ||||
| need_update_geometry = true; | need_update_geometry = true; | ||||
| scene->geometry_manager->need_update = true; | scene->get_geometry_manager()->need_update = true; | ||||
| scene->object_manager->need_flags_update = true; | scene->get_object_manager()->need_flags_update = true; | ||||
| } | } | ||||
| } | } | ||||
| /* compare if the attributes changed, mesh manager will check | /* compare if the attributes changed, mesh manager will check | ||||
| * need_update_geometry, update the relevant meshes and clear it. */ | * need_update_geometry, update the relevant meshes and clear it. */ | ||||
| if (attributes.modified(prev_attributes)) { | if (attributes.modified(prev_attributes)) { | ||||
| need_update_geometry = true; | need_update_geometry = true; | ||||
| scene->geometry_manager->need_update = true; | scene->get_geometry_manager()->need_update = true; | ||||
| } | } | ||||
| if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) { | if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) { | ||||
| scene->geometry_manager->need_flags_update = true; | scene->get_geometry_manager()->need_flags_update = true; | ||||
| scene->object_manager->need_flags_update = true; | scene->get_object_manager()->need_flags_update = true; | ||||
| prev_volume_step_rate = volume_step_rate; | prev_volume_step_rate = volume_step_rate; | ||||
| } | } | ||||
| } | } | ||||
| void Shader::tag_used(Scene *scene) | void Shader::tag_used(Scene *scene) | ||||
| { | { | ||||
| /* if an unused shader suddenly gets used somewhere, it needs to be | /* if an unused shader suddenly gets used somewhere, it needs to be | ||||
| * recompiled because it was skipped for compilation before */ | * recompiled because it was skipped for compilation before */ | ||||
| if (!used) { | if (!used) { | ||||
| tag_modified(); | tag_modified(); | ||||
| scene->shader_manager->need_update = true; | scene->get_shader_manager()->need_update = true; | ||||
| } | } | ||||
| } | } | ||||
| /* Shader Manager */ | /* Shader Manager */ | ||||
| ShaderManager::ShaderManager() | ShaderManager::ShaderManager() | ||||
| { | { | ||||
| need_update = true; | need_update = true; | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
| uint ShaderManager::get_attribute_id(AttributeStandard std) | uint ShaderManager::get_attribute_id(AttributeStandard std) | ||||
| { | { | ||||
| return (uint)std; | return (uint)std; | ||||
| } | } | ||||
| int ShaderManager::get_shader_id(Shader *shader, bool smooth) | int ShaderManager::get_shader_id(Shader *shader, bool smooth) | ||||
| { | { | ||||
| /* get a shader id to pass to the kernel */ | /* get a shader id to pass to the kernel */ | ||||
| int id = shader->id; | int id = shader->get_id(); | ||||
| /* smooth flag */ | /* smooth flag */ | ||||
| if (smooth) | if (smooth) | ||||
| id |= SHADER_SMOOTH_NORMAL; | id |= SHADER_SMOOTH_NORMAL; | ||||
| /* default flags */ | /* default flags */ | ||||
| id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT; | id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT; | ||||
| return id; | return id; | ||||
| } | } | ||||
| void ShaderManager::update_shaders_used(Scene *scene) | void ShaderManager::update_shaders_used(Scene *scene) | ||||
| { | { | ||||
| if (!need_update) { | if (!need_update) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* figure out which shaders are in use, so SVM/OSL can skip compiling them | /* figure out which shaders are in use, so SVM/OSL can skip compiling them | ||||
| * for speed and avoid loading image textures into memory */ | * for speed and avoid loading image textures into memory */ | ||||
| uint id = 0; | uint id = 0; | ||||
| foreach (Shader *shader, scene->shaders) { | foreach (Shader *shader, scene->get_shaders()) { | ||||
| shader->used = false; | shader->set_used(false); | ||||
| shader->id = id++; | shader->set_id(id++); | ||||
| } | } | ||||
| scene->default_surface->used = true; | scene->get_default_surface()->set_used(true); | ||||
| scene->default_light->used = true; | scene->get_default_light()->set_used(true); | ||||
| scene->default_background->used = true; | scene->get_default_background()->set_used(true); | ||||
| scene->default_empty->used = true; | scene->get_default_empty()->set_used(true); | ||||
| if (scene->background->get_shader()) | if (scene->get_background()->get_shader()) | ||||
| scene->background->get_shader()->used = true; | scene->get_background()->get_shader()->set_used(true); | ||||
| foreach (Geometry *geom, scene->geometry) | foreach (Geometry *geom, scene->get_geometry()) | ||||
| foreach (Node *node, geom->get_used_shaders()) { | foreach (Node *node, geom->get_used_shaders()) { | ||||
| Shader *shader = static_cast<Shader *>(node); | Shader *shader = static_cast<Shader *>(node); | ||||
| shader->used = true; | shader->set_used(true); | ||||
| } | } | ||||
| foreach (Light *light, scene->lights) | foreach (Light *light, scene->get_lights()) | ||||
| if (light->get_shader()) | if (light->get_shader()) | ||||
| const_cast<Shader *>(light->get_shader())->used = true; | const_cast<Shader *>(light->get_shader())->set_used(true); | ||||
| } | } | ||||
| void ShaderManager::device_update_common(Device *device, | void ShaderManager::device_update_common(Device *device, | ||||
| DeviceScene *dscene, | DeviceScene *dscene, | ||||
| Scene *scene, | Scene *scene, | ||||
| Progress & /*progress*/) | Progress & /*progress*/) | ||||
| { | { | ||||
| dscene->shaders.free(); | dscene->shaders.free(); | ||||
| if (scene->shaders.size() == 0) | if (scene->get_shaders().size() == 0) | ||||
| return; | return; | ||||
| KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size()); | KernelShader *kshader = dscene->shaders.alloc(scene->get_shaders().size()); | ||||
| bool has_volumes = false; | bool has_volumes = false; | ||||
| bool has_transparent_shadow = false; | bool has_transparent_shadow = false; | ||||
| foreach (Shader *shader, scene->shaders) { | foreach (Shader *shader, scene->get_shaders()) { | ||||
| uint flag = 0; | uint flag = 0; | ||||
| if (shader->get_use_mis()) | if (shader->get_use_mis()) | ||||
| flag |= SD_USE_MIS; | flag |= SD_USE_MIS; | ||||
| if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) | if (shader->get_has_surface_transparent() && shader->get_use_transparent_shadow()) | ||||
| flag |= SD_HAS_TRANSPARENT_SHADOW; | flag |= SD_HAS_TRANSPARENT_SHADOW; | ||||
| if (shader->has_volume) { | if (shader->get_has_volume()) { | ||||
| flag |= SD_HAS_VOLUME; | flag |= SD_HAS_VOLUME; | ||||
| has_volumes = true; | has_volumes = true; | ||||
| /* todo: this could check more fine grained, to skip useless volumes | /* todo: this could check more fine grained, to skip useless volumes | ||||
| * enclosed inside an opaque bsdf. | * enclosed inside an opaque bsdf. | ||||
| */ | */ | ||||
| flag |= SD_HAS_TRANSPARENT_SHADOW; | flag |= SD_HAS_TRANSPARENT_SHADOW; | ||||
| } | } | ||||
| /* in this case we can assume transparent surface */ | /* in this case we can assume transparent surface */ | ||||
| if (shader->has_volume_connected && !shader->has_surface) | if (shader->get_has_volume_connected() && !shader->get_has_surface()) | ||||
| flag |= SD_HAS_ONLY_VOLUME; | flag |= SD_HAS_ONLY_VOLUME; | ||||
| if (shader->has_volume) { | if (shader->get_has_volume()) { | ||||
| if (shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) | if (shader->get_heterogeneous_volume() && shader->get_has_volume_spatial_varying()) | ||||
| flag |= SD_HETEROGENEOUS_VOLUME; | flag |= SD_HETEROGENEOUS_VOLUME; | ||||
| } | } | ||||
| if (shader->has_volume_attribute_dependency) | if (shader->get_has_volume_attribute_dependency()) | ||||
| flag |= SD_NEED_VOLUME_ATTRIBUTES; | flag |= SD_NEED_VOLUME_ATTRIBUTES; | ||||
| if (shader->has_bssrdf_bump) | if (shader->get_has_bssrdf_bump()) | ||||
| flag |= SD_HAS_BSSRDF_BUMP; | flag |= SD_HAS_BSSRDF_BUMP; | ||||
| if (device->info.has_volume_decoupled) { | if (device->info.has_volume_decoupled) { | ||||
| if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR) | if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_EQUIANGULAR) | ||||
| flag |= SD_VOLUME_EQUIANGULAR; | flag |= SD_VOLUME_EQUIANGULAR; | ||||
| if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) | if (shader->get_volume_sampling_method() == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE) | ||||
| flag |= SD_VOLUME_MIS; | flag |= SD_VOLUME_MIS; | ||||
| } | } | ||||
| if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) | if (shader->get_volume_interpolation_method() == VOLUME_INTERPOLATION_CUBIC) | ||||
| flag |= SD_VOLUME_CUBIC; | flag |= SD_VOLUME_CUBIC; | ||||
| if (shader->has_bump) | if (shader->get_has_bump()) | ||||
| flag |= SD_HAS_BUMP; | flag |= SD_HAS_BUMP; | ||||
| if (shader->get_displacement_method() != DISPLACE_BUMP) | if (shader->get_displacement_method() != DISPLACE_BUMP) | ||||
| flag |= SD_HAS_DISPLACEMENT; | flag |= SD_HAS_DISPLACEMENT; | ||||
| /* constant emission check */ | /* constant emission check */ | ||||
| float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f); | float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f); | ||||
| if (shader->is_constant_emission(&constant_emission)) | if (shader->is_constant_emission(&constant_emission)) | ||||
| flag |= SD_HAS_CONSTANT_EMISSION; | flag |= SD_HAS_CONSTANT_EMISSION; | ||||
| uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0); | uint32_t cryptomatte_id = util_murmur_hash3( | ||||
| shader->get_name().c_str(), shader->get_name().length(), 0); | |||||
| /* regular shader */ | /* regular shader */ | ||||
| kshader->flags = flag; | kshader->flags = flag; | ||||
| kshader->pass_id = shader->get_pass_id(); | kshader->pass_id = shader->get_pass_id(); | ||||
| kshader->constant_emission[0] = constant_emission.x; | kshader->constant_emission[0] = constant_emission.x; | ||||
| kshader->constant_emission[1] = constant_emission.y; | kshader->constant_emission[1] = constant_emission.y; | ||||
| kshader->constant_emission[2] = constant_emission.z; | kshader->constant_emission[2] = constant_emission.z; | ||||
| kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id); | kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id); | ||||
| Show All 11 Lines | void ShaderManager::device_update_common(Device *device, | ||||
| if (beckmann_table_offset == TABLE_OFFSET_INVALID) { | if (beckmann_table_offset == TABLE_OFFSET_INVALID) { | ||||
| if (!beckmann_table_ready) { | if (!beckmann_table_ready) { | ||||
| thread_scoped_lock lock(lookup_table_mutex); | thread_scoped_lock lock(lookup_table_mutex); | ||||
| if (!beckmann_table_ready) { | if (!beckmann_table_ready) { | ||||
| beckmann_table_build(beckmann_table); | beckmann_table_build(beckmann_table); | ||||
| beckmann_table_ready = true; | beckmann_table_ready = true; | ||||
| } | } | ||||
| } | } | ||||
| beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table); | beckmann_table_offset = scene->get_lookup_tables()->add_table(dscene, beckmann_table); | ||||
| } | } | ||||
| ktables->beckmann_offset = (int)beckmann_table_offset; | ktables->beckmann_offset = (int)beckmann_table_offset; | ||||
| /* integrator */ | /* integrator */ | ||||
| KernelIntegrator *kintegrator = &dscene->data.integrator; | KernelIntegrator *kintegrator = &dscene->data.integrator; | ||||
| kintegrator->use_volumes = has_volumes; | kintegrator->use_volumes = has_volumes; | ||||
| /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */ | /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */ | ||||
| kintegrator->transparent_shadows = has_transparent_shadow; | kintegrator->transparent_shadows = has_transparent_shadow; | ||||
| /* film */ | /* film */ | ||||
| KernelFilm *kfilm = &dscene->data.film; | KernelFilm *kfilm = &dscene->data.film; | ||||
| /* color space, needs to be here because e.g. displacement shaders could depend on it */ | /* color space, needs to be here because e.g. displacement shaders could depend on it */ | ||||
| kfilm->xyz_to_r = float3_to_float4(xyz_to_r); | kfilm->xyz_to_r = float3_to_float4(xyz_to_r); | ||||
| kfilm->xyz_to_g = float3_to_float4(xyz_to_g); | kfilm->xyz_to_g = float3_to_float4(xyz_to_g); | ||||
| kfilm->xyz_to_b = float3_to_float4(xyz_to_b); | kfilm->xyz_to_b = float3_to_float4(xyz_to_b); | ||||
| kfilm->rgb_to_y = float3_to_float4(rgb_to_y); | kfilm->rgb_to_y = float3_to_float4(rgb_to_y); | ||||
| } | } | ||||
| void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene) | void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene) | ||||
| { | { | ||||
| scene->lookup_tables->remove_table(&beckmann_table_offset); | scene->get_lookup_tables()->remove_table(&beckmann_table_offset); | ||||
| dscene->shaders.free(); | dscene->shaders.free(); | ||||
| } | } | ||||
| void ShaderManager::add_default(Scene *scene) | void ShaderManager::add_default(Scene *scene) | ||||
| { | { | ||||
| /* default surface */ | /* default surface */ | ||||
| { | { | ||||
| ShaderGraph *graph = new ShaderGraph(); | ShaderGraph *graph = new ShaderGraph(); | ||||
| DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>(); | DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>(); | ||||
| diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f)); | diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f)); | ||||
| graph->add(diffuse); | graph->add(diffuse); | ||||
| graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface")); | graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface")); | ||||
| Shader *shader = scene->create_node<Shader>(); | Shader *shader = scene->create_node<Shader>(); | ||||
| shader->name = "default_surface"; | shader->get_name() = "default_surface"; | ||||
| shader->set_graph(graph); | shader->set_graph(graph); | ||||
| scene->default_surface = shader; | scene->set_default_surface(shader); | ||||
| shader->tag_update(scene); | shader->tag_update(scene); | ||||
| } | } | ||||
| /* default volume */ | /* default volume */ | ||||
| { | { | ||||
| ShaderGraph *graph = new ShaderGraph(); | ShaderGraph *graph = new ShaderGraph(); | ||||
| PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>(); | PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>(); | ||||
| graph->add(principled); | graph->add(principled); | ||||
| graph->connect(principled->output("Volume"), graph->output()->input("Volume")); | graph->connect(principled->output("Volume"), graph->output()->input("Volume")); | ||||
| Shader *shader = scene->create_node<Shader>(); | Shader *shader = scene->create_node<Shader>(); | ||||
| shader->name = "default_volume"; | shader->get_name() = "default_volume"; | ||||
| shader->set_graph(graph); | shader->set_graph(graph); | ||||
| scene->default_volume = shader; | scene->set_default_volume(shader); | ||||
| shader->tag_update(scene); | shader->tag_update(scene); | ||||
| } | } | ||||
| /* default light */ | /* default light */ | ||||
| { | { | ||||
| ShaderGraph *graph = new ShaderGraph(); | ShaderGraph *graph = new ShaderGraph(); | ||||
| EmissionNode *emission = graph->create_node<EmissionNode>(); | EmissionNode *emission = graph->create_node<EmissionNode>(); | ||||
| emission->set_color(make_float3(0.8f, 0.8f, 0.8f)); | emission->set_color(make_float3(0.8f, 0.8f, 0.8f)); | ||||
| emission->set_strength(0.0f); | emission->set_strength(0.0f); | ||||
| graph->add(emission); | graph->add(emission); | ||||
| graph->connect(emission->output("Emission"), graph->output()->input("Surface")); | graph->connect(emission->output("Emission"), graph->output()->input("Surface")); | ||||
| Shader *shader = scene->create_node<Shader>(); | Shader *shader = scene->create_node<Shader>(); | ||||
| shader->name = "default_light"; | shader->get_name() = "default_light"; | ||||
| shader->set_graph(graph); | shader->set_graph(graph); | ||||
| scene->default_light = shader; | scene->set_default_light(shader); | ||||
| shader->tag_update(scene); | shader->tag_update(scene); | ||||
| } | } | ||||
| /* default background */ | /* default background */ | ||||
| { | { | ||||
| ShaderGraph *graph = new ShaderGraph(); | ShaderGraph *graph = new ShaderGraph(); | ||||
| Shader *shader = scene->create_node<Shader>(); | Shader *shader = scene->create_node<Shader>(); | ||||
| shader->name = "default_background"; | shader->get_name() = "default_background"; | ||||
| shader->set_graph(graph); | shader->set_graph(graph); | ||||
| scene->default_background = shader; | scene->set_default_background(shader); | ||||
| shader->tag_update(scene); | shader->tag_update(scene); | ||||
| } | } | ||||
| /* default empty */ | /* default empty */ | ||||
| { | { | ||||
| ShaderGraph *graph = new ShaderGraph(); | ShaderGraph *graph = new ShaderGraph(); | ||||
| Shader *shader = scene->create_node<Shader>(); | Shader *shader = scene->create_node<Shader>(); | ||||
| shader->name = "default_empty"; | shader->get_name() = "default_empty"; | ||||
| shader->set_graph(graph); | shader->set_graph(graph); | ||||
| scene->default_empty = shader; | scene->set_default_empty(shader); | ||||
| shader->tag_update(scene); | shader->tag_update(scene); | ||||
| } | } | ||||
| } | } | ||||
| void ShaderManager::get_requested_graph_features(ShaderGraph *graph, | void ShaderManager::get_requested_graph_features(ShaderGraph *graph, | ||||
| DeviceRequestedFeatures *requested_features) | DeviceRequestedFeatures *requested_features) | ||||
| { | { | ||||
| foreach (ShaderNode *node, graph->nodes) { | foreach (ShaderNode *node, graph->get_nodes()) { | ||||
| requested_features->max_nodes_group = max(requested_features->max_nodes_group, | requested_features->max_nodes_group = max(requested_features->max_nodes_group, | ||||
| node->get_group()); | node->get_group()); | ||||
| requested_features->nodes_features |= node->get_feature(); | requested_features->nodes_features |= node->get_feature(); | ||||
| if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) { | if (node->get_special_type() == SHADER_SPECIAL_TYPE_CLOSURE) { | ||||
| BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node); | BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node); | ||||
| if (CLOSURE_IS_VOLUME(bsdf_node->get_closure_type())) { | if (CLOSURE_IS_VOLUME(bsdf_node->get_closure_type())) { | ||||
| requested_features->nodes_features |= NODE_FEATURE_VOLUME; | requested_features->nodes_features |= NODE_FEATURE_VOLUME; | ||||
| } | } | ||||
| else if (CLOSURE_IS_PRINCIPLED(bsdf_node->get_closure_type())) { | else if (CLOSURE_IS_PRINCIPLED(bsdf_node->get_closure_type())) { | ||||
| requested_features->use_principled = true; | requested_features->use_principled = true; | ||||
| } | } | ||||
| } | } | ||||
| Show All 9 Lines | void ShaderManager::get_requested_graph_features(ShaderGraph *graph, | ||||
| } | } | ||||
| } | } | ||||
| void ShaderManager::get_requested_features(Scene *scene, | void ShaderManager::get_requested_features(Scene *scene, | ||||
| DeviceRequestedFeatures *requested_features) | DeviceRequestedFeatures *requested_features) | ||||
| { | { | ||||
| requested_features->max_nodes_group = NODE_GROUP_LEVEL_0; | requested_features->max_nodes_group = NODE_GROUP_LEVEL_0; | ||||
| requested_features->nodes_features = 0; | requested_features->nodes_features = 0; | ||||
| for (int i = 0; i < scene->shaders.size(); i++) { | foreach (Shader *shader, scene->get_shaders()) { | ||||
| Shader *shader = scene->shaders[i]; | if (!shader->get_used()) { | ||||
| if (!shader->used) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| /* Gather requested features from all the nodes from the graph nodes. */ | /* Gather requested features from all the nodes from the graph nodes. */ | ||||
| get_requested_graph_features(shader->graph, requested_features); | get_requested_graph_features(shader->get_graph(), requested_features); | ||||
| ShaderNode *output_node = shader->graph->output(); | ShaderNode *output_node = shader->get_graph()->output(); | ||||
| if (output_node->input("Displacement")->link != NULL) { | if (output_node->input("Displacement")->get_link() != NULL) { | ||||
| requested_features->nodes_features |= NODE_FEATURE_BUMP; | requested_features->nodes_features |= NODE_FEATURE_BUMP; | ||||
| if (shader->get_displacement_method() == DISPLACE_BOTH) { | if (shader->get_displacement_method() == DISPLACE_BOTH) { | ||||
| requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE; | requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE; | ||||
| requested_features->max_nodes_group = max(requested_features->max_nodes_group, | requested_features->max_nodes_group = max(requested_features->max_nodes_group, | ||||
| NODE_GROUP_LEVEL_1); | NODE_GROUP_LEVEL_1); | ||||
| } | } | ||||
| } | } | ||||
| /* On top of volume nodes, also check if we need volume sampling because | /* On top of volume nodes, also check if we need volume sampling because | ||||
| * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */ | * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */ | ||||
| if (shader->has_volume) | if (shader->get_has_volume()) | ||||
| requested_features->use_volume |= true; | requested_features->use_volume |= true; | ||||
| } | } | ||||
| } | } | ||||
| void ShaderManager::free_memory() | void ShaderManager::free_memory() | ||||
| { | { | ||||
| beckmann_table.free_memory(); | beckmann_table.free_memory(); | ||||
| #ifdef WITH_OSL | #ifdef WITH_OSL | ||||
| OSLShaderManager::free_memory(); | OSLShaderManager::free_memory(); | ||||
| #endif | #endif | ||||
| ColorSpaceManager::free_memory(); | ColorSpaceManager::free_memory(); | ||||
| } | } | ||||
| float ShaderManager::linear_rgb_to_gray(float3 c) | float ShaderManager::linear_rgb_to_gray(float3 c) | ||||
| { | { | ||||
| return dot(c, rgb_to_y); | return dot(c, rgb_to_y); | ||||
| } | } | ||||
| string ShaderManager::get_cryptomatte_materials(Scene *scene) | string ShaderManager::get_cryptomatte_materials(Scene *scene) | ||||
| { | { | ||||
| string manifest = "{"; | string manifest = "{"; | ||||
| unordered_set<ustring, ustringHash> materials; | unordered_set<ustring, ustringHash> materials; | ||||
| foreach (Shader *shader, scene->shaders) { | foreach (Shader *shader, scene->get_shaders()) { | ||||
| if (materials.count(shader->name)) { | if (materials.count(shader->get_name())) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| materials.insert(shader->name); | materials.insert(shader->get_name()); | ||||
| uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0); | uint32_t cryptomatte_id = util_murmur_hash3( | ||||
| manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id); | shader->get_name().c_str(), shader->get_name().length(), 0); | ||||
| manifest += string_printf("\"%s\":\"%08x\",", shader->get_name().c_str(), cryptomatte_id); | |||||
| } | } | ||||
| manifest[manifest.size() - 1] = '}'; | manifest[manifest.size() - 1] = '}'; | ||||
| return manifest; | return manifest; | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||