Commit: 0aec2dcd3ae0ed382ffe7b3311a4e30fc88398e4
Author: Brecht Van Lommel
Date:   Tue Jan 30 15:05:19 2018 +0100
Branches: master
https://developer.blender.org/rB0aec2dcd3ae0ed382ffe7b3311a4e30fc88398e4

Cycles: add Principled Volume shader.

Similar to the Principled BSDF, this should make it easier to set up volume
materials. Smoke and fire can be rendererd with just a single principled
volume node, the appropriate attributes will be used when available. The node
also works for simpler homogeneous volumes like water or mist.

Differential Revision: https://developer.blender.org/D3033

===================================================================

M       intern/cycles/blender/blender_shader.cpp
M       intern/cycles/kernel/shaders/CMakeLists.txt
A       intern/cycles/kernel/shaders/node_principled_volume.osl
M       intern/cycles/kernel/svm/svm.h
M       intern/cycles/kernel/svm/svm_closure.h
M       intern/cycles/kernel/svm/svm_types.h
M       intern/cycles/render/nodes.cpp
M       intern/cycles/render/nodes.h
M       release/scripts/startup/bl_operators/object_quick_effects.py
M       release/scripts/startup/nodeitems_builtins.py
M       source/blender/blenkernel/BKE_node.h
M       source/blender/blenkernel/intern/node.c
M       source/blender/nodes/CMakeLists.txt
M       source/blender/nodes/NOD_shader.h
M       source/blender/nodes/NOD_static_types.h
A       source/blender/nodes/shader/nodes/node_shader_volume_principled.c
M       source/blender/nodes/shader/nodes/node_shader_volume_scatter.c

===================================================================

diff --git a/intern/cycles/blender/blender_shader.cpp 
b/intern/cycles/blender/blender_shader.cpp
index 33384709947..eb9968a85c2 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -566,6 +566,10 @@ static ShaderNode *add_node(Scene *scene,
        else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
                node = new AbsorptionVolumeNode();
        }
+       else if(b_node.is_a(&RNA_ShaderNodeVolumePrincipled)) {
+               PrincipledVolumeNode *principled = new PrincipledVolumeNode();
+               node = principled;
+       }
        else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
                node = new GeometryNode();
        }
@@ -1024,6 +1028,10 @@ static void add_nodes(Scene *scene,
                        for(b_node->internal_links.begin(b_link); b_link != 
b_node->internal_links.end(); ++b_link) {
                                BL::NodeSocket to_socket(b_link->to_socket());
                                SocketType::Type to_socket_type = 
convert_socket_type(to_socket);
+                               if (to_socket_type == SocketType::UNDEFINED) {
+                                       continue;
+                               }
+
                                ConvertNode *proxy = new 
ConvertNode(to_socket_type, to_socket_type, true);
 
                                input_map[b_link->from_socket().ptr.data] = 
proxy->inputs[0];
@@ -1047,6 +1055,10 @@ static void add_nodes(Scene *scene,
                         */
                        for(b_node->inputs.begin(b_input); b_input != 
b_node->inputs.end(); ++b_input) {
                                SocketType::Type input_type = 
convert_socket_type(*b_input);
+                               if (input_type == SocketType::UNDEFINED) {
+                                       continue;
+                               }
+
                                ConvertNode *proxy = new 
ConvertNode(input_type, input_type, true);
                                graph->add(proxy);
 
@@ -1059,6 +1071,10 @@ static void add_nodes(Scene *scene,
                        }
                        for(b_node->outputs.begin(b_output); b_output != 
b_node->outputs.end(); ++b_output) {
                                SocketType::Type output_type = 
convert_socket_type(*b_output);
+                               if (output_type == SocketType::UNDEFINED) {
+                                       continue;
+                               }
+
                                ConvertNode *proxy = new 
ConvertNode(output_type, output_type, true);
                                graph->add(proxy);
 
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt 
b/intern/cycles/kernel/shaders/CMakeLists.txt
index 19b7769200e..6ec651a96d8 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -36,6 +36,7 @@ set(SRC_OSL
        node_hair_info.osl
        node_scatter_volume.osl
        node_absorption_volume.osl
+       node_principled_volume.osl
        node_holdout.osl
        node_hsv.osl
        node_image_texture.osl
diff --git a/intern/cycles/kernel/shaders/node_principled_volume.osl 
b/intern/cycles/kernel/shaders/node_principled_volume.osl
new file mode 100644
index 00000000000..609fb95866d
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_principled_volume.osl
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdosl.h"
+
+shader node_principled_volume(
+       color Color = color(0.5, 0.5, 0.5),
+       float Density = 1.0,
+       float Anisotropy = 0.0,
+       color AbsorptionColor = color(0.0, 0.0, 0.0),
+       float EmissionStrength = 0.0,
+       color EmissionColor = color(1.0, 1.0, 1.0),
+       float BlackbodyIntensity = 0.0,
+       color BlackbodyTint = color(1.0, 1.0, 1.0),
+       float Temperature = 1500.0,
+       string DensityAttribute = "geom:density",
+       string ColorAttribute = "geom:color",
+       string TemperatureAttribute = "geom:temperature",
+       output closure color Volume = 0)
+{
+       /* Compute density. */
+       float primitive_density = 1.0;
+       float density = max(Density, 0.0);
+
+       if(density > 1e-5) {
+               if(getattribute(DensityAttribute, primitive_density)) {
+                       density = max(density * primitive_density, 0.0);
+               }
+       }
+
+       if(density > 1e-5) {
+               /* Compute scattering color. */
+               color scatter_color = Color;
+               color primitive_color;
+               if(getattribute(ColorAttribute, primitive_color)) {
+                       scatter_color *= primitive_color;
+               }
+
+               /* Add scattering and absorption closures. */
+               color scatter_coeff = scatter_color;
+               color absorption_coeff = max(1.0 - scatter_color, 0.0) * 
max(1.0 - AbsorptionColor, 0.0);
+               Volume = scatter_coeff * density * 
henyey_greenstein(Anisotropy) +
+                        absorption_coeff * density * absorption();
+       }
+
+       /* Compute emission. */
+       float emission_strength = max(EmissionStrength, 0.0);
+       float blackbody_intensity = BlackbodyIntensity;
+
+       if(emission_strength > 1e-5) {
+               Volume += emission_strength * EmissionColor * emission();
+       }
+
+       if(blackbody_intensity > 1e-3) {
+               float T = Temperature;
+
+               /* Add temperature from attribute if available. */
+               float temperature;
+               if(getattribute(TemperatureAttribute, temperature)) {
+                       T *= max(temperature, 0.0);
+               }
+
+               T = max(T, 0.0);
+
+               /* Stefan-Boltzman law. */
+               float T4 = (T * T) * (T * T);
+               float sigma = 5.670373e-8 * 1e-6 / M_PI;
+               float intensity = sigma * mix(1.0, T4, blackbody_intensity);
+
+               if(intensity > 1e-5) {
+                       color bb = blackbody(T);
+                       float l = luminance(bb);
+
+                       if(l != 0.0) {
+                               bb *= BlackbodyTint * intensity / l;
+                               Volume += bb * emission();
+                       }
+               }
+       }
+}
+
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index fae9f783483..39cd5da7b12 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -334,7 +334,10 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, 
ShaderData *sd, ccl_a
                                break;
 #  if NODES_FEATURE(NODE_FEATURE_VOLUME)
                        case NODE_CLOSURE_VOLUME:
-                               svm_node_closure_volume(kg, sd, stack, node, 
type, path_flag);
+                               svm_node_closure_volume(kg, sd, stack, node, 
type);
+                               break;
+                       case NODE_PRINCIPLED_VOLUME:
+                               svm_node_principled_volume(kg, sd, stack, node, 
type, path_flag, &offset);
                                break;
 #  endif  /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
 #  ifdef __EXTRA_NODES__
diff --git a/intern/cycles/kernel/svm/svm_closure.h 
b/intern/cycles/kernel/svm/svm_closure.h
index 24452c81fe0..819b256bde0 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -794,7 +794,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, 
ShaderData *sd, float *
        }
 }
 
-ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, 
float *stack, uint4 node, ShaderType shader_type, int path_flag)
+ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, 
float *stack, uint4 node, ShaderType shader_type)
 {
 #ifdef __VOLUME__
        /* Only sum extinction for volumes, variable is shared with surface 
transparency. */
@@ -802,19 +802,20 @@ ccl_device void svm_node_closure_volume(KernelGlobals 
*kg, ShaderData *sd, float
                return;
        }
 
-       uint type, param1_offset, param2_offset;
+       uint type, density_offset, anisotropy_offset;
 
        uint mix_weight_offset;
-       decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, 
&mix_weight_offset);
+       decode_node_uchar4(node.y, &type, &density_offset, &anisotropy_offset, 
&mix_weight_offset);
        float mix_weight = (stack_valid(mix_weight_offset)? 
stack_load_float(stack, mix_weight_offset): 1.0f);
 
-       if(mix_weight == 0.0f)
+       if(mix_weight == 0.0f) {
                return;
+       }
 
-       float param1 = (stack_valid(param1_offset))? stack_load_float(stack, 
param1_offset): __uint_as_float(node.z);
+       float density = (stack_valid(density_offset))? stack_load_float(stack, 
density_offset): __uint_as_float(node.z);
+       density = mix_weight * fmaxf(density, 0.0f);
 
        /* Compute scattering coefficient. */
-       float density = mix_weight * fmaxf(param1, 0.0f);
        float3 weight = sd->svm_closure_weight;
 
        if(type == CLOSURE_VOLUME_ABSORPTION_ID) {
@@ -825,11 +826,11 @@ ccl_device void svm_node_closure_volume(KernelGlobals 
*kg, ShaderData *sd, float
 
        /* Add closure for volume scattering. */
        if(type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
-               float param2 = (stack_valid(param2_offset))? 
stack_load_float(stack, param2_offset): __uint_as_float(node.w);
                HenyeyGreensteinVolume *volume = 
(HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
 
                if(volume) {
-                       volume->g = param2; /* g */
+                       float anisotropy = (stack_valid(anisotropy_offset))? 
stack_load_float(stack, anisotropy_offset): __uint_as_float(node.w);
+                       volume->g = anisotropy; /* g */
                        sd->flag |= volume_henyey_greenstein_setup(volume);
                }
        }
@@ -839,6 +840,106 @@ ccl_device void svm_node_closure_volume(KernelGlobals 
*kg, ShaderData *sd, float
 #endif
 }
 
+ccl_device void svm_node_principled_volume(KernelGlobals *kg, ShaderData *sd, 
float *stack, uint4 node, ShaderType shader_type, int path_flag, int *offset)
+{
+#ifdef __VOLUME__
+       uint4 value_node = read_node(kg, offset);
+       uint4 attr_node = read_node(kg, offset);
+
+       /* Only sum extinction for volumes, variable is shared with surface 
transparency. */
+       if(shader_type != SHADER_TYPE_VOLUME) {
+               return;
+       }
+
+       uint density_offset, anisotropy_offset, absorption_color_offset, 
mix_weight_offset;
+       decode_node_uchar4(node.y, &density_offset, &anisotropy_offset, 
&absorption_color_offset, &mix_weight_offset);
+       float mix_weight = (stack_valid(mix_weight_offset)? 
stack_load_float(stack, mix_weight_offset): 1.0f);
+
+       if(mix_weight == 0.0f) {
+               return;
+       }
+
+       /* Compute density. */
+       float primitive_density = 1.0f;
+       float density = (stack_valid(density_offset))? stack_load_float(stack, 
density_offset): __uint_as_float(value_node.x);
+       density = mix_weight * fmaxf(density, 0.0f);
+
+       if(density > CLOSURE_WEIGHT_CUTOFF) {
+               /* Density and color attribute lookup if available. */
+               const AttributeDescriptor attr_density = find_attribute(kg, sd, 
attr_node.x);
+               if(attr_density.offset != ATTR_STD_NOT_FOUND) {
+                       primitive_density = primitive_attribute_float(kg, sd, 
attr_density, NULL, NULL);
+                       density = fmaxf(density * primitive_density, 0.0f);
+               }
+       }
+
+       if(density > CLOSURE_WEIGHT_CUTOFF) {
+               /* Compute scattering color. */
+               float3 color = sd->svm_closure_weight;
+
+               const

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to