diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2013-12-28 04:54:44 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2013-12-28 19:57:02 +0400 |
commit | a35db17cee5a9b47dc9624f7dfcb41f5fc185b33 (patch) | |
tree | ef23032da73b9b202490307f865e2afd4e2e7e76 | |
parent | a06c9c277a8577f7ef473fffaf2258d2a3a6ab80 (diff) |
Cycles Volume Render: work on nodes and closures.
* 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, 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); } + |