Cycles Volume Render: work on nodes and closures.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 28 Dec 2013 00:54:44 +0000 (01:54 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 28 Dec 2013 15:57:02 +0000 (16:57 +0100)
* Henyey-Greenstein scattering closure implementation.
* Rename transparent to absorption node and isotropic to scatter node.
* Volume density is folded into the closure weights.
* OSL support for volume closures and nodes.
* This commit has no user visible changes, there is no volume render code yet.

This is work by "storm", Stuart Broadfoot, Thomas Dinges and myself.

28 files changed:
intern/cycles/app/cycles_xml.cpp
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/closure/volume.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/osl_closures.cpp
intern/cycles/kernel/osl/osl_closures.h
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/kernel/shaders/CMakeLists.txt
intern/cycles/kernel/shaders/node_absorption_volume.osl [new file with mode: 0644]
intern/cycles/kernel/shaders/node_light_path.osl
intern/cycles/kernel/shaders/node_scatter_volume.osl [new file with mode: 0644]
intern/cycles/kernel/shaders/stdosl.h
intern/cycles/kernel/svm/svm_closure.h
intern/cycles/kernel/svm/svm_light_path.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
intern/cycles/render/osl.cpp
release/scripts/addons
release/scripts/addons_contrib
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_shader.h
source/blender/nodes/NOD_static_types.h
source/blender/nodes/shader/nodes/node_shader_volume_absorption.c [moved from source/blender/nodes/shader/nodes/node_shader_volume_transparent.c with 70% similarity]
source/blender/nodes/shader/nodes/node_shader_volume_scatter.c [moved from source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c with 69% similarity]

index df187f046e5179941377caee32341295f1dafc6c..a483c766bed9933dca902a70fb48f902ae27ad74 100644 (file)
@@ -452,11 +452,11 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
                else if(string_iequals(node.name(), "background")) {
                        snode = new BackgroundNode();
                }
-               else if(string_iequals(node.name(), "transparent_volume")) {
-                       snode = new TransparentVolumeNode();
+               else if(string_iequals(node.name(), "absorption_volume")) {
+                       snode = new AbsorptionVolumeNode();
                }
-               else if(string_iequals(node.name(), "isotropic_volume")) {
-                       snode = new IsotropicVolumeNode();
+               else if(string_iequals(node.name(), "scatter_volume")) {
+                       snode = new ScatterVolumeNode();
                }
                else if(string_iequals(node.name(), "geometry")) {
                        snode = new GeometryNode();
index a6d2b537bc7b4b714fd94887ec9161f5786130eb..0c3a32af20db2305e2af08f2ed484d18da4ee745 100644 (file)
@@ -422,11 +422,11 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
        else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
                node = new AmbientOcclusionNode();
        }
-       else if (b_node.is_a(&RNA_ShaderNodeVolumeIsotropic)) {
-               node = new IsotropicVolumeNode();
+       else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
+               node = new ScatterVolumeNode();
        }
-       else if (b_node.is_a(&RNA_ShaderNodeVolumeTransparent)) {
-               node = new TransparentVolumeNode();
+       else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
+               node = new AbsorptionVolumeNode();
        }
        else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
                node = new GeometryNode();
index f4932568c1f9fb0a262d6f523a20512b2de66452..dae24fb03fd38a7f03153df63ce25a9a07330eac 100644 (file)
  * limitations under the License
  */
 
+#ifndef __VOLUME_H__
+#define __VOLUME_H__
+
 CCL_NAMESPACE_BEGIN
 
-/* note: the interfaces here are just as an example, need to figure
- * out the right functions and parameters to use */
+/* HENYEY-GREENSTEIN CLOSURE */
 
-/* ISOTROPIC VOLUME CLOSURE */
+/* Given cosine between rays, return probability density that a photon bounces
+ * to that direction. The g parameter controls how different it is from the
+ * uniform sphere. g=0 uniform diffuse-like, g=1 close to sharp single ray. */
+ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g)
+{
+       if(fabsf(g) < 1e-3f)
+               return M_1_PI_F * 0.25f;
+       
+       return ((1.0f - g * g) / safe_powf(1.0f + g * g - 2.0f * g * cos_theta, 1.5f)) * (M_1_PI_F * 0.25f);
+};
 
-ccl_device int volume_isotropic_setup(ShaderClosure *sc, float density)
+ccl_device int volume_henyey_greenstein_setup(ShaderClosure *sc)
 {
-       sc->type = CLOSURE_VOLUME_ISOTROPIC_ID;
-       sc->data0 = density;
+       sc->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+       
+       /* clamp anisotropy to avoid delta function */
+       sc->data0 = signf(sc->data0) * min(fabsf(sc->data0), 1.0f - 1e-3f);
 
-       return SD_VOLUME;
+       return SD_BSDF|SD_BSDF_HAS_EVAL;
 }
 
-ccl_device float3 volume_isotropic_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
+ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
 {
-       return make_float3(1.0f, 1.0f, 1.0f);
-}
+       float g = sc->data0;
 
-/* TRANSPARENT VOLUME CLOSURE */
+       /* note that I points towards the viewer */
+       float cos_theta = dot(-I, omega_in);
 
-ccl_device int volume_transparent_setup(ShaderClosure *sc, float density)
+       *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+
+       return make_float3(*pdf, *pdf, *pdf);
+}
+
+ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
+       float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
 {
-       sc->type = CLOSURE_VOLUME_TRANSPARENT_ID;
-       sc->data0 = density;
+       float g = sc->data0;
+       float cos_phi, sin_phi, cos_theta;
 
-       return SD_VOLUME;
+       /* match pdf for small g */
+       if(fabsf(g) < 1e-3f) {
+               cos_theta = (1.0f - 2.0f * randu);
+       }
+       else {
+               float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu);
+               cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
+       }
+
+       float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
+
+       float phi = M_2PI_F * randv;
+       cos_phi = cosf(phi);
+       sin_phi = sinf(phi);
+
+       /* note that I points towards the viewer and so is used negated */
+       float3 T, B;
+       make_orthonormals(-I, &T, &B);
+       *omega_in = sin_theta * cos_phi * T + sin_theta * sin_phi * B + cos_theta * (-I);
+
+       *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+       *eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */
+
+#ifdef __RAY_DIFFERENTIALS__
+       /* todo: implement ray differential estimation */
+       *domega_in_dx = make_float3(0.0f, 0.0f, 0.0f);
+       *domega_in_dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+       return LABEL_VOLUME_SCATTER;
 }
 
-ccl_device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
+/* ABSORPTION VOLUME CLOSURE */
+
+ccl_device int volume_absorption_setup(ShaderClosure *sc)
 {
-       return make_float3(1.0f, 1.0f, 1.0f);
+       sc->type = CLOSURE_VOLUME_ABSORPTION_ID;
+
+       return SD_VOLUME;
 }
 
 /* VOLUME CLOSURE */
 
-ccl_device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
+ccl_device float3 volume_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
 {
        float3 eval;
 
        switch(sc->type) {
-               case CLOSURE_VOLUME_ISOTROPIC_ID:
-                       eval = volume_isotropic_eval_phase(sc, omega_in, omega_out);
-                       break;
-               case CLOSURE_VOLUME_TRANSPARENT_ID:
-                       eval = volume_transparent_eval_phase(sc, omega_in, omega_out);
+               case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+                       eval = volume_henyey_greenstein_eval_phase(sc, I, omega_in, pdf);
                        break;
                default:
                        eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -70,5 +119,24 @@ ccl_device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc,
        return eval;
 }
 
+ccl_device int volume_sample(const ShaderData *sd, const ShaderClosure *sc, float randu,
+       float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
+{
+       int label;
+
+       switch(sc->type) {
+               case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+                       label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               default:
+                       *eval = make_float3(0.0f, 0.0f, 0.0f);
+                       label = LABEL_NONE;
+                       break;
+       }
+
+       return label;
+}
+
 CCL_NAMESPACE_END
 
+#endif
index 457a7f704c8479b0e4ada8094c981c3b0dfbbd1d..012aa4a7e19f00b6dc04a31e264a866c388b5853 100644 (file)
@@ -868,17 +868,19 @@ ccl_device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
 {
 #ifdef __MULTI_CLOSURE__
        float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+       float pdf;
 
        for(int i = 0; i< sd->num_closure; i++) {
                const ShaderClosure *sc = &sd->closure[i];
 
                if(CLOSURE_IS_VOLUME(sc->type))
-                       eval += volume_eval_phase(kg, sc, omega_in, omega_out);
+                       eval += volume_eval_phase(sc, omega_in, omega_out, &pdf);
        }
 
        return eval;
 #else
-       return volume_eval_phase(kg, &sd->closure, omega_in, omega_out);
+       float pdf;
+       return volume_eval_phase(&sd->closure, omega_in, omega_out, &pdf);
 #endif
 }
 
index 9b1893e8baa6877d80c6fd6bd3c52ddd5385aa6c..4821a1b482cf45b9c838d4707f0790d9ed4b49a6 100644 (file)
@@ -201,6 +201,7 @@ enum PathRayFlag {
        PATH_RAY_GLOSSY = 16,
        PATH_RAY_SINGULAR = 32,
        PATH_RAY_TRANSPARENT = 64,
+       PATH_RAY_VOLUME_SCATTER = 128,
 
        PATH_RAY_SHADOW_OPAQUE = 128,
        PATH_RAY_SHADOW_TRANSPARENT = 256,
@@ -224,18 +225,13 @@ enum PathRayFlag {
 
 typedef enum ClosureLabel {
        LABEL_NONE = 0,
-       LABEL_CAMERA = 1,
-       LABEL_LIGHT = 2,
-       LABEL_BACKGROUND = 4,
-       LABEL_TRANSMIT = 8,
-       LABEL_REFLECT = 16,
-       LABEL_VOLUME = 32,
-       LABEL_OBJECT = 64,
-       LABEL_DIFFUSE = 128,
-       LABEL_GLOSSY = 256,
-       LABEL_SINGULAR = 512,
-       LABEL_TRANSPARENT = 1024,
-       LABEL_STOP = 2048
+       LABEL_TRANSMIT = 1,
+       LABEL_REFLECT = 2,
+       LABEL_DIFFUSE = 4,
+       LABEL_GLOSSY = 8,
+       LABEL_SINGULAR = 16,
+       LABEL_TRANSPARENT = 32,
+       LABEL_VOLUME_SCATTER = 64,
 } ClosureLabel;
 
 /* Render Passes */
index 340e44925840baaedd1c755b8bd628c33c20fcc9..a96c0e2b1fb1cca9ac3860e86837fc18ccb32472 100644 (file)
@@ -55,6 +55,7 @@
 #include "closure/bsdf_westin.h"
 #include "closure/bsdf_toon.h"
 #include "closure/bsdf_hair.h"
+#include "closure/volume.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -169,6 +170,13 @@ BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, hair_transmission,
 #endif
 BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
 
+VOLUME_CLOSURE_CLASS_BEGIN(VolumeHenyeyGreenstein, henyey_greenstein, LABEL_VOLUME_SCATTER)
+       CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, sc.data0),
+VOLUME_CLOSURE_CLASS_END(VolumeHenyeyGreenstein, henyey_greenstein)
+
+VOLUME_CLOSURE_CLASS_BEGIN(VolumeAbsorption, absorption, LABEL_SINGULAR)
+VOLUME_CLOSURE_CLASS_END(VolumeAbsorption, absorption)
+
 /* Registration */
 
 static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
@@ -248,6 +256,11 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
                bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
        register_closure(ss, "hair_transmission", id++,
                bsdf_hair_transmission_params(), bsdf_hair_transmission_prepare);
+
+       register_closure(ss, "henyey_greenstein", id++,
+               volume_henyey_greenstein_params(), volume_henyey_greenstein_prepare);
+       register_closure(ss, "absorption", id++,
+               volume_absorption_params(), volume_absorption_prepare);
 }
 
 CCL_NAMESPACE_END
index b6c38e01b230ef48018862c92f6302bf337575a3..f2f79f80fdf9c78ea3b11bbc9d98e20fc9101eaf 100644 (file)
@@ -54,6 +54,7 @@ OSL::ClosureParam *closure_bssrdf_cubic_params();
 OSL::ClosureParam *closure_bssrdf_gaussian_params();
 OSL::ClosureParam *closure_bssrdf_cubic_extended_params();
 OSL::ClosureParam *closure_bssrdf_gaussian_extended_params();
+OSL::ClosureParam *closure_henyey_greenstein_volume_params();
 
 void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
 void closure_background_prepare(OSL::RendererServices *, int id, void *data);
@@ -65,6 +66,7 @@ void closure_westin_backscatter_prepare(OSL::RendererServices *, int id, void *d
 void closure_westin_sheen_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
+void closure_henyey_greenstein_volume_prepare(OSL::RendererServices *, int id, void *data);
 
 #define CCLOSURE_PREPARE(name, classname)          \
 void name(RendererServices *, int id, void *data) \
@@ -186,6 +188,54 @@ static ClosureParam *bsdf_##lower##_params() \
 \
 CCLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
 
+
+/* Volume */
+
+class CVolumeClosure : public CClosurePrimitive {
+public:
+       ShaderClosure sc;
+
+       CVolumeClosure(int scattering) : CClosurePrimitive(Volume),
+         m_scattering_label(scattering), m_shaderdata_flag(0)
+       { memset(&sc, 0, sizeof(sc)); }
+       ~CVolumeClosure() { }
+
+       int scattering() const { return m_scattering_label; }
+       int shaderdata_flag() const { return m_shaderdata_flag; }
+
+protected:
+       int m_scattering_label;
+       int m_shaderdata_flag;
+};
+
+#define VOLUME_CLOSURE_CLASS_BEGIN(Upper, lower, TYPE) \
+\
+class Upper##Closure : public CVolumeClosure { \
+public: \
+       Upper##Closure() : CVolumeClosure(TYPE) {} \
+\
+       void setup() \
+       { \
+               sc.prim = NULL; \
+               m_shaderdata_flag = volume_##lower##_setup(&sc); \
+       } \
+}; \
+\
+static ClosureParam *volume_##lower##_params() \
+{ \
+       static ClosureParam params[] = {
+
+/* parameters */
+
+#define VOLUME_CLOSURE_CLASS_END(Upper, lower) \
+               CLOSURE_STRING_KEYPARAM("label"), \
+           CLOSURE_FINISH_PARAM(Upper##Closure) \
+       }; \
+       return params; \
+} \
+\
+CCLOSURE_PREPARE_STATIC(volume_##lower##_prepare, Upper##Closure)
+
 CCL_NAMESPACE_END
 
 #endif /* __OSL_CLOSURES_H__ */
index b0461013239f4a8f3a38837c6c0ca815027d42a0..4358d3f2e76feb5ec992e961058e55ccc09067b1 100644 (file)
@@ -187,7 +187,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
 #endif
 
                                        /* add */
-                                       if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) {
+                                       if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
                                                sd->closure[sd->num_closure++] = sc;
                                                sd->flag |= bsdf->shaderdata_flag();
                                        }
@@ -243,7 +243,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
                                        CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
                                        float sample_weight = fabsf(average(weight));
 
-                                       if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
+                                       if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
                                                sc.sample_weight = sample_weight;
 
                                                sc.type = bssrdf->sc.type;
@@ -401,18 +401,21 @@ static void flatten_volume_closure_tree(ShaderData *sd,
 
                        switch (prim->category) {
                                case CClosurePrimitive::Volume: {
+                                       CVolumeClosure *volume = (CVolumeClosure *)prim;
                                        /* sample weight */
                                        float sample_weight = fabsf(average(weight));
 
                                        sc.sample_weight = sample_weight;
-                                       sc.type = CLOSURE_VOLUME_ID;
-                                       sc.data0 = 0.0f;
-                                       sc.data1 = 0.0f;
-                                       sc.prim = NULL;
+                                       sc.type = volume->sc.type;
+                                       sc.data0 = volume->sc.data0;
+                                       sc.data1 = volume->sc.data1;
 
                                        /* add */
-                                       if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE)
+                                       if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF &&
+                                          sd->num_closure < MAX_CLOSURE) {
                                                sd->closure[sd->num_closure++] = sc;
+                                               sd->flag |= volume->shaderdata_flag();
+                                       }
                                        break;
                                }
                                case CClosurePrimitive::Holdout:
@@ -451,6 +454,10 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
 
        if (kg->osl->volume_state[shader])
                ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals);
+       
+       /* flatten closure tree */
+       sd->num_closure = 0;
+       sd->randb_closure = randb;
 
        if (globals->Ci)
                flatten_volume_closure_tree(sd, globals->Ci);
index 0f8542b0546facf9fad421af868979895417213f..045abdb80af25941cfd43202c8a6f7cc3260e327 100644 (file)
@@ -29,6 +29,8 @@ set(SRC_OSL
        node_glossy_bsdf.osl
        node_gradient_texture.osl
        node_hair_info.osl
+       node_scatter_volume.osl
+       node_absorption_volume.osl
        node_holdout.osl
        node_hsv.osl
        node_image_texture.osl
diff --git a/intern/cycles/kernel/shaders/node_absorption_volume.osl b/intern/cycles/kernel/shaders/node_absorption_volume.osl
new file mode 100644 (file)
index 0000000..69c4c0e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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_absorption_volume(
+       color Color = color(0.8, 0.8, 0.8),
+       float Density = 1.0,
+       output closure color Volume = 0)
+{
+       Volume = ((color(1.0, 1.0, 1.0) - Color) * Density) * absorption();
+}
+
index db5c95be079559d98c98e603ca3548d203ef9645..599c7f5a2625b9f32c6cb85a6f959f65cf27839d 100644 (file)
@@ -24,6 +24,7 @@ shader node_light_path(
        output float IsSingularRay = 0.0,
        output float IsReflectionRay = 0.0,
        output float IsTransmissionRay = 0.0,
+       output float IsVolumeScatterRay = 0.0,
        output float RayLength = 0.0,
        output float RayDepth = 0.0)
 {
@@ -34,6 +35,7 @@ shader node_light_path(
        IsSingularRay = raytype("singular");
        IsReflectionRay = raytype("reflection");
        IsTransmissionRay = raytype("refraction");
+       IsVolumeScatterRay = raytype("volume_scatter");
 
        getattribute("path:ray_length", RayLength);
 
diff --git a/intern/cycles/kernel/shaders/node_scatter_volume.osl b/intern/cycles/kernel/shaders/node_scatter_volume.osl
new file mode 100644 (file)
index 0000000..bf23abb
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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_scatter_volume(
+       color Color = color(0.8, 0.8, 0.8),
+       float Density = 1.0,
+       float Anisotropy = 0.0,
+       output closure color Volume = 0)
+{
+       Volume = (Color * Density) * henyey_greenstein(Anisotropy);
+}
+
index d1d1222af4444f57ba3fff9d26975220af68aa50..6f824ea8ebd5d7a977e4ac519e961a4f78ee6fa1 100644 (file)
@@ -497,9 +497,14 @@ closure color ambient_occlusion() BUILTIN;
 closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN;
 closure color bssrdf_gaussian(normal N, vector radius, float texture_blur) BUILTIN;
 
+// Hair
 closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
 closure color hair_transmission(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
 
+// Volume
+closure color henyey_greenstein(float g) BUILTIN;
+closure color absorption() BUILTIN;
+
 // Backwards compatibility
 closure color bssrdf_cubic(normal N, vector radius) BUILTIN;
 closure color bssrdf_gaussian(normal N, vector radius) BUILTIN;
index 2c6fb5deca4349516f3e0ec3cc5735c05feb9c14..dca9c3a91e5d2fc01ba0c0f4308f85722755a0e6 100644 (file)
@@ -77,7 +77,7 @@ ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float
        float3 weight = sc->weight * mix_weight;
        float sample_weight = fabsf(average(weight));
 
-       if(sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) {
+       if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
                sc->weight = weight;
                sc->sample_weight = sample_weight;
                sd->num_closure++;
@@ -390,7 +390,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
                        if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
                                param1 = 0.0f;
 
-                       if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
+                       if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
                                /* radius * scale */
                                float3 radius = stack_load_float3(stack, data_node.z)*param1;
                                /* sharpness */
@@ -473,24 +473,25 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
 #endif
 
        float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
-       //float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
+       float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
+       float density = param1;
 
        switch(type) {
-               case CLOSURE_VOLUME_TRANSPARENT_ID: {
-                       ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+               case CLOSURE_VOLUME_ABSORPTION_ID: {
+                       ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight * density);
 
                        if(sc) {
-                               float density = param1;
-                               sd->flag |= volume_transparent_setup(sc, density);
+                               sd->flag |= volume_absorption_setup(sc);
                        }
                        break;
                }
-               case CLOSURE_VOLUME_ISOTROPIC_ID: {
-                       ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+               case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: {
+                       ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight * density);
 
                        if(sc) {
-                               float density = param1;
-                               sd->flag |= volume_isotropic_setup(sc, density);
+                               float g = param2;
+                               sc->data0 = g;
+                               sd->flag |= volume_henyey_greenstein_setup(sc);
                        }
                        break;
                }
index e7afa2d22000d8c11c62980848dc8a22079b1877..8968146c5e29ab8fa1ae3e60315229b89e657a80 100644 (file)
@@ -30,6 +30,7 @@ ccl_device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uin
                case NODE_LP_singular: info = (path_flag & PATH_RAY_SINGULAR)? 1.0f: 0.0f; break;
                case NODE_LP_reflection: info = (path_flag & PATH_RAY_REFLECT)? 1.0f: 0.0f; break;
                case NODE_LP_transmission: info = (path_flag & PATH_RAY_TRANSMIT)? 1.0f: 0.0f; break;
+               case NODE_LP_volume_scatter: info = (path_flag & PATH_RAY_VOLUME_SCATTER)? 1.0f: 0.0f; break;
                case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break;
                case NODE_LP_ray_length: info = sd->ray_length; break;
                case NODE_LP_ray_depth: info = (float)sd->ray_depth; break;
index abd63530d631eb167a565e2b7077aa6bf4009c65..e6df5fe17b727264baab2213c1436dd0f1cc580b 100644 (file)
@@ -154,6 +154,7 @@ typedef enum NodeLightPath {
        NODE_LP_singular,
        NODE_LP_reflection,
        NODE_LP_transmission,
+       NODE_LP_volume_scatter,
        NODE_LP_backfacing,
        NODE_LP_ray_length,
        NODE_LP_ray_depth
@@ -389,8 +390,8 @@ typedef enum ClosureType {
 
        /* Volume */
        CLOSURE_VOLUME_ID,
-       CLOSURE_VOLUME_TRANSPARENT_ID,
-       CLOSURE_VOLUME_ISOTROPIC_ID,
+       CLOSURE_VOLUME_ABSORPTION_ID,
+       CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID,
 
        NBUILTIN_CLOSURES
 } ClosureType;
@@ -402,12 +403,14 @@ typedef enum ClosureType {
 #define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
 #define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID)
 #define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_GAUSSIAN_ID)
-#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID)
+#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
 #define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
 #define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
 #define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID)
 #define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
 
+#define CLOSURE_WEIGHT_CUTOFF 1e-5f
+
 CCL_NAMESPACE_END
 
 #endif /*  __SVM_TYPES_H__ */
index c26ff7e7306ae5900a10667d4a449c795a74898f..d79886569523662b26b608058787e13ecc72878b 100644 (file)
@@ -1951,7 +1951,7 @@ void AmbientOcclusionNode::compile(OSLCompiler& compiler)
 VolumeNode::VolumeNode()
 : ShaderNode("volume")
 {
-       closure = CLOSURE_VOLUME_ISOTROPIC_ID;
+       closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
 
        add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
        add_input("Density", SHADER_SOCKET_FLOAT, 1.0f);
@@ -1995,38 +1995,40 @@ void VolumeNode::compile(OSLCompiler& compiler)
        assert(0);
 }
 
-/* Transparent Volume Closure */
+/* Absorption Volume Closure */
 
-TransparentVolumeNode::TransparentVolumeNode()
+AbsorptionVolumeNode::AbsorptionVolumeNode()
 {
-       closure = CLOSURE_VOLUME_TRANSPARENT_ID;
+       closure = CLOSURE_VOLUME_ABSORPTION_ID;
 }
 
-void TransparentVolumeNode::compile(SVMCompiler& compiler)
+void AbsorptionVolumeNode::compile(SVMCompiler& compiler)
 {
        VolumeNode::compile(compiler, input("Density"), NULL);
 }
 
-void TransparentVolumeNode::compile(OSLCompiler& compiler)
+void AbsorptionVolumeNode::compile(OSLCompiler& compiler)
 {
-       compiler.add(this, "node_transparent_volume");
+       compiler.add(this, "node_absorption_volume");
 }
 
-/* Isotropic Volume Closure */
+/* Scatter Volume Closure */
 
-IsotropicVolumeNode::IsotropicVolumeNode()
+ScatterVolumeNode::ScatterVolumeNode()
 {
-       closure = CLOSURE_VOLUME_ISOTROPIC_ID;
+       closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+       
+       add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.0f);
 }
 
-void IsotropicVolumeNode::compile(SVMCompiler& compiler)
+void ScatterVolumeNode::compile(SVMCompiler& compiler)
 {
-       VolumeNode::compile(compiler, input("Density"), NULL);
+       VolumeNode::compile(compiler, input("Density"), input("Anisotropy"));
 }
 
-void IsotropicVolumeNode::compile(OSLCompiler& compiler)
+void ScatterVolumeNode::compile(OSLCompiler& compiler)
 {
-       compiler.add(this, "node_isotropic_volume");
+       compiler.add(this, "node_scatter_volume");
 }
 
 /* Hair BSDF Closure */
@@ -2304,6 +2306,7 @@ LightPathNode::LightPathNode()
        add_output("Is Singular Ray", SHADER_SOCKET_FLOAT);
        add_output("Is Reflection Ray", SHADER_SOCKET_FLOAT);
        add_output("Is Transmission Ray", SHADER_SOCKET_FLOAT);
+       add_output("Is Volume Scatter Ray", SHADER_SOCKET_FLOAT);
        add_output("Ray Length", SHADER_SOCKET_FLOAT);
        add_output("Ray Depth", SHADER_SOCKET_FLOAT);
 }
@@ -2355,6 +2358,12 @@ void LightPathNode::compile(SVMCompiler& compiler)
                compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, out->stack_offset);
        }
        
+       out = output("Is Volume Scatter Ray");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(NODE_LIGHT_PATH, NODE_LP_volume_scatter, out->stack_offset);
+       }
+
        out = output("Ray Length");
        if(!out->links.empty()) {
                compiler.stack_assign(out);
index d7a110af83b75beb7832e9fda77c9c8df875d0e4..36348044bbcc9f96ebbbd3a2576ffb09fc1f6979 100644 (file)
@@ -316,14 +316,14 @@ public:
        ClosureType closure;
 };
 
-class TransparentVolumeNode : public VolumeNode {
+class AbsorptionVolumeNode : public VolumeNode {
 public:
-       SHADER_NODE_CLASS(TransparentVolumeNode)
+       SHADER_NODE_CLASS(AbsorptionVolumeNode)
 };
 
-class IsotropicVolumeNode : public VolumeNode {
+class ScatterVolumeNode : public VolumeNode {
 public:
-       SHADER_NODE_CLASS(IsotropicVolumeNode)
+       SHADER_NODE_CLASS(ScatterVolumeNode)
 };
 
 class HairBsdfNode : public BsdfNode {
index 4ed8ece0556fa1a325d1e73d142bf3b8e9f525db..043d8d138f6e8572d537905a472867088c6edb83 100644 (file)
@@ -195,15 +195,16 @@ void OSLShaderManager::shading_system_init()
 
                /* our own ray types */
                static const char *raytypes[] = {
-                       "camera",               /* PATH_RAY_CAMERA */
-                       "reflection",   /* PATH_RAY_REFLECT */
-                       "refraction",   /* PATH_RAY_TRANSMIT */
-                       "diffuse",              /* PATH_RAY_DIFFUSE */
-                       "glossy",               /* PATH_RAY_GLOSSY */
-                       "singular",             /* PATH_RAY_SINGULAR */
-                       "transparent",  /* PATH_RAY_TRANSPARENT */
-                       "shadow",               /* PATH_RAY_SHADOW_OPAQUE */
-                       "shadow",               /* PATH_RAY_SHADOW_TRANSPARENT */
+                       "camera",                       /* PATH_RAY_CAMERA */
+                       "reflection",           /* PATH_RAY_REFLECT */
+                       "refraction",           /* PATH_RAY_TRANSMIT */
+                       "diffuse",                      /* PATH_RAY_DIFFUSE */
+                       "glossy",                       /* PATH_RAY_GLOSSY */
+                       "singular",                     /* PATH_RAY_SINGULAR */
+                       "transparent",          /* PATH_RAY_TRANSPARENT */
+                       "volume_scatter",       /* PATH_RAY_VOLUME_SCATTER */
+                       "shadow",                       /* PATH_RAY_SHADOW_OPAQUE */
+                       "shadow",                       /* PATH_RAY_SHADOW_TRANSPARENT */
 
                        "__unused__",
                        "__unused__",
index 92a03a1b94b4fae0b6c04d3c4fa2bdcd4df8a085..c50944e808d6c74148237e85866e893628f0fee6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 92a03a1b94b4fae0b6c04d3c4fa2bdcd4df8a085
+Subproject commit c50944e808d6c74148237e85866e893628f0fee6
index 941d5d1857a13766fb39db1757659dc7a9e61275..31545d25c9cb41d271a3f3ef84d327708572290e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 941d5d1857a13766fb39db1757659dc7a9e61275
+Subproject commit 31545d25c9cb41d271a3f3ef84d327708572290e
index 28a4a30fa91f1481e63ce967a407ef2fa9e0a7c8..e3af696c8a9dccf5a7670635793b4f83b38a0625 100644 (file)
@@ -717,8 +717,8 @@ struct ShadeResult;
 #define SH_NODE_OUTPUT_TEXTURE                 158
 #define SH_NODE_HOLDOUT                                        159
 #define SH_NODE_LAYER_WEIGHT                   160
-#define SH_NODE_VOLUME_TRANSPARENT             161
-#define SH_NODE_VOLUME_ISOTROPIC               162
+#define SH_NODE_VOLUME_ABSORPTION              161
+#define SH_NODE_VOLUME_SCATTER                 162
 #define SH_NODE_GAMMA                                  163
 #define SH_NODE_TEX_CHECKER                            164
 #define SH_NODE_BRIGHTCONTRAST                 165
index 583739c00ecfbe0f0a224ee43c4da8fd0aea809c..e2c20699faba3aa12b72cad2d6b0a8a514d34860 100644 (file)
@@ -3499,8 +3499,8 @@ static void registerShaderNodes(void)
        register_node_type_sh_bsdf_hair();
        register_node_type_sh_emission();
        register_node_type_sh_holdout();
-       //register_node_type_sh_volume_transparent();
-       //register_node_type_sh_volume_isotropic();
+       //register_node_type_sh_volume_absorption();
+       //register_node_type_sh_volume_scatter();
        register_node_type_sh_subsurface_scattering();
        register_node_type_sh_mix_shader();
        register_node_type_sh_add_shader();
index 64feb0068cb7663987e9e3de87cd8286c04f67b6..16671e84da0d3ad09bf8839113da9adfe53d64d8 100644 (file)
@@ -197,8 +197,8 @@ set(SRC
        shader/nodes/node_shader_tex_sky.c
        shader/nodes/node_shader_tex_voronoi.c
        shader/nodes/node_shader_tex_wave.c
-       shader/nodes/node_shader_volume_isotropic.c
-       shader/nodes/node_shader_volume_transparent.c
+       shader/nodes/node_shader_volume_scatter.c
+       shader/nodes/node_shader_volume_absorption.c
        shader/node_shader_tree.c
        shader/node_shader_util.c
 
index 71c0638829f8a28f9c8cdde0bb3b0d0a79b0a116..0f388a890a41704ebd4c4ff3b57fca0a866ff31e 100644 (file)
@@ -105,8 +105,8 @@ void register_node_type_sh_bsdf_toon(void);
 void register_node_type_sh_bsdf_anisotropic(void);
 void register_node_type_sh_emission(void);
 void register_node_type_sh_holdout(void);
-void register_node_type_sh_volume_transparent(void);
-void register_node_type_sh_volume_isotropic(void);
+void register_node_type_sh_volume_absorption(void);
+void register_node_type_sh_volume_scatter(void);
 void register_node_type_sh_bsdf_hair(void);
 void register_node_type_sh_subsurface_scattering(void);
 void register_node_type_sh_mix_shader(void);
index beeaa7787fb848fec67f18d2c46ee89d0c28ecf8..260323d368cc54402be2345435785e7eec9ec125 100644 (file)
@@ -88,8 +88,8 @@ DefNode( ShaderNode,     SH_NODE_BSDF_VELVET,        0,                      "BS
 DefNode( ShaderNode,     SH_NODE_BSDF_TOON,          def_toon,               "BSDF_TOON",          BsdfToon,         "Toon BSDF",         ""       )
 DefNode( ShaderNode,     SH_NODE_BSDF_HAIR,          def_hair,               "BSDF_HAIR",          BsdfHair,         "Hair BSDF",         ""       )
 DefNode( ShaderNode,     SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface,   "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
-DefNode( ShaderNode,     SH_NODE_VOLUME_TRANSPARENT, 0,                      "VOLUME_TRANSPARENT", VolumeTransparent,"Transparent Volume",""       )
-DefNode( ShaderNode,     SH_NODE_VOLUME_ISOTROPIC,   0,                      "VOLUME_ISOTROPIC",   VolumeIsotropic,  "Isotropic Volume",  ""       )
+DefNode( ShaderNode,     SH_NODE_VOLUME_ABSORPTION,  0,                      "VOLUME_ABSORPTION",  VolumeAbsorption, "Volume Absorption", ""       )
+DefNode( ShaderNode,     SH_NODE_VOLUME_SCATTER,     0,                      "VOLUME_SCATTER",     VolumeScatter,    "Volume Scatter",    ""       )
 DefNode( ShaderNode,     SH_NODE_EMISSION,           0,                      "EMISSION",           Emission,         "Emission",          ""       )
 DefNode( ShaderNode,     SH_NODE_NEW_GEOMETRY,       0,                      "NEW_GEOMETRY",       NewGeometry,      "Geometry",          ""       )
 DefNode( ShaderNode,     SH_NODE_LIGHT_PATH,         0,                      "LIGHT_PATH",         LightPath,        "Light Path",        ""       )
similarity index 70%
rename from source/blender/nodes/shader/nodes/node_shader_volume_transparent.c
rename to source/blender/nodes/shader/nodes/node_shader_volume_absorption.c
index 31009a3585a7f9a57a512e85523b34e4333013d3..a271162bd19d6126043241e15bec72966a3484fa 100644 (file)
 
 /* **************** OUTPUT ******************** */
 
-static bNodeSocketTemplate sh_node_volume_transparent_in[] = {
+static bNodeSocketTemplate sh_node_volume_absorption_in[] = {
        {       SOCK_RGBA, 1, N_("Color"),              0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
        {       SOCK_FLOAT, 1, N_("Density"),   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
        {       -1, 0, ""       }
 };
 
-static bNodeSocketTemplate sh_node_volume_transparent_out[] = {
+static bNodeSocketTemplate sh_node_volume_absorption_out[] = {
        {       SOCK_SHADER, 0, N_("Volume")},
        {       -1, 0, ""       }
 };
 
-static int node_shader_gpu_volume_transparent(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_absorption(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
 {
        return 0;
 }
 
 /* node type definition */
-void register_node_type_sh_volume_transparent(void)
+void register_node_type_sh_volume_absorption(void)
 {
        static bNodeType ntype;
 
-       sh_node_type_base(&ntype, SH_NODE_VOLUME_TRANSPARENT, "Transparent Volume", NODE_CLASS_SHADER, 0);
+       sh_node_type_base(&ntype, SH_NODE_VOLUME_ABSORPTION, "Volume Absorption", NODE_CLASS_SHADER, 0);
        node_type_compatibility(&ntype, NODE_NEW_SHADING);
-       node_type_socket_templates(&ntype, sh_node_volume_transparent_in, sh_node_volume_transparent_out);
+       node_type_socket_templates(&ntype, sh_node_volume_absorption_in, sh_node_volume_absorption_out);
        node_type_init(&ntype, NULL);
        node_type_storage(&ntype, "", NULL, NULL);
-       node_type_gpu(&ntype, node_shader_gpu_volume_transparent);
+       node_type_gpu(&ntype, node_shader_gpu_volume_absorption);
 
        nodeRegisterType(&ntype);
 }
similarity index 69%
rename from source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c
rename to source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
index ef9fe014aa34f8e6afaf7f04e6bacf1905743d53..cb1377348e5541db84f0368925835c0c67f22179 100644 (file)
 
 /* **************** OUTPUT ******************** */
 
-static bNodeSocketTemplate sh_node_volume_isotropic_in[] = {
+static bNodeSocketTemplate sh_node_volume_scatter_in[] = {
        {       SOCK_RGBA, 1, N_("Color"),              0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
        {       SOCK_FLOAT, 1, N_("Density"),   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+       {       SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
        {       -1, 0, ""       }
 };
 
-static bNodeSocketTemplate sh_node_volume_isotropic_out[] = {
+static bNodeSocketTemplate sh_node_volume_scatter_out[] = {
        {       SOCK_SHADER, 0, N_("Volume")},
        {       -1, 0, ""       }
 };
 
-static int node_shader_gpu_volume_isotropic(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_scatter(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
 {
        return 0;
 }
 
 /* node type definition */
-void register_node_type_sh_volume_isotropic(void)
+void register_node_type_sh_volume_scatter(void)
 {
        static bNodeType ntype;
 
-       sh_node_type_base(&ntype, SH_NODE_VOLUME_ISOTROPIC, "Isotropic Volume", NODE_CLASS_SHADER, 0);
+       sh_node_type_base(&ntype, SH_NODE_VOLUME_SCATTER, "Volume Scatter", NODE_CLASS_SHADER, 0);
        node_type_compatibility(&ntype, NODE_NEW_SHADING);
-       node_type_socket_templates(&ntype, sh_node_volume_isotropic_in, sh_node_volume_isotropic_out);
+       node_type_socket_templates(&ntype, sh_node_volume_scatter_in, sh_node_volume_scatter_out);
        node_type_init(&ntype, NULL);
        node_type_storage(&ntype, "", NULL, NULL);
-       node_type_gpu(&ntype, node_shader_gpu_volume_isotropic);
+       node_type_gpu(&ntype, node_shader_gpu_volume_scatter);
 
        nodeRegisterType(&ntype);
 }
+