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:
@@ -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
|
||||
|
90
intern/cycles/kernel/closure/alloc.h
Normal file
90
intern/cycles/kernel/closure/alloc.h
Normal 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
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -35,20 +35,38 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc)
|
||||
typedef ccl_addr_space struct VelvetBsdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
float sigma;
|
||||
float invsigma2;
|
||||
float3 N;
|
||||
} VelvetBsdf;
|
||||
|
||||
ccl_device int bsdf_ashikhmin_velvet_setup(VelvetBsdf *bsdf)
|
||||
{
|
||||
float sigma = fmaxf(sc->data0, 0.01f);
|
||||
sc->data0 = 1.0f/(sigma * sigma); /* m_invsigma2 */
|
||||
float sigma = fmaxf(bsdf->sigma, 0.01f);
|
||||
bsdf->invsigma2 = 1.0f/(sigma * sigma);
|
||||
|
||||
sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
|
||||
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
|
||||
|
@@ -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
|
||||
|
@@ -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__ */
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
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);
|
||||
|
||||
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
||||
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,
|
||||
|
@@ -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;
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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__
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
@@ -25,7 +25,6 @@ set(SRC
|
||||
)
|
||||
|
||||
set(HEADER_SRC
|
||||
osl_bssrdf.h
|
||||
osl_closures.h
|
||||
osl_globals.h
|
||||
osl_services.h
|
||||
|
@@ -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()
|
||||
|
@@ -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, ¶ms);
|
||||
|
||||
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)
|
||||
|
@@ -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, ¶ms);
|
||||
|
||||
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)
|
||||
|
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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__ */
|
||||
|
@@ -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, ¶ms);
|
||||
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)
|
||||
|
@@ -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, ¶ms); \
|
||||
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, ¶ms); \
|
||||
sd->flag |= (volume) ? volume_##lower##_setup(volume) : 0; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
};
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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__
|
||||
|
Submodule release/scripts/addons updated: 407d0ea752...27a32b3ed5
Reference in New Issue
Block a user