Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/shader.cpp')
-rw-r--r--intern/cycles/render/shader.cpp1067
1 files changed, 535 insertions, 532 deletions
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 3c94f2dfb59..ac3303cbfeb 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -48,16 +48,15 @@ bool ShaderManager::beckmann_table_ready = false;
/* 2D slope distribution (alpha = 1.0) */
static float beckmann_table_P22(const float slope_x, const float slope_y)
{
- return expf(-(slope_x*slope_x + slope_y*slope_y));
+ return expf(-(slope_x * slope_x + slope_y * slope_y));
}
/* maximal slope amplitude (range that contains 99.99% of the distribution) */
static float beckmann_table_slope_max()
{
- return 6.0;
+ return 6.0;
}
-
/* MSVC 2015 needs this ugly hack to prevent a codegen bug on x86
* see T50176 for details
*/
@@ -74,327 +73,331 @@ static float beckmann_table_slope_max()
*/
static void beckmann_table_rows(float *table, int row_from, int row_to)
{
- /* allocate temporary data */
- const int DATA_TMP_SIZE = 512;
- vector<double> slope_x(DATA_TMP_SIZE);
- vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
-
- /* loop over incident directions */
- for(int index_theta = row_from; index_theta < row_to; index_theta++) {
- /* incident vector */
- const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
- const float sin_theta = safe_sqrtf(1.0f - cos_theta*cos_theta);
-
- /* for a given incident vector
- * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- slope_x[0] = (double)-beckmann_table_slope_max();
- CDF_P22_omega_i[0] = 0;
-
- for(MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
- /* slope_x */
- slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * index_slope_x/(DATA_TMP_SIZE - 1.0f));
-
- /* dot product with incident vector */
- float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x]*sin_theta + cos_theta);
- /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- float P22_omega_i = 0.0f;
-
- for(int j = 0; j < 100; ++j) {
- float slope_y = -beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * j * (1.0f/99.0f);
- P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
- }
-
- /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
- }
-
- /* renormalize CDF_P22_omega_i */
- for(int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
- CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
-
- /* loop over random number U1 */
- int index_slope_x = 0;
-
- for(int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
- const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
-
- /* inverse CDF_P22_omega_i, solve Eq.(11) */
- while(CDF_P22_omega_i[index_slope_x] <= U)
- ++index_slope_x;
-
- const double interp =
- (CDF_P22_omega_i[index_slope_x] - U) /
- (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
-
- /* store value */
- table[index_U + index_theta*BECKMANN_TABLE_SIZE] = (float)(
- interp * slope_x[index_slope_x - 1] +
- (1.0 - interp) * slope_x[index_slope_x]);
- }
- }
+ /* allocate temporary data */
+ const int DATA_TMP_SIZE = 512;
+ vector<double> slope_x(DATA_TMP_SIZE);
+ vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
+
+ /* loop over incident directions */
+ for (int index_theta = row_from; index_theta < row_to; index_theta++) {
+ /* incident vector */
+ const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
+ const float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
+
+ /* for a given incident vector
+ * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ slope_x[0] = (double)-beckmann_table_slope_max();
+ CDF_P22_omega_i[0] = 0;
+
+ for (MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
+ /* slope_x */
+ slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() +
+ 2.0f * beckmann_table_slope_max() * index_slope_x /
+ (DATA_TMP_SIZE - 1.0f));
+
+ /* dot product with incident vector */
+ float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x] * sin_theta + cos_theta);
+ /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ float P22_omega_i = 0.0f;
+
+ for (int j = 0; j < 100; ++j) {
+ float slope_y = -beckmann_table_slope_max() +
+ 2.0f * beckmann_table_slope_max() * j * (1.0f / 99.0f);
+ P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
+ }
+
+ /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
+ }
+
+ /* renormalize CDF_P22_omega_i */
+ for (int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
+ CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
+
+ /* loop over random number U1 */
+ int index_slope_x = 0;
+
+ for (int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
+ const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
+
+ /* inverse CDF_P22_omega_i, solve Eq.(11) */
+ while (CDF_P22_omega_i[index_slope_x] <= U)
+ ++index_slope_x;
+
+ const double interp = (CDF_P22_omega_i[index_slope_x] - U) /
+ (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
+
+ /* store value */
+ table[index_U + index_theta * BECKMANN_TABLE_SIZE] =
+ (float)(interp * slope_x[index_slope_x - 1] + (1.0 - interp) * slope_x[index_slope_x]);
+ }
+ }
}
#undef MSVC_VOLATILE
-static void beckmann_table_build(vector<float>& table)
+static void beckmann_table_build(vector<float> &table)
{
- table.resize(BECKMANN_TABLE_SIZE*BECKMANN_TABLE_SIZE);
+ table.resize(BECKMANN_TABLE_SIZE * BECKMANN_TABLE_SIZE);
- /* multithreaded build */
- TaskPool pool;
+ /* multithreaded build */
+ TaskPool pool;
- for(int i = 0; i < BECKMANN_TABLE_SIZE; i+=8)
- pool.push(function_bind(&beckmann_table_rows, &table[0], i, i+8));
+ for (int i = 0; i < BECKMANN_TABLE_SIZE; i += 8)
+ pool.push(function_bind(&beckmann_table_rows, &table[0], i, i + 8));
- pool.wait_work();
+ pool.wait_work();
}
/* Shader */
NODE_DEFINE(Shader)
{
- NodeType* type = NodeType::add("shader", create);
-
- SOCKET_BOOLEAN(use_mis, "Use MIS", true);
- SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
- SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
-
- static NodeEnum volume_sampling_method_enum;
- volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
- volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
- volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
- SOCKET_ENUM(volume_sampling_method, "Volume Sampling Method", volume_sampling_method_enum, VOLUME_SAMPLING_DISTANCE);
-
- static NodeEnum volume_interpolation_method_enum;
- volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
- volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
- SOCKET_ENUM(volume_interpolation_method, "Volume Interpolation Method", volume_interpolation_method_enum, VOLUME_INTERPOLATION_LINEAR);
-
- static NodeEnum displacement_method_enum;
- displacement_method_enum.insert("bump", DISPLACE_BUMP);
- displacement_method_enum.insert("true", DISPLACE_TRUE);
- displacement_method_enum.insert("both", DISPLACE_BOTH);
- SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
-
- return type;
+ NodeType *type = NodeType::add("shader", create);
+
+ SOCKET_BOOLEAN(use_mis, "Use MIS", true);
+ SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
+ SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
+
+ static NodeEnum volume_sampling_method_enum;
+ volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
+ volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
+ volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
+ SOCKET_ENUM(volume_sampling_method,
+ "Volume Sampling Method",
+ volume_sampling_method_enum,
+ VOLUME_SAMPLING_DISTANCE);
+
+ static NodeEnum volume_interpolation_method_enum;
+ volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
+ volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
+ SOCKET_ENUM(volume_interpolation_method,
+ "Volume Interpolation Method",
+ volume_interpolation_method_enum,
+ VOLUME_INTERPOLATION_LINEAR);
+
+ static NodeEnum displacement_method_enum;
+ displacement_method_enum.insert("bump", DISPLACE_BUMP);
+ displacement_method_enum.insert("true", DISPLACE_TRUE);
+ displacement_method_enum.insert("both", DISPLACE_BOTH);
+ SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
+
+ return type;
}
-Shader::Shader()
-: Node(node_type)
+Shader::Shader() : Node(node_type)
{
- pass_id = 0;
-
- graph = NULL;
-
- has_surface = false;
- has_surface_transparent = false;
- has_surface_emission = false;
- has_surface_bssrdf = false;
- has_volume = false;
- has_displacement = false;
- has_bump = false;
- has_bssrdf_bump = false;
- has_surface_spatial_varying = false;
- has_volume_spatial_varying = false;
- has_object_dependency = false;
- has_attribute_dependency = false;
- has_integrator_dependency = false;
- has_volume_connected = false;
-
- displacement_method = DISPLACE_BUMP;
-
- id = -1;
- used = false;
-
- need_update = true;
- need_update_mesh = true;
- need_sync_object = false;
+ pass_id = 0;
+
+ graph = NULL;
+
+ has_surface = false;
+ has_surface_transparent = false;
+ has_surface_emission = false;
+ has_surface_bssrdf = false;
+ has_volume = false;
+ has_displacement = false;
+ has_bump = false;
+ has_bssrdf_bump = false;
+ has_surface_spatial_varying = false;
+ has_volume_spatial_varying = false;
+ has_object_dependency = false;
+ has_attribute_dependency = false;
+ has_integrator_dependency = false;
+ has_volume_connected = false;
+
+ displacement_method = DISPLACE_BUMP;
+
+ id = -1;
+ used = false;
+
+ need_update = true;
+ need_update_mesh = true;
+ need_sync_object = false;
}
Shader::~Shader()
{
- delete graph;
+ delete graph;
}
bool Shader::is_constant_emission(float3 *emission)
{
- ShaderInput *surf = graph->output()->input("Surface");
+ ShaderInput *surf = graph->output()->input("Surface");
- if(surf->link == NULL) {
- return false;
- }
+ if (surf->link == NULL) {
+ return false;
+ }
- if(surf->link->parent->type == EmissionNode::node_type) {
- EmissionNode *node = (EmissionNode*) surf->link->parent;
+ if (surf->link->parent->type == EmissionNode::node_type) {
+ EmissionNode *node = (EmissionNode *)surf->link->parent;
- assert(node->input("Color"));
- assert(node->input("Strength"));
+ assert(node->input("Color"));
+ assert(node->input("Strength"));
- if(node->input("Color")->link || node->input("Strength")->link) {
- return false;
- }
+ if (node->input("Color")->link || node->input("Strength")->link) {
+ return false;
+ }
- *emission = node->color*node->strength;
- }
- else if(surf->link->parent->type == BackgroundNode::node_type) {
- BackgroundNode *node = (BackgroundNode*) surf->link->parent;
+ *emission = node->color * node->strength;
+ }
+ else if (surf->link->parent->type == BackgroundNode::node_type) {
+ BackgroundNode *node = (BackgroundNode *)surf->link->parent;
- assert(node->input("Color"));
- assert(node->input("Strength"));
+ assert(node->input("Color"));
+ assert(node->input("Strength"));
- if(node->input("Color")->link || node->input("Strength")->link) {
- return false;
- }
+ if (node->input("Color")->link || node->input("Strength")->link) {
+ return false;
+ }
- *emission = node->color*node->strength;
- }
- else {
- return false;
- }
+ *emission = node->color * node->strength;
+ }
+ else {
+ return false;
+ }
- return true;
+ return true;
}
void Shader::set_graph(ShaderGraph *graph_)
{
- /* do this here already so that we can detect if mesh or object attributes
- * are needed, since the node attribute callbacks check if their sockets
- * are connected but proxy nodes should not count */
- if(graph_) {
- graph_->remove_proxy_nodes();
-
- if(displacement_method != DISPLACE_BUMP) {
- graph_->compute_displacement_hash();
- }
- }
-
- /* update geometry if displacement changed */
- if(displacement_method != DISPLACE_BUMP) {
- const char *old_hash = (graph)? graph->displacement_hash.c_str() : "";
- const char *new_hash = (graph_)? graph_->displacement_hash.c_str() : "";
-
- if(strcmp(old_hash, new_hash) != 0) {
- need_update_mesh = true;
- }
- }
-
- /* assign graph */
- delete graph;
- graph = graph_;
-
- /* Store info here before graph optimization to make sure that
- * nodes that get optimized away still count. */
- has_volume_connected = (graph->output()->input("Volume")->link != NULL);
+ /* do this here already so that we can detect if mesh or object attributes
+ * are needed, since the node attribute callbacks check if their sockets
+ * are connected but proxy nodes should not count */
+ if (graph_) {
+ graph_->remove_proxy_nodes();
+
+ if (displacement_method != DISPLACE_BUMP) {
+ graph_->compute_displacement_hash();
+ }
+ }
+
+ /* update geometry if displacement changed */
+ if (displacement_method != DISPLACE_BUMP) {
+ const char *old_hash = (graph) ? graph->displacement_hash.c_str() : "";
+ const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
+
+ if (strcmp(old_hash, new_hash) != 0) {
+ need_update_mesh = true;
+ }
+ }
+
+ /* assign graph */
+ delete graph;
+ graph = graph_;
+
+ /* Store info here before graph optimization to make sure that
+ * nodes that get optimized away still count. */
+ has_volume_connected = (graph->output()->input("Volume")->link != NULL);
}
void Shader::tag_update(Scene *scene)
{
- /* update tag */
- need_update = true;
- scene->shader_manager->need_update = true;
-
- /* if the shader previously was emissive, update light distribution,
- * if the new shader is emissive, a light manager update tag will be
- * done in the shader manager device update. */
- if(use_mis && has_surface_emission)
- scene->light_manager->need_update = true;
-
- /* 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
- * better to be safe.
- */
- if(this == scene->default_background &&
- scene->light_manager->has_background_light(scene))
- {
- scene->light_manager->need_update = true;
- }
-
- /* 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
- * be more fine grained but it's better than nothing */
- OutputNode *output = graph->output();
- bool prev_has_volume = has_volume;
- has_surface = has_surface || output->input("Surface")->link;
- has_volume = has_volume || output->input("Volume")->link;
- has_displacement = has_displacement || output->input("Displacement")->link;
-
- /* get requested attributes. this could be optimized by pruning unused
- * 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
- * disconnect a node */
-
- AttributeRequestSet prev_attributes = attributes;
-
- attributes.clear();
- foreach(ShaderNode *node, graph->nodes)
- node->attributes(this, &attributes);
-
- if(has_displacement && displacement_method == DISPLACE_BOTH) {
- attributes.add(ATTR_STD_POSITION_UNDISPLACED);
- }
-
- /* compare if the attributes changed, mesh manager will check
- * need_update_mesh, update the relevant meshes and clear it. */
- if(attributes.modified(prev_attributes)) {
- need_update_mesh = true;
- scene->mesh_manager->need_update = true;
- }
-
- if(has_volume != prev_has_volume) {
- scene->mesh_manager->need_flags_update = true;
- scene->object_manager->need_flags_update = true;
- }
+ /* update tag */
+ need_update = true;
+ scene->shader_manager->need_update = true;
+
+ /* if the shader previously was emissive, update light distribution,
+ * if the new shader is emissive, a light manager update tag will be
+ * done in the shader manager device update. */
+ if (use_mis && has_surface_emission)
+ scene->light_manager->need_update = true;
+
+ /* 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
+ * better to be safe.
+ */
+ if (this == scene->default_background && scene->light_manager->has_background_light(scene)) {
+ scene->light_manager->need_update = true;
+ }
+
+ /* 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
+ * be more fine grained but it's better than nothing */
+ OutputNode *output = graph->output();
+ bool prev_has_volume = has_volume;
+ has_surface = has_surface || output->input("Surface")->link;
+ has_volume = has_volume || output->input("Volume")->link;
+ has_displacement = has_displacement || output->input("Displacement")->link;
+
+ /* get requested attributes. this could be optimized by pruning unused
+ * 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
+ * disconnect a node */
+
+ AttributeRequestSet prev_attributes = attributes;
+
+ attributes.clear();
+ foreach (ShaderNode *node, graph->nodes)
+ node->attributes(this, &attributes);
+
+ if (has_displacement && displacement_method == DISPLACE_BOTH) {
+ attributes.add(ATTR_STD_POSITION_UNDISPLACED);
+ }
+
+ /* compare if the attributes changed, mesh manager will check
+ * need_update_mesh, update the relevant meshes and clear it. */
+ if (attributes.modified(prev_attributes)) {
+ need_update_mesh = true;
+ scene->mesh_manager->need_update = true;
+ }
+
+ if (has_volume != prev_has_volume) {
+ scene->mesh_manager->need_flags_update = true;
+ scene->object_manager->need_flags_update = true;
+ }
}
void Shader::tag_used(Scene *scene)
{
- /* if an unused shader suddenly gets used somewhere, it needs to be
- * recompiled because it was skipped for compilation before */
- if(!used) {
- need_update = true;
- scene->shader_manager->need_update = true;
- }
+ /* if an unused shader suddenly gets used somewhere, it needs to be
+ * recompiled because it was skipped for compilation before */
+ if (!used) {
+ need_update = true;
+ scene->shader_manager->need_update = true;
+ }
}
/* Shader Manager */
ShaderManager::ShaderManager()
{
- need_update = true;
- beckmann_table_offset = TABLE_OFFSET_INVALID;
+ need_update = true;
+ beckmann_table_offset = TABLE_OFFSET_INVALID;
- xyz_to_r = make_float3( 3.2404542f, -1.5371385f, -0.4985314f);
- xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
- xyz_to_b = make_float3( 0.0556434f, -0.2040259f, 1.0572252f);
- rgb_to_y = make_float3( 0.2126729f, 0.7151522f, 0.0721750f);
+ xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
+ xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
+ xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
+ rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
#ifdef WITH_OCIO
- OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
- if(config) {
- if(config->hasRole("XYZ") && config->hasRole("scene_linear")) {
- OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
- OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
- if(to_rgb_processor && to_xyz_processor) {
- float r[] = {1.0f, 0.0f, 0.0f};
- float g[] = {0.0f, 1.0f, 0.0f};
- float b[] = {0.0f, 0.0f, 1.0f};
- to_xyz_processor->applyRGB(r);
- to_xyz_processor->applyRGB(g);
- to_xyz_processor->applyRGB(b);
- rgb_to_y = make_float3(r[1], g[1], b[1]);
-
- float x[] = {1.0f, 0.0f, 0.0f};
- float y[] = {0.0f, 1.0f, 0.0f};
- float z[] = {0.0f, 0.0f, 1.0f};
- to_rgb_processor->applyRGB(x);
- to_rgb_processor->applyRGB(y);
- to_rgb_processor->applyRGB(z);
- xyz_to_r = make_float3(x[0], y[0], z[0]);
- xyz_to_g = make_float3(x[1], y[1], z[1]);
- xyz_to_b = make_float3(x[2], y[2], z[2]);
- }
- }
- }
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ if (config) {
+ if (config->hasRole("XYZ") && config->hasRole("scene_linear")) {
+ OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
+ OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
+ if (to_rgb_processor && to_xyz_processor) {
+ float r[] = {1.0f, 0.0f, 0.0f};
+ float g[] = {0.0f, 1.0f, 0.0f};
+ float b[] = {0.0f, 0.0f, 1.0f};
+ to_xyz_processor->applyRGB(r);
+ to_xyz_processor->applyRGB(g);
+ to_xyz_processor->applyRGB(b);
+ rgb_to_y = make_float3(r[1], g[1], b[1]);
+
+ float x[] = {1.0f, 0.0f, 0.0f};
+ float y[] = {0.0f, 1.0f, 0.0f};
+ float z[] = {0.0f, 0.0f, 1.0f};
+ to_rgb_processor->applyRGB(x);
+ to_rgb_processor->applyRGB(y);
+ to_rgb_processor->applyRGB(z);
+ xyz_to_r = make_float3(x[0], y[0], z[0]);
+ xyz_to_g = make_float3(x[1], y[1], z[1]);
+ xyz_to_b = make_float3(x[2], y[2], z[2]);
+ }
+ }
+ }
#endif
}
@@ -404,337 +407,337 @@ ShaderManager::~ShaderManager()
ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
{
- ShaderManager *manager;
+ ShaderManager *manager;
- (void) shadingsystem; /* Ignored when built without OSL. */
+ (void)shadingsystem; /* Ignored when built without OSL. */
#ifdef WITH_OSL
- if(shadingsystem == SHADINGSYSTEM_OSL) {
- manager = new OSLShaderManager();
- }
- else
+ if (shadingsystem == SHADINGSYSTEM_OSL) {
+ manager = new OSLShaderManager();
+ }
+ else
#endif
- {
- manager = new SVMShaderManager();
- }
+ {
+ manager = new SVMShaderManager();
+ }
- add_default(scene);
+ add_default(scene);
- return manager;
+ return manager;
}
uint ShaderManager::get_attribute_id(ustring name)
{
- thread_scoped_spin_lock lock(attribute_lock_);
+ thread_scoped_spin_lock lock(attribute_lock_);
- /* get a unique id for each name, for SVM attribute lookup */
- AttributeIDMap::iterator it = unique_attribute_id.find(name);
+ /* get a unique id for each name, for SVM attribute lookup */
+ AttributeIDMap::iterator it = unique_attribute_id.find(name);
- if(it != unique_attribute_id.end())
- return it->second;
+ if (it != unique_attribute_id.end())
+ return it->second;
- uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
- unique_attribute_id[name] = id;
- return id;
+ uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
+ unique_attribute_id[name] = id;
+ return id;
}
uint ShaderManager::get_attribute_id(AttributeStandard std)
{
- return (uint)std;
+ return (uint)std;
}
int ShaderManager::get_shader_id(Shader *shader, bool smooth)
{
- /* get a shader id to pass to the kernel */
- int id = shader->id;
+ /* get a shader id to pass to the kernel */
+ int id = shader->id;
- /* smooth flag */
- if(smooth)
- id |= SHADER_SMOOTH_NORMAL;
+ /* smooth flag */
+ if (smooth)
+ id |= SHADER_SMOOTH_NORMAL;
- /* default flags */
- id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
+ /* default flags */
+ id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT;
- return id;
+ return id;
}
void ShaderManager::device_update_shaders_used(Scene *scene)
{
- /* figure out which shaders are in use, so SVM/OSL can skip compiling them
- * for speed and avoid loading image textures into memory */
- uint id = 0;
- foreach(Shader *shader, scene->shaders) {
- shader->used = false;
- shader->id = id++;
- }
-
- scene->default_surface->used = true;
- scene->default_light->used = true;
- scene->default_background->used = true;
- scene->default_empty->used = true;
-
- if(scene->background->shader)
- scene->background->shader->used = true;
-
- foreach(Mesh *mesh, scene->meshes)
- foreach(Shader *shader, mesh->used_shaders)
- shader->used = true;
-
- foreach(Light *light, scene->lights)
- if(light->shader)
- light->shader->used = true;
+ /* figure out which shaders are in use, so SVM/OSL can skip compiling them
+ * for speed and avoid loading image textures into memory */
+ uint id = 0;
+ foreach (Shader *shader, scene->shaders) {
+ shader->used = false;
+ shader->id = id++;
+ }
+
+ scene->default_surface->used = true;
+ scene->default_light->used = true;
+ scene->default_background->used = true;
+ scene->default_empty->used = true;
+
+ if (scene->background->shader)
+ scene->background->shader->used = true;
+
+ foreach (Mesh *mesh, scene->meshes)
+ foreach (Shader *shader, mesh->used_shaders)
+ shader->used = true;
+
+ foreach (Light *light, scene->lights)
+ if (light->shader)
+ light->shader->used = true;
}
void ShaderManager::device_update_common(Device *device,
DeviceScene *dscene,
Scene *scene,
- Progress& /*progress*/)
+ Progress & /*progress*/)
{
- dscene->shaders.free();
-
- if(scene->shaders.size() == 0)
- return;
-
- KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
- bool has_volumes = false;
- bool has_transparent_shadow = false;
-
- foreach(Shader *shader, scene->shaders) {
- uint flag = 0;
-
- if(shader->use_mis)
- flag |= SD_USE_MIS;
- if(shader->has_surface_transparent && shader->use_transparent_shadow)
- flag |= SD_HAS_TRANSPARENT_SHADOW;
- if(shader->has_volume) {
- flag |= SD_HAS_VOLUME;
- has_volumes = true;
-
- /* todo: this could check more fine grained, to skip useless volumes
- * enclosed inside an opaque bsdf.
- */
- flag |= SD_HAS_TRANSPARENT_SHADOW;
- }
- /* in this case we can assume transparent surface */
- if(shader->has_volume_connected && !shader->has_surface)
- flag |= SD_HAS_ONLY_VOLUME;
- if(shader->heterogeneous_volume && shader->has_volume_spatial_varying)
- flag |= SD_HETEROGENEOUS_VOLUME;
- if(shader->has_attribute_dependency)
- flag |= SD_NEED_ATTRIBUTES;
- if(shader->has_bssrdf_bump)
- flag |= SD_HAS_BSSRDF_BUMP;
- if(device->info.has_volume_decoupled) {
- if(shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
- flag |= SD_VOLUME_EQUIANGULAR;
- if(shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
- flag |= SD_VOLUME_MIS;
- }
- if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
- flag |= SD_VOLUME_CUBIC;
- if(shader->has_bump)
- flag |= SD_HAS_BUMP;
- if(shader->displacement_method != DISPLACE_BUMP)
- flag |= SD_HAS_DISPLACEMENT;
-
- /* constant emission check */
- float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
- if(shader->is_constant_emission(&constant_emission))
- flag |= SD_HAS_CONSTANT_EMISSION;
-
- uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
-
- /* regular shader */
- kshader->flags = flag;
- kshader->pass_id = shader->pass_id;
- kshader->constant_emission[0] = constant_emission.x;
- kshader->constant_emission[1] = constant_emission.y;
- kshader->constant_emission[2] = constant_emission.z;
- kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
- kshader++;
-
- has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
- }
-
- dscene->shaders.copy_to_device();
-
- /* lookup tables */
- KernelTables *ktables = &dscene->data.tables;
-
- /* beckmann lookup table */
- if(beckmann_table_offset == TABLE_OFFSET_INVALID) {
- if(!beckmann_table_ready) {
- thread_scoped_lock lock(lookup_table_mutex);
- if(!beckmann_table_ready) {
- beckmann_table_build(beckmann_table);
- beckmann_table_ready = true;
- }
- }
- beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
- }
- ktables->beckmann_offset = (int)beckmann_table_offset;
-
- /* integrator */
- KernelIntegrator *kintegrator = &dscene->data.integrator;
- kintegrator->use_volumes = has_volumes;
- /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
- kintegrator->transparent_shadows = has_transparent_shadow;
-
- /* film */
- KernelFilm *kfilm = &dscene->data.film;
- /* 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_g = float3_to_float4(xyz_to_g);
- kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
- kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
+ dscene->shaders.free();
+
+ if (scene->shaders.size() == 0)
+ return;
+
+ KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
+ bool has_volumes = false;
+ bool has_transparent_shadow = false;
+
+ foreach (Shader *shader, scene->shaders) {
+ uint flag = 0;
+
+ if (shader->use_mis)
+ flag |= SD_USE_MIS;
+ if (shader->has_surface_transparent && shader->use_transparent_shadow)
+ flag |= SD_HAS_TRANSPARENT_SHADOW;
+ if (shader->has_volume) {
+ flag |= SD_HAS_VOLUME;
+ has_volumes = true;
+
+ /* todo: this could check more fine grained, to skip useless volumes
+ * enclosed inside an opaque bsdf.
+ */
+ flag |= SD_HAS_TRANSPARENT_SHADOW;
+ }
+ /* in this case we can assume transparent surface */
+ if (shader->has_volume_connected && !shader->has_surface)
+ flag |= SD_HAS_ONLY_VOLUME;
+ if (shader->heterogeneous_volume && shader->has_volume_spatial_varying)
+ flag |= SD_HETEROGENEOUS_VOLUME;
+ if (shader->has_attribute_dependency)
+ flag |= SD_NEED_ATTRIBUTES;
+ if (shader->has_bssrdf_bump)
+ flag |= SD_HAS_BSSRDF_BUMP;
+ if (device->info.has_volume_decoupled) {
+ if (shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
+ flag |= SD_VOLUME_EQUIANGULAR;
+ if (shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
+ flag |= SD_VOLUME_MIS;
+ }
+ if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
+ flag |= SD_VOLUME_CUBIC;
+ if (shader->has_bump)
+ flag |= SD_HAS_BUMP;
+ if (shader->displacement_method != DISPLACE_BUMP)
+ flag |= SD_HAS_DISPLACEMENT;
+
+ /* constant emission check */
+ float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
+ if (shader->is_constant_emission(&constant_emission))
+ flag |= SD_HAS_CONSTANT_EMISSION;
+
+ uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+
+ /* regular shader */
+ kshader->flags = flag;
+ kshader->pass_id = shader->pass_id;
+ kshader->constant_emission[0] = constant_emission.x;
+ kshader->constant_emission[1] = constant_emission.y;
+ kshader->constant_emission[2] = constant_emission.z;
+ kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
+ kshader++;
+
+ has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
+ }
+
+ dscene->shaders.copy_to_device();
+
+ /* lookup tables */
+ KernelTables *ktables = &dscene->data.tables;
+
+ /* beckmann lookup table */
+ if (beckmann_table_offset == TABLE_OFFSET_INVALID) {
+ if (!beckmann_table_ready) {
+ thread_scoped_lock lock(lookup_table_mutex);
+ if (!beckmann_table_ready) {
+ beckmann_table_build(beckmann_table);
+ beckmann_table_ready = true;
+ }
+ }
+ beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
+ }
+ ktables->beckmann_offset = (int)beckmann_table_offset;
+
+ /* integrator */
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ kintegrator->use_volumes = has_volumes;
+ /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
+ kintegrator->transparent_shadows = has_transparent_shadow;
+
+ /* film */
+ KernelFilm *kfilm = &dscene->data.film;
+ /* 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_g = float3_to_float4(xyz_to_g);
+ kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
+ kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
}
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
{
- scene->lookup_tables->remove_table(&beckmann_table_offset);
+ scene->lookup_tables->remove_table(&beckmann_table_offset);
- dscene->shaders.free();
+ dscene->shaders.free();
}
void ShaderManager::add_default(Scene *scene)
{
- /* default surface */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
- diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
- graph->add(diffuse);
-
- graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
-
- Shader *shader = new Shader();
- shader->name = "default_surface";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_surface = shader;
- }
-
- /* default light */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- EmissionNode *emission = new EmissionNode();
- emission->color = make_float3(0.8f, 0.8f, 0.8f);
- emission->strength = 0.0f;
- graph->add(emission);
-
- graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
-
- Shader *shader = new Shader();
- shader->name = "default_light";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_light = shader;
- }
-
- /* default background */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- Shader *shader = new Shader();
- shader->name = "default_background";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_background = shader;
- }
-
- /* default empty */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- Shader *shader = new Shader();
- shader->name = "default_empty";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_empty = shader;
- }
+ /* default surface */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
+ graph->add(diffuse);
+
+ graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
+
+ Shader *shader = new Shader();
+ shader->name = "default_surface";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_surface = shader;
+ }
+
+ /* default light */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ EmissionNode *emission = new EmissionNode();
+ emission->color = make_float3(0.8f, 0.8f, 0.8f);
+ emission->strength = 0.0f;
+ graph->add(emission);
+
+ graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
+
+ Shader *shader = new Shader();
+ shader->name = "default_light";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_light = shader;
+ }
+
+ /* default background */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ Shader *shader = new Shader();
+ shader->name = "default_background";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_background = shader;
+ }
+
+ /* default empty */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ Shader *shader = new Shader();
+ shader->name = "default_empty";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_empty = shader;
+ }
}
void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
DeviceRequestedFeatures *requested_features)
{
- foreach(ShaderNode *node, graph->nodes) {
- requested_features->max_nodes_group = max(requested_features->max_nodes_group,
- node->get_group());
- requested_features->nodes_features |= node->get_feature();
- if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
- BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode*>(node);
- if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
- requested_features->nodes_features |= NODE_FEATURE_VOLUME;
- }
- else if(CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
- requested_features->use_principled = true;
- }
- }
- if(node->has_surface_bssrdf()) {
- requested_features->use_subsurface = true;
- }
- if(node->has_surface_transparent()) {
- requested_features->use_transparent = true;
- }
- if(node->has_raytrace()) {
- requested_features->use_shader_raytrace = true;
- }
- }
+ foreach (ShaderNode *node, graph->nodes) {
+ requested_features->max_nodes_group = max(requested_features->max_nodes_group,
+ node->get_group());
+ requested_features->nodes_features |= node->get_feature();
+ if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
+ if (CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+ requested_features->nodes_features |= NODE_FEATURE_VOLUME;
+ }
+ else if (CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
+ requested_features->use_principled = true;
+ }
+ }
+ if (node->has_surface_bssrdf()) {
+ requested_features->use_subsurface = true;
+ }
+ if (node->has_surface_transparent()) {
+ requested_features->use_transparent = true;
+ }
+ if (node->has_raytrace()) {
+ requested_features->use_shader_raytrace = true;
+ }
+ }
}
void ShaderManager::get_requested_features(Scene *scene,
DeviceRequestedFeatures *requested_features)
{
- requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
- requested_features->nodes_features = 0;
- for(int i = 0; i < scene->shaders.size(); i++) {
- Shader *shader = scene->shaders[i];
- /* Gather requested features from all the nodes from the graph nodes. */
- get_requested_graph_features(shader->graph, requested_features);
- ShaderNode *output_node = shader->graph->output();
- if(output_node->input("Displacement")->link != NULL) {
- requested_features->nodes_features |= NODE_FEATURE_BUMP;
- if(shader->displacement_method == DISPLACE_BOTH) {
- requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
- }
- }
- /* 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 */
- if(shader->has_volume)
- requested_features->use_volume |= true;
- }
+ requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
+ requested_features->nodes_features = 0;
+ for (int i = 0; i < scene->shaders.size(); i++) {
+ Shader *shader = scene->shaders[i];
+ /* Gather requested features from all the nodes from the graph nodes. */
+ get_requested_graph_features(shader->graph, requested_features);
+ ShaderNode *output_node = shader->graph->output();
+ if (output_node->input("Displacement")->link != NULL) {
+ requested_features->nodes_features |= NODE_FEATURE_BUMP;
+ if (shader->displacement_method == DISPLACE_BOTH) {
+ requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
+ }
+ }
+ /* 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 */
+ if (shader->has_volume)
+ requested_features->use_volume |= true;
+ }
}
void ShaderManager::free_memory()
{
- beckmann_table.free_memory();
+ beckmann_table.free_memory();
#ifdef WITH_OSL
- OSLShaderManager::free_memory();
+ OSLShaderManager::free_memory();
#endif
}
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 manifest = "{";
- unordered_set<ustring, ustringHash> materials;
- foreach(Shader *shader, scene->shaders) {
- if(materials.count(shader->name)) {
- continue;
- }
- materials.insert(shader->name);
- uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
- manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
- }
- manifest[manifest.size()-1] = '}';
- return manifest;
+ string manifest = "{";
+ unordered_set<ustring, ustringHash> materials;
+ foreach (Shader *shader, scene->shaders) {
+ if (materials.count(shader->name)) {
+ continue;
+ }
+ materials.insert(shader->name);
+ uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+ manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
+ }
+ manifest[manifest.size() - 1] = '}';
+ return manifest;
}
CCL_NAMESPACE_END