Cycles: refactor kernel closure storage to use structs per closure type.

Reviewed By: dingto, sergey

Differential Revision: https://developer.blender.org/D2127
This commit is contained in:
Brecht Van Lommel
2016-07-25 03:03:23 +02:00
parent 1776f75c3b
commit 9b6ed3a42b
36 changed files with 1219 additions and 1364 deletions

View File

@@ -87,6 +87,7 @@ set(SRC_KERNELS_CPU_HEADERS
)
set(SRC_CLOSURE_HEADERS
closure/alloc.h
closure/bsdf.h
closure/bsdf_ashikhmin_velvet.h
closure/bsdf_diffuse.h

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2011-2016 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.
*/
CCL_NAMESPACE_BEGIN
ccl_device ShaderClosure *closure_alloc(ShaderData *sd, int size, ClosureType type, float3 weight)
{
kernel_assert(size <= sizeof(ShaderClosure));
int num_closure = ccl_fetch(sd, num_closure);
int num_closure_extra = ccl_fetch(sd, num_closure_extra);
if(num_closure + num_closure_extra >= MAX_CLOSURE)
return NULL;
ShaderClosure *sc = &ccl_fetch(sd, closure)[num_closure];
sc->type = type;
sc->weight = weight;
ccl_fetch(sd, num_closure)++;
return sc;
}
ccl_device ccl_addr_space void *closure_alloc_extra(ShaderData *sd, int size)
{
/* Allocate extra space for closure that need more parameters. We allocate
* in chunks of sizeof(ShaderClosure) starting from the end of the closure
* array.
*
* This lets us keep the same fast array iteration over closures, as we
* found linked list iteration and iteration with skipping to be slower. */
int num_extra = ((size + sizeof(ShaderClosure) - 1) / sizeof(ShaderClosure));
int num_closure = ccl_fetch(sd, num_closure);
int num_closure_extra = ccl_fetch(sd, num_closure_extra) + num_extra;
if(num_closure + num_closure_extra > MAX_CLOSURE) {
/* Remove previous closure. */
ccl_fetch(sd, num_closure)--;
ccl_fetch(sd, num_closure_extra)++;
return NULL;
}
ccl_fetch(sd, num_closure_extra) = num_closure_extra;
return (ccl_addr_space void*)(ccl_fetch(sd, closure) + MAX_CLOSURE - num_closure_extra);
}
ccl_device_inline ShaderClosure *bsdf_alloc(ShaderData *sd, int size, float3 weight)
{
ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
if(!sc)
return NULL;
float sample_weight = fabsf(average(weight));
sc->sample_weight = sample_weight;
return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
}
#ifdef __OSL__
ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, int size, float3 weight, void *data)
{
ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
if(!sc)
return NULL;
memcpy(sc, data, size);
float sample_weight = fabsf(average(weight));
sc->weight = weight;
sc->sample_weight = sample_weight;
return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
}
#endif
CCL_NAMESPACE_END

View File

@@ -40,11 +40,6 @@ ccl_device int bsdf_sample(KernelGlobals *kg, ShaderData *sd, const ShaderClosur
{
int label;
#ifdef __OSL__
if(kg->osl && sc->prim)
return OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
#endif
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
@@ -56,14 +51,16 @@ ccl_device int bsdf_sample(KernelGlobals *kg, ShaderData *sd, const ShaderClosur
label = bsdf_oren_nayar_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
/*case CLOSURE_BSDF_PHONG_RAMP_ID:
#ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID:
label = bsdf_phong_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
label = bsdf_diffuse_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;*/
break;
#endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
label = bsdf_translucent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
@@ -143,11 +140,6 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, ShaderData *sd, const ShaderClosu
{
float3 eval;
#ifdef __OSL__
if(kg->osl && sc->prim)
return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf);
#endif
if(dot(ccl_fetch(sd, Ng), omega_in) >= 0.0f) {
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
@@ -158,12 +150,14 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, ShaderData *sd, const ShaderClosu
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
/*case CLOSURE_BSDF_PHONG_RAMP_ID:
#ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID:
eval = bsdf_phong_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
eval = bsdf_diffuse_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;*/
break;
#endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
@@ -296,15 +290,7 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, ShaderData *sd, const ShaderClosu
ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
{
/* ToDo: do we want to blur volume closures? */
#ifdef __OSL__
if(kg->osl && sc->prim) {
OSLShader::bsdf_blur(sc, roughness);
return;
}
#endif
/* ToDo: do we want to blur volume closures? */
#ifdef __SVM__
switch(sc->type) {
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
@@ -331,5 +317,48 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
#endif
}
ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
{
#ifdef __SVM__
switch(a->type) {
case CLOSURE_BSDF_TRANSPARENT_ID:
return true;
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
case CLOSURE_BSDF_TRANSLUCENT_ID:
return bsdf_diffuse_merge(a, b);
case CLOSURE_BSDF_OREN_NAYAR_ID:
return bsdf_oren_nayar_merge(a, b);
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
return bsdf_microfacet_merge(a, b);
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
return bsdf_ashikhmin_velvet_merge(a, b);
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
case CLOSURE_BSDF_GLOSSY_TOON_ID:
return bsdf_toon_merge(a, b);
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
return bsdf_hair_merge(a, b);
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
return volume_henyey_greenstein_merge(a, b);
#endif
default:
return false;
}
#endif
}
CCL_NAMESPACE_END

View File

@@ -31,28 +31,30 @@ Other than that, the implementation directly follows the paper.
CCL_NAMESPACE_BEGIN
ccl_device int bsdf_ashikhmin_shirley_setup(ShaderClosure *sc)
ccl_device int bsdf_ashikhmin_shirley_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
sc->data1 = sc->data0;
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
bsdf->alpha_y = bsdf->alpha_x;
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(ShaderClosure *sc)
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
sc->data1 = clamp(sc->data1, 1e-4f, 1.0f);
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_ashikhmin_shirley_blur(ShaderClosure *sc, float roughness)
{
sc->data0 = fmaxf(roughness, sc->data0); /* clamp roughness */
sc->data1 = fmaxf(roughness, sc->data1);
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float roughness)
@@ -62,14 +64,15 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float3 N = bsdf->N;
float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */
float out = 0.0f;
if(fmaxf(sc->data0, sc->data1) <= 1e-4f)
if(fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f)
return make_float3(0.0f, 0.0f, 0.0f);
if(NdotI > 0.0f && NdotO > 0.0f) {
@@ -82,8 +85,8 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
float pump = 1.0f / fmaxf(1e-6f, (HdotI*fmaxf(NdotO, NdotI))); /* pump from original paper (first derivative disc., but cancels the HdotI in the pdf nicely) */
/*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ /* pump from d-brdf paper */
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1);
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
if(n_x == n_y) {
/* isotropic */
@@ -97,7 +100,7 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
else {
/* anisotropic */
float3 X, Y;
make_orthonormals_tangent(N, sc->T, &X, &Y);
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
float HdotX = dot(H, X);
float HdotY = dot(H, Y);
@@ -134,13 +137,14 @@ ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, f
ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, 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)
{
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float3 N = bsdf->N;
float NdotI = dot(N, I);
if(NdotI > 0.0f) {
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1);
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
/* get x,y basis on the surface for anisotropy */
float3 X, Y;
@@ -148,7 +152,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
if(n_x == n_y)
make_orthonormals(N, &X, &Y);
else
make_orthonormals_tangent(N, sc->T, &X, &Y);
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
/* sample spherical coords for h in tangent space */
float phi;
@@ -199,7 +203,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
/* reflect I on H to get omega_in */
*omega_in = -I + (2.0f * HdotI) * H;
if(fmaxf(sc->data0, sc->data1) <= 1e-4f) {
if(fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);

View File

@@ -35,20 +35,38 @@
CCL_NAMESPACE_BEGIN
ccl_device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc)
{
float sigma = fmaxf(sc->data0, 0.01f);
sc->data0 = 1.0f/(sigma * sigma); /* m_invsigma2 */
typedef ccl_addr_space struct VelvetBsdf {
SHADER_CLOSURE_BASE;
sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
float sigma;
float invsigma2;
float3 N;
} VelvetBsdf;
ccl_device int bsdf_ashikhmin_velvet_setup(VelvetBsdf *bsdf)
{
float sigma = fmaxf(bsdf->sigma, 0.01f);
bsdf->invsigma2 = 1.0f/(sigma * sigma);
bsdf->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_ashikhmin_velvet_merge(const ShaderClosure *a, const ShaderClosure *b)
{
const VelvetBsdf *bsdf_a = (const VelvetBsdf*)a;
const VelvetBsdf *bsdf_b = (const VelvetBsdf*)b;
return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
(bsdf_a->sigma == bsdf_b->sigma);
}
ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_invsigma2 = sc->data0;
float3 N = sc->N;
const VelvetBsdf *bsdf = (const VelvetBsdf*)sc;
float m_invsigma2 = bsdf->invsigma2;
float3 N = bsdf->N;
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
@@ -90,8 +108,9 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, c
ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng, 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 m_invsigma2 = sc->data0;
float3 N = sc->N;
const VelvetBsdf *bsdf = (const VelvetBsdf*)sc;
float m_invsigma2 = bsdf->invsigma2;
float3 N = bsdf->N;
// we are viewing the surface from above - send a ray out with uniform
// distribution over the hemisphere

View File

@@ -35,17 +35,31 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct DiffuseBsdf {
SHADER_CLOSURE_BASE;
float3 N;
} DiffuseBsdf;
/* DIFFUSE */
ccl_device int bsdf_diffuse_setup(ShaderClosure *sc)
ccl_device int bsdf_diffuse_setup(DiffuseBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_DIFFUSE_ID;
bsdf->type = CLOSURE_BSDF_DIFFUSE_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_diffuse_merge(const ShaderClosure *a, const ShaderClosure *b)
{
const DiffuseBsdf *bsdf_a = (const DiffuseBsdf*)a;
const DiffuseBsdf *bsdf_b = (const DiffuseBsdf*)b;
return (isequal_float3(bsdf_a->N, bsdf_b->N));
}
ccl_device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 N = sc->N;
const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
float3 N = bsdf->N;
float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
*pdf = cos_pi;
@@ -59,7 +73,8 @@ ccl_device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc, const floa
ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, 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)
{
float3 N = sc->N;
const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
float3 N = bsdf->N;
// distribution over the hemisphere
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
@@ -80,9 +95,9 @@ ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I,
/* TRANSLUCENT */
ccl_device int bsdf_translucent_setup(ShaderClosure *sc)
ccl_device int bsdf_translucent_setup(DiffuseBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_TRANSLUCENT_ID;
bsdf->type = CLOSURE_BSDF_TRANSLUCENT_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
@@ -93,7 +108,8 @@ ccl_device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc, const f
ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 N = sc->N;
const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
float3 N = bsdf->N;
float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F;
*pdf = cos_pi;
@@ -102,7 +118,8 @@ ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const
ccl_device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, 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)
{
float3 N = sc->N;
const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
float3 N = bsdf->N;
// we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere

View File

@@ -35,7 +35,16 @@
CCL_NAMESPACE_BEGIN
ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const float3 colors[8], float pos)
#ifdef __OSL__
typedef ccl_addr_space struct DiffuseRampBsdf {
SHADER_CLOSURE_BASE;
float3 N;
float3 *colors;
} DiffuseRampBsdf;
ccl_device float3 bsdf_diffuse_ramp_get_color(const float3 colors[8], float pos)
{
int MAXCOLORS = 8;
@@ -49,11 +58,9 @@ ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const flo
return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
}
ccl_device int bsdf_diffuse_ramp_setup(ShaderClosure *sc)
ccl_device int bsdf_diffuse_ramp_setup(DiffuseRampBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
sc->data0 = 0.0f;
sc->data1 = 0.0f;
bsdf->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
@@ -61,29 +68,31 @@ ccl_device void bsdf_diffuse_ramp_blur(ShaderClosure *sc, float roughness)
{
}
ccl_device float3 bsdf_diffuse_ramp_eval_reflect(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf)
ccl_device float3 bsdf_diffuse_ramp_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 N = sc->N;
const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf*)sc;
float3 N = bsdf->N;
float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
*pdf = cos_pi * M_1_PI_F;
return bsdf_diffuse_ramp_get_color(sc, colors, cos_pi) * M_1_PI_F;
return bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F;
}
ccl_device float3 bsdf_diffuse_ramp_eval_transmit(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf)
ccl_device float3 bsdf_diffuse_ramp_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, const float3 colors[8], float3 Ng, 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)
ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, float3 Ng, 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)
{
float3 N = sc->N;
const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf*)sc;
float3 N = bsdf->N;
// distribution over the hemisphere
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0.0f) {
*eval = bsdf_diffuse_ramp_get_color(sc, colors, *pdf * M_PI_F) * M_1_PI_F;
*eval = bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F;
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
@@ -95,6 +104,8 @@ ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, const float3 co
return LABEL_REFLECT|LABEL_DIFFUSE;
}
#endif /* __OSL__ */
CCL_NAMESPACE_END
#endif /* __BSDF_DIFFUSE_RAMP_H__ */

View File

@@ -35,29 +35,49 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct HairBsdf {
SHADER_CLOSURE_BASE;
ccl_device int bsdf_hair_reflection_setup(ShaderClosure *sc)
float3 T;
float roughness1;
float roughness2;
float offset;
} HairBsdf;
ccl_device int bsdf_hair_reflection_setup(HairBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
bsdf->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc)
ccl_device int bsdf_hair_transmission_setup(HairBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
bsdf->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_hair_merge(const ShaderClosure *a, const ShaderClosure *b)
{
const HairBsdf *bsdf_a = (const HairBsdf*)a;
const HairBsdf *bsdf_b = (const HairBsdf*)b;
return (isequal_float3(bsdf_a->T, bsdf_b->T)) &&
(bsdf_a->roughness1 == bsdf_b->roughness1) &&
(bsdf_a->roughness2 == bsdf_b->roughness2) &&
(bsdf_a->offset == bsdf_b->offset);
}
ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float offset = sc->data2;
float3 Tg = sc->T;
float roughness1 = sc->data0;
float roughness2 = sc->data1;
const HairBsdf *bsdf = (const HairBsdf*)sc;
float offset = bsdf->offset;
float3 Tg = bsdf->T;
float roughness1 = bsdf->roughness1;
float roughness2 = bsdf->roughness2;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
@@ -107,10 +127,11 @@ ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, co
ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float offset = sc->data2;
float3 Tg = sc->T;
float roughness1 = sc->data0;
float roughness2 = sc->data1;
const HairBsdf *bsdf = (const HairBsdf*)sc;
float offset = bsdf->offset;
float3 Tg = bsdf->T;
float roughness1 = bsdf->roughness1;
float roughness2 = bsdf->roughness2;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
@@ -148,10 +169,11 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc,
ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, 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 offset = sc->data2;
float3 Tg = sc->T;
float roughness1 = sc->data0;
float roughness2 = sc->data1;
const HairBsdf *bsdf = (const HairBsdf*)sc;
float offset = bsdf->offset;
float3 Tg = bsdf->T;
float roughness1 = bsdf->roughness1;
float roughness2 = bsdf->roughness2;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
float3 locx = cross(locy, Tg);
@@ -198,10 +220,11 @@ ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, f
ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng, 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 offset = sc->data2;
float3 Tg = sc->T;
float roughness1 = sc->data0;
float roughness2 = sc->data1;
const HairBsdf *bsdf = (const HairBsdf*)sc;
float offset = bsdf->offset;
float3 Tg = bsdf->T;
float roughness1 = bsdf->roughness1;
float roughness2 = bsdf->roughness2;
float Iz = dot(Tg, I);
float3 locy = normalize(I - Tg * Iz);
float3 locx = cross(locy, Tg);

View File

@@ -35,6 +35,19 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct MicrofacetExtra {
float3 color;
} MicrofacetExtra;
typedef ccl_addr_space struct MicrofacetBsdf {
SHADER_CLOSURE_BASE;
float alpha_x, alpha_y, ior;
MicrofacetExtra *extra;
float3 T;
float3 N;
} MicrofacetBsdf;
/* Beckmann and GGX microfacet importance sampling. */
ccl_device_inline void microfacet_beckmann_sample_slopes(
@@ -233,48 +246,66 @@ ccl_device_inline float3 microfacet_sample_stretched(
* Anisotropy is only supported for reflection currently, but adding it for
* transmission is just a matter of copying code from reflection if needed. */
ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosure *b)
{
sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = saturate(sc->data1); /* alpha_y */
const MicrofacetBsdf *bsdf_a = (const MicrofacetBsdf*)a;
const MicrofacetBsdf *bsdf_b = (const MicrofacetBsdf*)b;
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
(bsdf_a->alpha_x == bsdf_b->alpha_x) &&
(bsdf_a->alpha_y == bsdf_b->alpha_y) &&
(isequal_float3(bsdf_a->T, bsdf_b->T)) &&
(bsdf_a->ior == bsdf_b->ior) &&
((!bsdf_a->extra && !bsdf_b->extra) ||
((bsdf_a->extra && bsdf_b->extra) &&
(isequal_float3(bsdf_a->extra->color, bsdf_b->extra->color))));
}
ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
{
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = saturate(bsdf->alpha_y);
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
{
sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = bsdf->N;
if(m_refractive || alpha_x*alpha_y <= 1e-7f)
return make_float3(0.0f, 0.0f, 0.0f);
@@ -305,7 +336,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
else {
/* anisotropic */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, sc->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
@@ -361,11 +392,12 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
float m_eta = sc->data2;
bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
float m_eta = bsdf->ior;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = bsdf->N;
if(!m_refractive || alpha_x*alpha_y <= 1e-7f)
return make_float3(0.0f, 0.0f, 0.0f);
@@ -415,10 +447,11 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, 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 alpha_x = sc->data0;
float alpha_y = sc->data1;
bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = bsdf->N;
float cosNO = dot(N, I);
if(cosNO > 0) {
@@ -427,7 +460,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
if(alpha_x == alpha_y)
make_orthonormals(Z, &X, &Y);
else
make_orthonormals_tangent(Z, sc->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* importance sampling with distribution of visible normals. vectors are
* transformed to local space before and after */
@@ -522,7 +555,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
#ifdef __RAY_DIFFERENTIALS__
float3 dRdx, dRdy, dTdx, dTdy;
#endif
float m_eta = sc->data2, fresnel;
float m_eta = bsdf->ior, fresnel;
bool inside;
fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
@@ -582,37 +615,39 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
* Microfacet Models for Refraction through Rough Surfaces
* B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007 */
ccl_device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_beckmann_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_beckmann_aniso_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = saturate(sc->data1); /* alpha_y */
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = saturate(bsdf->alpha_y);
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_beckmann_refraction_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = saturate(sc->data0); /* alpha_x */
sc->data1 = sc->data0; /* alpha_y */
bsdf->alpha_x = saturate(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
{
sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n)
@@ -647,10 +682,11 @@ ccl_device_inline float bsdf_beckmann_aniso_G1(float alpha_x, float alpha_y, flo
ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = bsdf->N;
if(m_refractive || alpha_x*alpha_y <= 1e-7f)
return make_float3(0.0f, 0.0f, 0.0f);
@@ -682,7 +718,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
else {
/* anisotropic */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, sc->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
@@ -722,11 +758,12 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float alpha_x = sc->data0;
float alpha_y = sc->data1;
float m_eta = sc->data2;
bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
float m_eta = bsdf->ior;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = bsdf->N;
if(!m_refractive || alpha_x*alpha_y <= 1e-7f)
return make_float3(0.0f, 0.0f, 0.0f);
@@ -773,10 +810,11 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, 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 alpha_x = sc->data0;
float alpha_y = sc->data1;
bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 N = bsdf->N;
float cosNO = dot(N, I);
if(cosNO > 0) {
@@ -785,7 +823,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
if(alpha_x == alpha_y)
make_orthonormals(Z, &X, &Y);
else
make_orthonormals_tangent(Z, sc->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* importance sampling with distribution of visible normals. vectors are
* transformed to local space before and after */
@@ -872,7 +910,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
#ifdef __RAY_DIFFERENTIALS__
float3 dRdx, dRdy, dTdx, dTdy;
#endif
float m_eta = sc->data2, fresnel;
float m_eta = bsdf->ior, fresnel;
bool inside;
fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,

View File

@@ -328,40 +328,42 @@ ccl_device_inline float mf_glass_pdf(const float3 wi, const float3 wo, const flo
ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
{
sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
/* === Closure implementations === */
/* Multiscattering GGX Glossy closure */
ccl_device int bsdf_microfacet_multi_ggx_common_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); /* alpha */
sc->data1 = clamp(sc->data1, 1e-4f, 1.0f);
sc->custom1 = saturate(sc->custom1); /* color */
sc->custom2 = saturate(sc->custom2);
sc->custom3 = saturate(sc->custom3);
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
bsdf->extra->color.x = saturate(bsdf->extra->color.x);
bsdf->extra->color.y = saturate(bsdf->extra->color.y);
bsdf->extra->color.z = saturate(bsdf->extra->color.z);
sc->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG|SD_BSDF_HAS_CUSTOM;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
}
ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
{
if(is_zero(sc->T))
sc->T = make_float3(1.0f, 0.0f, 0.0f);
if(is_zero(bsdf->T))
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
return bsdf_microfacet_multi_ggx_common_setup(sc);
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device int bsdf_microfacet_multi_ggx_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
{
sc->data1 = sc->data0;
bsdf->alpha_y = bsdf->alpha_x;
return bsdf_microfacet_multi_ggx_common_setup(sc);
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
@@ -370,11 +372,12 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *s
}
ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
bool is_aniso = (sc->data0 != sc->data1);
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
float3 X, Y, Z;
Z = sc->N;
Z = bsdf->N;
if(is_aniso)
make_orthonormals_tangent(Z, sc->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
else
make_orthonormals(Z, &X, &Y);
@@ -382,30 +385,31 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
if(is_aniso)
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(sc->data0, sc->data1));
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
else
*pdf = mf_ggx_pdf(localI, localO, sc->data0);
return mf_eval_glossy(localI, localO, true, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, NULL, NULL);
*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL);
}
ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, 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, ccl_addr_space uint *lcg_state)
{
bool is_aniso = (sc->data0 != sc->data1);
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
float3 X, Y, Z;
Z = sc->N;
Z = bsdf->N;
if(is_aniso)
make_orthonormals_tangent(Z, sc->T, &X, &Y);
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
else
make_orthonormals(Z, &X, &Y);
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
float3 localO;
*eval = mf_sample_glossy(localI, &localO, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, NULL, NULL);
*eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL);
if(is_aniso)
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(sc->data0, sc->data1));
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
else
*pdf = mf_ggx_pdf(localI, localO, sc->data0);
*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
*eval *= *pdf;
*omega_in = X*localO.x + Y*localO.y + Z*localO.z;
@@ -418,55 +422,58 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
/* Multiscattering GGX Glass closure */
ccl_device int bsdf_microfacet_multi_ggx_glass_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
{
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); /* alpha */
sc->data1 = sc->data0;
sc->data2 = max(0.0f, sc->data2); /* ior */
sc->custom1 = saturate(sc->custom1); /* color */
sc->custom2 = saturate(sc->custom2);
sc->custom3 = saturate(sc->custom3);
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
bsdf->alpha_y = bsdf->alpha_x;
bsdf->ior = max(0.0f, bsdf->ior);
bsdf->extra->color.x = saturate(bsdf->extra->color.x);
bsdf->extra->color.y = saturate(bsdf->extra->color.y);
bsdf->extra->color.z = saturate(bsdf->extra->color.z);
sc->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG|SD_BSDF_HAS_CUSTOM;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
}
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float3 X, Y, Z;
Z = sc->N;
Z = bsdf->N;
make_orthonormals(Z, &X, &Y);
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
*pdf = mf_glass_pdf(localI, localO, sc->data0, sc->data2);
return mf_eval_glass(localI, localO, false, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, sc->data2);
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
}
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float3 X, Y, Z;
Z = sc->N;
Z = bsdf->N;
make_orthonormals(Z, &X, &Y);
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
*pdf = mf_glass_pdf(localI, localO, sc->data0, sc->data2);
return mf_eval_glass(localI, localO, true, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, sc->data2);
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
}
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, 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, ccl_addr_space uint *lcg_state)
{
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float3 X, Y, Z;
Z = sc->N;
Z = bsdf->N;
make_orthonormals(Z, &X, &Y);
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
float3 localO;
*eval = mf_sample_glass(localI, &localO, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, sc->data2);
*pdf = mf_glass_pdf(localI, localO, sc->data0, sc->data2);
*eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
*eval *= *pdf;
*omega_in = X*localO.x + Y*localO.y + Z*localO.z;
@@ -480,9 +487,9 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const S
else {
#ifdef __RAY_DIFFERENTIALS__
float cosI = dot(Z, I);
float dnp = max(sqrtf(1.0f - (sc->data2 * sc->data2 * (1.0f - cosI*cosI))), 1e-7f);
*domega_in_dx = -(sc->data2 * dIdx) + ((sc->data2 - sc->data2 * sc->data2 * cosI / dnp) * dot(dIdx, Z)) * Z;
*domega_in_dy = -(sc->data2 * dIdy) + ((sc->data2 - sc->data2 * sc->data2 * cosI / dnp) * dot(dIdy, Z)) * Z;
float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI*cosI))), 1e-7f);
*domega_in_dx = -(bsdf->ior * dIdx) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
*domega_in_dy = -(bsdf->ior * dIdy) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
#endif
return LABEL_TRANSMIT|LABEL_GLOSSY;

View File

@@ -19,39 +19,59 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct OrenNayarBsdf {
SHADER_CLOSURE_BASE;
float3 N;
float roughness;
float a;
float b;
} OrenNayarBsdf;
ccl_device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, float3 v, float3 l)
{
const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
float nl = max(dot(n, l), 0.0f);
float nv = max(dot(n, v), 0.0f);
float t = dot(l, v) - nl * nv;
if(t > 0.0f)
t /= max(nl, nv) + FLT_MIN;
float is = nl * (sc->data0 + sc->data1 * t);
float is = nl * (bsdf->a + bsdf->b * t);
return make_float3(is, is, is);
}
ccl_device int bsdf_oren_nayar_setup(ShaderClosure *sc)
ccl_device int bsdf_oren_nayar_setup(OrenNayarBsdf *bsdf)
{
float sigma = sc->data0;
float sigma = bsdf->roughness;
sc->type = CLOSURE_BSDF_OREN_NAYAR_ID;
bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID;
sigma = saturate(sigma);
float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma);
sc->data0 = 1.0f * div;
sc->data1 = sigma * div;
bsdf->a = 1.0f * div;
bsdf->b = sigma * div;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_oren_nayar_merge(const ShaderClosure *a, const ShaderClosure *b)
{
const OrenNayarBsdf *bsdf_a = (const OrenNayarBsdf*)a;
const OrenNayarBsdf *bsdf_b = (const OrenNayarBsdf*)b;
return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
(bsdf_a->roughness == bsdf_b->roughness);
}
ccl_device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
if(dot(sc->N, omega_in) > 0.0f) {
const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
if(dot(bsdf->N, omega_in) > 0.0f) {
*pdf = 0.5f * M_1_PI_F;
return bsdf_oren_nayar_get_intensity(sc, sc->N, I, omega_in);
return bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, omega_in);
}
else {
*pdf = 0.0f;
@@ -66,15 +86,16 @@ ccl_device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc, const f
ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, 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)
{
sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf);
const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
sample_uniform_hemisphere(bsdf->N, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, sc->N, I, *omega_in);
*eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, *omega_in);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the bounce
*domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
*domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
*domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
}
else {

View File

@@ -35,7 +35,17 @@
CCL_NAMESPACE_BEGIN
ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float3 colors[8], float pos)
#ifdef __OSL__
typedef ccl_addr_space struct PhongRampBsdf {
SHADER_CLOSURE_BASE;
float3 N;
float exponent;
float3 *colors;
} PhongRampBsdf;
ccl_device float3 bsdf_phong_ramp_get_color(const float3 colors[8], float pos)
{
int MAXCOLORS = 8;
@@ -49,57 +59,54 @@ ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float
return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
}
ccl_device int bsdf_phong_ramp_setup(ShaderClosure *sc)
ccl_device int bsdf_phong_ramp_setup(PhongRampBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_PHONG_RAMP_ID;
sc->data0 = max(sc->data0, 0.0f);
sc->data1 = 0.0f;
bsdf->type = CLOSURE_BSDF_PHONG_RAMP_ID;
bsdf->exponent = max(bsdf->exponent, 0.0f);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness)
ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
}
ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf)
{
float m_exponent = sc->data0;
float cosNI = dot(sc->N, omega_in);
float cosNO = dot(sc->N, I);
const PhongRampBsdf *bsdf = (const PhongRampBsdf*)sc;
float m_exponent = bsdf->exponent;
float cosNI = dot(bsdf->N, omega_in);
float cosNO = dot(bsdf->N, I);
if(cosNI > 0 && cosNO > 0) {
// reflect the view vector
float3 R = (2 * cosNO) * sc->N - I;
float3 R = (2 * cosNO) * bsdf->N - I;
float cosRI = dot(R, omega_in);
if(cosRI > 0) {
float cosp = powf(cosRI, m_exponent);
float common = 0.5f * M_1_PI_F * cosp;
float out = cosNI * (m_exponent + 2) * common;
*pdf = (m_exponent + 1) * common;
return bsdf_phong_ramp_get_color(sc, colors, cosp) * out;
return bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
}
}
return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf)
ccl_device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colors[8], float3 Ng, 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)
ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, float3 Ng, 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 cosNO = dot(sc->N, I);
float m_exponent = sc->data0;
const PhongRampBsdf *bsdf = (const PhongRampBsdf*)sc;
float cosNO = dot(bsdf->N, I);
float m_exponent = bsdf->exponent;
if(cosNO > 0) {
// reflect the view vector
float3 R = (2 * cosNO) * sc->N - I;
float3 R = (2 * cosNO) * bsdf->N - I;
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy;
*domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
*domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
float3 T, B;
@@ -114,7 +121,7 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo
if(dot(Ng, *omega_in) > 0.0f)
{
// common terms for pdf and eval
float cosNI = dot(sc->N, *omega_in);
float cosNI = dot(bsdf->N, *omega_in);
// make sure the direction we chose is still in the right hemisphere
if(cosNI > 0)
{
@@ -122,13 +129,14 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo
float common = 0.5f * M_1_PI_F * cosp;
*pdf = (m_exponent + 1) * common;
float out = cosNI * (m_exponent + 2) * common;
*eval = bsdf_phong_ramp_get_color(sc, colors, cosp) * out;
*eval = bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
}
}
}
return LABEL_REFLECT|LABEL_GLOSSY;
}
#endif /* __OSL__ */
CCL_NAMESPACE_END

View File

@@ -37,9 +37,9 @@ CCL_NAMESPACE_BEGIN
/* REFLECTION */
ccl_device int bsdf_reflection_setup(ShaderClosure *sc)
ccl_device int bsdf_reflection_setup(MicrofacetBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_REFLECTION_ID;
bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
return SD_BSDF;
}
@@ -55,7 +55,8 @@ ccl_device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc, const f
ccl_device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, 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)
{
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float3 N = bsdf->N;
// only one direction is possible
float cosNO = dot(N, I);

View File

@@ -37,9 +37,9 @@ CCL_NAMESPACE_BEGIN
/* REFRACTION */
ccl_device int bsdf_refraction_setup(ShaderClosure *sc)
ccl_device int bsdf_refraction_setup(MicrofacetBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_REFRACTION_ID;
bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
return SD_BSDF;
}
@@ -55,8 +55,9 @@ ccl_device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc, const f
ccl_device int bsdf_refraction_sample(const ShaderClosure *sc, float3 Ng, 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 m_eta = sc->data0;
float3 N = sc->N;
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
float m_eta = bsdf->ior;
float3 N = bsdf->N;
float3 R, T;
#ifdef __RAY_DIFFERENTIALS__

View File

@@ -35,17 +35,35 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct ToonBsdf {
SHADER_CLOSURE_BASE;
float3 N;
float size;
float smooth;
} ToonBsdf;
/* DIFFUSE TOON */
ccl_device int bsdf_diffuse_toon_setup(ShaderClosure *sc)
ccl_device int bsdf_diffuse_toon_setup(ToonBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
sc->data0 = saturate(sc->data0);
sc->data1 = saturate(sc->data1);
bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
bsdf->size = saturate(bsdf->size);
bsdf->smooth = saturate(bsdf->smooth);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_toon_merge(const ShaderClosure *a, const ShaderClosure *b)
{
const ToonBsdf *bsdf_a = (const ToonBsdf*)a;
const ToonBsdf *bsdf_b = (const ToonBsdf*)b;
return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
(bsdf_a->size == bsdf_b->size) &&
(bsdf_a->smooth == bsdf_b->smooth);
}
ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
{
float is;
@@ -67,9 +85,10 @@ ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
ccl_device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
float angle = safe_acosf(fmaxf(dot(sc->N, omega_in), 0.0f));
const ToonBsdf *bsdf = (const ToonBsdf*)sc;
float max_angle = bsdf->size*M_PI_2_F;
float smooth = bsdf->smooth*M_PI_2_F;
float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
@@ -90,21 +109,22 @@ ccl_device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc, const
ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, 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 max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
const ToonBsdf *bsdf = (const ToonBsdf*)sc;
float max_angle = bsdf->size*M_PI_2_F;
float smooth = bsdf->smooth*M_PI_2_F;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float angle = sample_angle*randu;
if(sample_angle > 0.0f) {
sample_uniform_cone(sc->N, sample_angle, randu, randv, omega_in, pdf);
sample_uniform_cone(bsdf->N, sample_angle, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0.0f) {
*eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the bounce
*domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
*domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
*domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
}
else
@@ -117,25 +137,26 @@ ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, floa
/* GLOSSY TOON */
ccl_device int bsdf_glossy_toon_setup(ShaderClosure *sc)
ccl_device int bsdf_glossy_toon_setup(ToonBsdf *bsdf)
{
sc->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
sc->data0 = saturate(sc->data0);
sc->data1 = saturate(sc->data1);
bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
bsdf->size = saturate(bsdf->size);
bsdf->smooth = saturate(bsdf->smooth);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
float cosNI = dot(sc->N, omega_in);
float cosNO = dot(sc->N, I);
const ToonBsdf *bsdf = (const ToonBsdf*)sc;
float max_angle = bsdf->size*M_PI_2_F;
float smooth = bsdf->smooth*M_PI_2_F;
float cosNI = dot(bsdf->N, omega_in);
float cosNO = dot(bsdf->N, I);
if(cosNI > 0 && cosNO > 0) {
/* reflect the view vector */
float3 R = (2 * cosNO) * sc->N - I;
float3 R = (2 * cosNO) * bsdf->N - I;
float cosRI = dot(R, omega_in);
float angle = safe_acosf(fmaxf(cosRI, 0.0f));
@@ -157,13 +178,14 @@ ccl_device float3 bsdf_glossy_toon_eval_transmit(const ShaderClosure *sc, const
ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc, float3 Ng, 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 max_angle = sc->data0*M_PI_2_F;
float smooth = sc->data1*M_PI_2_F;
float cosNO = dot(sc->N, I);
const ToonBsdf *bsdf = (const ToonBsdf*)sc;
float max_angle = bsdf->size*M_PI_2_F;
float smooth = bsdf->smooth*M_PI_2_F;
float cosNO = dot(bsdf->N, I);
if(cosNO > 0) {
/* reflect the view vector */
float3 R = (2 * cosNO) * sc->N - I;
float3 R = (2 * cosNO) * bsdf->N - I;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float angle = sample_angle*randu;
@@ -171,15 +193,15 @@ ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc, float3 Ng, float
sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0.0f) {
float cosNI = dot(sc->N, *omega_in);
float cosNI = dot(bsdf->N, *omega_in);
/* make sure the direction we chose is still in the right hemisphere */
if(cosNI > 0) {
*eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy;
*domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
*domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
}
else

View File

@@ -19,6 +19,17 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct Bssrdf {
SHADER_CLOSURE_BASE;
float radius;
float sharpness;
float d;
float texture_blur;
float albedo;
float3 N;
} Bssrdf;
/* Planar Truncated Gaussian
*
* Note how this is different from the typical gaussian, this one integrates
@@ -28,11 +39,12 @@ CCL_NAMESPACE_BEGIN
/* paper suggests 1/12.46 which is much too small, suspect it's *12.46 */
#define GAUSS_TRUNCATE 12.46f
ccl_device float bssrdf_gaussian_eval(ShaderClosure *sc, float r)
ccl_device float bssrdf_gaussian_eval(const ShaderClosure *sc, float r)
{
/* integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) from 0 to Rm
* = 1 - exp(-Rm*Rm/(2*v)) */
const float v = sc->data0*sc->data0*(0.25f*0.25f);
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float v = bssrdf->radius*bssrdf->radius*(0.25f*0.25f);
const float Rm = sqrtf(v*GAUSS_TRUNCATE);
if(r >= Rm)
@@ -41,7 +53,7 @@ ccl_device float bssrdf_gaussian_eval(ShaderClosure *sc, float r)
return expf(-r*r/(2.0f*v))/(2.0f*M_PI_F*v);
}
ccl_device float bssrdf_gaussian_pdf(ShaderClosure *sc, float r)
ccl_device float bssrdf_gaussian_pdf(const ShaderClosure *sc, float r)
{
/* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
const float area_truncated = 1.0f - expf(-0.5f*GAUSS_TRUNCATE);
@@ -49,12 +61,12 @@ ccl_device float bssrdf_gaussian_pdf(ShaderClosure *sc, float r)
return bssrdf_gaussian_eval(sc, r) * (1.0f/(area_truncated));
}
ccl_device void bssrdf_gaussian_sample(ShaderClosure *sc, float xi, float *r, float *h)
ccl_device void bssrdf_gaussian_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
/* xi = integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) = -exp(-r^2/(2*v))
* r = sqrt(-2*v*logf(xi)) */
const float v = sc->data0*sc->data0*(0.25f*0.25f);
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float v = bssrdf->radius*bssrdf->radius*(0.25f*0.25f);
const float Rm = sqrtf(v*GAUSS_TRUNCATE);
/* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
@@ -75,12 +87,13 @@ ccl_device void bssrdf_gaussian_sample(ShaderClosure *sc, float xi, float *r, fl
* far as I can tell has no closed form solution. So we get an iterative solution
* instead with newton-raphson. */
ccl_device float bssrdf_cubic_eval(ShaderClosure *sc, float r)
ccl_device float bssrdf_cubic_eval(const ShaderClosure *sc, float r)
{
const float sharpness = sc->T.x;
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float sharpness = bssrdf->sharpness;
if(sharpness == 0.0f) {
const float Rm = sc->data0;
const float Rm = bssrdf->radius;
if(r >= Rm)
return 0.0f;
@@ -94,7 +107,7 @@ ccl_device float bssrdf_cubic_eval(ShaderClosure *sc, float r)
}
else {
float Rm = sc->data0*(1.0f + sharpness);
float Rm = bssrdf->radius*(1.0f + sharpness);
if(r >= Rm)
return 0.0f;
@@ -122,7 +135,7 @@ ccl_device float bssrdf_cubic_eval(ShaderClosure *sc, float r)
}
}
ccl_device float bssrdf_cubic_pdf(ShaderClosure *sc, float r)
ccl_device float bssrdf_cubic_pdf(const ShaderClosure *sc, float r)
{
return bssrdf_cubic_eval(sc, r);
}
@@ -155,12 +168,13 @@ ccl_device float bssrdf_cubic_quintic_root_find(float xi)
return x;
}
ccl_device void bssrdf_cubic_sample(ShaderClosure *sc, float xi, float *r, float *h)
ccl_device void bssrdf_cubic_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
float Rm = sc->data0;
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float sharpness = bssrdf->sharpness;
float Rm = bssrdf->radius;
float r_ = bssrdf_cubic_quintic_root_find(xi);
const float sharpness = sc->T.x;
if(sharpness != 0.0f) {
r_ = powf(r_, 1.0f + sharpness);
Rm *= (1.0f + sharpness);
@@ -198,21 +212,22 @@ ccl_device_inline float bssrdf_burley_compatible_mfp(float r)
return 0.25f * M_1_PI_F * r;
}
ccl_device void bssrdf_burley_setup(ShaderClosure *sc)
ccl_device void bssrdf_burley_setup(Bssrdf *bssrdf)
{
/* Mean free path length. */
const float l = bssrdf_burley_compatible_mfp(sc->data0);
const float l = bssrdf_burley_compatible_mfp(bssrdf->radius);
/* Surface albedo. */
const float A = sc->data2;
const float A = bssrdf->albedo;
const float s = bssrdf_burley_fitting(A);
const float d = l / s;
sc->custom1 = d;
bssrdf->d = d;
}
ccl_device float bssrdf_burley_eval(ShaderClosure *sc, float r)
ccl_device float bssrdf_burley_eval(const ShaderClosure *sc, float r)
{
const float d = sc->custom1;
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float d = bssrdf->d;
const float Rm = BURLEY_TRUNCATE * d;
if(r >= Rm)
@@ -231,7 +246,7 @@ ccl_device float bssrdf_burley_eval(ShaderClosure *sc, float r)
return (exp_r_d + exp_r_3_d) / (4.0f*d);
}
ccl_device float bssrdf_burley_pdf(ShaderClosure *sc, float r)
ccl_device float bssrdf_burley_pdf(const ShaderClosure *sc, float r)
{
return bssrdf_burley_eval(sc, r) * (1.0f/BURLEY_TRUNCATE_CDF);
}
@@ -276,12 +291,13 @@ ccl_device float bssrdf_burley_root_find(float xi)
return r;
}
ccl_device void bssrdf_burley_sample(ShaderClosure *sc,
ccl_device void bssrdf_burley_sample(const ShaderClosure *sc,
float xi,
float *r,
float *h)
{
const float d = sc->custom1;
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float d = bssrdf->d;
const float Rm = BURLEY_TRUNCATE * d;
const float r_ = bssrdf_burley_root_find(xi * BURLEY_TRUNCATE_CDF) * d;
@@ -295,26 +311,29 @@ ccl_device void bssrdf_burley_sample(ShaderClosure *sc,
*
* Samples distributed over disk with no falloff, for reference. */
ccl_device float bssrdf_none_eval(ShaderClosure *sc, float r)
ccl_device float bssrdf_none_eval(const ShaderClosure *sc, float r)
{
const float Rm = sc->data0;
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float Rm = bssrdf->radius;
return (r < Rm)? 1.0f: 0.0f;
}
ccl_device float bssrdf_none_pdf(ShaderClosure *sc, float r)
ccl_device float bssrdf_none_pdf(const ShaderClosure *sc, float r)
{
/* integrate (2*pi*r)/(pi*Rm*Rm) from 0 to Rm = 1 */
const float Rm = sc->data0;
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float Rm = bssrdf->radius;
const float area = (M_PI_F*Rm*Rm);
return bssrdf_none_eval(sc, r) / area;
}
ccl_device void bssrdf_none_sample(ShaderClosure *sc, float xi, float *r, float *h)
ccl_device void bssrdf_none_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
/* xi = integrate (2*pi*r)/(pi*Rm*Rm) = r^2/Rm^2
* r = sqrt(xi)*Rm */
const float Rm = sc->data0;
const Bssrdf *bssrdf = (const Bssrdf*)sc;
const float Rm = bssrdf->radius;
const float r_ = sqrtf(xi)*Rm;
*r = r_;
@@ -325,30 +344,42 @@ ccl_device void bssrdf_none_sample(ShaderClosure *sc, float xi, float *r, float
/* Generic */
ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type)
ccl_device_inline Bssrdf *bssrdf_alloc(ShaderData *sd, float3 weight)
{
if(sc->data0 < BSSRDF_MIN_RADIUS) {
Bssrdf *bssrdf = (Bssrdf*)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
if(!bssrdf)
return NULL;
float sample_weight = fabsf(average(weight));
bssrdf->sample_weight = sample_weight;
return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? bssrdf : NULL;
}
ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
{
if(bssrdf->radius < BSSRDF_MIN_RADIUS) {
/* revert to diffuse BSDF if radius too small */
sc->data0 = 0.0f;
sc->data1 = 0.0f;
int flag = bsdf_diffuse_setup(sc);
sc->type = CLOSURE_BSDF_BSSRDF_ID;
DiffuseBsdf *bsdf = (DiffuseBsdf*)bssrdf;
bsdf->N = bssrdf->N;
int flag = bsdf_diffuse_setup(bsdf);
bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
return flag;
}
else {
sc->data1 = saturate(sc->data1); /* texture blur */
sc->T.x = saturate(sc->T.x); /* sharpness */
sc->type = type;
bssrdf->texture_blur = saturate(bssrdf->texture_blur);
bssrdf->sharpness = saturate(bssrdf->sharpness);
bssrdf->type = type;
if(type == CLOSURE_BSSRDF_BURLEY_ID) {
bssrdf_burley_setup(sc);
bssrdf_burley_setup(bssrdf);
}
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF;
}
}
ccl_device void bssrdf_sample(ShaderClosure *sc, float xi, float *r, float *h)
ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
if(sc->type == CLOSURE_BSSRDF_CUBIC_ID)
bssrdf_cubic_sample(sc, xi, r, h);
@@ -358,7 +389,7 @@ ccl_device void bssrdf_sample(ShaderClosure *sc, float xi, float *r, float *h)
bssrdf_burley_sample(sc, xi, r, h);
}
ccl_device float bssrdf_pdf(ShaderClosure *sc, float r)
ccl_device float bssrdf_pdf(const ShaderClosure *sc, float r)
{
if(sc->type == CLOSURE_BSSRDF_CUBIC_ID)
return bssrdf_cubic_pdf(sc, r);

View File

@@ -19,6 +19,12 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct HenyeyGreensteinVolume {
SHADER_CLOSURE_BASE;
float g;
} HenyeyGreensteinVolume;
/* HENYEY-GREENSTEIN CLOSURE */
/* Given cosine between rays, return probability density that a photon bounces
@@ -29,19 +35,28 @@ ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g)
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)
ccl_device int volume_henyey_greenstein_setup(HenyeyGreensteinVolume *volume)
{
sc->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
volume->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);
volume->g = signf(volume->g) * min(fabsf(volume->g), 1.0f - 1e-3f);
return SD_SCATTER;
}
ccl_device bool volume_henyey_greenstein_merge(const ShaderClosure *a, const ShaderClosure *b)
{
const HenyeyGreensteinVolume *volume_a = (const HenyeyGreensteinVolume*)a;
const HenyeyGreensteinVolume *volume_b = (const HenyeyGreensteinVolume*)b;
return (volume_a->g == volume_b->g);
}
ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
{
float g = sc->data0;
const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
float g = volume->g;
/* note that I points towards the viewer */
if(fabsf(g) < 1e-3f) {
@@ -58,7 +73,8 @@ ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, c
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;
const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
float g = volume->g;
float cos_phi, sin_phi, cos_theta;
/* match pdf for small g */

View File

@@ -24,6 +24,7 @@
*
*/
#include "closure/alloc.h"
#include "closure/bsdf_util.h"
#include "closure/bsdf.h"
#include "closure/emissive.h"
@@ -453,22 +454,9 @@ ccl_device void shader_merge_closures(ShaderData *sd)
for(int j = i + 1; j < sd->num_closure; j++) {
ShaderClosure *scj = &sd->closure[j];
#ifdef __OSL__
if(sci->prim || scj->prim)
if(sci->type != scj->type)
continue;
#endif
if(!(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1 && sci->data2 == scj->data2))
continue;
if(CLOSURE_IS_BSDF_OR_BSSRDF(sci->type)) {
if(sci->N != scj->N)
continue;
else if(CLOSURE_IS_BSDF_ANISOTROPIC(sci->type) && sci->T != scj->T)
continue;
}
if((sd->flag & SD_BSDF_HAS_CUSTOM) && !(sci->custom1 == scj->custom1 && sci->custom2 == scj->custom2 && sci->custom3 == scj->custom3))
if(!bsdf_merge(sci, scj))
continue;
sci->weight += scj->weight;
@@ -741,8 +729,9 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
eval += sc->weight*ao_factor;
N += sc->N*average(sc->weight);
N += bsdf->N*average(sc->weight);
}
else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
eval += sc->weight;
@@ -759,6 +748,7 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
return eval;
}
#ifdef __SUBSURFACE__
ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_blur_)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -769,11 +759,12 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSSRDF(sc->type)) {
const Bssrdf *bssrdf = (const Bssrdf*)sc;
float avg_weight = fabsf(average(sc->weight));
N += sc->N*avg_weight;
N += bssrdf->N*avg_weight;
eval += sc->weight;
texture_blur += sc->data1*avg_weight;
texture_blur += bssrdf->texture_blur*avg_weight;
weight_sum += avg_weight;
}
}
@@ -786,6 +777,7 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
return eval;
}
#endif
/* Emission */
@@ -831,6 +823,7 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_
ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
{
ccl_fetch(sd, num_closure) = 0;
ccl_fetch(sd, num_closure_extra) = 0;
ccl_fetch(sd, randb_closure) = randb;
#ifdef __OSL__
@@ -861,33 +854,33 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
ccl_addr_space PathState *state, int path_flag, ShaderContext ctx)
{
ccl_fetch(sd, num_closure) = 0;
ccl_fetch(sd, num_closure_extra) = 0;
ccl_fetch(sd, randb_closure) = 0.0f;
#ifdef __SVM__
#ifdef __OSL__
if(kg->osl) {
return OSLShader::eval_background(kg, sd, state, path_flag, ctx);
OSLShader::eval_background(kg, sd, state, path_flag, ctx);
}
else
#endif
{
#ifdef __SVM__
svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BACKGROUND(sc->type))
eval += sc->weight;
}
return eval;
#else
return make_float3(0.8f, 0.8f, 0.8f);
#endif
}
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BACKGROUND(sc->type))
eval += sc->weight;
}
return eval;
#else
return make_float3(0.8f, 0.8f, 0.8f);
#endif
}
/* Volume */
@@ -1004,6 +997,7 @@ ccl_device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
/* reset closures once at the start, we will be accumulating the closures
* for all volumes in the stack into a single array of closures */
sd->num_closure = 0;
sd->num_closure_extra = 0;
sd->flag = 0;
for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
@@ -1051,6 +1045,7 @@ ccl_device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, ShaderContext ctx)
{
ccl_fetch(sd, num_closure) = 0;
ccl_fetch(sd, num_closure_extra) = 0;
ccl_fetch(sd, randb_closure) = 0.0f;
/* this will modify sd->P */

View File

@@ -140,24 +140,21 @@ ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 wei
{
sd->flag &= ~SD_CLOSURE_FLAGS;
sd->randb_closure = 0.0f;
sd->num_closure = 0;
sd->num_closure_extra = 0;
if(hit) {
ShaderClosure *sc = &sd->closure[0];
sd->num_closure = 1;
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
sc->weight = weight;
sc->sample_weight = 1.0f;
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->N = N;
sd->flag |= bsdf_diffuse_setup(sc);
if(bsdf) {
bsdf->N = N;
sd->flag |= bsdf_diffuse_setup(bsdf);
/* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
* can recognize it as not being a regular diffuse closure */
sc->type = CLOSURE_BSDF_BSSRDF_ID;
/* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
* can recognize it as not being a regular diffuse closure */
bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
}
}
else
sd->num_closure = 0;
}
/* optionally do blurring of color and/or bump mapping, at the cost of a shader evaluation */

View File

@@ -636,32 +636,30 @@ typedef enum AttributeStandard {
# define MAX_CLOSURE 1
#endif
/* This struct is to be 16 bytes aligned, we also keep some extra precautions:
* - All the float3 members are in the beginning of the struct, so compiler
* does not put own padding trying to align this members.
* - We make sure OSL pointer is also 16 bytes aligned.
*/
/* This struct is the base class for all closures. The common members are
* duplicated in all derived classes since we don't have C++ in the kernel
* yet, and because it lets us lay out the members to minimize padding. The
* weight member is located at the beginning of the struct for this reason.
*
* ShaderClosure has a fixed size, and any extra space must be allocated
* with closure_alloc_extra().
*
* float3 is 12 bytes on CUDA and 16 bytes on CPU/OpenCL, we set the data
* size to ensure ShaderClosure is 80 bytes total everywhere. */
#define SHADER_CLOSURE_BASE \
float3 weight; \
ClosureType type; \
float sample_weight \
typedef ccl_addr_space struct ShaderClosure {
float3 weight;
float3 N;
float3 T;
SHADER_CLOSURE_BASE;
ClosureType type;
float sample_weight;
float data0;
float data1;
float data2;
/* Following fields could be used to store pre-calculated
* values by various BSDF closures for more effective sampling
* and evaluation.
*/
float custom1;
float custom2;
float custom3;
#ifdef __OSL__
void *prim, *pad4;
/* pad to 80 bytes, data types are aligned to own size */
#ifdef __KERNEL_CUDA__
float data[15];
#else
float data[14];
#endif
} ShaderClosure;
@@ -697,11 +695,10 @@ enum ShaderDataFlag {
SD_AO = (1 << 8), /* have ao closure? */
SD_TRANSPARENT = (1 << 9), /* have transparent closure? */
SD_BSDF_NEEDS_LCG = (1 << 10),
SD_BSDF_HAS_CUSTOM = (1 << 11), /* are the custom variables relevant? */
SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF|
SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO|
SD_BSDF_NEEDS_LCG|SD_BSDF_HAS_CUSTOM),
SD_BSDF_NEEDS_LCG),
/* shader flags */
SD_USE_MIS = (1 << 12), /* direct light sample */
@@ -815,7 +812,9 @@ typedef ccl_addr_space struct ShaderData {
/* Closure data, we store a fixed array of closures */
ccl_soa_member(struct ShaderClosure, closure[MAX_CLOSURE]);
ccl_soa_member(int, num_closure);
ccl_soa_member(int, num_closure_extra);
ccl_soa_member(float, randb_closure);
ccl_soa_member(float3, svm_closure_weight);
/* LCG state for closures that require additional random numbers. */
ccl_soa_member(uint, lcg_state);

View File

@@ -25,7 +25,6 @@ set(SRC
)
set(HEADER_SRC
osl_bssrdf.h
osl_closures.h
osl_globals.h
osl_services.h

View File

@@ -36,6 +36,9 @@
#include "osl_closures.h"
#include "kernel_compat_cpu.h"
#include "closure/alloc.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
@@ -48,7 +51,10 @@ using namespace OSL;
///
class GenericBackgroundClosure : public CClosurePrimitive {
public:
GenericBackgroundClosure() : CClosurePrimitive(Background) {}
void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, weight);
}
};
/// Holdout closure
@@ -60,7 +66,11 @@ public:
///
class HoldoutClosure : CClosurePrimitive {
public:
HoldoutClosure () : CClosurePrimitive(Holdout) {}
void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, weight);
sd->flag |= SD_HOLDOUT;
}
};
/// ambient occlusion closure
@@ -71,7 +81,11 @@ public:
///
class AmbientOcclusionClosure : public CClosurePrimitive {
public:
AmbientOcclusionClosure () : CClosurePrimitive(AmbientOcclusion) {}
void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, weight);
sd->flag |= SD_AO;
}
};
ClosureParam *closure_background_params()

View File

@@ -39,6 +39,7 @@
#include "kernel_types.h"
#include "kernel_montecarlo.h"
#include "closure/alloc.h"
#include "closure/bsdf_diffuse_ramp.h"
CCL_NAMESPACE_BEGIN
@@ -47,51 +48,30 @@ using namespace OSL;
class DiffuseRampClosure : public CBSDFClosure {
public:
DiffuseRampBsdf params;
Color3 colors[8];
float3 fcolors[8];
DiffuseRampClosure() : CBSDFClosure(LABEL_DIFFUSE)
{}
void setup()
void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
sc.prim = this;
m_shaderdata_flag = bsdf_diffuse_ramp_setup(&sc);
DiffuseRampBsdf *bsdf = (DiffuseRampBsdf*)bsdf_alloc_osl(sd, sizeof(DiffuseRampBsdf), weight, &params);
for(int i = 0; i < 8; i++)
fcolors[i] = TO_FLOAT3(colors[i]);
}
if(bsdf) {
bsdf->colors = (float3*)closure_alloc_extra(sd, sizeof(float3)*8);
void blur(float roughness)
{
bsdf_diffuse_ramp_blur(&sc, roughness);
}
if(bsdf->colors) {
for(int i = 0; i < 8; i++)
bsdf->colors[i] = TO_FLOAT3(colors[i]);
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_diffuse_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
}
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_diffuse_ramp_eval_transmit(&sc, fcolors, omega_out, omega_in, &pdf);
}
int sample(const float3 &Ng,
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
float randu, float randv,
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
float &pdf, float3 &eval) const
{
return bsdf_diffuse_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy,
randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
sd->flag |= bsdf_diffuse_ramp_setup(bsdf);
}
}
}
};
ClosureParam *closure_bsdf_diffuse_ramp_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, sc.N),
CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, params.N),
CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8),
CLOSURE_STRING_KEYPARAM(DiffuseRampClosure, label, "label"),
CLOSURE_FINISH_PARAM(DiffuseRampClosure)

View File

@@ -38,6 +38,7 @@
#include "osl_closures.h"
#include "kernel_types.h"
#include "closure/alloc.h"
#include "closure/bsdf_phong_ramp.h"
CCL_NAMESPACE_BEGIN
@@ -46,52 +47,31 @@ using namespace OSL;
class PhongRampClosure : public CBSDFClosure {
public:
PhongRampBsdf params;
Color3 colors[8];
float3 fcolors[8];
PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY)
{}
void setup()
void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
sc.prim = this;
m_shaderdata_flag = bsdf_phong_ramp_setup(&sc);
PhongRampBsdf *bsdf = (PhongRampBsdf*)bsdf_alloc_osl(sd, sizeof(PhongRampBsdf), weight, &params);
for(int i = 0; i < 8; i++)
fcolors[i] = TO_FLOAT3(colors[i]);
}
if(bsdf) {
bsdf->colors = (float3*)closure_alloc_extra(sd, sizeof(float3)*8);
void blur(float roughness)
{
bsdf_phong_ramp_blur(&sc, roughness);
}
if(bsdf->colors) {
for(int i = 0; i < 8; i++)
bsdf->colors[i] = TO_FLOAT3(colors[i]);
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_phong_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
}
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
return bsdf_phong_ramp_eval_transmit(&sc, fcolors, omega_out, omega_in, &pdf);
}
int sample(const float3 &Ng,
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
float randu, float randv,
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
float &pdf, float3 &eval) const
{
return bsdf_phong_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy,
randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
sd->flag |= bsdf_phong_ramp_setup(bsdf);
}
}
}
};
ClosureParam *closure_bsdf_phong_ramp_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(PhongRampClosure, sc.N),
CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0),
CLOSURE_FLOAT3_PARAM(PhongRampClosure, params.N),
CLOSURE_FLOAT_PARAM(PhongRampClosure, params.exponent),
CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8),
CLOSURE_STRING_KEYPARAM(PhongRampClosure, label, "label"),
CLOSURE_FINISH_PARAM(PhongRampClosure)

View File

@@ -36,7 +36,9 @@
#include "osl_closures.h"
#include "kernel_compat_cpu.h"
#include "kernel_types.h"
#include "closure/alloc.h"
#include "closure/emissive.h"
CCL_NAMESPACE_BEGIN
@@ -52,25 +54,10 @@ using namespace OSL;
///
class GenericEmissiveClosure : public CClosurePrimitive {
public:
GenericEmissiveClosure() : CClosurePrimitive(Emissive) { }
Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
float3 result = emissive_simple_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
return TO_COLOR3(result);
}
void sample(const Vec3 &Ng, float randu, float randv,
Vec3 &omega_out, float &pdf) const
{
float3 omega_out_;
emissive_sample(TO_FLOAT3(Ng), randu, randv, &omega_out_, &pdf);
omega_out = TO_VEC3(omega_out_);
}
float pdf(const Vec3 &Ng, const Vec3 &omega_out) const
{
return emissive_pdf(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, weight);
sd->flag |= SD_EMISSION;
}
};

View File

@@ -30,17 +30,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "kernel_compat_cpu.h"
#include "osl_bssrdf.h"
#include "osl_closures.h"
#include "kernel_types.h"
#include "kernel_montecarlo.h"
#include "closure/alloc.h"
#include "closure/bsdf_diffuse.h"
#include "closure/bssrdf.h"
@@ -48,27 +46,83 @@ CCL_NAMESPACE_BEGIN
using namespace OSL;
class CBSSRDFClosure : public CClosurePrimitive {
public:
Bssrdf params;
float3 radius;
float3 albedo;
void alloc(ShaderData *sd, int path_flag, float3 weight, ClosureType type)
{
float sample_weight = fabsf(average(weight));
/* disable in case of diffuse ancestor, can't see it well then and
* adds considerably noise due to probabilities of continuing path
* getting lower and lower */
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
radius = make_float3(0.0f, 0.0f, 0.0f);
}
if(sample_weight > CLOSURE_WEIGHT_CUTOFF) {
/* sharpness */
float sharpness = params.sharpness;
/* texture color blur */
float texture_blur = params.texture_blur;
/* create one closure per color channel */
Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(weight.x, 0.0f, 0.0f));
if(bssrdf) {
bssrdf->sample_weight = sample_weight;
bssrdf->radius = radius.x;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.x;
bssrdf->sharpness = sharpness;
bssrdf->N = params.N;
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, weight.y, 0.0f));
if(bssrdf) {
bssrdf->sample_weight = sample_weight;
bssrdf->radius = radius.y;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.y;
bssrdf->sharpness = sharpness;
bssrdf->N = params.N;
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, weight.z));
if(bssrdf) {
bssrdf->sample_weight = sample_weight;
bssrdf->radius = radius.z;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.z;
bssrdf->sharpness = sharpness;
bssrdf->N = params.N;
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
}
}
};
/* Cubic */
class CubicBSSRDFClosure : public CBSSRDFClosure {
public:
CubicBSSRDFClosure()
{}
void setup()
void setup(ShaderData *sd, int path_flag, float3 weight)
{
sc.type = CLOSURE_BSSRDF_CUBIC_ID;
sc.data0 = fabsf(average(radius));
alloc(sd, path_flag, weight, CLOSURE_BSSRDF_CUBIC_ID);
}
};
ClosureParam *closure_bssrdf_cubic_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, sc.N),
CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, params.N),
CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, radius),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.data1),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.T.x),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, params.texture_blur),
CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, params.sharpness),
CLOSURE_STRING_KEYPARAM(CubicBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(CubicBSSRDFClosure)
};
@@ -81,22 +135,18 @@ CCLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
class GaussianBSSRDFClosure : public CBSSRDFClosure {
public:
GaussianBSSRDFClosure()
{}
void setup()
void setup(ShaderData *sd, int path_flag, float3 weight)
{
sc.type = CLOSURE_BSSRDF_GAUSSIAN_ID;
sc.data0 = fabsf(average(radius));
alloc(sd, path_flag, weight, CLOSURE_BSSRDF_GAUSSIAN_ID);
}
};
ClosureParam *closure_bssrdf_gaussian_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, sc.N),
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, params.N),
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, radius),
CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, sc.data1),
CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, params.texture_blur),
CLOSURE_STRING_KEYPARAM(GaussianBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
};
@@ -109,22 +159,18 @@ CCLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
class BurleyBSSRDFClosure : public CBSSRDFClosure {
public:
BurleyBSSRDFClosure()
{}
void setup()
void setup(ShaderData *sd, int path_flag, float3 weight)
{
sc.type = CLOSURE_BSSRDF_BURLEY_ID;
sc.data0 = fabsf(average(radius));
alloc(sd, path_flag, weight, CLOSURE_BSSRDF_BURLEY_ID);
}
};
ClosureParam *closure_bssrdf_burley_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, sc.N),
CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, params.N),
CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, radius),
CLOSURE_FLOAT_PARAM(BurleyBSSRDFClosure, sc.data1),
CLOSURE_FLOAT_PARAM(BurleyBSSRDFClosure, params.texture_blur),
CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, albedo),
CLOSURE_STRING_KEYPARAM(BurleyBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(BurleyBSSRDFClosure)

View File

@@ -1,61 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __OSL_BSSRDF_H__
#define __OSL_BSSRDF_H__
#include <OSL/oslclosure.h>
#include <OSL/oslexec.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "kernel_types.h"
#include "util_types.h"
CCL_NAMESPACE_BEGIN
class CBSSRDFClosure : public CClosurePrimitive {
public:
ShaderClosure sc;
float3 radius;
float3 albedo;
CBSSRDFClosure() : CClosurePrimitive(BSSRDF) { }
int scattering() const { return LABEL_DIFFUSE; }
};
CCL_NAMESPACE_END
#endif /* __OSL_BSSRDF_H__ */

View File

@@ -46,6 +46,7 @@
#include "kernel_montecarlo.h"
#include "kernel_random.h"
#include "closure/alloc.h"
#include "closure/bsdf_util.h"
#include "closure/bsdf_ashikhmin_velvet.h"
#include "closure/bsdf_diffuse.h"
@@ -66,112 +67,112 @@ using namespace OSL;
/* BSDF class definitions */
BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, diffuse, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(DiffuseClosure, sc.N),
BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, DiffuseBsdf, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
BSDF_CLOSURE_CLASS_END(Diffuse, diffuse)
BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, translucent, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(TranslucentClosure, sc.N),
BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, DiffuseBsdf, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(TranslucentClosure, params.N),
BSDF_CLOSURE_CLASS_END(Translucent, translucent)
BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, oren_nayar, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(OrenNayarClosure, sc.N),
CLOSURE_FLOAT_PARAM(OrenNayarClosure, sc.data0),
BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, OrenNayarBsdf, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(OrenNayarClosure, params.N),
CLOSURE_FLOAT_PARAM(OrenNayarClosure, params.roughness),
BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar)
BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, reflection, LABEL_SINGULAR)
CLOSURE_FLOAT3_PARAM(ReflectionClosure, sc.N),
BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, MicrofacetBsdf, LABEL_SINGULAR)
CLOSURE_FLOAT3_PARAM(ReflectionClosure, params.N),
BSDF_CLOSURE_CLASS_END(Reflection, reflection)
BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR)
CLOSURE_FLOAT3_PARAM(RefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0),
BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, MicrofacetBsdf, LABEL_SINGULAR)
CLOSURE_FLOAT3_PARAM(RefractionClosure, params.N),
CLOSURE_FLOAT_PARAM(RefractionClosure, params.ior),
BSDF_CLOSURE_CLASS_END(Refraction, refraction)
BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR)
BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, ShaderClosure, LABEL_SINGULAR)
BSDF_CLOSURE_CLASS_END(Transparent, transparent)
BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, sc.N),
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0),
BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, VelvetBsdf, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, params.N),
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, params.sigma),
BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley_aniso, ashikhmin_shirley, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.N),
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.T),
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, sc.data0),
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, sc.data1),
BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N),
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T),
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y),
BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley_aniso)
BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, diffuse_toon, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, sc.N),
CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data0),
CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data1),
BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE)
CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N),
CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.size),
CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.smooth),
BSDF_CLOSURE_CLASS_END(DiffuseToon, diffuse_toon)
BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, glossy_toon, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(GlossyToonClosure, sc.N),
CLOSURE_FLOAT_PARAM(GlossyToonClosure, sc.data0),
CLOSURE_FLOAT_PARAM(GlossyToonClosure, sc.data1),
BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, ToonBsdf, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(GlossyToonClosure, params.N),
CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.size),
CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth),
BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0),
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x),
BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso, microfacet_ggx_aniso, microfacet_ggx, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.N),
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.T),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data1),
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso, microfacet_ggx_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.N),
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.T),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_y),
BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0),
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso, microfacet_beckmann_aniso, microfacet_beckmann, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.N),
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.T),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data1),
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso, microfacet_beckmann_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.N),
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.T),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_y),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY|LABEL_TRANSMIT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data2),
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, MicrofacetBsdf, LABEL_GLOSSY|LABEL_TRANSMIT)
CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, params.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.ior),
BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY|LABEL_TRANSMIT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data2),
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, MicrofacetBsdf, LABEL_GLOSSY|LABEL_TRANSMIT)
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, params.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.ior),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, hair_reflection, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1),
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data2),
BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, unused),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness1),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness2),
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection)
BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, hair_transmission, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, sc.N),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data1),
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data2),
BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY)
CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, unused),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness1),
CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness2),
CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
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_BEGIN(VolumeHenyeyGreenstein, henyey_greenstein, HenyeyGreensteinVolume, LABEL_VOLUME_SCATTER)
CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, params.g),
VOLUME_CLOSURE_CLASS_END(VolumeHenyeyGreenstein, henyey_greenstein)
VOLUME_CLOSURE_CLASS_BEGIN(VolumeAbsorption, absorption, LABEL_SINGULAR)
VOLUME_CLOSURE_CLASS_BEGIN(VolumeAbsorption, absorption, ShaderClosure, LABEL_SINGULAR)
VOLUME_CLOSURE_CLASS_END(VolumeAbsorption, absorption)
/* Registration */
@@ -258,69 +259,64 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
volume_absorption_params(), volume_absorption_prepare);
}
/* BSDF Closure */
bool CBSDFClosure::skip(const ShaderData *sd, int path_flag, int scattering)
{
/* caustic options */
if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
KernelGlobals *kg = sd->osl_globals;
if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
(!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT)))
{
return true;
}
}
return false;
}
/* Multiscattering GGX closures */
class MicrofacetMultiClosure : public CBSDFClosure {
public:
MicrofacetBsdf params;
float3 color;
/* Technically, the MultiGGX Glass closure may also transmit.
* However, since this is set statically and only used for caustic flags, this is probably as good as it gets. */
MicrofacetMultiClosure() : CBSDFClosure(LABEL_GLOSSY|LABEL_REFLECT)
MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
{
}
/* Technically, the MultiGGX Glass closure may also transmit. However,
* since this is set statically and only used for caustic flags, this
* is probably as good as it gets. */
if(!skip(sd, path_flag, LABEL_GLOSSY|LABEL_REFLECT)) {
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->extra = extra;
bsdf->extra->color = color;
return bsdf;
}
}
void setup()
{
sc.prim = NULL;
sc.custom1 = color.x;
sc.custom2 = color.y;
sc.custom3 = color.z;
}
void blur(float roughness)
{
}
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
{
pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}
int sample(const float3 &Ng,
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
float randu, float randv,
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
float &pdf, float3 &eval) const
{
pdf = 0;
return LABEL_NONE;
return NULL;
}
};
class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure {
public:
MicrofacetMultiGGXClosure() : MicrofacetMultiClosure() {}
void setup()
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetMultiClosure::setup();
m_shaderdata_flag = bsdf_microfacet_multi_ggx_setup(&sc);
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_setup(bsdf) : 0;
}
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data0),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
@@ -331,22 +327,20 @@ CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_prepare, MicrofacetMultiGGXCl
class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure {
public:
MicrofacetMultiGGXAnisoClosure() : MicrofacetMultiClosure() {}
void setup()
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetMultiClosure::setup();
m_shaderdata_flag = bsdf_microfacet_multi_ggx_aniso_setup(&sc);
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_aniso_setup(bsdf) : 0;
}
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.N),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.T),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data1),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.T),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_y),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
@@ -359,19 +353,19 @@ class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure {
public:
MicrofacetMultiGGXGlassClosure() : MicrofacetMultiClosure() {}
void setup()
void setup(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetMultiClosure::setup();
m_shaderdata_flag = bsdf_microfacet_multi_ggx_glass_setup(&sc);
MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_glass_setup(bsdf) : 0;
}
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data2),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.ior),
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)

View File

@@ -90,21 +90,7 @@ void name(RendererServices *, int id, void *data) \
class CClosurePrimitive {
public:
enum Category {
BSDF, ///< Reflective and/or transmissive surface
BSSRDF, ///< Sub-surface light transfer
Emissive, ///< Light emission
Background, ///< Background emission
Volume, ///< Volume scattering
Holdout, ///< Holdout from alpha
AmbientOcclusion, ///< Ambient occlusion
};
CClosurePrimitive (Category category_) : category (category_) {}
virtual ~CClosurePrimitive() {}
virtual void setup() {}
Category category;
virtual void setup(ShaderData *sd, int path_flag, float3 weight) = 0;
OSL::ustring label;
};
@@ -113,68 +99,22 @@ public:
class CBSDFClosure : public CClosurePrimitive {
public:
ShaderClosure sc;
CBSDFClosure(int scattering) : CClosurePrimitive(BSDF),
m_scattering_label(scattering), m_shaderdata_flag(0)
{}
int scattering() const { return m_scattering_label; }
int shaderdata_flag() const { return m_shaderdata_flag; }
virtual void blur(float roughness) = 0;
virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0;
virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0;
virtual int sample(const float3 &Ng,
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
float randu, float randv,
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
float &pdf, float3 &eval) const = 0;
protected:
int m_scattering_label;
int m_shaderdata_flag;
bool skip(const ShaderData *sd, int path_flag, int scattering);
};
#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, svmlower, TYPE) \
#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, structname, TYPE) \
\
class Upper##Closure : public CBSDFClosure { \
public: \
Upper##Closure() : CBSDFClosure(TYPE) \
{ \
} \
structname params; \
float3 unused; \
\
void setup() \
void setup(ShaderData *sd, int path_flag, float3 weight) \
{ \
sc.prim = NULL; \
m_shaderdata_flag = bsdf_##lower##_setup(&sc); \
} \
\
void blur(float roughness) \
{ \
} \
\
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
pdf = 0.0f; \
return make_float3(0.0f, 0.0f, 0.0f); \
} \
\
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
pdf = 0.0f; \
return make_float3(0.0f, 0.0f, 0.0f); \
} \
\
int sample(const float3 &Ng, \
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, \
float randu, float randv, \
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, \
float &pdf, float3 &eval) const \
{ \
pdf = 0; \
return LABEL_NONE; \
if(!skip(sd, path_flag, TYPE)) { \
structname *bsdf = (structname*)bsdf_alloc_osl(sd, sizeof(structname), weight, &params); \
sd->flag |= (bsdf) ? bsdf_##lower##_setup(bsdf) : 0; \
} \
} \
}; \
\
@@ -193,36 +133,18 @@ 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)
{}
~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) \
#define VOLUME_CLOSURE_CLASS_BEGIN(Upper, lower, structname, TYPE) \
\
class Upper##Closure : public CVolumeClosure { \
class Upper##Closure : public CBSDFClosure { \
public: \
Upper##Closure() : CVolumeClosure(TYPE) {} \
structname params; \
\
void setup() \
void setup(ShaderData *sd, int path_flag, float3 weight) \
{ \
sc.prim = NULL; \
m_shaderdata_flag = volume_##lower##_setup(&sc); \
structname *volume = (structname*)bsdf_alloc_osl(sd, sizeof(structname), weight, &params); \
sd->flag |= (volume) ? volume_##lower##_setup(volume) : 0; \
} \
}; \
\

View File

@@ -23,10 +23,6 @@
#include "geom/geom_object.h"
#include "closure/bsdf_diffuse.h"
#include "closure/bssrdf.h"
#include "osl_bssrdf.h"
#include "osl_closures.h"
#include "osl_globals.h"
#include "osl_services.h"
@@ -141,8 +137,10 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, PathS
/* Surface */
static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
static void flatten_surface_closure_tree(ShaderData *sd,
int path_flag,
const OSL::ClosureColor *closure,
float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
/* OSL gives us a closure tree, we flatten it into arrays per
* closure type, for evaluation, sampling, etc later on. */
@@ -164,164 +162,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if(prim) {
ShaderClosure sc;
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
weight = weight*TO_FLOAT3(comp->w);
#endif
sc.weight = weight;
prim->setup();
switch(prim->category) {
case CClosurePrimitive::BSDF: {
CBSDFClosure *bsdf = (CBSDFClosure *)prim;
int scattering = bsdf->scattering();
int shaderdata_flag = bsdf->shaderdata_flag();
/* caustic options */
if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
KernelGlobals *kg = sd->osl_globals;
if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
(!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT)))
{
return;
}
}
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = bsdf->sc.type;
sc.N = bsdf->sc.N;
sc.T = bsdf->sc.T;
sc.data0 = bsdf->sc.data0;
sc.data1 = bsdf->sc.data1;
sc.data2 = bsdf->sc.data2;
sc.prim = bsdf->sc.prim;
if(shaderdata_flag & SD_BSDF_HAS_CUSTOM) {
sc.custom1 = bsdf->sc.custom1;
sc.custom2 = bsdf->sc.custom2;
sc.custom3 = bsdf->sc.custom3;
}
/* add */
if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
sd->flag |= shaderdata_flag;
}
break;
}
case CClosurePrimitive::Emissive: {
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = CLOSURE_EMISSION_ID;
sc.data0 = 0.0f;
sc.data1 = 0.0f;
sc.data2 = 0.0f;
sc.prim = NULL;
/* flag */
if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
sd->flag |= SD_EMISSION;
}
break;
}
case CClosurePrimitive::AmbientOcclusion: {
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
sc.data0 = 0.0f;
sc.data1 = 0.0f;
sc.data2 = 0.0f;
sc.prim = NULL;
if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
sd->flag |= SD_AO;
}
break;
}
case CClosurePrimitive::Holdout: {
sc.sample_weight = 0.0f;
sc.type = CLOSURE_HOLDOUT_ID;
sc.data0 = 0.0f;
sc.data1 = 0.0f;
sc.data2 = 0.0f;
sc.prim = NULL;
if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
sd->flag |= SD_HOLDOUT;
}
break;
}
case CClosurePrimitive::BSSRDF: {
CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
float sample_weight = fabsf(average(weight));
if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
sc.sample_weight = sample_weight;
sc.type = bssrdf->sc.type;
sc.N = bssrdf->sc.N;
sc.data1 = bssrdf->sc.data1;
sc.T.x = bssrdf->sc.T.x;
sc.prim = NULL;
/* disable in case of diffuse ancestor, can't see it well then and
* adds considerably noise due to probabilities of continuing path
* getting lower and lower */
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
float3 albedo =
(bssrdf->sc.type == CLOSURE_BSSRDF_BURLEY_ID)
? bssrdf->albedo
: make_float3(0.0f, 0.0f, 0.0f);
/* create one closure for each color channel */
if(fabsf(weight.x) > 0.0f) {
sc.weight = make_float3(weight.x, 0.0f, 0.0f);
sc.data0 = bssrdf->radius.x;
sc.data1 = 0.0f;
sc.data2 = albedo.x;
sd->flag |= bssrdf_setup(&sc, sc.type);
sd->closure[sd->num_closure++] = sc;
}
if(fabsf(weight.y) > 0.0f) {
sc.weight = make_float3(0.0f, weight.y, 0.0f);
sc.data0 = bssrdf->radius.y;
sc.data1 = 0.0f;
sc.data2 = albedo.y;
sd->flag |= bssrdf_setup(&sc, sc.type);
sd->closure[sd->num_closure++] = sc;
}
if(fabsf(weight.z) > 0.0f) {
sc.weight = make_float3(0.0f, 0.0f, weight.z);
sc.data0 = bssrdf->radius.z;
sc.data1 = 0.0f;
sc.data2 = albedo.z;
sd->flag |= bssrdf_setup(&sc, sc.type);
sd->closure[sd->num_closure++] = sc;
}
}
break;
}
case CClosurePrimitive::Background:
case CClosurePrimitive::Volume:
break; /* not relevant */
}
prim->setup(sd, path_flag, weight);
}
break;
}
@@ -351,7 +195,9 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state
/* Background */
static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
static void flatten_background_closure_tree(ShaderData *sd,
const OSL::ClosureColor *closure,
float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
/* OSL gives us a closure tree, if we are shading for background there
* is only one supported closure type at the moment, which has no evaluation
@@ -360,32 +206,32 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
switch(closure->id) {
case OSL::ClosureColor::MUL: {
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
flatten_background_closure_tree(sd, mul->closure, weight * TO_FLOAT3(mul->weight));
break;
}
case OSL::ClosureColor::ADD: {
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
return flatten_background_closure_tree(add->closureA) +
flatten_background_closure_tree(add->closureB);
flatten_background_closure_tree(sd, add->closureA, weight);
flatten_background_closure_tree(sd, add->closureB, weight);
break;
}
default: {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if(prim && prim->category == CClosurePrimitive::Background)
if(prim) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
return TO_FLOAT3(comp->w);
#else
return make_float3(1.0f, 1.0f, 1.0f);
weight = weight*TO_FLOAT3(comp->w);
#endif
prim->setup(sd, 0, weight);
}
break;
}
}
return make_float3(0.0f, 0.0f, 0.0f);
}
float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx)
void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx)
{
/* setup shader globals from shader data */
OSLThreadData *tdata = kg->osl_tdata;
@@ -402,15 +248,14 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *
/* return background color immediately */
if(globals->Ci)
return flatten_background_closure_tree(globals->Ci);
return make_float3(0.0f, 0.0f, 0.0f);
flatten_background_closure_tree(sd, globals->Ci);
}
/* Volume */
static void flatten_volume_closure_tree(ShaderData *sd,
const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
const OSL::ClosureColor *closure,
float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
/* OSL gives us a closure tree, we flatten it into arrays per
* closure type, for evaluation, sampling, etc later on. */
@@ -432,60 +277,10 @@ static void flatten_volume_closure_tree(ShaderData *sd,
CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if(prim) {
ShaderClosure sc;
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
weight = weight*TO_FLOAT3(comp->w);
#endif
sc.weight = weight;
prim->setup();
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 = volume->sc.type;
sc.data0 = volume->sc.data0;
sc.data1 = volume->sc.data1;
/* add */
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::Emissive: {
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = CLOSURE_EMISSION_ID;
sc.data0 = 0.0f;
sc.data1 = 0.0f;
sc.prim = NULL;
/* flag */
if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
sd->flag |= SD_EMISSION;
}
break;
}
case CClosurePrimitive::Holdout:
break; /* not implemented */
case CClosurePrimitive::Background:
case CClosurePrimitive::BSDF:
case CClosurePrimitive::BSSRDF:
case CClosurePrimitive::AmbientOcclusion:
break; /* not relevant */
}
prim->setup(sd, 0, weight);
}
}
}
@@ -537,40 +332,6 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte
sd->P = TO_FLOAT3(globals->P);
}
/* BSDF Closure */
int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
{
CBSDFClosure *sample_bsdf = (CBSDFClosure *)sc->prim;
pdf = 0.0f;
return sample_bsdf->sample(sd->Ng,
sd->I, sd->dI.dx, sd->dI.dy,
randu, randv,
omega_in, domega_in.dx, domega_in.dy,
pdf, eval);
}
float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
{
CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
float3 bsdf_eval;
if(dot(sd->Ng, omega_in) >= 0.0f)
bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf);
else
bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf);
return bsdf_eval;
}
void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness)
{
CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
bsdf->blur(roughness);
}
/* Attributes */
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)

View File

@@ -54,18 +54,10 @@ public:
/* eval */
static void eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
static float3 eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
static void eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
static void eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx);
/* sample & eval */
static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
float randu, float randv,
float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
const float3& omega_in, float& pdf);
static void bsdf_blur(ShaderClosure *sc, float roughness);
/* attributes */
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
};

View File

@@ -18,104 +18,44 @@ CCL_NAMESPACE_BEGIN
/* Closure Nodes */
ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
ccl_device void svm_node_glass_setup(ShaderData *sd, MicrofacetBsdf *bsdf, int type, float eta, float roughness, bool refract)
{
if(type == CLOSURE_BSDF_SHARP_GLASS_ID) {
if(refract) {
sc->data0 = eta;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc);
bsdf->alpha_y = 0.0f;
bsdf->alpha_x = 0.0f;
bsdf->ior = eta;
ccl_fetch(sd, flag) |= bsdf_refraction_setup(bsdf);
}
else {
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc);
bsdf->alpha_y = 0.0f;
bsdf->alpha_x = 0.0f;
bsdf->ior = 0.0f;
ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
}
}
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
sc->data0 = roughness;
sc->data1 = roughness;
sc->data2 = eta;
bsdf->alpha_x = roughness;
bsdf->alpha_y = roughness;
bsdf->ior = eta;
if(refract)
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
else
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(bsdf);
}
else {
sc->data0 = roughness;
sc->data1 = roughness;
sc->data2 = eta;
bsdf->alpha_x = roughness;
bsdf->alpha_y = roughness;
bsdf->ior = eta;
if(refract)
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
else
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf);
}
}
ccl_device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, ClosureType type, float mix_weight)
{
ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
sc->weight *= mix_weight;
sc->type = type;
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
#ifdef __OSL__
sc->prim = NULL;
#endif
ccl_fetch(sd, num_closure)++;
return sc;
}
return NULL;
}
ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float mix_weight)
{
ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
float3 weight = sc->weight * mix_weight;
float sample_weight = fabsf(average(weight));
if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
sc->weight = weight;
sc->sample_weight = sample_weight;
ccl_fetch(sd, num_closure)++;
#ifdef __OSL__
sc->prim = NULL;
#endif
return sc;
}
return NULL;
}
ccl_device_inline ShaderClosure *svm_node_closure_get_absorption(ShaderData *sd, float mix_weight)
{
ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - sc->weight) * mix_weight;
float sample_weight = fabsf(average(weight));
if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
sc->weight = weight;
sc->sample_weight = sample_weight;
ccl_fetch(sd, num_closure)++;
#ifdef __OSL__
sc->prim = NULL;
#endif
return sc;
}
return NULL;
}
ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag, int *offset)
{
uint type, param1_offset, param2_offset;
@@ -137,49 +77,40 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
switch(type) {
case CLOSURE_BSDF_DIFFUSE_ID: {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
if(sc) {
sc->N = N;
if(bsdf) {
bsdf->N = N;
float roughness = param1;
if(roughness == 0.0f) {
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
ccl_fetch(sd, flag) |= bsdf_diffuse_setup(sc);
ccl_fetch(sd, flag) |= bsdf_diffuse_setup((DiffuseBsdf*)bsdf);
}
else {
sc->data0 = roughness;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
ccl_fetch(sd, flag) |= bsdf_oren_nayar_setup(sc);
bsdf->roughness = roughness;
ccl_fetch(sd, flag) |= bsdf_oren_nayar_setup(bsdf);
}
}
break;
}
case CLOSURE_BSDF_TRANSLUCENT_ID: {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
if(sc) {
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
sc->N = N;
ccl_fetch(sd, flag) |= bsdf_translucent_setup(sc);
if(bsdf) {
bsdf->N = N;
ccl_fetch(sd, flag) |= bsdf_translucent_setup(bsdf);
}
break;
}
case CLOSURE_BSDF_TRANSPARENT_ID: {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
if(sc) {
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
sc->N = N;
ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc);
if(bsdf) {
ccl_fetch(sd, flag) |= bsdf_transparent_setup(bsdf);
}
break;
}
@@ -192,31 +123,33 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
if(sc) {
sc->N = N;
sc->data0 = param1;
sc->data1 = param1;
sc->data2 = 0.0f;
if(bsdf) {
bsdf->N = N;
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
bsdf->ior = 0.0f;
bsdf->extra = NULL;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID)
ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc);
ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
kernel_assert(stack_valid(data_node.z));
float3 color = stack_load_float3(stack, data_node.z);
sc->custom1 = color.x;
sc->custom2 = color.y;
sc->custom3 = color.z;
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_setup(sc);
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf->extra) {
bsdf->extra->color = stack_load_float3(stack, data_node.z);
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_setup(bsdf);
}
}
else
ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(sc);
ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(bsdf);
}
break;
@@ -228,31 +161,33 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
if(sc) {
sc->N = N;
if(bsdf) {
bsdf->N = N;
bsdf->extra = NULL;
float eta = fmaxf(param2, 1e-5f);
eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFRACTION_ID) {
sc->data0 = eta;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
bsdf->alpha_x = 0.0f;
bsdf->alpha_y = 0.0f;
bsdf->ior = eta;
ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc);
ccl_fetch(sd, flag) |= bsdf_refraction_setup(bsdf);
}
else {
sc->data0 = param1;
sc->data1 = param1;
sc->data2 = eta;
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
bsdf->ior = eta;
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
else
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
}
@@ -268,7 +203,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
}
#endif
int num_closure = ccl_fetch(sd, num_closure);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
/* index of refraction */
float eta = fmaxf(param2, 1e-5f);
@@ -280,37 +215,30 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float roughness = param1;
/* reflection */
ShaderClosure *sc = ccl_fetch_array(sd, closure, num_closure);
float3 weight = sc->weight;
float sample_weight = sc->sample_weight;
sc = svm_node_closure_get_bsdf(sd, mix_weight*fresnel);
#ifdef __CAUSTICS_TRICKS__
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
if(sc) {
sc->N = N;
svm_node_glass_setup(sd, sc, type, eta, roughness, false);
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight*fresnel);
if(bsdf) {
bsdf->N = N;
bsdf->extra = NULL;
svm_node_glass_setup(sd, bsdf, type, eta, roughness, false);
}
}
#ifdef __CAUSTICS_TRICKS__
if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
/* refraction */
if(num_closure + 1 < MAX_CLOSURE) {
sc = ccl_fetch_array(sd, closure, num_closure + 1);
sc->weight = weight;
sc->sample_weight = sample_weight;
#ifdef __CAUSTICS_TRICKS__
if(kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight*(1.0f - fresnel));
sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel));
if(sc) {
sc->N = N;
svm_node_glass_setup(sd, sc, type, eta, roughness, true);
if(bsdf) {
bsdf->N = N;
bsdf->extra = NULL;
svm_node_glass_setup(sd, bsdf, type, eta, roughness, true);
}
}
@@ -321,24 +249,25 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_reflective && !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(sc) {
sc->N = N;
if(bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
sc->data0 = param1;
sc->data1 = param1;
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
float eta = fmaxf(param2, 1e-5f);
sc->data2 = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
bsdf->ior = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
kernel_assert(stack_valid(data_node.z));
float3 color = stack_load_float3(stack, data_node.z);
sc->custom1 = color.x;
sc->custom2 = color.y;
sc->custom3 = color.z;
bsdf->extra->color = stack_load_float3(stack, data_node.z);
/* setup bsdf */
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(sc);
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
}
break;
@@ -351,62 +280,63 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
if(sc) {
sc->N = N;
sc->T = stack_load_float3(stack, data_node.y);
if(bsdf) {
bsdf->N = N;
bsdf->extra = NULL;
bsdf->T = stack_load_float3(stack, data_node.y);
/* rotate tangent */
float rotation = stack_load_float(stack, data_node.z);
if(rotation != 0.0f)
sc->T = rotate_around_axis(sc->T, sc->N, rotation * M_2PI_F);
bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
/* compute roughness */
float roughness = param1;
float anisotropy = clamp(param2, -0.99f, 0.99f);
if(anisotropy < 0.0f) {
sc->data0 = roughness/(1.0f + anisotropy);
sc->data1 = roughness*(1.0f + anisotropy);
bsdf->alpha_x = roughness/(1.0f + anisotropy);
bsdf->alpha_y = roughness*(1.0f + anisotropy);
}
else {
sc->data0 = roughness*(1.0f - anisotropy);
sc->data1 = roughness/(1.0f - anisotropy);
bsdf->alpha_x = roughness*(1.0f - anisotropy);
bsdf->alpha_y = roughness/(1.0f - anisotropy);
}
sc->data2 = 0.0f;
bsdf->ior = 0.0f;
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID)
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(sc);
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID)
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(sc);
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
}
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(bsdf);
}
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
kernel_assert(stack_valid(data_node.w));
float3 color = stack_load_float3(stack, data_node.w);
sc->custom1 = color.x;
sc->custom2 = color.y;
sc->custom3 = color.z;
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(sc);
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf->extra) {
bsdf->extra->color = stack_load_float3(stack, data_node.w);
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
}
}
else
ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(sc);
ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
}
break;
}
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
VelvetBsdf *bsdf = (VelvetBsdf*)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
if(sc) {
sc->N = N;
if(bsdf) {
bsdf->N = N;
/* sigma */
sc->data0 = saturate(param1);
sc->data1 = 0.0f;
sc->data2 = 0.0f;
ccl_fetch(sd, flag) |= bsdf_ashikhmin_velvet_setup(sc);
bsdf->sigma = saturate(param1);
ccl_fetch(sd, flag) |= bsdf_ashikhmin_velvet_setup(bsdf);
}
break;
}
@@ -416,68 +346,62 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
#endif
case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
ToonBsdf *bsdf = (ToonBsdf*)bsdf_alloc(sd, sizeof(ToonBsdf), weight);
if(sc) {
/* Normal, Size and Smooth */
sc->N = N;
sc->data0 = param1;
sc->data1 = param2;
sc->data2 = 0.0f;
if(bsdf) {
bsdf->N = N;
bsdf->size = param1;
bsdf->smooth = param2;
if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
ccl_fetch(sd, flag) |= bsdf_diffuse_toon_setup(sc);
ccl_fetch(sd, flag) |= bsdf_diffuse_toon_setup(bsdf);
else
ccl_fetch(sd, flag) |= bsdf_glossy_toon_setup(sc);
ccl_fetch(sd, flag) |= bsdf_glossy_toon_setup(bsdf);
}
break;
}
#ifdef __HAIR__
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
if(ccl_fetch(sd, flag) & SD_BACKFACING && ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
if(sc) {
if(bsdf) {
/* todo: giving a fixed weight here will cause issues when
* mixing multiple BSDFS. energy will not be conserved and
* the throughput can blow up after multiple bounces. we
* better figure out a way to skip backfaces from rays
* spawned by transmission from the front */
sc->weight = make_float3(1.0f, 1.0f, 1.0f);
sc->N = N;
sc->data0 = 0.0f;
sc->data1 = 0.0f;
sc->data2 = 0.0f;
ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc);
bsdf->weight = make_float3(1.0f, 1.0f, 1.0f);
ccl_fetch(sd, flag) |= bsdf_transparent_setup(bsdf);
}
}
else {
ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
sc = svm_node_closure_get_bsdf(sd, mix_weight);
HairBsdf *bsdf = (HairBsdf*)bsdf_alloc(sd, sizeof(HairBsdf), weight);
if(sc) {
sc->N = N;
sc->data0 = param1;
sc->data1 = param2;
sc->data2 = -stack_load_float(stack, data_node.z);
if(bsdf) {
bsdf->roughness1 = param1;
bsdf->roughness2 = param2;
bsdf->offset = -stack_load_float(stack, data_node.z);
if(stack_valid(data_node.y)) {
sc->T = normalize(stack_load_float3(stack, data_node.y));
bsdf->T = normalize(stack_load_float3(stack, data_node.y));
}
else if(!(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)) {
sc->T = normalize(ccl_fetch(sd, dPdv));
sc->data2 = 0.0f;
bsdf->T = normalize(ccl_fetch(sd, dPdv));
bsdf->offset = 0.0f;
}
else
sc->T = normalize(ccl_fetch(sd, dPdu));
bsdf->T = normalize(ccl_fetch(sd, dPdu));
if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
ccl_fetch(sd, flag) |= bsdf_hair_reflection_setup(sc);
ccl_fetch(sd, flag) |= bsdf_hair_reflection_setup(bsdf);
}
else {
ccl_fetch(sd, flag) |= bsdf_hair_transmission_setup(sc);
ccl_fetch(sd, flag) |= bsdf_hair_transmission_setup(bsdf);
}
}
}
@@ -487,17 +411,11 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
#ifdef __SUBSURFACE__
# ifndef __SPLIT_KERNEL__
# define sc_next(sc) sc++
# else
# define sc_next(sc) sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure))
# endif
case CLOSURE_BSSRDF_CUBIC_ID:
case CLOSURE_BSSRDF_GAUSSIAN_ID:
case CLOSURE_BSSRDF_BURLEY_ID: {
ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
float3 albedo = sc->weight;
float3 weight = sc->weight * mix_weight;
float3 albedo = ccl_fetch(sd, svm_closure_weight);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
float sample_weight = fabsf(average(weight));
/* disable in case of diffuse ancestor, can't see it well then and
@@ -506,7 +424,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 > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure)+2 < MAX_CLOSURE) {
if(sample_weight > CLOSURE_WEIGHT_CUTOFF) {
/* radius * scale */
float3 radius = stack_load_float3(stack, data_node.z)*param1;
/* sharpness */
@@ -515,61 +433,42 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float texture_blur = param2;
/* create one closure per color channel */
if(fabsf(weight.x) > 0.0f) {
sc->weight = make_float3(weight.x, 0.0f, 0.0f);
sc->sample_weight = sample_weight;
sc->data0 = radius.x;
sc->data1 = texture_blur;
sc->data2 = albedo.x;
sc->T.x = sharpness;
# ifdef __OSL__
sc->prim = NULL;
# endif
sc->N = N;
ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
ccl_fetch(sd, num_closure)++;
sc_next(sc);
Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(weight.x, 0.0f, 0.0f));
if(bssrdf) {
bssrdf->sample_weight = sample_weight;
bssrdf->radius = radius.x;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.x;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
if(fabsf(weight.y) > 0.0f) {
sc->weight = make_float3(0.0f, weight.y, 0.0f);
sc->sample_weight = sample_weight;
sc->data0 = radius.y;
sc->data1 = texture_blur;
sc->data2 = albedo.y;
sc->T.x = sharpness;
# ifdef __OSL__
sc->prim = NULL;
# endif
sc->N = N;
ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
ccl_fetch(sd, num_closure)++;
sc_next(sc);
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, weight.y, 0.0f));
if(bssrdf) {
bssrdf->sample_weight = sample_weight;
bssrdf->radius = radius.y;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.y;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
if(fabsf(weight.z) > 0.0f) {
sc->weight = make_float3(0.0f, 0.0f, weight.z);
sc->sample_weight = sample_weight;
sc->data0 = radius.z;
sc->data1 = texture_blur;
sc->data2 = albedo.z;
sc->T.x = sharpness;
# ifdef __OSL__
sc->prim = NULL;
# endif
sc->N = N;
ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
ccl_fetch(sd, num_closure)++;
sc_next(sc);
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, weight.z));
if(bssrdf) {
bssrdf->sample_weight = sample_weight;
bssrdf->radius = radius.z;
bssrdf->texture_blur = texture_blur;
bssrdf->albedo = albedo.z;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
}
break;
}
# undef sc_next
#endif
default:
break;
@@ -594,7 +493,8 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
switch(type) {
case CLOSURE_VOLUME_ABSORPTION_ID: {
ShaderClosure *sc = svm_node_closure_get_absorption(sd, mix_weight * density);
float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - ccl_fetch(sd, svm_closure_weight)) * mix_weight * density;
ShaderClosure *sc = closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_NONE_ID, weight);
if(sc) {
ccl_fetch(sd, flag) |= volume_absorption_setup(sc);
@@ -602,13 +502,12 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
break;
}
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight * density);
float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight * density;
HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
if(sc) {
sc->data0 = param2; /* g */
sc->data1 = 0.0f;
sc->data2 = 0.0f;
ccl_fetch(sd, flag) |= volume_henyey_greenstein_setup(sc);
if(volume) {
volume->g = param2; /* g */
ccl_fetch(sd, flag) |= volume_henyey_greenstein_setup(volume);
}
break;
}
@@ -628,10 +527,10 @@ ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 no
if(mix_weight == 0.0f)
return;
svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, mix_weight);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, 1.0f);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, ccl_fetch(sd, svm_closure_weight));
ccl_fetch(sd, flag) |= SD_EMISSION;
}
@@ -646,10 +545,10 @@ ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4
if(mix_weight == 0.0f)
return;
svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, mix_weight);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, 1.0f);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, ccl_fetch(sd, svm_closure_weight));
}
ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
@@ -662,10 +561,10 @@ ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 nod
if(mix_weight == 0.0f)
return;
svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, mix_weight);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, 1.0f);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, ccl_fetch(sd, svm_closure_weight));
ccl_fetch(sd, flag) |= SD_HOLDOUT;
}
@@ -680,10 +579,10 @@ ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack,
if(mix_weight == 0.0f)
return;
svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, mix_weight);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, 1.0f);
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, ccl_fetch(sd, svm_closure_weight));
ccl_fetch(sd, flag) |= SD_AO;
}
@@ -692,10 +591,7 @@ ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack,
ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
{
if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
sc->weight = weight;
}
ccl_fetch(sd, svm_closure_weight) = weight;
}
ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)

View File

@@ -449,6 +449,9 @@ 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_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID)
#define CLOSURE_IS_BSDF_MULTISCATTER(type) (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID ||\
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_BURLEY_ID)
#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_BURLEY_ID)
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)

View File

@@ -967,6 +967,9 @@ int ShaderGraph::get_num_closures()
else if(CLOSURE_IS_GLASS(closure_type)) {
num_closures += 2;
}
else if(CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
num_closures += 2;
}
else {
++num_closures;
}

View File

@@ -690,6 +690,15 @@ ccl_device_inline float average(const float3 a)
return reduce_add(a)*(1.0f/3.0f);
}
ccl_device_inline bool isequal_float3(const float3 a, const float3 b)
{
#ifdef __KERNEL_OPENCL__
return all(a == b);
#else
return a == b;
#endif
}
/* Float4 Vector */
#ifdef __KERNEL_SSE__