diff options
28 files changed, 332 insertions, 117 deletions
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index df187f046e5..a483c766bed 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -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(); diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index a6d2b537bc7..0c3a32af20d 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -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(); diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h index f4932568c1f..dae24fb03fd 100644 --- a/intern/cycles/kernel/closure/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -14,53 +14,102 @@ * 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 diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 457a7f704c8..012aa4a7e19 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -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 } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 9b1893e8baa..4821a1b482c 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -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 */ diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 340e4492584..a96c0e2b1fb 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -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 diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index b6c38e01b23..f2f79f80fdf 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -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__ */ diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index b0461013239..4358d3f2e76 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -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); diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 0f8542b0546..045abdb80af 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -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 index 00000000000..69c4c0ef7af --- /dev/null +++ b/intern/cycles/kernel/shaders/node_absorption_volume.osl @@ -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(); +} + diff --git a/intern/cycles/kernel/shaders/node_light_path.osl b/intern/cycles/kernel/shaders/node_light_path.osl index db5c95be079..599c7f5a262 100644 --- a/intern/cycles/kernel/shaders/node_light_path.osl +++ b/intern/cycles/kernel/shaders/node_light_path.osl @@ -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 index 00000000000..bf23abbf933 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_scatter_volume.osl @@ -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); +} + diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index d1d1222af44..6f824ea8ebd 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -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; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 2c6fb5deca4..dca9c3a91e5 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -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; } diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h index e7afa2d2200..8968146c5e2 100644 --- a/intern/cycles/kernel/svm/svm_light_path.h +++ b/intern/cycles/kernel/svm/svm_light_path.h @@ -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; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index abd63530d63..e6df5fe17b7 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -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__ */ diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index c26ff7e7306..d7988656952 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -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); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index d7a110af83b..36348044bbc 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -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 { diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 4ed8ece0556..043d8d138f6 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -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__", diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 92a03a1b94b4fae0b6c04d3c4fa2bdcd4df8a08 +Subproject c50944e808d6c74148237e85866e893628f0fee diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject 941d5d1857a13766fb39db1757659dc7a9e6127 +Subproject 31545d25c9cb41d271a3f3ef84d327708572290 diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 28a4a30fa91..e3af696c8a9 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -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 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 583739c00ec..e2c20699fab 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -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(); diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 64feb0068cb..16671e84da0 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -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 diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 71c0638829f..0f388a890a4 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -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); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index beeaa7787fb..260323d368c 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -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", "" ) diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c index 31009a3585a..a271162bd19 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c @@ -29,33 +29,33 @@ /* **************** 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); } diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c index ef9fe014aa3..cb1377348e5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c @@ -29,33 +29,35 @@ /* **************** 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); } + |