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.
This commit is contained in:
Brecht Van Lommel 2013-12-28 01:54:44 +01:00
parent a06c9c277a
commit a35db17cee
28 changed files with 344 additions and 129 deletions

View 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();

View 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();

View File

@ -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 */
ccl_device int volume_isotropic_setup(ShaderClosure *sc, float density)
/* 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)
{
sc->type = CLOSURE_VOLUME_ISOTROPIC_ID;
sc->data0 = density;
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_henyey_greenstein_setup(ShaderClosure *sc)
{
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_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
{
float g = sc->data0;
/* note that I points towards the viewer */
float cos_theta = dot(-I, omega_in);
*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)
{
float g = sc->data0;
float cos_phi, sin_phi, cos_theta;
/* 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;
}
/* ABSORPTION VOLUME CLOSURE */
ccl_device int volume_absorption_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_VOLUME_ABSORPTION_ID;
return SD_VOLUME;
}
ccl_device float3 volume_isotropic_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
return make_float3(1.0f, 1.0f, 1.0f);
}
/* TRANSPARENT VOLUME CLOSURE */
ccl_device int volume_transparent_setup(ShaderClosure *sc, float density)
{
sc->type = CLOSURE_VOLUME_TRANSPARENT_ID;
sc->data0 = density;
return SD_VOLUME;
}
ccl_device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
return make_float3(1.0f, 1.0f, 1.0f);
}
/* 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

View 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
}

View 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 */

View 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

View 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__ */

View 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);

View 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

View File

@ -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();
}

View 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);

View File

@ -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);
}

View 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;

View 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;
}

View 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;

View 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__ */

View 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);

View 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 {

View 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__",

@ -1 +1 @@
Subproject commit 92a03a1b94b4fae0b6c04d3c4fa2bdcd4df8a085
Subproject commit c50944e808d6c74148237e85866e893628f0fee6

@ -1 +1 @@
Subproject commit 941d5d1857a13766fb39db1757659dc7a9e61275
Subproject commit 31545d25c9cb41d271a3f3ef84d327708572290e

View 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

View 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();

View 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

View 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);

View 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", "" )

View File

@ -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);
}

View File

@ -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);
}