Cycles: add new Spectrum and PackedSpectrum types
These replace float3 and packed_float3 in various places in the kernel where a spectral color representation will be used in the future. That representation will require more than 3 channels and conversion to from/RGB. The kernel code was refactored to remove the assumption that Spectrum and RGB colors are the same thing. There are no functional changes, Spectrum is still a float3 and the conversion functions are no-ops. Differential Revision: https://developer.blender.org/D15535
This commit is contained in:
parent
7921faa651
commit
d832d993c5
@ -266,6 +266,7 @@ ForEachMacros:
|
||||
- MAP_SLOT_PROBING_BEGIN
|
||||
- VECTOR_SET_SLOT_PROBING_BEGIN
|
||||
- WL_ARRAY_FOR_EACH
|
||||
- FOREACH_SPECTRUM_CHANNEL
|
||||
|
||||
StatementMacros:
|
||||
- PyObject_HEAD
|
||||
|
@ -342,6 +342,7 @@ set(SRC_UTIL_HEADERS
|
||||
../util/types_int3_impl.h
|
||||
../util/types_int4.h
|
||||
../util/types_int4_impl.h
|
||||
../util/types_spectrum.h
|
||||
../util/types_uchar2.h
|
||||
../util/types_uchar2_impl.h
|
||||
../util/types_uchar3.h
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "kernel/geom/geom.h"
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device void kernel_displace_evaluate(KernelGlobals kg,
|
||||
@ -65,7 +67,7 @@ ccl_device void kernel_background_evaluate(KernelGlobals kg,
|
||||
shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT &
|
||||
~(KERNEL_FEATURE_NODE_RAYTRACE | KERNEL_FEATURE_NODE_LIGHT_PATH)>(
|
||||
kg, INTEGRATOR_STATE_NULL, &sd, NULL, path_flag);
|
||||
float3 color = shader_background_eval(&sd);
|
||||
Spectrum color = shader_background_eval(&sd);
|
||||
|
||||
#ifdef __KERNEL_DEBUG_NAN__
|
||||
if (!isfinite_safe(color)) {
|
||||
@ -76,10 +78,12 @@ ccl_device void kernel_background_evaluate(KernelGlobals kg,
|
||||
/* Ensure finite color, avoiding possible numerical instabilities in the path tracing kernels. */
|
||||
color = ensure_finite(color);
|
||||
|
||||
float3 color_rgb = spectrum_to_rgb(color);
|
||||
|
||||
/* Write output. */
|
||||
output[offset * 3 + 0] += color.x;
|
||||
output[offset * 3 + 1] += color.y;
|
||||
output[offset * 3 + 2] += color.z;
|
||||
output[offset * 3 + 0] += color_rgb.x;
|
||||
output[offset * 3 + 1] += color_rgb.y;
|
||||
output[offset * 3 + 2] += color_rgb.z;
|
||||
}
|
||||
|
||||
ccl_device void kernel_curve_shadow_transparency_evaluate(
|
||||
|
@ -8,7 +8,7 @@ CCL_NAMESPACE_BEGIN
|
||||
ccl_device ccl_private ShaderClosure *closure_alloc(ccl_private ShaderData *sd,
|
||||
int size,
|
||||
ClosureType type,
|
||||
float3 weight)
|
||||
Spectrum weight)
|
||||
{
|
||||
kernel_assert(size <= sizeof(ShaderClosure));
|
||||
|
||||
@ -49,7 +49,7 @@ ccl_device ccl_private void *closure_alloc_extra(ccl_private ShaderData *sd, int
|
||||
|
||||
ccl_device_inline ccl_private ShaderClosure *bsdf_alloc(ccl_private ShaderData *sd,
|
||||
int size,
|
||||
float3 weight)
|
||||
Spectrum weight)
|
||||
{
|
||||
kernel_assert(isfinite_safe(weight));
|
||||
|
||||
@ -74,7 +74,7 @@ ccl_device_inline ccl_private ShaderClosure *bsdf_alloc(ccl_private ShaderData *
|
||||
#ifdef __OSL__
|
||||
ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd,
|
||||
int size,
|
||||
float3 weight,
|
||||
Spectrum weight,
|
||||
void *data)
|
||||
{
|
||||
kernel_assert(isfinite_safe(weight));
|
||||
|
@ -103,7 +103,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private differential3 *domega_in,
|
||||
ccl_private float *pdf)
|
||||
@ -458,7 +458,7 @@ ccl_device
|
||||
#else
|
||||
ccl_device_inline
|
||||
#endif
|
||||
float3
|
||||
Spectrum
|
||||
bsdf_eval(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
@ -466,7 +466,7 @@ ccl_device_inline
|
||||
const bool is_transmission,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
if (!is_transmission) {
|
||||
switch (sc->type) {
|
||||
|
@ -39,7 +39,7 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
|
||||
return 2.0f / (roughness * roughness) - 2.0f;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float3
|
||||
ccl_device_forceinline Spectrum
|
||||
bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
@ -55,7 +55,7 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
|
||||
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
if (NdotI > 0.0f && NdotO > 0.0f) {
|
||||
NdotI = fmaxf(NdotI, 1e-6f);
|
||||
@ -105,16 +105,16 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
}
|
||||
|
||||
return make_float3(out, out, out);
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_ashikhmin_shirley_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_ashikhmin_shirley_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x,
|
||||
@ -137,7 +137,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -214,7 +214,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
|
||||
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
|
||||
/* Some high number for MIS. */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
label = LABEL_REFLECT | LABEL_SINGULAR;
|
||||
}
|
||||
else {
|
||||
|
@ -31,10 +31,10 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc;
|
||||
float m_invsigma2 = bsdf->invsigma2;
|
||||
@ -50,7 +50,7 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClo
|
||||
|
||||
if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
float cosNHdivHO = cosNH / cosHO;
|
||||
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
|
||||
@ -68,20 +68,20 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClo
|
||||
float out = 0.25f * (D * G) / cosNO;
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F;
|
||||
return make_float3(out, out, out);
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -91,7 +91,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -129,7 +129,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
|
||||
|
||||
float power = 0.25f * (D * G) / cosNO;
|
||||
|
||||
*eval = make_float3(power, power, power);
|
||||
*eval = make_spectrum(power);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the retroreflective bounce
|
||||
@ -139,12 +139,12 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
}
|
||||
|
@ -26,26 +26,26 @@ ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
*pdf = cos_pi;
|
||||
return make_float3(cos_pi, cos_pi, cos_pi);
|
||||
return make_spectrum(cos_pi);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -55,7 +55,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -68,7 +68,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
|
||||
if (dot(Ng, *omega_in) > 0.0f) {
|
||||
*eval = make_float3(*pdf, *pdf, *pdf);
|
||||
*eval = make_spectrum(*pdf);
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
|
||||
@ -77,7 +77,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
}
|
||||
@ -90,26 +90,26 @@ ccl_device int bsdf_translucent_setup(ccl_private DiffuseBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_translucent_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_translucent_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
*pdf = cos_pi;
|
||||
return make_float3(cos_pi, cos_pi, cos_pi);
|
||||
return make_spectrum(cos_pi);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -119,7 +119,7 @@ ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -132,7 +132,7 @@ ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc,
|
||||
// distribution over the hemisphere
|
||||
sample_cos_hemisphere(-N, randu, randv, omega_in, pdf);
|
||||
if (dot(Ng, *omega_in) < 0) {
|
||||
*eval = make_float3(*pdf, *pdf, *pdf);
|
||||
*eval = make_spectrum(*pdf);
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
|
||||
@ -141,7 +141,7 @@ ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
else {
|
||||
*pdf = 0;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_TRANSMIT | LABEL_DIFFUSE;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "kernel/sample/mapping.h"
|
||||
#include "kernel/util/color.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@ -46,25 +47,25 @@ ccl_device void bsdf_diffuse_ramp_blur(ccl_private ShaderClosure *sc, float roug
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_diffuse_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
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(bsdf->colors, cos_pi) * M_1_PI_F;
|
||||
return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_diffuse_ramp_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_ramp_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -74,7 +75,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -87,7 +88,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
|
||||
if (dot(Ng, *omega_in) > 0.0f) {
|
||||
*eval = bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F;
|
||||
*eval = rgb_to_spectrum(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,7 +96,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
}
|
||||
|
@ -37,10 +37,10 @@ ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
||||
float offset = bsdf->offset;
|
||||
@ -61,7 +61,7 @@ ccl_device float3 bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClos
|
||||
|
||||
if (M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(*pdf, *pdf, *pdf);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float roughness1_inv = 1.0f / roughness1;
|
||||
@ -81,31 +81,31 @@ ccl_device float3 bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClos
|
||||
(2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i);
|
||||
*pdf = phi_pdf * theta_pdf;
|
||||
|
||||
return make_float3(*pdf, *pdf, *pdf);
|
||||
return make_spectrum(*pdf);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_hair_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
ccl_device Spectrum bsdf_hair_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
||||
float offset = bsdf->offset;
|
||||
@ -125,7 +125,7 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(ccl_private const ShaderC
|
||||
|
||||
if (M_PI_2_F - fabsf(theta_i) < 0.001f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(*pdf, *pdf, *pdf);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float costheta_i = fast_cosf(theta_i);
|
||||
@ -145,7 +145,7 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(ccl_private const ShaderC
|
||||
float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
|
||||
|
||||
*pdf = phi_pdf * theta_pdf;
|
||||
return make_float3(*pdf, *pdf, *pdf);
|
||||
return make_spectrum(*pdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -155,7 +155,7 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -204,7 +204,7 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
if (M_PI_2_F - fabsf(theta_i) < 0.001f)
|
||||
*pdf = 0.0f;
|
||||
|
||||
*eval = make_float3(*pdf, *pdf, *pdf);
|
||||
*eval = make_spectrum(*pdf);
|
||||
|
||||
return LABEL_REFLECT | LABEL_GLOSSY;
|
||||
}
|
||||
@ -216,7 +216,7 @@ ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -266,7 +266,7 @@ ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
|
||||
*eval = make_float3(*pdf, *pdf, *pdf);
|
||||
*eval = make_spectrum(*pdf);
|
||||
|
||||
/* TODO(sergey): Should always be negative, but seems some precision issue
|
||||
* is involved here.
|
||||
|
@ -20,7 +20,7 @@ typedef struct PrincipledHairBSDF {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
/* Absorption coefficient. */
|
||||
float3 sigma;
|
||||
Spectrum sigma;
|
||||
/* Variance of the underlying logistic distribution. */
|
||||
float v;
|
||||
/* Scale factor of the underlying logistic distribution. */
|
||||
@ -166,12 +166,6 @@ ccl_device_inline float longitudinal_scattering(
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine the three values using their luminances. */
|
||||
ccl_device_inline float4 combine_with_energy(KernelGlobals kg, float3 c)
|
||||
{
|
||||
return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
|
||||
}
|
||||
|
||||
#ifdef __HAIR__
|
||||
/* Set up the hair closure. */
|
||||
ccl_device int bsdf_principled_hair_setup(ccl_private ShaderData *sd,
|
||||
@ -214,34 +208,36 @@ ccl_device int bsdf_principled_hair_setup(ccl_private ShaderData *sd,
|
||||
#endif /* __HAIR__ */
|
||||
|
||||
/* Given the Fresnel term and transmittance, generate the attenuation terms for each bounce. */
|
||||
ccl_device_inline void hair_attenuation(KernelGlobals kg,
|
||||
float f,
|
||||
float3 T,
|
||||
ccl_private float4 *Ap)
|
||||
ccl_device_inline void hair_attenuation(
|
||||
KernelGlobals kg, float f, Spectrum T, ccl_private Spectrum *Ap, ccl_private float *Ap_energy)
|
||||
{
|
||||
/* Primary specular (R). */
|
||||
Ap[0] = make_float4(f, f, f, f);
|
||||
Ap[0] = make_spectrum(f);
|
||||
Ap_energy[0] = f;
|
||||
|
||||
/* Transmission (TT). */
|
||||
float3 col = sqr(1.0f - f) * T;
|
||||
Ap[1] = combine_with_energy(kg, col);
|
||||
Spectrum col = sqr(1.0f - f) * T;
|
||||
Ap[1] = col;
|
||||
Ap_energy[1] = spectrum_to_gray(kg, col);
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
col *= T * f;
|
||||
Ap[2] = combine_with_energy(kg, col);
|
||||
Ap[2] = col;
|
||||
Ap_energy[2] = spectrum_to_gray(kg, col);
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
col *= safe_divide_color(T * f, make_float3(1.0f, 1.0f, 1.0f) - T * f);
|
||||
Ap[3] = combine_with_energy(kg, col);
|
||||
col *= safe_divide(T * f, one_spectrum() - T * f);
|
||||
Ap[3] = col;
|
||||
Ap_energy[3] = spectrum_to_gray(kg, col);
|
||||
|
||||
/* Normalize sampling weights. */
|
||||
float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
|
||||
float totweight = Ap_energy[0] + Ap_energy[1] + Ap_energy[2] + Ap_energy[3];
|
||||
float fac = safe_divide(1.0f, totweight);
|
||||
|
||||
Ap[0].w *= fac;
|
||||
Ap[1].w *= fac;
|
||||
Ap[2].w *= fac;
|
||||
Ap[3].w *= fac;
|
||||
Ap_energy[0] *= fac;
|
||||
Ap_energy[1] *= fac;
|
||||
Ap_energy[2] *= fac;
|
||||
Ap_energy[3] *= fac;
|
||||
}
|
||||
|
||||
/* Given the tilt angle, generate the rotated theta_i for the different bounces. */
|
||||
@ -266,11 +262,11 @@ ccl_device_inline void hair_alpha_angles(float sin_theta_i,
|
||||
}
|
||||
|
||||
/* Evaluation function for our shader. */
|
||||
ccl_device float3 bsdf_principled_hair_eval(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_principled_hair_eval(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
kernel_assert(isfinite_safe(sd->P) && isfinite_safe(sd->ray_length));
|
||||
|
||||
@ -299,9 +295,11 @@ ccl_device float3 bsdf_principled_hair_eval(KernelGlobals kg,
|
||||
float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
float gamma_t = safe_asinf(sin_gamma_t);
|
||||
|
||||
float3 T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
float4 Ap[4];
|
||||
hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
|
||||
Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
Spectrum Ap[4];
|
||||
float Ap_energy[4];
|
||||
hair_attenuation(
|
||||
kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy);
|
||||
|
||||
float sin_theta_i = wi.x;
|
||||
float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||
@ -312,35 +310,40 @@ ccl_device float3 bsdf_principled_hair_eval(KernelGlobals kg,
|
||||
float angles[6];
|
||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||
|
||||
float4 F;
|
||||
Spectrum F;
|
||||
float F_energy;
|
||||
float Mp, Np;
|
||||
|
||||
/* Primary specular (R). */
|
||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
||||
F = Ap[0] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy = Ap_energy[0] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Transmission (TT). */
|
||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[1] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy += Ap_energy[1] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[2] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy += Ap_energy[2] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy += Ap_energy[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
*pdf = F.w;
|
||||
return float4_to_float3(F);
|
||||
*pdf = F_energy;
|
||||
return F;
|
||||
}
|
||||
|
||||
/* Sampling function for the hair shader. */
|
||||
@ -349,7 +352,7 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -385,16 +388,18 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
||||
float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
float gamma_t = safe_asinf(sin_gamma_t);
|
||||
|
||||
float3 T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
float4 Ap[4];
|
||||
hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
|
||||
Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
Spectrum Ap[4];
|
||||
float Ap_energy[4];
|
||||
hair_attenuation(
|
||||
kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy);
|
||||
|
||||
int p = 0;
|
||||
for (; p < 3; p++) {
|
||||
if (u[0].x < Ap[p].w) {
|
||||
if (u[0].x < Ap_energy[p]) {
|
||||
break;
|
||||
}
|
||||
u[0].x -= Ap[p].w;
|
||||
u[0].x -= Ap_energy[p];
|
||||
}
|
||||
|
||||
float v = bsdf->v;
|
||||
@ -429,35 +434,40 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
||||
|
||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||
|
||||
float4 F;
|
||||
Spectrum F;
|
||||
float F_energy;
|
||||
float Mp, Np;
|
||||
|
||||
/* Primary specular (R). */
|
||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
||||
F = Ap[0] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy = Ap_energy[0] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Transmission (TT). */
|
||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[1] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy += Ap_energy[1] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[2] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy += Ap_energy[2] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(float4_to_float3(F)));
|
||||
F_energy += Ap_energy[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
*eval = float4_to_float3(F);
|
||||
*pdf = F.w;
|
||||
*eval = F;
|
||||
*pdf = F_energy;
|
||||
|
||||
*omega_in = X * sin_theta_i + Y * cos_theta_i * cosf(phi_i) + Z * cos_theta_i * sinf(phi_i);
|
||||
|
||||
@ -489,25 +499,28 @@ ccl_device_inline float bsdf_principled_hair_albedo_roughness_scale(
|
||||
return (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x + 5.969f;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc)
|
||||
ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc)
|
||||
{
|
||||
ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)sc;
|
||||
return exp(-sqrt(bsdf->sigma) * bsdf_principled_hair_albedo_roughness_scale(bsdf->v));
|
||||
}
|
||||
|
||||
ccl_device_inline float3
|
||||
bsdf_principled_hair_sigma_from_reflectance(const float3 color, const float azimuthal_roughness)
|
||||
ccl_device_inline Spectrum
|
||||
bsdf_principled_hair_sigma_from_reflectance(const Spectrum color, const float azimuthal_roughness)
|
||||
{
|
||||
const float3 sigma = log(color) /
|
||||
bsdf_principled_hair_albedo_roughness_scale(azimuthal_roughness);
|
||||
const Spectrum sigma = log(color) /
|
||||
bsdf_principled_hair_albedo_roughness_scale(azimuthal_roughness);
|
||||
return sigma * sigma;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 bsdf_principled_hair_sigma_from_concentration(const float eumelanin,
|
||||
const float pheomelanin)
|
||||
ccl_device_inline Spectrum bsdf_principled_hair_sigma_from_concentration(const float eumelanin,
|
||||
const float pheomelanin)
|
||||
{
|
||||
return eumelanin * make_float3(0.506f, 0.841f, 1.653f) +
|
||||
pheomelanin * make_float3(0.343f, 0.733f, 1.924f);
|
||||
const float3 eumelanin_color = make_float3(0.506f, 0.841f, 1.653f);
|
||||
const float3 pheomelanin_color = make_float3(0.343f, 0.733f, 1.924f);
|
||||
|
||||
return eumelanin * rgb_to_spectrum(eumelanin_color) +
|
||||
pheomelanin * rgb_to_spectrum(pheomelanin_color);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -17,8 +17,8 @@
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef struct MicrofacetExtra {
|
||||
float3 color, cspec0;
|
||||
float3 fresnel_color;
|
||||
Spectrum color, cspec0;
|
||||
Spectrum fresnel_color;
|
||||
float clearcoat;
|
||||
} MicrofacetExtra;
|
||||
|
||||
@ -233,11 +233,11 @@ ccl_device_forceinline float3 microfacet_sample_stretched(KernelGlobals kg,
|
||||
*
|
||||
* Else it is simply white
|
||||
*/
|
||||
ccl_device_forceinline float3 reflection_color(ccl_private const MicrofacetBsdf *bsdf,
|
||||
float3 L,
|
||||
float3 H)
|
||||
ccl_device_forceinline Spectrum reflection_color(ccl_private const MicrofacetBsdf *bsdf,
|
||||
float3 L,
|
||||
float3 H)
|
||||
{
|
||||
float3 F = make_float3(1.0f, 1.0f, 1.0f);
|
||||
Spectrum F = one_spectrum();
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
|
||||
if (use_fresnel) {
|
||||
@ -357,10 +357,10 @@ ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float ro
|
||||
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
@ -370,7 +370,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosu
|
||||
|
||||
if (m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
@ -451,12 +451,12 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosu
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
|
||||
float3 F = reflection_color(bsdf, omega_in, m);
|
||||
Spectrum F = reflection_color(bsdf, omega_in, m);
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
F *= 0.25f * bsdf->extra->clearcoat;
|
||||
}
|
||||
|
||||
float3 out = F * G * common;
|
||||
Spectrum out = F * G * common;
|
||||
|
||||
/* eq. 2 in distribution of visible normals sampling
|
||||
* `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */
|
||||
@ -469,13 +469,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosu
|
||||
return out;
|
||||
}
|
||||
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
@ -486,7 +486,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClos
|
||||
|
||||
if (!m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
@ -494,7 +494,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClos
|
||||
|
||||
if (cosNO <= 0 || cosNI >= 0) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */
|
||||
return zero_spectrum(); /* vectors on same side -- not possible */
|
||||
}
|
||||
/* compute half-vector of the refraction (eq. 16) */
|
||||
float3 ht = -(m_eta * omega_in + I);
|
||||
@ -530,7 +530,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClos
|
||||
float out = G * fabsf(cosHI * cosHO) * common;
|
||||
*pdf = G1o * fabsf(cosHO * cosHI) * common;
|
||||
|
||||
return make_float3(out, out, out);
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
@ -541,7 +541,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -588,7 +588,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
if (alpha_x * alpha_y <= 1e-7f) {
|
||||
/* some high number for MIS */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
|
||||
@ -664,7 +664,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
float common = (G1o * D) * 0.25f / cosNO;
|
||||
*pdf = common;
|
||||
|
||||
float3 F = reflection_color(bsdf, *omega_in, m);
|
||||
Spectrum F = reflection_color(bsdf, *omega_in, m);
|
||||
|
||||
*eval = G1i * common * F;
|
||||
}
|
||||
@ -679,7 +679,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
}
|
||||
@ -722,7 +722,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
|
||||
/* some high number for MIS */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
label = LABEL_TRANSMIT | LABEL_SINGULAR;
|
||||
}
|
||||
else {
|
||||
@ -750,11 +750,11 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
float out = G1i * fabsf(cosHI * cosHO) * common;
|
||||
*pdf = cosHO * fabsf(cosHI) * common;
|
||||
|
||||
*eval = make_float3(out, out, out);
|
||||
*eval = make_spectrum(out);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
}
|
||||
@ -835,10 +835,10 @@ ccl_device_inline float bsdf_beckmann_aniso_G1(
|
||||
return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
@ -848,7 +848,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(ccl_private const Shader
|
||||
|
||||
if (m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
@ -910,16 +910,16 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(ccl_private const Shader
|
||||
* pdf = pm * 0.25 / dot(m, I); */
|
||||
*pdf = G1o * common;
|
||||
|
||||
return make_float3(out, out, out);
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
@ -930,7 +930,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const Shade
|
||||
|
||||
if (!m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
@ -938,7 +938,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const Shade
|
||||
|
||||
if (cosNO <= 0 || cosNI >= 0) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
/* compute half-vector of the refraction (eq. 16) */
|
||||
float3 ht = -(m_eta * omega_in + I);
|
||||
@ -971,7 +971,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const Shade
|
||||
float out = G * fabsf(cosHI * cosHO) * common;
|
||||
*pdf = G1o * fabsf(cosHO * cosHI) * common;
|
||||
|
||||
return make_float3(out, out, out);
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
@ -982,7 +982,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -1028,7 +1028,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
if (alpha_x * alpha_y <= 1e-7f) {
|
||||
/* some high number for MIS */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
label = LABEL_REFLECT | LABEL_SINGULAR;
|
||||
}
|
||||
else {
|
||||
@ -1074,7 +1074,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
float out = G * common;
|
||||
*pdf = G1o * common;
|
||||
|
||||
*eval = make_float3(out, out, out);
|
||||
*eval = make_spectrum(out);
|
||||
}
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
@ -1083,7 +1083,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
}
|
||||
@ -1126,7 +1126,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
|
||||
/* some high number for MIS */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
label = LABEL_TRANSMIT | LABEL_SINGULAR;
|
||||
}
|
||||
else {
|
||||
@ -1155,11 +1155,11 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
float out = G * fabsf(cosHI * cosHO) * common;
|
||||
*pdf = G1o * cosHO * fabsf(cosHI) * common;
|
||||
|
||||
*eval = make_float3(out, out, out);
|
||||
*eval = make_spectrum(out);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
}
|
||||
|
@ -95,29 +95,29 @@ ccl_device_forceinline float3 mf_sample_vndf(const float3 wi,
|
||||
|
||||
/* Phase function for reflective materials. */
|
||||
ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi,
|
||||
ccl_private float3 *weight,
|
||||
ccl_private Spectrum *weight,
|
||||
const float3 wm)
|
||||
{
|
||||
return -wi + 2.0f * wm * dot(wi, wm);
|
||||
}
|
||||
|
||||
ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w,
|
||||
const float lambda,
|
||||
const float3 wo,
|
||||
const float2 alpha)
|
||||
ccl_device_forceinline Spectrum mf_eval_phase_glossy(const float3 w,
|
||||
const float lambda,
|
||||
const float3 wo,
|
||||
const float2 alpha)
|
||||
{
|
||||
if (w.z > 0.9999f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
|
||||
const float3 wh = normalize(wo - w);
|
||||
if (wh.z < 0.0f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
|
||||
float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
|
||||
|
||||
const float dotW_WH = dot(-w, wh);
|
||||
if (dotW_WH < 0.0f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
|
||||
float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
|
||||
if (alpha.x == alpha.y)
|
||||
@ -125,7 +125,7 @@ ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w,
|
||||
else
|
||||
phase *= D_ggx_aniso(wh, alpha);
|
||||
|
||||
return make_float3(phase, phase, phase);
|
||||
return make_spectrum(phase);
|
||||
}
|
||||
|
||||
/* Phase function for dielectric transmissive materials, including both reflection and refraction
|
||||
@ -148,22 +148,22 @@ ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi,
|
||||
return normalize(wm * (cosI * inv_eta + cosT) - wi * inv_eta);
|
||||
}
|
||||
|
||||
ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w,
|
||||
const float lambda,
|
||||
const float3 wo,
|
||||
const bool wo_outside,
|
||||
const float2 alpha,
|
||||
const float eta)
|
||||
ccl_device_forceinline Spectrum mf_eval_phase_glass(const float3 w,
|
||||
const float lambda,
|
||||
const float3 wo,
|
||||
const bool wo_outside,
|
||||
const float2 alpha,
|
||||
const float eta)
|
||||
{
|
||||
if (w.z > 0.9999f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
|
||||
float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
|
||||
float v;
|
||||
if (wo_outside) {
|
||||
const float3 wh = normalize(wo - w);
|
||||
if (wh.z < 0.0f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
|
||||
const float dotW_WH = dot(-w, wh);
|
||||
v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f /
|
||||
@ -175,14 +175,14 @@ ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w,
|
||||
wh = -wh;
|
||||
const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
|
||||
if (dotW_WH < 0.0f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
|
||||
float temp = dotW_WH + eta * dotWO_WH;
|
||||
v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) *
|
||||
D_ggx(wh, alpha.x) / (pArea * temp * temp);
|
||||
}
|
||||
|
||||
return make_float3(v, v, v);
|
||||
return make_spectrum(v);
|
||||
}
|
||||
|
||||
/* === Utility functions for the random walks === */
|
||||
@ -415,27 +415,27 @@ ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private Microfacet
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float3 X, Y, Z;
|
||||
@ -444,7 +444,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const Shade
|
||||
/* Ensure that the both directions are on the outside w.r.t. the shading normal. */
|
||||
if (dot(Z, I) <= 0.0f || dot(Z, omega_in) <= 0.0f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
|
||||
@ -482,7 +482,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -509,7 +509,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
|
||||
return LABEL_NONE;
|
||||
}
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
*domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
|
||||
*domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
|
||||
@ -588,7 +588,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
ccl_device float3
|
||||
ccl_device Spectrum
|
||||
bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
@ -599,7 +599,7 @@ bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *s
|
||||
|
||||
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float3 X, Y, Z;
|
||||
@ -622,17 +622,18 @@ bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *s
|
||||
bsdf->extra->color);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
ccl_device Spectrum
|
||||
bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
|
||||
@ -665,7 +666,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -699,7 +700,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
|
||||
&inside);
|
||||
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
if (randu < fresnel) {
|
||||
*omega_in = R;
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
|
@ -12,16 +12,16 @@
|
||||
* multi-scattered energy is used. In combination with MIS, that is enough to produce an unbiased
|
||||
* result, although the balance heuristic isn't necessarily optimal anymore.
|
||||
*/
|
||||
ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
float3 wo,
|
||||
const bool wo_outside,
|
||||
const float3 color,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
ccl_private uint *lcg_state,
|
||||
const float eta,
|
||||
bool use_fresnel,
|
||||
const float3 cspec0)
|
||||
ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
float3 wo,
|
||||
const bool wo_outside,
|
||||
const Spectrum color,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
ccl_private uint *lcg_state,
|
||||
const float eta,
|
||||
bool use_fresnel,
|
||||
const Spectrum cspec0)
|
||||
{
|
||||
/* Evaluating for a shallower incoming direction produces less noise, and the properties of the
|
||||
* BSDF guarantee reciprocity. */
|
||||
@ -46,7 +46,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
}
|
||||
|
||||
if (wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
|
||||
const float2 alpha = make_float2(alpha_x, alpha_y);
|
||||
|
||||
@ -54,8 +54,8 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
float shadowing_lambda = mf_lambda(wo_outside ? wo : -wo, alpha);
|
||||
|
||||
/* Analytically compute single scattering for lower noise. */
|
||||
float3 eval;
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
Spectrum eval;
|
||||
Spectrum throughput = one_spectrum();
|
||||
const float3 wh = normalize(wi + wo);
|
||||
#ifdef MF_MULTI_GLASS
|
||||
eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
|
||||
@ -70,7 +70,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
val *= D_ggx(wh, alpha.x);
|
||||
else
|
||||
val *= D_ggx_aniso(wh, alpha);
|
||||
eval = make_float3(val, val, val);
|
||||
eval = make_spectrum(val);
|
||||
#endif
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
@ -99,7 +99,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
#ifdef MF_MULTI_GLASS
|
||||
if (order == 0 && use_fresnel) {
|
||||
/* Evaluate amount of scattering towards wo on this microfacet. */
|
||||
float3 phase;
|
||||
Spectrum phase;
|
||||
if (outside)
|
||||
phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
|
||||
else
|
||||
@ -113,7 +113,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
#endif
|
||||
if (order > 0) {
|
||||
/* Evaluate amount of scattering towards wo on this microfacet. */
|
||||
float3 phase;
|
||||
Spectrum phase;
|
||||
#ifdef MF_MULTI_GLASS
|
||||
if (outside)
|
||||
phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
|
||||
@ -172,19 +172,19 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
|
||||
* walk escaped the surface in wo. The function returns the throughput between wi and wo. Without
|
||||
* reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal.
|
||||
*/
|
||||
ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
|
||||
ccl_private float3 *wo,
|
||||
const float3 color,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
ccl_private uint *lcg_state,
|
||||
const float eta,
|
||||
bool use_fresnel,
|
||||
const float3 cspec0)
|
||||
ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
|
||||
ccl_private float3 *wo,
|
||||
const Spectrum color,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
ccl_private uint *lcg_state,
|
||||
const float eta,
|
||||
bool use_fresnel,
|
||||
const Spectrum cspec0)
|
||||
{
|
||||
const float2 alpha = make_float2(alpha_x, alpha_y);
|
||||
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
Spectrum throughput = one_spectrum();
|
||||
float3 wr = -wi;
|
||||
float lambda_r = mf_lambda(wr, alpha);
|
||||
float hr = 1.0f;
|
||||
@ -229,7 +229,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
|
||||
throughput *= color;
|
||||
}
|
||||
else {
|
||||
float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
|
||||
Spectrum t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
|
||||
|
||||
if (order == 0)
|
||||
throughput = t_color;
|
||||
@ -239,7 +239,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
|
||||
}
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
if (use_fresnel) {
|
||||
float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
|
||||
Spectrum t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
|
||||
|
||||
if (order == 0)
|
||||
throughput = t_color;
|
||||
@ -254,7 +254,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
|
||||
G1_r = mf_G1(wr, C1_r, lambda_r);
|
||||
}
|
||||
*wo = make_float3(0.0f, 0.0f, 1.0f);
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
#undef MF_MULTI_GLASS
|
||||
|
@ -15,10 +15,10 @@ typedef struct OrenNayarBsdf {
|
||||
|
||||
static_assert(sizeof(ShaderClosure) >= sizeof(OrenNayarBsdf), "OrenNayarBsdf is too large!");
|
||||
|
||||
ccl_device float3 bsdf_oren_nayar_get_intensity(ccl_private const ShaderClosure *sc,
|
||||
float3 n,
|
||||
float3 v,
|
||||
float3 l)
|
||||
ccl_device Spectrum bsdf_oren_nayar_get_intensity(ccl_private const ShaderClosure *sc,
|
||||
float3 n,
|
||||
float3 v,
|
||||
float3 l)
|
||||
{
|
||||
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
|
||||
float nl = max(dot(n, l), 0.0f);
|
||||
@ -28,7 +28,7 @@ ccl_device float3 bsdf_oren_nayar_get_intensity(ccl_private const ShaderClosure
|
||||
if (t > 0.0f)
|
||||
t /= max(nl, nv) + FLT_MIN;
|
||||
float is = nl * (bsdf->a + bsdf->b * t);
|
||||
return make_float3(is, is, is);
|
||||
return make_spectrum(is);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf)
|
||||
@ -47,10 +47,10 @@ ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
|
||||
if (dot(bsdf->N, omega_in) > 0.0f) {
|
||||
@ -59,17 +59,17 @@ ccl_device float3 bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_oren_nayar_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_oren_nayar_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -79,7 +79,7 @@ ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -99,7 +99,7 @@ ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef __OSL__
|
||||
@ -42,10 +44,10 @@ ccl_device int bsdf_phong_ramp_setup(ccl_private PhongRampBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc;
|
||||
float m_exponent = bsdf->exponent;
|
||||
@ -61,11 +63,11 @@ ccl_device float3 bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *
|
||||
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(bsdf->colors, cosp) * out;
|
||||
return rgb_to_spectrum(bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out);
|
||||
}
|
||||
}
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_phong_ramp_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
@ -84,7 +86,7 @@ ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -119,12 +121,12 @@ ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
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(bsdf->colors, cosp) * out;
|
||||
*eval = rgb_to_spectrum(bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_GLOSSY;
|
||||
|
@ -42,7 +42,7 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf *
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3
|
||||
ccl_device Spectrum
|
||||
bsdf_principled_diffuse_compute_brdf(ccl_private const PrincipledDiffuseBsdf *bsdf,
|
||||
float3 N,
|
||||
float3 V,
|
||||
@ -52,7 +52,7 @@ bsdf_principled_diffuse_compute_brdf(ccl_private const PrincipledDiffuseBsdf *bs
|
||||
const float NdotL = dot(N, L);
|
||||
|
||||
if (NdotL <= 0) {
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
const float NdotV = dot(N, V);
|
||||
@ -82,7 +82,7 @@ bsdf_principled_diffuse_compute_brdf(ccl_private const PrincipledDiffuseBsdf *bs
|
||||
|
||||
float value = M_1_PI_F * NdotL * f;
|
||||
|
||||
return make_float3(value, value, value);
|
||||
return make_spectrum(value);
|
||||
}
|
||||
|
||||
/* Compute Fresnel at entry point, to be combined with #PRINCIPLED_DIFFUSE_LAMBERT_EXIT
|
||||
@ -109,10 +109,10 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf *
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc;
|
||||
|
||||
@ -126,17 +126,17 @@ ccl_device float3 bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderC
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_principled_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -146,7 +146,7 @@ ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *s
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -169,7 +169,7 @@ ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *s
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ ccl_device_inline float calculate_avg_principled_sheen_brdf(float3 N, float3 I)
|
||||
return schlick_fresnel(NdotI) * NdotI;
|
||||
}
|
||||
|
||||
ccl_device float3
|
||||
ccl_device Spectrum
|
||||
calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_private float *pdf)
|
||||
{
|
||||
float NdotL = dot(N, L);
|
||||
@ -40,14 +40,14 @@ calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_priv
|
||||
|
||||
if (NdotL < 0 || NdotV < 0) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float LdotH = dot(L, H);
|
||||
|
||||
float value = schlick_fresnel(LdotH) * NdotL;
|
||||
|
||||
return make_float3(value, value, value);
|
||||
return make_spectrum(value);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
|
||||
@ -59,10 +59,10 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc;
|
||||
|
||||
@ -77,17 +77,17 @@ ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClo
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_sheen_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_principled_sheen_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -97,7 +97,7 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -121,7 +121,7 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
|
@ -18,22 +18,22 @@ ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -43,7 +43,7 @@ ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -63,12 +63,12 @@ ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
#endif
|
||||
/* Some high number for MIS. */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_REFLECT | LABEL_SINGULAR;
|
||||
}
|
||||
|
@ -18,22 +18,22 @@ ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_refraction_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_refraction_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -43,7 +43,7 @@ ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -77,7 +77,7 @@ ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc,
|
||||
if (!inside && fresnel != 1.0f) {
|
||||
/* Some high number for MIS. */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
*eval = make_spectrum(1e6f);
|
||||
*omega_in = T;
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
*domega_in_dx = dTdx;
|
||||
@ -86,7 +86,7 @@ ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
return LABEL_TRANSMIT | LABEL_SINGULAR;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ ccl_device int bsdf_diffuse_toon_setup(ccl_private ToonBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
|
||||
ccl_device float bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
|
||||
{
|
||||
float is;
|
||||
|
||||
@ -41,7 +41,7 @@ ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float a
|
||||
else
|
||||
is = 0.0f;
|
||||
|
||||
return make_float3(is, is, is);
|
||||
return is;
|
||||
}
|
||||
|
||||
ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
|
||||
@ -49,35 +49,35 @@ ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
|
||||
return fminf(max_angle + smooth, M_PI_2_F);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private 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);
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
|
||||
if (eval.x > 0.0f) {
|
||||
if (eval > 0.0f) {
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
||||
return *pdf * eval;
|
||||
return make_spectrum(*pdf * eval);
|
||||
}
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -87,7 +87,7 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -103,7 +103,7 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
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);
|
||||
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle));
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the bounce
|
||||
@ -112,12 +112,12 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.f, 0.f, 0.f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*eval = make_float3(0.f, 0.f, 0.f);
|
||||
*eval = zero_spectrum();
|
||||
*pdf = 0.0f;
|
||||
}
|
||||
|
||||
@ -135,10 +135,10 @@ ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
@ -153,23 +153,23 @@ ccl_device float3 bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure
|
||||
|
||||
float angle = safe_acosf(fmaxf(cosRI, 0.0f));
|
||||
|
||||
float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
||||
return *pdf * eval;
|
||||
return make_spectrum(*pdf * eval);
|
||||
}
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -179,7 +179,7 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -204,7 +204,7 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
|
||||
/* 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);
|
||||
*eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle));
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
*domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
|
||||
@ -213,12 +213,12 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd,
|
||||
const float3 weight,
|
||||
const Spectrum weight,
|
||||
uint32_t path_flag)
|
||||
{
|
||||
/* Check cutoff weight. */
|
||||
@ -59,22 +59,22 @@ ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd,
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_transparent_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_transparent_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_transparent_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_transparent_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc,
|
||||
@ -84,7 +84,7 @@ ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -97,7 +97,7 @@ ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc,
|
||||
*domega_in_dy = -dIdy;
|
||||
#endif
|
||||
*pdf = 1;
|
||||
*eval = make_float3(1, 1, 1);
|
||||
*eval = one_spectrum();
|
||||
return LABEL_TRANSMIT | LABEL_TRANSPARENT;
|
||||
}
|
||||
|
||||
|
@ -110,8 +110,8 @@ ccl_device float schlick_fresnel(float u)
|
||||
}
|
||||
|
||||
/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
|
||||
ccl_device_forceinline float3
|
||||
interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0)
|
||||
ccl_device_forceinline Spectrum
|
||||
interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, Spectrum cspec0)
|
||||
{
|
||||
/* Calculate the fresnel interpolation factor
|
||||
* The value from fresnel_dielectric_cos(...) has to be normalized because
|
||||
@ -121,7 +121,7 @@ interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0
|
||||
float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
|
||||
|
||||
/* Blend between white and a specular color with respect to the fresnel */
|
||||
return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
|
||||
return cspec0 * (1.0f - FH) + make_spectrum(FH);
|
||||
}
|
||||
|
||||
ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N)
|
||||
|
@ -8,8 +8,8 @@ CCL_NAMESPACE_BEGIN
|
||||
typedef struct Bssrdf {
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
float3 radius;
|
||||
float3 albedo;
|
||||
Spectrum radius;
|
||||
Spectrum albedo;
|
||||
float roughness;
|
||||
float anisotropy;
|
||||
} Bssrdf;
|
||||
@ -69,12 +69,13 @@ ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf,
|
||||
const float fourthirdA = (4.0f / 3.0f) * (1.0f + F_dr) /
|
||||
(1.0f - F_dr); /* From Jensen's `Fdr` ratio formula. */
|
||||
|
||||
const float3 alpha_prime = make_float3(
|
||||
bssrdf_dipole_compute_alpha_prime(bssrdf->albedo.x, fourthirdA),
|
||||
bssrdf_dipole_compute_alpha_prime(bssrdf->albedo.y, fourthirdA),
|
||||
bssrdf_dipole_compute_alpha_prime(bssrdf->albedo.z, fourthirdA));
|
||||
Spectrum alpha_prime;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
GET_SPECTRUM_CHANNEL(alpha_prime, i) = bssrdf_dipole_compute_alpha_prime(
|
||||
GET_SPECTRUM_CHANNEL(bssrdf->albedo, i), fourthirdA);
|
||||
}
|
||||
|
||||
bssrdf->radius *= sqrt(3.0f * (one_float3() - alpha_prime));
|
||||
bssrdf->radius *= sqrt(3.0f * (one_spectrum() - alpha_prime));
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +99,7 @@ ccl_device_inline float bssrdf_burley_fitting(float A)
|
||||
|
||||
/* Scale mean free path length so it gives similar looking result
|
||||
* to Cubic and Gaussian models. */
|
||||
ccl_device_inline float3 bssrdf_burley_compatible_mfp(float3 r)
|
||||
ccl_device_inline Spectrum bssrdf_burley_compatible_mfp(Spectrum r)
|
||||
{
|
||||
return 0.25f * M_1_PI_F * r;
|
||||
}
|
||||
@ -106,11 +107,13 @@ ccl_device_inline float3 bssrdf_burley_compatible_mfp(float3 r)
|
||||
ccl_device void bssrdf_burley_setup(ccl_private Bssrdf *bssrdf)
|
||||
{
|
||||
/* Mean free path length. */
|
||||
const float3 l = bssrdf_burley_compatible_mfp(bssrdf->radius);
|
||||
const Spectrum l = bssrdf_burley_compatible_mfp(bssrdf->radius);
|
||||
/* Surface albedo. */
|
||||
const float3 A = bssrdf->albedo;
|
||||
const float3 s = make_float3(
|
||||
bssrdf_burley_fitting(A.x), bssrdf_burley_fitting(A.y), bssrdf_burley_fitting(A.z));
|
||||
const Spectrum A = bssrdf->albedo;
|
||||
Spectrum s;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
GET_SPECTRUM_CHANNEL(s, i) = bssrdf_burley_fitting(GET_SPECTRUM_CHANNEL(A, i));
|
||||
}
|
||||
|
||||
bssrdf->radius = l / s;
|
||||
}
|
||||
@ -198,22 +201,18 @@ ccl_device void bssrdf_burley_sample(const float d,
|
||||
*h = safe_sqrtf(Rm * Rm - r_ * r_);
|
||||
}
|
||||
|
||||
ccl_device float bssrdf_num_channels(const float3 radius)
|
||||
ccl_device float bssrdf_num_channels(const Spectrum radius)
|
||||
{
|
||||
float channels = 0;
|
||||
if (radius.x > 0.0f) {
|
||||
channels += 1.0f;
|
||||
}
|
||||
if (radius.y > 0.0f) {
|
||||
channels += 1.0f;
|
||||
}
|
||||
if (radius.z > 0.0f) {
|
||||
channels += 1.0f;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
if (GET_SPECTRUM_CHANNEL(radius, i) > 0.0f) {
|
||||
channels += 1.0f;
|
||||
}
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
ccl_device void bssrdf_sample(const float3 radius,
|
||||
ccl_device void bssrdf_sample(const Spectrum radius,
|
||||
float xi,
|
||||
ccl_private float *r,
|
||||
ccl_private float *h)
|
||||
@ -224,39 +223,45 @@ ccl_device void bssrdf_sample(const float3 radius,
|
||||
/* Sample color channel and reuse random number. Only a subset of channels
|
||||
* may be used if their radius was too small to handle as BSSRDF. */
|
||||
xi *= num_channels;
|
||||
sampled_radius = 0.0f;
|
||||
|
||||
if (xi < 1.0f) {
|
||||
sampled_radius = (radius.x > 0.0f) ? radius.x : (radius.y > 0.0f) ? radius.y : radius.z;
|
||||
}
|
||||
else if (xi < 2.0f) {
|
||||
xi -= 1.0f;
|
||||
sampled_radius = (radius.x > 0.0f && radius.y > 0.0f) ? radius.y : radius.z;
|
||||
}
|
||||
else {
|
||||
xi -= 2.0f;
|
||||
sampled_radius = radius.z;
|
||||
float sum = 0.0f;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
const float channel_radius = GET_SPECTRUM_CHANNEL(radius, i);
|
||||
if (channel_radius > 0.0f) {
|
||||
const float next_sum = sum + 1.0f;
|
||||
if (xi < next_sum) {
|
||||
xi -= sum;
|
||||
sampled_radius = channel_radius;
|
||||
break;
|
||||
}
|
||||
sum = next_sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sample BSSRDF. */
|
||||
bssrdf_burley_sample(sampled_radius, xi, r, h);
|
||||
}
|
||||
|
||||
ccl_device_forceinline float3 bssrdf_eval(const float3 radius, float r)
|
||||
ccl_device_forceinline Spectrum bssrdf_eval(const Spectrum radius, float r)
|
||||
{
|
||||
return make_float3(bssrdf_burley_pdf(radius.x, r),
|
||||
bssrdf_burley_pdf(radius.y, r),
|
||||
bssrdf_burley_pdf(radius.z, r));
|
||||
Spectrum result;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
GET_SPECTRUM_CHANNEL(result, i) = bssrdf_burley_pdf(GET_SPECTRUM_CHANNEL(radius, i), r);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float bssrdf_pdf(const float3 radius, float r)
|
||||
ccl_device_forceinline float bssrdf_pdf(const Spectrum radius, float r)
|
||||
{
|
||||
float3 pdf = bssrdf_eval(radius, r);
|
||||
return (pdf.x + pdf.y + pdf.z) / bssrdf_num_channels(radius);
|
||||
Spectrum pdf = bssrdf_eval(radius, r);
|
||||
return reduce_add(pdf) / bssrdf_num_channels(radius);
|
||||
}
|
||||
|
||||
/* Setup */
|
||||
|
||||
ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, float3 weight)
|
||||
ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd,
|
||||
Spectrum weight)
|
||||
{
|
||||
ccl_private Bssrdf *bssrdf = (ccl_private Bssrdf *)closure_alloc(
|
||||
sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
|
||||
@ -294,29 +299,19 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd,
|
||||
}
|
||||
|
||||
/* Verify if the radii are large enough to sample without precision issues. */
|
||||
int bssrdf_channels = 3;
|
||||
float3 diffuse_weight = make_float3(0.0f, 0.0f, 0.0f);
|
||||
int bssrdf_channels = SPECTRUM_CHANNELS;
|
||||
Spectrum diffuse_weight = zero_spectrum();
|
||||
|
||||
if (bssrdf->radius.x < BSSRDF_MIN_RADIUS) {
|
||||
diffuse_weight.x = bssrdf->weight.x;
|
||||
bssrdf->weight.x = 0.0f;
|
||||
bssrdf->radius.x = 0.0f;
|
||||
bssrdf_channels--;
|
||||
}
|
||||
if (bssrdf->radius.y < BSSRDF_MIN_RADIUS) {
|
||||
diffuse_weight.y = bssrdf->weight.y;
|
||||
bssrdf->weight.y = 0.0f;
|
||||
bssrdf->radius.y = 0.0f;
|
||||
bssrdf_channels--;
|
||||
}
|
||||
if (bssrdf->radius.z < BSSRDF_MIN_RADIUS) {
|
||||
diffuse_weight.z = bssrdf->weight.z;
|
||||
bssrdf->weight.z = 0.0f;
|
||||
bssrdf->radius.z = 0.0f;
|
||||
bssrdf_channels--;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
if (GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < BSSRDF_MIN_RADIUS) {
|
||||
GET_SPECTRUM_CHANNEL(diffuse_weight, i) = GET_SPECTRUM_CHANNEL(bssrdf->weight, i);
|
||||
GET_SPECTRUM_CHANNEL(bssrdf->weight, i) = 0.0f;
|
||||
GET_SPECTRUM_CHANNEL(bssrdf->radius, i) = 0.0f;
|
||||
bssrdf_channels--;
|
||||
}
|
||||
}
|
||||
|
||||
if (bssrdf_channels < 3) {
|
||||
if (bssrdf_channels < SPECTRUM_CHANNELS) {
|
||||
/* Add diffuse BSDF if any radius too small. */
|
||||
#ifdef __PRINCIPLED__
|
||||
if (bssrdf->roughness != FLT_MAX) {
|
||||
|
@ -12,7 +12,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* BACKGROUND CLOSURE */
|
||||
|
||||
ccl_device void background_setup(ccl_private ShaderData *sd, const float3 weight)
|
||||
ccl_device void background_setup(ccl_private ShaderData *sd, const Spectrum weight)
|
||||
{
|
||||
if (sd->flag & SD_EMISSION) {
|
||||
sd->closure_emission_background += weight;
|
||||
@ -25,7 +25,7 @@ ccl_device void background_setup(ccl_private ShaderData *sd, const float3 weight
|
||||
|
||||
/* EMISSION CLOSURE */
|
||||
|
||||
ccl_device void emission_setup(ccl_private ShaderData *sd, const float3 weight)
|
||||
ccl_device void emission_setup(ccl_private ShaderData *sd, const Spectrum weight)
|
||||
{
|
||||
if (sd->flag & SD_EMISSION) {
|
||||
sd->closure_emission_background += weight;
|
||||
@ -54,11 +54,11 @@ ccl_device void emissive_sample(const float3 Ng,
|
||||
/* todo: not implemented and used yet */
|
||||
}
|
||||
|
||||
ccl_device float3 emissive_simple_eval(const float3 Ng, const float3 I)
|
||||
ccl_device Spectrum emissive_simple_eval(const float3 Ng, const float3 I)
|
||||
{
|
||||
float res = emissive_pdf(Ng, I);
|
||||
|
||||
return make_float3(res, res, res);
|
||||
return make_spectrum(res);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -7,7 +7,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* VOLUME EXTINCTION */
|
||||
|
||||
ccl_device void volume_extinction_setup(ccl_private ShaderData *sd, float3 weight)
|
||||
ccl_device void volume_extinction_setup(ccl_private ShaderData *sd, Spectrum weight)
|
||||
{
|
||||
if (sd->flag & SD_EXTINCTION) {
|
||||
sd->closure_transparent_extinction += weight;
|
||||
@ -48,10 +48,10 @@ ccl_device int volume_henyey_greenstein_setup(ccl_private HenyeyGreensteinVolume
|
||||
return SD_SCATTER;
|
||||
}
|
||||
|
||||
ccl_device float3 volume_henyey_greenstein_eval_phase(ccl_private const ShaderVolumeClosure *svc,
|
||||
const float3 I,
|
||||
float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum volume_henyey_greenstein_eval_phase(ccl_private const ShaderVolumeClosure *svc,
|
||||
const float3 I,
|
||||
float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
float g = svc->g;
|
||||
|
||||
@ -64,7 +64,7 @@ ccl_device float3 volume_henyey_greenstein_eval_phase(ccl_private const ShaderVo
|
||||
*pdf = single_peaked_henyey_greenstein(cos_theta, g);
|
||||
}
|
||||
|
||||
return make_float3(*pdf, *pdf, *pdf);
|
||||
return make_spectrum(*pdf);
|
||||
}
|
||||
|
||||
ccl_device float3
|
||||
@ -105,7 +105,7 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo
|
||||
float3 dIdy,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float3 *domega_in_dx,
|
||||
ccl_private float3 *domega_in_dy,
|
||||
@ -115,7 +115,7 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo
|
||||
|
||||
/* note that I points towards the viewer and so is used negated */
|
||||
*omega_in = henyey_greenstrein_sample(-I, g, randu, randv, pdf);
|
||||
*eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */
|
||||
*eval = make_spectrum(*pdf); /* perfect importance sampling */
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
/* todo: implement ray differential estimation */
|
||||
@ -128,10 +128,10 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo
|
||||
|
||||
/* VOLUME CLOSURE */
|
||||
|
||||
ccl_device float3 volume_phase_eval(ccl_private const ShaderData *sd,
|
||||
ccl_private const ShaderVolumeClosure *svc,
|
||||
float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum volume_phase_eval(ccl_private const ShaderData *sd,
|
||||
ccl_private const ShaderVolumeClosure *svc,
|
||||
float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
return volume_henyey_greenstein_eval_phase(svc, sd->I, omega_in, pdf);
|
||||
}
|
||||
@ -140,7 +140,7 @@ ccl_device int volume_phase_sample(ccl_private const ShaderData *sd,
|
||||
ccl_private const ShaderVolumeClosure *svc,
|
||||
float randu,
|
||||
float randv,
|
||||
ccl_private float3 *eval,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private differential3 *domega_in,
|
||||
ccl_private float *pdf)
|
||||
@ -164,45 +164,44 @@ ccl_device int volume_phase_sample(ccl_private const ShaderData *sd,
|
||||
* unnecessary work in volumes and subsurface scattering. */
|
||||
#define VOLUME_THROUGHPUT_EPSILON 1e-6f
|
||||
|
||||
ccl_device float3 volume_color_transmittance(float3 sigma, float t)
|
||||
ccl_device Spectrum volume_color_transmittance(Spectrum sigma, float t)
|
||||
{
|
||||
return exp(-sigma * t);
|
||||
}
|
||||
|
||||
ccl_device float volume_channel_get(float3 value, int channel)
|
||||
ccl_device float volume_channel_get(Spectrum value, int channel)
|
||||
{
|
||||
return (channel == 0) ? value.x : ((channel == 1) ? value.y : value.z);
|
||||
return GET_SPECTRUM_CHANNEL(value, channel);
|
||||
}
|
||||
|
||||
ccl_device int volume_sample_channel(float3 albedo,
|
||||
float3 throughput,
|
||||
ccl_device int volume_sample_channel(Spectrum albedo,
|
||||
Spectrum throughput,
|
||||
float rand,
|
||||
ccl_private float3 *pdf)
|
||||
ccl_private Spectrum *pdf)
|
||||
{
|
||||
/* Sample color channel proportional to throughput and single scattering
|
||||
* albedo, to significantly reduce noise with many bounce, following:
|
||||
*
|
||||
* "Practical and Controllable Subsurface Scattering for Production Path
|
||||
* Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */
|
||||
float3 weights = fabs(throughput * albedo);
|
||||
float sum_weights = weights.x + weights.y + weights.z;
|
||||
Spectrum weights = fabs(throughput * albedo);
|
||||
float sum_weights = reduce_add(weights);
|
||||
|
||||
if (sum_weights > 0.0f) {
|
||||
*pdf = weights / sum_weights;
|
||||
}
|
||||
else {
|
||||
*pdf = make_float3(1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f);
|
||||
*pdf = make_spectrum(1.0f / SPECTRUM_CHANNELS);
|
||||
}
|
||||
|
||||
if (rand < pdf->x) {
|
||||
return 0;
|
||||
}
|
||||
else if (rand < pdf->x + pdf->y) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 2;
|
||||
float pdf_sum = 0.0f;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
pdf_sum += GET_SPECTRUM_CHANNEL(*pdf, i);
|
||||
if (rand < pdf_sum) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return SPECTRUM_CHANNELS - 1;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -21,10 +21,10 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval,
|
||||
const ClosureType closure_type,
|
||||
float3 value)
|
||||
Spectrum value)
|
||||
{
|
||||
eval->diffuse = zero_float3();
|
||||
eval->glossy = zero_float3();
|
||||
eval->diffuse = zero_spectrum();
|
||||
eval->glossy = zero_spectrum();
|
||||
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) {
|
||||
eval->diffuse = value;
|
||||
@ -38,7 +38,7 @@ ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval,
|
||||
|
||||
ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval,
|
||||
const ClosureType closure_type,
|
||||
float3 value)
|
||||
Spectrum value)
|
||||
{
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) {
|
||||
eval->diffuse += value;
|
||||
@ -62,26 +62,26 @@ ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, float value)
|
||||
eval->sum *= value;
|
||||
}
|
||||
|
||||
ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, float3 value)
|
||||
ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, Spectrum value)
|
||||
{
|
||||
eval->diffuse *= value;
|
||||
eval->glossy *= value;
|
||||
eval->sum *= value;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 bsdf_eval_sum(ccl_private const BsdfEval *eval)
|
||||
ccl_device_inline Spectrum bsdf_eval_sum(ccl_private const BsdfEval *eval)
|
||||
{
|
||||
return eval->sum;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 bsdf_eval_pass_diffuse_weight(ccl_private const BsdfEval *eval)
|
||||
ccl_device_inline Spectrum bsdf_eval_pass_diffuse_weight(ccl_private const BsdfEval *eval)
|
||||
{
|
||||
/* Ratio of diffuse weight to recover proportions for writing to render pass.
|
||||
* We assume reflection, transmission and volume scatter to be exclusive. */
|
||||
return safe_divide(eval->diffuse, eval->sum);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 bsdf_eval_pass_glossy_weight(ccl_private const BsdfEval *eval)
|
||||
ccl_device_inline Spectrum bsdf_eval_pass_glossy_weight(ccl_private const BsdfEval *eval)
|
||||
{
|
||||
/* Ratio of glossy weight to recover proportions for writing to render pass.
|
||||
* We assume reflection, transmission and volume scatter to be exclusive. */
|
||||
@ -95,7 +95,9 @@ ccl_device_inline float3 bsdf_eval_pass_glossy_weight(ccl_private const BsdfEval
|
||||
* to render buffers instead of using per-thread memory, and to avoid the
|
||||
* impact of clamping on other contributions. */
|
||||
|
||||
ccl_device_forceinline void kernel_accum_clamp(KernelGlobals kg, ccl_private float3 *L, int bounce)
|
||||
ccl_device_forceinline void kernel_accum_clamp(KernelGlobals kg,
|
||||
ccl_private Spectrum *L,
|
||||
int bounce)
|
||||
{
|
||||
#ifdef __KERNEL_DEBUG_NAN__
|
||||
if (!isfinite_safe(*L)) {
|
||||
@ -154,7 +156,7 @@ ccl_device_inline int kernel_accum_sample(KernelGlobals kg,
|
||||
|
||||
ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg,
|
||||
const int sample,
|
||||
const float3 contribution,
|
||||
const Spectrum contribution,
|
||||
ccl_global float *ccl_restrict buffer)
|
||||
{
|
||||
/* Adaptive Sampling. Fill the additional buffer with the odd samples and calculate our stopping
|
||||
@ -167,9 +169,13 @@ ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg,
|
||||
}
|
||||
|
||||
if (sample_is_even(kernel_data.integrator.sampling_pattern, sample)) {
|
||||
kernel_write_pass_float4(
|
||||
buffer + kernel_data.film.pass_adaptive_aux_buffer,
|
||||
make_float4(contribution.x * 2.0f, contribution.y * 2.0f, contribution.z * 2.0f, 0.0f));
|
||||
const float3 contribution_rgb = spectrum_to_rgb(contribution);
|
||||
|
||||
kernel_write_pass_float4(buffer + kernel_data.film.pass_adaptive_aux_buffer,
|
||||
make_float4(contribution_rgb.x * 2.0f,
|
||||
contribution_rgb.y * 2.0f,
|
||||
contribution_rgb.z * 2.0f,
|
||||
0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +192,7 @@ ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg,
|
||||
|
||||
ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg,
|
||||
const uint32_t path_flag,
|
||||
const float3 contribution,
|
||||
const Spectrum contribution,
|
||||
ccl_global float *ccl_restrict buffer)
|
||||
{
|
||||
if (!kernel_data.integrator.has_shadow_catcher) {
|
||||
@ -198,7 +204,7 @@ ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg,
|
||||
|
||||
/* Matte pass. */
|
||||
if (kernel_shadow_catcher_is_matte_path(path_flag)) {
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow_catcher_matte, contribution);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow_catcher_matte, contribution);
|
||||
/* NOTE: Accumulate the combined pass and to the samples count pass, so that the adaptive
|
||||
* sampling is based on how noisy the combined pass is as if there were no catchers in the
|
||||
* scene. */
|
||||
@ -206,7 +212,7 @@ ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg,
|
||||
|
||||
/* Shadow catcher pass. */
|
||||
if (kernel_shadow_catcher_is_object_pass(path_flag)) {
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow_catcher, contribution);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow_catcher, contribution);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -215,7 +221,7 @@ ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg,
|
||||
|
||||
ccl_device bool kernel_accum_shadow_catcher_transparent(KernelGlobals kg,
|
||||
const uint32_t path_flag,
|
||||
const float3 contribution,
|
||||
const Spectrum contribution,
|
||||
const float transparent,
|
||||
ccl_global float *ccl_restrict buffer)
|
||||
{
|
||||
@ -232,9 +238,11 @@ ccl_device bool kernel_accum_shadow_catcher_transparent(KernelGlobals kg,
|
||||
|
||||
/* Matte pass. */
|
||||
if (kernel_shadow_catcher_is_matte_path(path_flag)) {
|
||||
const float3 contribution_rgb = spectrum_to_rgb(contribution);
|
||||
|
||||
kernel_write_pass_float4(
|
||||
buffer + kernel_data.film.pass_shadow_catcher_matte,
|
||||
make_float4(contribution.x, contribution.y, contribution.z, transparent));
|
||||
make_float4(contribution_rgb.x, contribution_rgb.y, contribution_rgb.z, transparent));
|
||||
/* NOTE: Accumulate the combined pass and to the samples count pass, so that the adaptive
|
||||
* sampling is based on how noisy the combined pass is as if there were no catchers in the
|
||||
* scene. */
|
||||
@ -245,7 +253,7 @@ ccl_device bool kernel_accum_shadow_catcher_transparent(KernelGlobals kg,
|
||||
/* NOTE: The transparency of the shadow catcher pass is ignored. It is not needed for the
|
||||
* calculation and the alpha channel of the pass contains numbers of samples contributed to a
|
||||
* pixel of the pass. */
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow_catcher, contribution);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow_catcher, contribution);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -279,7 +287,7 @@ ccl_device void kernel_accum_shadow_catcher_transparent_only(KernelGlobals kg,
|
||||
ccl_device_inline void kernel_accum_combined_pass(KernelGlobals kg,
|
||||
const uint32_t path_flag,
|
||||
const int sample,
|
||||
const float3 contribution,
|
||||
const Spectrum contribution,
|
||||
ccl_global float *ccl_restrict buffer)
|
||||
{
|
||||
#ifdef __SHADOW_CATCHER__
|
||||
@ -289,7 +297,7 @@ ccl_device_inline void kernel_accum_combined_pass(KernelGlobals kg,
|
||||
#endif
|
||||
|
||||
if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) {
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_combined, contribution);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_combined, contribution);
|
||||
}
|
||||
|
||||
kernel_accum_adaptive_buffer(kg, sample, contribution, buffer);
|
||||
@ -299,7 +307,7 @@ ccl_device_inline void kernel_accum_combined_pass(KernelGlobals kg,
|
||||
ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg,
|
||||
const uint32_t path_flag,
|
||||
const int sample,
|
||||
const float3 contribution,
|
||||
const Spectrum contribution,
|
||||
const float transparent,
|
||||
ccl_global float *ccl_restrict
|
||||
buffer)
|
||||
@ -311,9 +319,11 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg,
|
||||
#endif
|
||||
|
||||
if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) {
|
||||
const float3 contribution_rgb = spectrum_to_rgb(contribution);
|
||||
|
||||
kernel_write_pass_float4(
|
||||
buffer + kernel_data.film.pass_combined,
|
||||
make_float4(contribution.x, contribution.y, contribution.z, transparent));
|
||||
make_float4(contribution_rgb.x, contribution_rgb.y, contribution_rgb.z, transparent));
|
||||
}
|
||||
|
||||
kernel_accum_adaptive_buffer(kg, sample, contribution, buffer);
|
||||
@ -323,7 +333,7 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg,
|
||||
ccl_device_inline void kernel_accum_emission_or_background_pass(
|
||||
KernelGlobals kg,
|
||||
ConstIntegratorState state,
|
||||
float3 contribution,
|
||||
Spectrum contribution,
|
||||
ccl_global float *ccl_restrict buffer,
|
||||
const int pass,
|
||||
const int lightgroup = LIGHTGROUP_NONE)
|
||||
@ -340,17 +350,18 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(
|
||||
# ifdef __DENOISING_FEATURES__
|
||||
if (path_flag & PATH_RAY_DENOISING_FEATURES) {
|
||||
if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) {
|
||||
const float3 denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
const Spectrum denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
state, path, denoising_feature_throughput);
|
||||
const float3 denoising_albedo = denoising_feature_throughput * contribution;
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo);
|
||||
const Spectrum denoising_albedo = denoising_feature_throughput * contribution;
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo,
|
||||
denoising_albedo);
|
||||
}
|
||||
}
|
||||
# endif /* __DENOISING_FEATURES__ */
|
||||
|
||||
if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) {
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
|
||||
contribution);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
|
||||
contribution);
|
||||
}
|
||||
|
||||
if (!(path_flag & PATH_RAY_ANY_PASS)) {
|
||||
@ -366,15 +377,15 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(
|
||||
|
||||
if (path_flag & PATH_RAY_SURFACE_PASS) {
|
||||
/* Indirectly visible through reflection. */
|
||||
const float3 diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
|
||||
const float3 glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight);
|
||||
const Spectrum diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
|
||||
const Spectrum glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight);
|
||||
|
||||
/* Glossy */
|
||||
const int glossy_pass_offset = ((INTEGRATOR_STATE(state, path, bounce) == 1) ?
|
||||
kernel_data.film.pass_glossy_direct :
|
||||
kernel_data.film.pass_glossy_indirect);
|
||||
if (glossy_pass_offset != PASS_UNUSED) {
|
||||
kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_weight * contribution);
|
||||
kernel_write_pass_spectrum(buffer + glossy_pass_offset, glossy_weight * contribution);
|
||||
}
|
||||
|
||||
/* Transmission */
|
||||
@ -385,9 +396,9 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(
|
||||
if (transmission_pass_offset != PASS_UNUSED) {
|
||||
/* Transmission is what remains if not diffuse and glossy, not stored explicitly to save
|
||||
* GPU memory. */
|
||||
const float3 transmission_weight = one_float3() - diffuse_weight - glossy_weight;
|
||||
kernel_write_pass_float3(buffer + transmission_pass_offset,
|
||||
transmission_weight * contribution);
|
||||
const Spectrum transmission_weight = one_spectrum() - diffuse_weight - glossy_weight;
|
||||
kernel_write_pass_spectrum(buffer + transmission_pass_offset,
|
||||
transmission_weight * contribution);
|
||||
}
|
||||
|
||||
/* Reconstruct diffuse subset of throughput. */
|
||||
@ -408,7 +419,7 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(
|
||||
|
||||
/* Single write call for GPU coherence. */
|
||||
if (pass_offset != PASS_UNUSED) {
|
||||
kernel_write_pass_float3(buffer + pass_offset, contribution);
|
||||
kernel_write_pass_spectrum(buffer + pass_offset, contribution);
|
||||
}
|
||||
#endif /* __PASSES__ */
|
||||
}
|
||||
@ -419,7 +430,7 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
|
||||
ccl_global float *ccl_restrict render_buffer)
|
||||
{
|
||||
/* The throughput for shadow paths already contains the light shader evaluation. */
|
||||
float3 contribution = INTEGRATOR_STATE(state, shadow_path, throughput);
|
||||
Spectrum contribution = INTEGRATOR_STATE(state, shadow_path, throughput);
|
||||
kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, shadow_path, bounce));
|
||||
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, shadow_path, render_pixel_index);
|
||||
@ -433,10 +444,10 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
|
||||
/* Ambient occlusion. */
|
||||
if (path_flag & PATH_RAY_SHADOW_FOR_AO) {
|
||||
if ((kernel_data.kernel_features & KERNEL_FEATURE_AO_PASS) && (path_flag & PATH_RAY_CAMERA)) {
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, contribution);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_ao, contribution);
|
||||
}
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) {
|
||||
const float3 ao_weight = INTEGRATOR_STATE(state, shadow_path, unshadowed_throughput);
|
||||
const Spectrum ao_weight = INTEGRATOR_STATE(state, shadow_path, unshadowed_throughput);
|
||||
kernel_accum_combined_pass(kg, path_flag, sample, contribution * ao_weight, buffer);
|
||||
}
|
||||
return;
|
||||
@ -458,8 +469,8 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
|
||||
/* Write lightgroup pass. LIGHTGROUP_NONE is ~0 so decode from unsigned to signed */
|
||||
const int lightgroup = (int)(INTEGRATOR_STATE(state, shadow_path, lightgroup)) - 1;
|
||||
if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) {
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
|
||||
contribution);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
|
||||
contribution);
|
||||
}
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
@ -467,15 +478,15 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
|
||||
|
||||
if (path_flag & PATH_RAY_SURFACE_PASS) {
|
||||
/* Indirectly visible through reflection. */
|
||||
const float3 diffuse_weight = INTEGRATOR_STATE(state, shadow_path, pass_diffuse_weight);
|
||||
const float3 glossy_weight = INTEGRATOR_STATE(state, shadow_path, pass_glossy_weight);
|
||||
const Spectrum diffuse_weight = INTEGRATOR_STATE(state, shadow_path, pass_diffuse_weight);
|
||||
const Spectrum glossy_weight = INTEGRATOR_STATE(state, shadow_path, pass_glossy_weight);
|
||||
|
||||
/* Glossy */
|
||||
const int glossy_pass_offset = ((INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ?
|
||||
kernel_data.film.pass_glossy_direct :
|
||||
kernel_data.film.pass_glossy_indirect);
|
||||
if (glossy_pass_offset != PASS_UNUSED) {
|
||||
kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_weight * contribution);
|
||||
kernel_write_pass_spectrum(buffer + glossy_pass_offset, glossy_weight * contribution);
|
||||
}
|
||||
|
||||
/* Transmission */
|
||||
@ -486,9 +497,9 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
|
||||
if (transmission_pass_offset != PASS_UNUSED) {
|
||||
/* Transmission is what remains if not diffuse and glossy, not stored explicitly to save
|
||||
* GPU memory. */
|
||||
const float3 transmission_weight = one_float3() - diffuse_weight - glossy_weight;
|
||||
kernel_write_pass_float3(buffer + transmission_pass_offset,
|
||||
transmission_weight * contribution);
|
||||
const Spectrum transmission_weight = one_spectrum() - diffuse_weight - glossy_weight;
|
||||
kernel_write_pass_spectrum(buffer + transmission_pass_offset,
|
||||
transmission_weight * contribution);
|
||||
}
|
||||
|
||||
/* Reconstruct diffuse subset of throughput. */
|
||||
@ -508,19 +519,19 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
|
||||
|
||||
/* Single write call for GPU coherence. */
|
||||
if (pass_offset != PASS_UNUSED) {
|
||||
kernel_write_pass_float3(buffer + pass_offset, contribution);
|
||||
kernel_write_pass_spectrum(buffer + pass_offset, contribution);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write shadow pass. */
|
||||
if (kernel_data.film.pass_shadow != PASS_UNUSED && (path_flag & PATH_RAY_SHADOW_FOR_LIGHT) &&
|
||||
(path_flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
|
||||
const float3 unshadowed_throughput = INTEGRATOR_STATE(
|
||||
const Spectrum unshadowed_throughput = INTEGRATOR_STATE(
|
||||
state, shadow_path, unshadowed_throughput);
|
||||
const float3 shadowed_throughput = INTEGRATOR_STATE(state, shadow_path, throughput);
|
||||
const float3 shadow = safe_divide(shadowed_throughput, unshadowed_throughput) *
|
||||
kernel_data.film.pass_shadow_scale;
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow, shadow);
|
||||
const Spectrum shadowed_throughput = INTEGRATOR_STATE(state, shadow_path, throughput);
|
||||
const Spectrum shadow = safe_divide(shadowed_throughput, unshadowed_throughput) *
|
||||
kernel_data.film.pass_shadow_scale;
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow, shadow);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -560,12 +571,12 @@ ccl_device_inline void kernel_accum_holdout(KernelGlobals kg,
|
||||
* Includes transparency, matching kernel_accum_transparent. */
|
||||
ccl_device_inline void kernel_accum_background(KernelGlobals kg,
|
||||
ConstIntegratorState state,
|
||||
const float3 L,
|
||||
const Spectrum L,
|
||||
const float transparent,
|
||||
const bool is_transparent_background_ray,
|
||||
ccl_global float *ccl_restrict render_buffer)
|
||||
{
|
||||
float3 contribution = float3(INTEGRATOR_STATE(state, path, throughput)) * L;
|
||||
Spectrum contribution = INTEGRATOR_STATE(state, path, throughput) * L;
|
||||
kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1);
|
||||
|
||||
ccl_global float *buffer = kernel_accum_pixel_render_buffer(kg, state, render_buffer);
|
||||
@ -590,11 +601,11 @@ ccl_device_inline void kernel_accum_background(KernelGlobals kg,
|
||||
/* Write emission to render buffer. */
|
||||
ccl_device_inline void kernel_accum_emission(KernelGlobals kg,
|
||||
ConstIntegratorState state,
|
||||
const float3 L,
|
||||
const Spectrum L,
|
||||
ccl_global float *ccl_restrict render_buffer,
|
||||
const int lightgroup = LIGHTGROUP_NONE)
|
||||
{
|
||||
float3 contribution = L;
|
||||
Spectrum contribution = L;
|
||||
kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1);
|
||||
|
||||
ccl_global float *buffer = kernel_accum_pixel_render_buffer(kg, state, render_buffer);
|
||||
|
@ -40,7 +40,7 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
|
||||
ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer);
|
||||
|
||||
if (kernel_data.film.pass_denoising_depth != PASS_UNUSED) {
|
||||
const float3 denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
const Spectrum denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
state, path, denoising_feature_throughput);
|
||||
const float denoising_depth = ensure_finite(average(denoising_feature_throughput) *
|
||||
sd->ray_length);
|
||||
@ -48,8 +48,8 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
|
||||
}
|
||||
|
||||
float3 normal = zero_float3();
|
||||
float3 diffuse_albedo = zero_float3();
|
||||
float3 specular_albedo = zero_float3();
|
||||
Spectrum diffuse_albedo = zero_spectrum();
|
||||
Spectrum specular_albedo = zero_spectrum();
|
||||
float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f;
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
@ -63,7 +63,7 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
|
||||
normal += sc->N * sc->sample_weight;
|
||||
sum_weight += sc->sample_weight;
|
||||
|
||||
float3 closure_albedo = sc->weight;
|
||||
Spectrum closure_albedo = sc->weight;
|
||||
/* Closures that include a Fresnel term typically have weights close to 1 even though their
|
||||
* actual contribution is significantly lower.
|
||||
* To account for this, we scale their weight by the average fresnel factor (the same is also
|
||||
@ -113,10 +113,12 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
|
||||
}
|
||||
|
||||
if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) {
|
||||
const float3 denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
const Spectrum denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
state, path, denoising_feature_throughput);
|
||||
const float3 denoising_albedo = ensure_finite(denoising_feature_throughput * diffuse_albedo);
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo);
|
||||
const Spectrum denoising_albedo = ensure_finite(denoising_feature_throughput *
|
||||
diffuse_albedo);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo,
|
||||
denoising_albedo);
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(state, path, flag) &= ~PATH_RAY_DENOISING_FEATURES;
|
||||
@ -128,13 +130,13 @@ ccl_device_forceinline void kernel_write_denoising_features_surface(
|
||||
|
||||
ccl_device_forceinline void kernel_write_denoising_features_volume(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 albedo,
|
||||
const Spectrum albedo,
|
||||
const bool scatter,
|
||||
ccl_global float *ccl_restrict
|
||||
render_buffer)
|
||||
{
|
||||
ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer);
|
||||
const float3 denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
const Spectrum denoising_feature_throughput = INTEGRATOR_STATE(
|
||||
state, path, denoising_feature_throughput);
|
||||
|
||||
if (scatter && kernel_data.film.pass_denoising_normal != PASS_UNUSED) {
|
||||
@ -148,8 +150,8 @@ ccl_device_forceinline void kernel_write_denoising_features_volume(KernelGlobals
|
||||
|
||||
if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) {
|
||||
/* Write albedo. */
|
||||
const float3 denoising_albedo = ensure_finite(denoising_feature_throughput * albedo);
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo);
|
||||
const Spectrum denoising_albedo = ensure_finite(denoising_feature_throughput * albedo);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo);
|
||||
}
|
||||
}
|
||||
#endif /* __DENOISING_FEATURES__ */
|
||||
@ -228,7 +230,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals kg,
|
||||
}
|
||||
|
||||
if (kernel_data.film.cryptomatte_passes) {
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const float matte_weight = average(throughput) *
|
||||
(1.0f - average(shader_bsdf_transparency(kg, sd)));
|
||||
if (matte_weight > 0.0f) {
|
||||
@ -252,19 +254,19 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals kg,
|
||||
}
|
||||
|
||||
if (flag & PASSMASK(DIFFUSE_COLOR)) {
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color,
|
||||
shader_bsdf_diffuse(kg, sd) * throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_diffuse_color,
|
||||
shader_bsdf_diffuse(kg, sd) * throughput);
|
||||
}
|
||||
if (flag & PASSMASK(GLOSSY_COLOR)) {
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color,
|
||||
shader_bsdf_glossy(kg, sd) * throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_glossy_color,
|
||||
shader_bsdf_glossy(kg, sd) * throughput);
|
||||
}
|
||||
if (flag & PASSMASK(TRANSMISSION_COLOR)) {
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color,
|
||||
shader_bsdf_transmission(kg, sd) * throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_write_pass_spectrum(buffer + kernel_data.film.pass_transmission_color,
|
||||
shader_bsdf_transmission(kg, sd) * throughput);
|
||||
}
|
||||
if (flag & PASSMASK(MIST)) {
|
||||
/* Bring depth into 0..1 range. */
|
||||
@ -287,8 +289,8 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals kg,
|
||||
mist = powf(mist, mist_falloff);
|
||||
|
||||
/* Modulate by transparency */
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const float3 alpha = shader_bsdf_alpha(kg, sd);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum alpha = shader_bsdf_alpha(kg, sd);
|
||||
const float mist_output = (1.0f - mist) * average(throughput * alpha);
|
||||
|
||||
/* Note that the final value in the render buffer we want is 1 - mist_output,
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
|
||||
#ifdef __KERNEL_GPU__
|
||||
# define __ATOMIC_PASS_WRITE__
|
||||
#endif
|
||||
@ -36,6 +38,12 @@ ccl_device_inline void kernel_write_pass_float3(ccl_global float *ccl_restrict b
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_write_pass_spectrum(ccl_global float *ccl_restrict buffer,
|
||||
Spectrum value)
|
||||
{
|
||||
kernel_write_pass_float3(buffer, spectrum_to_rgb(value));
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_write_pass_float4(ccl_global float *ccl_restrict buffer,
|
||||
float4 value)
|
||||
{
|
||||
|
@ -634,9 +634,9 @@ mnee_sample_bsdf_dh(ClosureType type, float alpha_x, float alpha_y, float sample
|
||||
* We assume here that the pdf (in half-vector measure) is the same as
|
||||
* the one calculation when sampling the microfacet normals from the
|
||||
* specular chain above: this allows us to simplify the bsdf weight */
|
||||
ccl_device_forceinline float3 mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure,
|
||||
float3 wi,
|
||||
float3 wo)
|
||||
ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure,
|
||||
float3 wi,
|
||||
float3 wo)
|
||||
{
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)closure;
|
||||
|
||||
@ -835,7 +835,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
||||
1;
|
||||
INTEGRATOR_STATE_WRITE(state, path, bounce) = bounce + vertex_count;
|
||||
|
||||
float3 light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time);
|
||||
Spectrum light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time);
|
||||
bsdf_eval_mul(throughput, light_eval / ls->pdf);
|
||||
|
||||
/* Generalized geometry term. */
|
||||
@ -924,7 +924,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
||||
/* Evaluate product term inside eq.6 at solution interface. vi
|
||||
* divided by corresponding sampled pdf:
|
||||
* fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h| */
|
||||
float3 bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo);
|
||||
Spectrum bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo);
|
||||
bsdf_eval_mul(throughput, bsdf_contribution);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg,
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = 0.0f;
|
||||
INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = FLT_MAX;
|
||||
INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = 1.0f;
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = make_float3(1.0f, 1.0f, 1.0f);
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = one_spectrum();
|
||||
|
||||
#ifdef __MNEE__
|
||||
INTEGRATOR_STATE_WRITE(state, path, mnee) = 0;
|
||||
@ -74,7 +74,7 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg,
|
||||
#ifdef __DENOISING_FEATURES__
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_DENOISING) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_DENOISING_FEATURES;
|
||||
INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) = one_float3();
|
||||
INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) = one_spectrum();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -10,9 +10,9 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device float3 integrator_eval_background_shader(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_global float *ccl_restrict render_buffer)
|
||||
ccl_device Spectrum integrator_eval_background_shader(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_global float *ccl_restrict render_buffer)
|
||||
{
|
||||
#ifdef __BACKGROUND__
|
||||
const int shader = kernel_data.background.surface_shader;
|
||||
@ -26,11 +26,11 @@ ccl_device float3 integrator_eval_background_shader(KernelGlobals kg,
|
||||
((shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) ||
|
||||
((shader & SHADER_EXCLUDE_CAMERA) && (path_flag & PATH_RAY_CAMERA)) ||
|
||||
((shader & SHADER_EXCLUDE_SCATTER) && (path_flag & PATH_RAY_VOLUME_SCATTER)))
|
||||
return zero_float3();
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
/* Use fast constant background color if available. */
|
||||
float3 L = zero_float3();
|
||||
Spectrum L = zero_spectrum();
|
||||
if (!shader_constant_emission_eval(kg, shader, &L)) {
|
||||
/* Evaluate background shader. */
|
||||
|
||||
@ -73,7 +73,7 @@ ccl_device float3 integrator_eval_background_shader(KernelGlobals kg,
|
||||
|
||||
return L;
|
||||
#else
|
||||
return make_float3(0.8f, 0.8f, 0.8f);
|
||||
return make_spectrum(0.8f);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -117,8 +117,8 @@ ccl_device_inline void integrate_background(KernelGlobals kg,
|
||||
#endif /* __MNEE__ */
|
||||
|
||||
/* Evaluate background shader. */
|
||||
float3 L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) :
|
||||
zero_float3();
|
||||
Spectrum L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) :
|
||||
zero_spectrum();
|
||||
|
||||
/* When using the ao bounces approximation, adjust background
|
||||
* shader intensity with ao factor. */
|
||||
@ -169,7 +169,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
||||
/* TODO: does aliasing like this break automatic SoA in CUDA? */
|
||||
ShaderDataTinyStorage emission_sd_storage;
|
||||
ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
|
||||
float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time);
|
||||
Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time);
|
||||
if (is_zero(light_eval)) {
|
||||
return;
|
||||
}
|
||||
@ -184,7 +184,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
||||
}
|
||||
|
||||
/* Write to render buffer. */
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_accum_emission(
|
||||
kg, state, throughput * light_eval, render_buffer, kernel_data.background.lightgroup);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
|
||||
/* TODO: does aliasing like this break automatic SoA in CUDA? */
|
||||
ShaderDataTinyStorage emission_sd_storage;
|
||||
ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
|
||||
float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time);
|
||||
Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time);
|
||||
if (is_zero(light_eval)) {
|
||||
return;
|
||||
}
|
||||
@ -66,7 +66,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
|
||||
}
|
||||
|
||||
/* Write to render buffer. */
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_accum_emission(kg, state, throughput * light_eval, render_buffer, ls.group);
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,9 @@ ccl_device_inline bool shadow_intersections_has_remaining(const uint num_hits)
|
||||
}
|
||||
|
||||
#ifdef __TRANSPARENT_SHADOWS__
|
||||
ccl_device_inline float3 integrate_transparent_surface_shadow(KernelGlobals kg,
|
||||
IntegratorShadowState state,
|
||||
const int hit)
|
||||
ccl_device_inline Spectrum integrate_transparent_surface_shadow(KernelGlobals kg,
|
||||
IntegratorShadowState state,
|
||||
const int hit)
|
||||
{
|
||||
PROFILING_INIT(kg, PROFILING_SHADE_SHADOW_SURFACE);
|
||||
|
||||
@ -58,7 +58,7 @@ ccl_device_inline void integrate_transparent_volume_shadow(KernelGlobals kg,
|
||||
IntegratorShadowState state,
|
||||
const int hit,
|
||||
const int num_recorded_hits,
|
||||
ccl_private float3 *ccl_restrict
|
||||
ccl_private Spectrum *ccl_restrict
|
||||
throughput)
|
||||
{
|
||||
PROFILING_INIT(kg, PROFILING_SHADE_SHADOW_VOLUME);
|
||||
@ -100,7 +100,7 @@ ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg,
|
||||
if (hit < num_recorded_hits || !shadow_intersections_has_remaining(num_hits)) {
|
||||
# ifdef __VOLUME__
|
||||
if (!integrator_state_shadow_volume_stack_is_empty(kg, state)) {
|
||||
float3 throughput = INTEGRATOR_STATE(state, shadow_path, throughput);
|
||||
Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput);
|
||||
integrate_transparent_volume_shadow(kg, state, hit, num_recorded_hits, &throughput);
|
||||
if (is_zero(throughput)) {
|
||||
return true;
|
||||
@ -113,8 +113,8 @@ ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg,
|
||||
|
||||
/* Surface shaders. */
|
||||
if (hit < num_recorded_hits) {
|
||||
const float3 shadow = integrate_transparent_surface_shadow(kg, state, hit);
|
||||
const float3 throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow;
|
||||
const Spectrum shadow = integrate_transparent_surface_shadow(kg, state, hit);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow;
|
||||
if (is_zero(throughput)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ ccl_device_forceinline bool integrate_surface_holdout(KernelGlobals kg,
|
||||
|
||||
if (((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
|
||||
(path_flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
|
||||
const float3 holdout_weight = shader_holdout_apply(kg, sd);
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum holdout_weight = shader_holdout_apply(kg, sd);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const float transparent = average(holdout_weight * throughput);
|
||||
kernel_accum_holdout(kg, state, path_flag, transparent, render_buffer);
|
||||
if (isequal(holdout_weight, one_float3())) {
|
||||
if (isequal(holdout_weight, one_spectrum())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -65,7 +65,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
|
||||
/* Evaluate emissive closure. */
|
||||
float3 L = shader_emissive_eval(sd);
|
||||
Spectrum L = shader_emissive_eval(sd);
|
||||
|
||||
# ifdef __HAIR__
|
||||
if (!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) &&
|
||||
@ -84,7 +84,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
|
||||
L *= mis_weight;
|
||||
}
|
||||
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_accum_emission(
|
||||
kg, state, throughput * L, render_buffer, object_lightgroup(kg, sd->object));
|
||||
}
|
||||
@ -161,7 +161,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
else
|
||||
# endif /* __MNEE__ */
|
||||
{
|
||||
const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time);
|
||||
const Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time);
|
||||
if (is_zero(light_eval)) {
|
||||
return;
|
||||
}
|
||||
@ -211,11 +211,12 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
/* Copy state from main path to shadow path. */
|
||||
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput) *
|
||||
bsdf_eval_sum(&bsdf_eval);
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
packed_float3 pass_diffuse_weight;
|
||||
packed_float3 pass_glossy_weight;
|
||||
PackedSpectrum pass_diffuse_weight;
|
||||
PackedSpectrum pass_glossy_weight;
|
||||
|
||||
if (shadow_flag & PATH_RAY_ANY_PASS) {
|
||||
/* Indirect bounce, use weights from earlier surface or volume bounce. */
|
||||
@ -225,8 +226,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
else {
|
||||
/* Direct light, use BSDFs at this bounce. */
|
||||
shadow_flag |= PATH_RAY_SURFACE_PASS;
|
||||
pass_diffuse_weight = packed_float3(bsdf_eval_pass_diffuse_weight(&bsdf_eval));
|
||||
pass_glossy_weight = packed_float3(bsdf_eval_pass_glossy_weight(&bsdf_eval));
|
||||
pass_diffuse_weight = PackedSpectrum(bsdf_eval_pass_diffuse_weight(&bsdf_eval));
|
||||
pass_glossy_weight = PackedSpectrum(bsdf_eval_pass_glossy_weight(&bsdf_eval));
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
|
||||
@ -338,7 +339,7 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
||||
}
|
||||
|
||||
/* Update throughput. */
|
||||
float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
throughput *= bsdf_eval_sum(&bsdf_eval) / bsdf_pdf;
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput;
|
||||
|
||||
@ -410,7 +411,7 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
|
||||
path_state_rng_2D(kg, rng_state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
|
||||
|
||||
float3 ao_N;
|
||||
const float3 ao_weight = shader_bsdf_ao(
|
||||
const Spectrum ao_weight = shader_bsdf_ao(
|
||||
kg, sd, kernel_data.integrator.ao_additive_factor, &ao_N);
|
||||
|
||||
float3 ao_D;
|
||||
@ -450,7 +451,8 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
|
||||
const uint16_t bounce = INTEGRATOR_STATE(state, path, bounce);
|
||||
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
|
||||
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag) | PATH_RAY_SHADOW_FOR_AO;
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * shader_bsdf_alpha(kg, sd);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput) *
|
||||
shader_bsdf_alpha(kg, sd);
|
||||
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, render_pixel_index) = INTEGRATOR_STATE(
|
||||
state, path, render_pixel_index);
|
||||
|
@ -29,13 +29,13 @@ typedef enum VolumeIntegrateEvent {
|
||||
typedef struct VolumeIntegrateResult {
|
||||
/* Throughput and offset for direct light scattering. */
|
||||
bool direct_scatter;
|
||||
float3 direct_throughput;
|
||||
Spectrum direct_throughput;
|
||||
float direct_t;
|
||||
ShaderVolumePhases direct_phases;
|
||||
|
||||
/* Throughput and offset for indirect light scattering. */
|
||||
bool indirect_scatter;
|
||||
float3 indirect_throughput;
|
||||
Spectrum indirect_throughput;
|
||||
float indirect_t;
|
||||
ShaderVolumePhases indirect_phases;
|
||||
} VolumeIntegrateResult;
|
||||
@ -52,16 +52,16 @@ typedef struct VolumeIntegrateResult {
|
||||
* sigma_t = sigma_a + sigma_s */
|
||||
|
||||
typedef struct VolumeShaderCoefficients {
|
||||
float3 sigma_t;
|
||||
float3 sigma_s;
|
||||
float3 emission;
|
||||
Spectrum sigma_t;
|
||||
Spectrum sigma_s;
|
||||
Spectrum emission;
|
||||
} VolumeShaderCoefficients;
|
||||
|
||||
/* Evaluate shader to get extinction coefficient at P. */
|
||||
ccl_device_inline bool shadow_volume_shader_sample(KernelGlobals kg,
|
||||
IntegratorShadowState state,
|
||||
ccl_private ShaderData *ccl_restrict sd,
|
||||
ccl_private float3 *ccl_restrict extinction)
|
||||
ccl_private Spectrum *ccl_restrict extinction)
|
||||
{
|
||||
VOLUME_READ_LAMBDA(integrator_state_read_shadow_volume_stack(state, i))
|
||||
shader_eval_volume<true>(kg, state, sd, PATH_RAY_SHADOW, volume_read_lambda_pass);
|
||||
@ -89,9 +89,10 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals kg,
|
||||
return false;
|
||||
}
|
||||
|
||||
coeff->sigma_s = zero_float3();
|
||||
coeff->sigma_t = (sd->flag & SD_EXTINCTION) ? sd->closure_transparent_extinction : zero_float3();
|
||||
coeff->emission = (sd->flag & SD_EMISSION) ? sd->closure_emission_background : zero_float3();
|
||||
coeff->sigma_s = zero_spectrum();
|
||||
coeff->sigma_t = (sd->flag & SD_EXTINCTION) ? sd->closure_transparent_extinction :
|
||||
zero_spectrum();
|
||||
coeff->emission = (sd->flag & SD_EMISSION) ? sd->closure_emission_background : zero_spectrum();
|
||||
|
||||
if (sd->flag & SD_SCATTER) {
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
@ -162,9 +163,9 @@ ccl_device_forceinline void volume_step_init(KernelGlobals kg,
|
||||
ccl_device void volume_shadow_homogeneous(KernelGlobals kg, IntegratorState state,
|
||||
ccl_private Ray *ccl_restrict ray,
|
||||
ccl_private ShaderData *ccl_restrict sd,
|
||||
ccl_global float3 *ccl_restrict throughput)
|
||||
ccl_global Spectrum *ccl_restrict throughput)
|
||||
{
|
||||
float3 sigma_t = zero_float3();
|
||||
Spectrum sigma_t = zero_spectrum();
|
||||
|
||||
if (shadow_volume_shader_sample(kg, state, sd, &sigma_t)) {
|
||||
*throughput *= volume_color_transmittance(sigma_t, ray->tmax - ray->tmin);
|
||||
@ -178,14 +179,14 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg,
|
||||
IntegratorShadowState state,
|
||||
ccl_private Ray *ccl_restrict ray,
|
||||
ccl_private ShaderData *ccl_restrict sd,
|
||||
ccl_private float3 *ccl_restrict throughput,
|
||||
ccl_private Spectrum *ccl_restrict throughput,
|
||||
const float object_step_size)
|
||||
{
|
||||
/* Load random number state. */
|
||||
RNGState rng_state;
|
||||
shadow_path_state_rng_load(state, &rng_state);
|
||||
|
||||
float3 tp = *throughput;
|
||||
Spectrum tp = *throughput;
|
||||
|
||||
/* Prepare for stepping.
|
||||
* For shadows we do not offset all segments, since the starting point is
|
||||
@ -207,7 +208,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg,
|
||||
/* compute extinction at the start */
|
||||
float t = ray->tmin;
|
||||
|
||||
float3 sum = zero_float3();
|
||||
Spectrum sum = zero_spectrum();
|
||||
|
||||
for (int i = 0; i < max_steps; i++) {
|
||||
/* advance to new position */
|
||||
@ -215,7 +216,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg,
|
||||
float dt = new_t - t;
|
||||
|
||||
float3 new_P = ray->P + ray->D * (t + dt * step_shade_offset);
|
||||
float3 sigma_t = zero_float3();
|
||||
Spectrum sigma_t = zero_spectrum();
|
||||
|
||||
/* compute attenuation over segment */
|
||||
sd->P = new_P;
|
||||
@ -228,8 +229,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg,
|
||||
tp = *throughput * exp(sum);
|
||||
|
||||
/* stop if nearly all light is blocked */
|
||||
if (tp.x < VOLUME_THROUGHPUT_EPSILON && tp.y < VOLUME_THROUGHPUT_EPSILON &&
|
||||
tp.z < VOLUME_THROUGHPUT_EPSILON)
|
||||
if (reduce_max(tp) < VOLUME_THROUGHPUT_EPSILON)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -334,22 +334,22 @@ ccl_device float volume_equiangular_cdf(ccl_private const Ray *ccl_restrict ray,
|
||||
/* Distance sampling */
|
||||
|
||||
ccl_device float volume_distance_sample(float max_t,
|
||||
float3 sigma_t,
|
||||
Spectrum sigma_t,
|
||||
int channel,
|
||||
float xi,
|
||||
ccl_private float3 *transmittance,
|
||||
ccl_private float3 *pdf)
|
||||
ccl_private Spectrum *transmittance,
|
||||
ccl_private Spectrum *pdf)
|
||||
{
|
||||
/* xi is [0, 1[ so log(0) should never happen, division by zero is
|
||||
* avoided because sample_sigma_t > 0 when SD_SCATTER is set */
|
||||
float sample_sigma_t = volume_channel_get(sigma_t, channel);
|
||||
float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
|
||||
Spectrum full_transmittance = volume_color_transmittance(sigma_t, max_t);
|
||||
float sample_transmittance = volume_channel_get(full_transmittance, channel);
|
||||
|
||||
float sample_t = min(max_t, -logf(1.0f - xi * (1.0f - sample_transmittance)) / sample_sigma_t);
|
||||
|
||||
*transmittance = volume_color_transmittance(sigma_t, sample_t);
|
||||
*pdf = safe_divide_color(sigma_t * *transmittance, one_float3() - full_transmittance);
|
||||
*pdf = safe_divide_color(sigma_t * *transmittance, one_spectrum() - full_transmittance);
|
||||
|
||||
/* todo: optimization: when taken together with hit/miss decision,
|
||||
* the full_transmittance cancels out drops out and xi does not
|
||||
@ -358,33 +358,36 @@ ccl_device float volume_distance_sample(float max_t,
|
||||
return sample_t;
|
||||
}
|
||||
|
||||
ccl_device float3 volume_distance_pdf(float max_t, float3 sigma_t, float sample_t)
|
||||
ccl_device Spectrum volume_distance_pdf(float max_t, Spectrum sigma_t, float sample_t)
|
||||
{
|
||||
float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
|
||||
float3 transmittance = volume_color_transmittance(sigma_t, sample_t);
|
||||
Spectrum full_transmittance = volume_color_transmittance(sigma_t, max_t);
|
||||
Spectrum transmittance = volume_color_transmittance(sigma_t, sample_t);
|
||||
|
||||
return safe_divide_color(sigma_t * transmittance, one_float3() - full_transmittance);
|
||||
return safe_divide_color(sigma_t * transmittance, one_spectrum() - full_transmittance);
|
||||
}
|
||||
|
||||
/* Emission */
|
||||
|
||||
ccl_device float3 volume_emission_integrate(ccl_private VolumeShaderCoefficients *coeff,
|
||||
int closure_flag,
|
||||
float3 transmittance,
|
||||
float t)
|
||||
ccl_device Spectrum volume_emission_integrate(ccl_private VolumeShaderCoefficients *coeff,
|
||||
int closure_flag,
|
||||
Spectrum transmittance,
|
||||
float t)
|
||||
{
|
||||
/* integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t
|
||||
* this goes to E * t as sigma_t goes to zero
|
||||
*
|
||||
* todo: we should use an epsilon to avoid precision issues near zero sigma_t */
|
||||
float3 emission = coeff->emission;
|
||||
Spectrum emission = coeff->emission;
|
||||
|
||||
if (closure_flag & SD_EXTINCTION) {
|
||||
float3 sigma_t = coeff->sigma_t;
|
||||
Spectrum sigma_t = coeff->sigma_t;
|
||||
|
||||
emission.x *= (sigma_t.x > 0.0f) ? (1.0f - transmittance.x) / sigma_t.x : t;
|
||||
emission.y *= (sigma_t.y > 0.0f) ? (1.0f - transmittance.y) / sigma_t.y : t;
|
||||
emission.z *= (sigma_t.z > 0.0f) ? (1.0f - transmittance.z) / sigma_t.z : t;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
GET_SPECTRUM_CHANNEL(emission, i) *= (GET_SPECTRUM_CHANNEL(sigma_t, i) > 0.0f) ?
|
||||
(1.0f - GET_SPECTRUM_CHANNEL(transmittance, i)) /
|
||||
GET_SPECTRUM_CHANNEL(sigma_t, i) :
|
||||
t;
|
||||
}
|
||||
}
|
||||
else
|
||||
emission *= t;
|
||||
@ -419,14 +422,14 @@ ccl_device_forceinline void volume_integrate_step_scattering(
|
||||
ccl_private const Ray *ray,
|
||||
const float3 equiangular_light_P,
|
||||
ccl_private const VolumeShaderCoefficients &ccl_restrict coeff,
|
||||
const float3 transmittance,
|
||||
const Spectrum transmittance,
|
||||
ccl_private VolumeIntegrateState &ccl_restrict vstate,
|
||||
ccl_private VolumeIntegrateResult &ccl_restrict result)
|
||||
{
|
||||
/* Pick random color channel, we use the Veach one-sample
|
||||
* model with balance heuristic for the channels. */
|
||||
const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
|
||||
float3 channel_pdf;
|
||||
const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
|
||||
Spectrum channel_pdf;
|
||||
const int channel = volume_sample_channel(
|
||||
albedo, result.indirect_throughput, vstate.rphase, &channel_pdf);
|
||||
|
||||
@ -435,7 +438,7 @@ ccl_device_forceinline void volume_integrate_step_scattering(
|
||||
if (result.direct_t >= vstate.tmin && result.direct_t <= vstate.tmax &&
|
||||
vstate.equiangular_pdf > VOLUME_SAMPLE_PDF_CUTOFF) {
|
||||
const float new_dt = result.direct_t - vstate.tmin;
|
||||
const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
|
||||
const Spectrum new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
|
||||
|
||||
result.direct_scatter = true;
|
||||
result.direct_throughput *= coeff.sigma_s * new_transmittance / vstate.equiangular_pdf;
|
||||
@ -467,7 +470,7 @@ ccl_device_forceinline void volume_integrate_step_scattering(
|
||||
const float new_t = vstate.tmin + new_dt;
|
||||
|
||||
/* transmittance and pdf */
|
||||
const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
|
||||
const Spectrum new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
|
||||
const float distance_pdf = dot(channel_pdf, coeff.sigma_t * new_transmittance);
|
||||
|
||||
if (vstate.distance_pdf * distance_pdf > VOLUME_SAMPLE_PDF_CUTOFF) {
|
||||
@ -566,7 +569,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
||||
vstate.distance_pdf = 1.0f;
|
||||
|
||||
/* Initialize volume integration result. */
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
result.direct_throughput = throughput;
|
||||
result.indirect_throughput = throughput;
|
||||
|
||||
@ -579,9 +582,9 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
||||
# ifdef __DENOISING_FEATURES__
|
||||
const bool write_denoising_features = (INTEGRATOR_STATE(state, path, flag) &
|
||||
PATH_RAY_DENOISING_FEATURES);
|
||||
float3 accum_albedo = zero_float3();
|
||||
Spectrum accum_albedo = zero_spectrum();
|
||||
# endif
|
||||
float3 accum_emission = zero_float3();
|
||||
Spectrum accum_emission = zero_spectrum();
|
||||
|
||||
for (int i = 0; i < max_steps; i++) {
|
||||
/* Advance to new position */
|
||||
@ -596,16 +599,16 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
||||
|
||||
/* Evaluate transmittance over segment. */
|
||||
const float dt = (vstate.tmax - vstate.tmin);
|
||||
const float3 transmittance = (closure_flag & SD_EXTINCTION) ?
|
||||
volume_color_transmittance(coeff.sigma_t, dt) :
|
||||
one_float3();
|
||||
const Spectrum transmittance = (closure_flag & SD_EXTINCTION) ?
|
||||
volume_color_transmittance(coeff.sigma_t, dt) :
|
||||
one_spectrum();
|
||||
|
||||
/* Emission. */
|
||||
if (closure_flag & SD_EMISSION) {
|
||||
/* Only write emission before indirect light scatter position, since we terminate
|
||||
* stepping at that point if we have already found a direct light scatter position. */
|
||||
if (!result.indirect_scatter) {
|
||||
const float3 emission = volume_emission_integrate(
|
||||
const Spectrum emission = volume_emission_integrate(
|
||||
&coeff, closure_flag, transmittance, dt);
|
||||
accum_emission += result.indirect_throughput * emission;
|
||||
}
|
||||
@ -616,8 +619,8 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
||||
# ifdef __DENOISING_FEATURES__
|
||||
/* Accumulate albedo for denoising features. */
|
||||
if (write_denoising_features && (closure_flag & SD_SCATTER)) {
|
||||
const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
|
||||
accum_albedo += result.indirect_throughput * albedo * (one_float3() - transmittance);
|
||||
const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
|
||||
accum_albedo += result.indirect_throughput * albedo * (one_spectrum() - transmittance);
|
||||
}
|
||||
# endif
|
||||
|
||||
@ -634,7 +637,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
||||
/* Stop if nearly all light blocked. */
|
||||
if (!result.indirect_scatter) {
|
||||
if (reduce_max(result.indirect_throughput) < VOLUME_THROUGHPUT_EPSILON) {
|
||||
result.indirect_throughput = zero_float3();
|
||||
result.indirect_throughput = zero_spectrum();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -715,7 +718,7 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
||||
ccl_private const RNGState *ccl_restrict rng_state,
|
||||
const float3 P,
|
||||
ccl_private const ShaderVolumePhases *ccl_restrict phases,
|
||||
ccl_private const float3 throughput,
|
||||
ccl_private const Spectrum throughput,
|
||||
ccl_private LightSample *ccl_restrict ls)
|
||||
{
|
||||
PROFILING_INIT(kg, PROFILING_SHADE_VOLUME_DIRECT_LIGHT);
|
||||
@ -753,7 +756,7 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
||||
* non-constant light sources. */
|
||||
ShaderDataTinyStorage emission_sd_storage;
|
||||
ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
|
||||
const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, ls, sd->time);
|
||||
const Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, ls, sd->time);
|
||||
if (is_zero(light_eval)) {
|
||||
return;
|
||||
}
|
||||
@ -796,11 +799,11 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
||||
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
|
||||
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
|
||||
const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval);
|
||||
const Spectrum throughput_phase = throughput * bsdf_eval_sum(&phase_eval);
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
packed_float3 pass_diffuse_weight;
|
||||
packed_float3 pass_glossy_weight;
|
||||
PackedSpectrum pass_diffuse_weight;
|
||||
PackedSpectrum pass_glossy_weight;
|
||||
|
||||
if (shadow_flag & PATH_RAY_ANY_PASS) {
|
||||
/* Indirect bounce, use weights from earlier surface or volume bounce. */
|
||||
@ -810,8 +813,8 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
||||
else {
|
||||
/* Direct light, no diffuse/glossy distinction needed for volumes. */
|
||||
shadow_flag |= PATH_RAY_VOLUME_PASS;
|
||||
pass_diffuse_weight = packed_float3(one_float3());
|
||||
pass_glossy_weight = packed_float3(zero_float3());
|
||||
pass_diffuse_weight = one_spectrum();
|
||||
pass_glossy_weight = zero_spectrum();
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
|
||||
@ -898,13 +901,13 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
||||
INTEGRATOR_STATE_WRITE(state, isect, object) = sd->object;
|
||||
|
||||
/* Update throughput. */
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval) / phase_pdf;
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput_phase = throughput * bsdf_eval_sum(&phase_eval) / phase_pdf;
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase;
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3();
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3();
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
|
||||
}
|
||||
|
||||
/* Update path state */
|
||||
|
@ -98,7 +98,7 @@ ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg,
|
||||
/* Filter out closures. */
|
||||
if (kernel_data.integrator.filter_closures) {
|
||||
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_EMISSION) {
|
||||
sd->closure_emission_background = zero_float3();
|
||||
sd->closure_emission_background = zero_spectrum();
|
||||
}
|
||||
|
||||
if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) {
|
||||
@ -231,7 +231,7 @@ ccl_device_inline float _shader_bsdf_multi_eval(KernelGlobals kg,
|
||||
if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
|
||||
if (CLOSURE_IS_BSDF(sc->type) && !_shader_bsdf_exclude(sc->type, light_shader_flags)) {
|
||||
float bsdf_pdf = 0.0f;
|
||||
float3 eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf);
|
||||
Spectrum eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf);
|
||||
|
||||
if (bsdf_pdf != 0.0f) {
|
||||
bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
|
||||
@ -259,7 +259,7 @@ ccl_device_inline
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
const uint light_shader_flags)
|
||||
{
|
||||
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_float3());
|
||||
bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum());
|
||||
|
||||
return _shader_bsdf_multi_eval(
|
||||
kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
|
||||
@ -309,11 +309,11 @@ ccl_device_inline ccl_private const ShaderClosure *shader_bsdf_bssrdf_pick(
|
||||
}
|
||||
|
||||
/* Return weight for picked BSSRDF. */
|
||||
ccl_device_inline float3
|
||||
ccl_device_inline Spectrum
|
||||
shader_bssrdf_sample_weight(ccl_private const ShaderData *ccl_restrict sd,
|
||||
ccl_private const ShaderClosure *ccl_restrict bssrdf_sc)
|
||||
{
|
||||
float3 weight = bssrdf_sc->weight;
|
||||
Spectrum weight = bssrdf_sc->weight;
|
||||
|
||||
if (sd->num_closure > 1) {
|
||||
float sum = 0.0f;
|
||||
@ -346,7 +346,7 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals kg,
|
||||
kernel_assert(CLOSURE_IS_BSDF(sc->type));
|
||||
|
||||
int label;
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
*pdf = 0.0f;
|
||||
label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
|
||||
@ -385,16 +385,16 @@ ccl_device float shader_bsdf_average_roughness(ccl_private const ShaderData *sd)
|
||||
return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f;
|
||||
}
|
||||
|
||||
ccl_device float3 shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
ccl_device Spectrum shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
{
|
||||
if (sd->flag & SD_HAS_ONLY_VOLUME) {
|
||||
return one_float3();
|
||||
return one_spectrum();
|
||||
}
|
||||
else if (sd->flag & SD_TRANSPARENT) {
|
||||
return sd->closure_transparent_extinction;
|
||||
}
|
||||
else {
|
||||
return zero_float3();
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,7 +406,7 @@ ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private S
|
||||
|
||||
if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
|
||||
sc->sample_weight = 0.0f;
|
||||
sc->weight = zero_float3();
|
||||
sc->weight = zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,19 +414,18 @@ ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private S
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
ccl_device Spectrum shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
{
|
||||
float3 alpha = one_float3() - shader_bsdf_transparency(kg, sd);
|
||||
Spectrum alpha = one_spectrum() - shader_bsdf_transparency(kg, sd);
|
||||
|
||||
alpha = max(alpha, zero_float3());
|
||||
alpha = min(alpha, one_float3());
|
||||
alpha = saturate(alpha);
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
ccl_device Spectrum shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
{
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
ccl_private const ShaderClosure *sc = &sd->closure[i];
|
||||
@ -438,9 +437,9 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const Shader
|
||||
return eval;
|
||||
}
|
||||
|
||||
ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
ccl_device Spectrum shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
{
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
ccl_private const ShaderClosure *sc = &sd->closure[i];
|
||||
@ -452,9 +451,9 @@ ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderD
|
||||
return eval;
|
||||
}
|
||||
|
||||
ccl_device float3 shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
ccl_device Spectrum shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd)
|
||||
{
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
ccl_private const ShaderClosure *sc = &sd->closure[i];
|
||||
@ -479,12 +478,12 @@ ccl_device float3 shader_bsdf_average_normal(KernelGlobals kg, ccl_private const
|
||||
return (is_zero(N)) ? sd->N : normalize(N);
|
||||
}
|
||||
|
||||
ccl_device float3 shader_bsdf_ao(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
const float ao_factor,
|
||||
ccl_private float3 *N_)
|
||||
ccl_device Spectrum shader_bsdf_ao(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
const float ao_factor,
|
||||
ccl_private float3 *N_)
|
||||
{
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
float3 N = zero_float3();
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
@ -525,15 +524,17 @@ ccl_device float3 shader_bssrdf_normal(ccl_private const ShaderData *sd)
|
||||
|
||||
ccl_device bool shader_constant_emission_eval(KernelGlobals kg,
|
||||
int shader,
|
||||
ccl_private float3 *eval)
|
||||
ccl_private Spectrum *eval)
|
||||
{
|
||||
int shader_index = shader & SHADER_MASK;
|
||||
int shader_flag = kernel_data_fetch(shaders, shader_index).flags;
|
||||
|
||||
if (shader_flag & SD_HAS_CONSTANT_EMISSION) {
|
||||
*eval = make_float3(kernel_data_fetch(shaders, shader_index).constant_emission[0],
|
||||
kernel_data_fetch(shaders, shader_index).constant_emission[1],
|
||||
kernel_data_fetch(shaders, shader_index).constant_emission[2]);
|
||||
const float3 emission_rgb = make_float3(
|
||||
kernel_data_fetch(shaders, shader_index).constant_emission[0],
|
||||
kernel_data_fetch(shaders, shader_index).constant_emission[1],
|
||||
kernel_data_fetch(shaders, shader_index).constant_emission[2]);
|
||||
*eval = rgb_to_spectrum(emission_rgb);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -543,39 +544,39 @@ ccl_device bool shader_constant_emission_eval(KernelGlobals kg,
|
||||
|
||||
/* Background */
|
||||
|
||||
ccl_device float3 shader_background_eval(ccl_private const ShaderData *sd)
|
||||
ccl_device Spectrum shader_background_eval(ccl_private const ShaderData *sd)
|
||||
{
|
||||
if (sd->flag & SD_EMISSION) {
|
||||
return sd->closure_emission_background;
|
||||
}
|
||||
else {
|
||||
return zero_float3();
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
/* Emission */
|
||||
|
||||
ccl_device float3 shader_emissive_eval(ccl_private const ShaderData *sd)
|
||||
ccl_device Spectrum shader_emissive_eval(ccl_private const ShaderData *sd)
|
||||
{
|
||||
if (sd->flag & SD_EMISSION) {
|
||||
return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background;
|
||||
}
|
||||
else {
|
||||
return zero_float3();
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
/* Holdout */
|
||||
|
||||
ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd)
|
||||
ccl_device Spectrum shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd)
|
||||
{
|
||||
float3 weight = zero_float3();
|
||||
Spectrum weight = zero_spectrum();
|
||||
|
||||
/* For objects marked as holdout, preserve transparency and remove all other
|
||||
* closures, replacing them with a holdout weight. */
|
||||
if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
|
||||
if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) {
|
||||
weight = one_float3() - sd->closure_transparent_extinction;
|
||||
weight = one_spectrum() - sd->closure_transparent_extinction;
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
ccl_private ShaderClosure *sc = &sd->closure[i];
|
||||
@ -587,7 +588,7 @@ ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData
|
||||
sd->flag &= ~(SD_CLOSURE_FLAGS - (SD_TRANSPARENT | SD_BSDF));
|
||||
}
|
||||
else {
|
||||
weight = one_float3();
|
||||
weight = one_spectrum();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -642,12 +643,12 @@ ccl_device void shader_eval_surface(KernelGlobals kg,
|
||||
svm_eval_nodes<node_feature_mask, SHADER_TYPE_SURFACE>(kg, state, sd, buffer, path_flag);
|
||||
#else
|
||||
if (sd->object == OBJECT_NONE) {
|
||||
sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f);
|
||||
sd->closure_emission_background = make_spectrum(0.8f);
|
||||
sd->flag |= SD_EMISSION;
|
||||
}
|
||||
else {
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), make_float3(0.8f, 0.8f, 0.8f));
|
||||
sd, sizeof(DiffuseBsdf), make_spectrum(0.8f));
|
||||
if (bsdf != NULL) {
|
||||
bsdf->N = sd->N;
|
||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||
@ -676,7 +677,7 @@ ccl_device_inline float _shader_volume_phase_multi_eval(
|
||||
|
||||
ccl_private const ShaderVolumeClosure *svc = &phases->closure[i];
|
||||
float phase_pdf = 0.0f;
|
||||
float3 eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf);
|
||||
Spectrum eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf);
|
||||
|
||||
if (phase_pdf != 0.0f) {
|
||||
bsdf_eval_accum(result_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval);
|
||||
@ -695,7 +696,7 @@ ccl_device float shader_volume_phase_eval(KernelGlobals kg,
|
||||
const float3 omega_in,
|
||||
ccl_private BsdfEval *phase_eval)
|
||||
{
|
||||
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_float3());
|
||||
bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum());
|
||||
|
||||
return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f);
|
||||
}
|
||||
@ -747,7 +748,7 @@ ccl_device int shader_volume_phase_sample(KernelGlobals kg,
|
||||
* depending on color channels, even if this is perhaps not a common case */
|
||||
ccl_private const ShaderVolumeClosure *svc = &phases->closure[sampled];
|
||||
int label;
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
*pdf = 0.0f;
|
||||
label = volume_phase_sample(sd, svc, randu, randv, &eval, omega_in, domega_in, pdf);
|
||||
@ -770,7 +771,7 @@ ccl_device int shader_phase_sample_closure(KernelGlobals kg,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
int label;
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
*pdf = 0.0f;
|
||||
label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
|
||||
|
@ -93,7 +93,7 @@ ccl_device_forceinline void kernel_write_shadow_catcher_bounce_data(
|
||||
|
||||
/* Since the split is done, the sample does not contribute to the matte, so accumulate it as
|
||||
* transparency to the matte. */
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_matte + 3,
|
||||
average(throughput));
|
||||
}
|
||||
|
@ -27,15 +27,15 @@ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, queued_kernel, KERNEL_FEATURE_PATH_T
|
||||
/* enum PathRayFlag */
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, uint32_t, flag, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Throughput. */
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, throughput, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, throughput, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Throughput for shadow pass. */
|
||||
KERNEL_STRUCT_MEMBER(shadow_path,
|
||||
packed_float3,
|
||||
PackedSpectrum,
|
||||
unshadowed_throughput,
|
||||
KERNEL_FEATURE_SHADOW_PASS | KERNEL_FEATURE_AO_ADDITIVE)
|
||||
/* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
/* Number of intersections found by ray-tracing. */
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, num_hits, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Light group. */
|
||||
|
@ -46,12 +46,12 @@ KERNEL_STRUCT_MEMBER(path, float, min_ray_pdf, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Continuation probability for path termination. */
|
||||
KERNEL_STRUCT_MEMBER(path, float, continuation_probability, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Throughput. */
|
||||
KERNEL_STRUCT_MEMBER(path, packed_float3, throughput, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER(path, PackedSpectrum, throughput, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */
|
||||
KERNEL_STRUCT_MEMBER(path, packed_float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
KERNEL_STRUCT_MEMBER(path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
KERNEL_STRUCT_MEMBER(path, PackedSpectrum, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
KERNEL_STRUCT_MEMBER(path, PackedSpectrum, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES)
|
||||
/* Denoising. */
|
||||
KERNEL_STRUCT_MEMBER(path, packed_float3, denoising_feature_throughput, KERNEL_FEATURE_DENOISING)
|
||||
KERNEL_STRUCT_MEMBER(path, PackedSpectrum, denoising_feature_throughput, KERNEL_FEATURE_DENOISING)
|
||||
/* Shader sorting. */
|
||||
/* TODO: compress as uint16? or leave out entirely and recompute key in sorting code? */
|
||||
KERNEL_STRUCT_MEMBER(path, uint32_t, shader_sort_key, KERNEL_FEATURE_PATH_TRACING)
|
||||
@ -84,8 +84,8 @@ KERNEL_STRUCT_END(isect)
|
||||
/*************** Subsurface closure state for subsurface kernel ***************/
|
||||
|
||||
KERNEL_STRUCT_BEGIN(subsurface)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, packed_float3, albedo, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, packed_float3, radius, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, albedo, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, radius, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, float, anisotropy, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_MEMBER(subsurface, packed_float3, Ng, KERNEL_FEATURE_SUBSURFACE)
|
||||
KERNEL_STRUCT_END(subsurface)
|
||||
|
@ -51,7 +51,7 @@ ccl_device int subsurface_bounce(KernelGlobals kg,
|
||||
PATH_RAY_SUBSURFACE_RANDOM_WALK);
|
||||
|
||||
/* Compute weight, optionally including Fresnel from entry point. */
|
||||
float3 weight = shader_bssrdf_sample_weight(sd, sc);
|
||||
Spectrum weight = shader_bssrdf_sample_weight(sd, sc);
|
||||
# ifdef __PRINCIPLED__
|
||||
if (bssrdf->roughness != FLT_MAX) {
|
||||
path_flag |= PATH_RAY_SUBSURFACE_USE_FRESNEL;
|
||||
@ -70,8 +70,8 @@ ccl_device int subsurface_bounce(KernelGlobals kg,
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3();
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3();
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum();
|
||||
INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ ccl_device void subsurface_shader_data_setup(KernelGlobals kg,
|
||||
sd->num_closure = 0;
|
||||
sd->num_closure_left = kernel_data.max_closures;
|
||||
|
||||
const float3 weight = one_float3();
|
||||
const Spectrum weight = one_spectrum();
|
||||
|
||||
# ifdef __PRINCIPLED__
|
||||
if (path_flag & PATH_RAY_SUBSURFACE_USE_FRESNEL) {
|
||||
|
@ -9,11 +9,11 @@ CCL_NAMESPACE_BEGIN
|
||||
* http://library.imageworks.com/pdfs/imageworks-library-BSSRDF-sampling.pdf
|
||||
*/
|
||||
|
||||
ccl_device_inline float3 subsurface_disk_eval(const float3 radius, float disk_r, float r)
|
||||
ccl_device_inline Spectrum subsurface_disk_eval(const Spectrum radius, float disk_r, float r)
|
||||
{
|
||||
const float3 eval = bssrdf_eval(radius, r);
|
||||
const Spectrum eval = bssrdf_eval(radius, r);
|
||||
const float pdf = bssrdf_pdf(radius, disk_r);
|
||||
return (pdf > 0.0f) ? eval / pdf : zero_float3();
|
||||
return (pdf > 0.0f) ? eval / pdf : zero_spectrum();
|
||||
}
|
||||
|
||||
/* Subsurface scattering step, from a point on the surface to other
|
||||
@ -37,7 +37,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg,
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
|
||||
/* Read subsurface scattering parameters. */
|
||||
const float3 radius = INTEGRATOR_STATE(state, subsurface, radius);
|
||||
const Spectrum radius = INTEGRATOR_STATE(state, subsurface, radius);
|
||||
|
||||
/* Pick random axis in local frame and point on disk. */
|
||||
float3 disk_N, disk_T, disk_B;
|
||||
@ -108,7 +108,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg,
|
||||
* traversal algorithm. */
|
||||
sort_intersections_and_normals(ss_isect.hits, ss_isect.Ng, num_eval_hits);
|
||||
|
||||
float3 weights[BSSRDF_MAX_HITS]; /* TODO: zero? */
|
||||
Spectrum weights[BSSRDF_MAX_HITS]; /* TODO: zero? */
|
||||
float sum_weights = 0.0f;
|
||||
|
||||
for (int hit = 0; hit < num_eval_hits; hit++) {
|
||||
@ -150,7 +150,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg,
|
||||
const float r = len(hit_P - P);
|
||||
|
||||
/* Evaluate profiles. */
|
||||
const float3 weight = subsurface_disk_eval(radius, disk_r, r) * w;
|
||||
const Spectrum weight = subsurface_disk_eval(radius, disk_r, r) * w;
|
||||
|
||||
/* Store result. */
|
||||
ss_isect.Ng[hit] = hit_Ng;
|
||||
@ -167,7 +167,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg,
|
||||
float partial_sum = 0.0f;
|
||||
|
||||
for (int hit = 0; hit < num_eval_hits; hit++) {
|
||||
const float3 weight = weights[hit];
|
||||
const Spectrum weight = weights[hit];
|
||||
const float sample_weight = average(fabs(weight));
|
||||
float next_sum = partial_sum + sample_weight;
|
||||
|
||||
|
@ -65,19 +65,20 @@ ccl_device void subsurface_random_walk_remap(const float albedo,
|
||||
*sigma_t = sigma_t_prime / (1.0f - g);
|
||||
}
|
||||
|
||||
ccl_device void subsurface_random_walk_coefficients(const float3 albedo,
|
||||
const float3 radius,
|
||||
ccl_device void subsurface_random_walk_coefficients(const Spectrum albedo,
|
||||
const Spectrum radius,
|
||||
const float anisotropy,
|
||||
ccl_private float3 *sigma_t,
|
||||
ccl_private float3 *alpha,
|
||||
ccl_private float3 *throughput)
|
||||
ccl_private Spectrum *sigma_t,
|
||||
ccl_private Spectrum *alpha,
|
||||
ccl_private Spectrum *throughput)
|
||||
{
|
||||
float sigma_t_x, sigma_t_y, sigma_t_z;
|
||||
float alpha_x, alpha_y, alpha_z;
|
||||
|
||||
subsurface_random_walk_remap(albedo.x, radius.x, anisotropy, &sigma_t_x, &alpha_x);
|
||||
subsurface_random_walk_remap(albedo.y, radius.y, anisotropy, &sigma_t_y, &alpha_y);
|
||||
subsurface_random_walk_remap(albedo.z, radius.z, anisotropy, &sigma_t_z, &alpha_z);
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
subsurface_random_walk_remap(GET_SPECTRUM_CHANNEL(albedo, i),
|
||||
GET_SPECTRUM_CHANNEL(radius, i),
|
||||
anisotropy,
|
||||
&GET_SPECTRUM_CHANNEL(*sigma_t, i),
|
||||
&GET_SPECTRUM_CHANNEL(*alpha, i));
|
||||
}
|
||||
|
||||
/* Throughput already contains closure weight at this point, which includes the
|
||||
* albedo, as well as closure mixing and Fresnel weights. Divide out the albedo
|
||||
@ -88,21 +89,12 @@ ccl_device void subsurface_random_walk_coefficients(const float3 albedo,
|
||||
* infinite phase functions. To avoid a sharp discontinuity as we go from
|
||||
* such values to 0.0, increase alpha and reduce the throughput to compensate. */
|
||||
const float min_alpha = 0.2f;
|
||||
if (alpha_x < min_alpha) {
|
||||
(*throughput).x *= alpha_x / min_alpha;
|
||||
alpha_x = min_alpha;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
if (GET_SPECTRUM_CHANNEL(*alpha, i) < min_alpha) {
|
||||
GET_SPECTRUM_CHANNEL(*throughput, i) *= GET_SPECTRUM_CHANNEL(*alpha, i) / min_alpha;
|
||||
GET_SPECTRUM_CHANNEL(*alpha, i) = min_alpha;
|
||||
}
|
||||
}
|
||||
if (alpha_y < min_alpha) {
|
||||
(*throughput).y *= alpha_y / min_alpha;
|
||||
alpha_y = min_alpha;
|
||||
}
|
||||
if (alpha_z < min_alpha) {
|
||||
(*throughput).z *= alpha_z / min_alpha;
|
||||
alpha_z = min_alpha;
|
||||
}
|
||||
|
||||
*sigma_t = make_float3(sigma_t_x, sigma_t_y, sigma_t_z);
|
||||
*alpha = make_float3(alpha_x, alpha_y, alpha_z);
|
||||
}
|
||||
|
||||
/* References for Dwivedi sampling:
|
||||
@ -151,12 +143,12 @@ ccl_device_forceinline float3 direction_from_cosine(float3 D, float cos_theta, f
|
||||
return dir.x * T + dir.y * B + dir.z * D;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float3 subsurface_random_walk_pdf(float3 sigma_t,
|
||||
float t,
|
||||
bool hit,
|
||||
ccl_private float3 *transmittance)
|
||||
ccl_device_forceinline Spectrum subsurface_random_walk_pdf(Spectrum sigma_t,
|
||||
float t,
|
||||
bool hit,
|
||||
ccl_private Spectrum *transmittance)
|
||||
{
|
||||
float3 T = volume_color_transmittance(sigma_t, t);
|
||||
Spectrum T = volume_color_transmittance(sigma_t, t);
|
||||
if (transmittance) {
|
||||
*transmittance = T;
|
||||
}
|
||||
@ -207,14 +199,14 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
||||
|
||||
/* Convert subsurface to volume coefficients.
|
||||
* The single-scattering albedo is named alpha to avoid confusion with the surface albedo. */
|
||||
const float3 albedo = INTEGRATOR_STATE(state, subsurface, albedo);
|
||||
const float3 radius = INTEGRATOR_STATE(state, subsurface, radius);
|
||||
const Spectrum albedo = INTEGRATOR_STATE(state, subsurface, albedo);
|
||||
const Spectrum radius = INTEGRATOR_STATE(state, subsurface, radius);
|
||||
const float anisotropy = INTEGRATOR_STATE(state, subsurface, anisotropy);
|
||||
|
||||
float3 sigma_t, alpha;
|
||||
float3 throughput = INTEGRATOR_STATE_WRITE(state, path, throughput);
|
||||
Spectrum sigma_t, alpha;
|
||||
Spectrum throughput = INTEGRATOR_STATE_WRITE(state, path, throughput);
|
||||
subsurface_random_walk_coefficients(albedo, radius, anisotropy, &sigma_t, &alpha, &throughput);
|
||||
float3 sigma_s = sigma_t * alpha;
|
||||
Spectrum sigma_s = sigma_t * alpha;
|
||||
|
||||
/* Theoretically it should be better to use the exact alpha for the channel we're sampling at
|
||||
* each bounce, but in practice there doesn't seem to be a noticeable difference in exchange
|
||||
@ -249,10 +241,10 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
||||
const float guided_fraction = 1.0f - fmaxf(0.5f, powf(fabsf(anisotropy), 0.125f));
|
||||
|
||||
#ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL
|
||||
float3 sigma_s_star = sigma_s * (1.0f - anisotropy);
|
||||
float3 sigma_t_star = sigma_t - sigma_s + sigma_s_star;
|
||||
float3 sigma_t_org = sigma_t;
|
||||
float3 sigma_s_org = sigma_s;
|
||||
Spectrum sigma_s_star = sigma_s * (1.0f - anisotropy);
|
||||
Spectrum sigma_t_star = sigma_t - sigma_s + sigma_s_star;
|
||||
Spectrum sigma_t_org = sigma_t;
|
||||
Spectrum sigma_s_org = sigma_s;
|
||||
const float anisotropy_org = anisotropy;
|
||||
const float guided_fraction_org = guided_fraction;
|
||||
#endif
|
||||
@ -264,7 +256,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
||||
#ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL
|
||||
// shadow with local variables according to depth
|
||||
float anisotropy, guided_fraction;
|
||||
float3 sigma_s, sigma_t;
|
||||
Spectrum sigma_s, sigma_t;
|
||||
if (bounce <= SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL) {
|
||||
anisotropy = anisotropy_org;
|
||||
guided_fraction = guided_fraction_org;
|
||||
@ -281,7 +273,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
||||
|
||||
/* Sample color channel, use MIS with balance heuristic. */
|
||||
float rphase = path_state_rng_1D(kg, &rng_state, PRNG_PHASE_CHANNEL);
|
||||
float3 channel_pdf;
|
||||
Spectrum channel_pdf;
|
||||
int channel = volume_sample_channel(alpha, throughput, rphase, &channel_pdf);
|
||||
float sample_sigma_t = volume_channel_get(sigma_t, channel);
|
||||
float randt = path_state_rng_1D(kg, &rng_state, PRNG_SCATTER_DISTANCE);
|
||||
@ -399,16 +391,17 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
||||
/* Advance to new scatter location. */
|
||||
ray.P += t * ray.D;
|
||||
|
||||
float3 transmittance;
|
||||
float3 pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance);
|
||||
Spectrum transmittance;
|
||||
Spectrum pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance);
|
||||
if (bounce > 0) {
|
||||
/* Compute PDF just like we do for classic sampling, but with the stretched sigma_t. */
|
||||
float3 guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit, NULL);
|
||||
Spectrum guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit, NULL);
|
||||
|
||||
if (have_opposite_interface) {
|
||||
/* First step of MIS: Depending on geometry we might have two methods for guided
|
||||
* sampling, so perform MIS between them. */
|
||||
float3 back_pdf = subsurface_random_walk_pdf(backward_stretching * sigma_t, t, hit, NULL);
|
||||
Spectrum back_pdf = subsurface_random_walk_pdf(
|
||||
backward_stretching * sigma_t, t, hit, NULL);
|
||||
guided_pdf = mix(
|
||||
guided_pdf * forward_pdf_factor, back_pdf * backward_pdf_factor, backward_fraction);
|
||||
}
|
||||
@ -430,9 +423,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg,
|
||||
/* If we hit the surface, we are done. */
|
||||
break;
|
||||
}
|
||||
else if (throughput.x < VOLUME_THROUGHPUT_EPSILON &&
|
||||
throughput.y < VOLUME_THROUGHPUT_EPSILON &&
|
||||
throughput.z < VOLUME_THROUGHPUT_EPSILON) {
|
||||
else if (reduce_max(throughput) < VOLUME_THROUGHPUT_EPSILON) {
|
||||
/* Avoid unnecessary work and precision issue when throughput gets really small. */
|
||||
break;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Evaluate shader on light. */
|
||||
ccl_device_noinline_cpu float3
|
||||
ccl_device_noinline_cpu Spectrum
|
||||
light_sample_shader_eval(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *ccl_restrict emission_sd,
|
||||
@ -22,7 +22,7 @@ light_sample_shader_eval(KernelGlobals kg,
|
||||
float time)
|
||||
{
|
||||
/* setup shading at emitter */
|
||||
float3 eval = zero_float3();
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
if (shader_constant_emission_eval(kg, ls->shader, &eval)) {
|
||||
if ((ls->prim != PRIM_NONE) && dot(ls->Ng, ls->D) > 0.0f) {
|
||||
@ -82,7 +82,8 @@ light_sample_shader_eval(KernelGlobals kg,
|
||||
|
||||
if (ls->lamp != LAMP_NONE) {
|
||||
ccl_global const KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
|
||||
eval *= make_float3(klight->strength[0], klight->strength[1], klight->strength[2]);
|
||||
eval *= rgb_to_spectrum(
|
||||
make_float3(klight->strength[0], klight->strength[1], klight->strength[2]));
|
||||
}
|
||||
|
||||
return eval;
|
||||
|
@ -14,8 +14,12 @@
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/device/cpu/compat.h"
|
||||
#include "kernel/device/cpu/globals.h"
|
||||
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/emissive.h"
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
// clang-format on
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@ -32,7 +36,7 @@ class GenericBackgroundClosure : public CClosurePrimitive {
|
||||
public:
|
||||
void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight)
|
||||
{
|
||||
background_setup(sd, weight);
|
||||
background_setup(sd, rgb_to_spectrum(weight));
|
||||
}
|
||||
};
|
||||
|
||||
@ -47,7 +51,7 @@ class HoldoutClosure : CClosurePrimitive {
|
||||
public:
|
||||
void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight)
|
||||
{
|
||||
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, weight);
|
||||
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, rgb_to_spectrum(weight));
|
||||
sd->flag |= SD_HOLDOUT;
|
||||
}
|
||||
};
|
||||
|
@ -14,10 +14,15 @@
|
||||
#include "kernel/osl/closures.h"
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/device/cpu/compat.h"
|
||||
#include "kernel/device/cpu/globals.h"
|
||||
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/bsdf_diffuse_ramp.h"
|
||||
#include "kernel/closure/bsdf_util.h"
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
// clang-format on
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@ -34,7 +39,7 @@ class DiffuseRampClosure : public CBSDFClosure {
|
||||
params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N);
|
||||
|
||||
DiffuseRampBsdf *bsdf = (DiffuseRampBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(DiffuseRampBsdf), weight, ¶ms);
|
||||
sd, sizeof(DiffuseRampBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
|
||||
|
@ -14,10 +14,15 @@
|
||||
#include "kernel/osl/closures.h"
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/device/cpu/compat.h"
|
||||
#include "kernel/device/cpu/globals.h"
|
||||
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/bsdf_phong_ramp.h"
|
||||
#include "kernel/closure/bsdf_util.h"
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
// clang-format on
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@ -34,7 +39,7 @@ class PhongRampClosure : public CBSDFClosure {
|
||||
params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N);
|
||||
|
||||
PhongRampBsdf *bsdf = (PhongRampBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(PhongRampBsdf), weight, ¶ms);
|
||||
sd, sizeof(PhongRampBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
|
||||
|
@ -12,6 +12,9 @@
|
||||
#include "kernel/osl/closures.h"
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/device/cpu/compat.h"
|
||||
#include "kernel/device/cpu/globals.h"
|
||||
|
||||
#include "kernel/types.h"
|
||||
|
||||
#include "kernel/closure/alloc.h"
|
||||
@ -19,6 +22,8 @@
|
||||
#include "kernel/closure/bsdf_diffuse.h"
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bssrdf.h"
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
// clang-format on
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@ -59,14 +64,14 @@ class CBSSRDFClosure : public CClosurePrimitive {
|
||||
|
||||
void alloc(ShaderData *sd, uint32_t path_flag, float3 weight, ClosureType type)
|
||||
{
|
||||
Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
|
||||
Bssrdf *bssrdf = bssrdf_alloc(sd, rgb_to_spectrum(weight));
|
||||
|
||||
if (bssrdf) {
|
||||
/* 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) {
|
||||
params.radius = make_float3(0.0f, 0.0f, 0.0f);
|
||||
params.radius = zero_spectrum();
|
||||
}
|
||||
|
||||
/* create one closure per color channel */
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "kernel/closure/bsdf_principled_diffuse.h"
|
||||
#include "kernel/closure/bsdf_principled_sheen.h"
|
||||
#include "kernel/closure/volume.h"
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
// clang-format on
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@ -183,7 +185,7 @@ class PrincipledSheenClosure : public CBSDFClosure {
|
||||
params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N);
|
||||
|
||||
PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(PrincipledSheenBsdf), weight, ¶ms);
|
||||
sd, sizeof(PrincipledSheenBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
sd->flag |= (bsdf) ? bsdf_principled_sheen_setup(sd, bsdf) : 0;
|
||||
}
|
||||
}
|
||||
@ -207,7 +209,7 @@ class PrincipledHairClosure : public CBSDFClosure {
|
||||
PrincipledHairBSDF *alloc(ShaderData *sd, uint32_t path_flag, float3 weight)
|
||||
{
|
||||
PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)bsdf_alloc_osl(
|
||||
sd, sizeof(PrincipledHairBSDF), weight, ¶ms);
|
||||
sd, sizeof(PrincipledHairBSDF), rgb_to_spectrum(weight), ¶ms);
|
||||
if (!bsdf) {
|
||||
return NULL;
|
||||
}
|
||||
@ -263,7 +265,7 @@ class PrincipledClearcoatClosure : public CBSDFClosure {
|
||||
MicrofacetBsdf *alloc(ShaderData *sd, uint32_t path_flag, float3 weight)
|
||||
{
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
if (!bsdf) {
|
||||
return NULL;
|
||||
}
|
||||
@ -273,13 +275,13 @@ class PrincipledClearcoatClosure : public CBSDFClosure {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->extra = extra;
|
||||
bsdf->ior = 1.5f;
|
||||
bsdf->alpha_x = clearcoat_roughness;
|
||||
bsdf->alpha_y = clearcoat_roughness;
|
||||
bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
|
||||
bsdf->extra->color = zero_spectrum();
|
||||
bsdf->extra->cspec0 = make_spectrum(0.04f);
|
||||
bsdf->extra->clearcoat = clearcoat;
|
||||
return bsdf;
|
||||
}
|
||||
@ -511,7 +513,7 @@ class MicrofacetClosure : public CBSDFClosure {
|
||||
params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N);
|
||||
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
|
||||
if (!bsdf) {
|
||||
return;
|
||||
@ -586,7 +588,7 @@ class MicrofacetFresnelClosure : public CBSDFClosure {
|
||||
}
|
||||
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
if (!bsdf) {
|
||||
return NULL;
|
||||
}
|
||||
@ -597,8 +599,8 @@ class MicrofacetFresnelClosure : public CBSDFClosure {
|
||||
}
|
||||
|
||||
bsdf->extra = extra;
|
||||
bsdf->extra->color = color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
bsdf->extra->color = rgb_to_spectrum(color);
|
||||
bsdf->extra->cspec0 = rgb_to_spectrum(cspec0);
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
return bsdf;
|
||||
}
|
||||
@ -615,7 +617,7 @@ class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure {
|
||||
return;
|
||||
}
|
||||
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
|
||||
}
|
||||
@ -684,7 +686,7 @@ class MicrofacetMultiClosure : public CBSDFClosure {
|
||||
}
|
||||
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
if (!bsdf) {
|
||||
return NULL;
|
||||
}
|
||||
@ -695,8 +697,8 @@ class MicrofacetMultiClosure : public CBSDFClosure {
|
||||
}
|
||||
|
||||
bsdf->extra = extra;
|
||||
bsdf->extra->color = color;
|
||||
bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->extra->color = rgb_to_spectrum(color);
|
||||
bsdf->extra->cspec0 = zero_spectrum();
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
return bsdf;
|
||||
}
|
||||
@ -714,7 +716,7 @@ class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure {
|
||||
}
|
||||
|
||||
bsdf->ior = 0.0f;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
|
||||
}
|
||||
@ -777,7 +779,7 @@ class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure {
|
||||
return;
|
||||
}
|
||||
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
|
||||
}
|
||||
@ -814,7 +816,7 @@ class MicrofacetMultiFresnelClosure : public CBSDFClosure {
|
||||
}
|
||||
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
|
||||
sd, sizeof(MicrofacetBsdf), weight, ¶ms);
|
||||
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms);
|
||||
if (!bsdf) {
|
||||
return NULL;
|
||||
}
|
||||
@ -825,8 +827,8 @@ class MicrofacetMultiFresnelClosure : public CBSDFClosure {
|
||||
}
|
||||
|
||||
bsdf->extra = extra;
|
||||
bsdf->extra->color = color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
bsdf->extra->color = rgb_to_spectrum(color);
|
||||
bsdf->extra->cspec0 = rgb_to_spectrum(cspec0);
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
return bsdf;
|
||||
}
|
||||
@ -843,7 +845,7 @@ class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure {
|
||||
return;
|
||||
}
|
||||
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
|
||||
}
|
||||
@ -911,7 +913,7 @@ class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosu
|
||||
return;
|
||||
}
|
||||
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
|
||||
}
|
||||
@ -941,7 +943,7 @@ class TransparentClosure : public CBSDFClosure {
|
||||
|
||||
void setup(ShaderData *sd, uint32_t path_flag, float3 weight)
|
||||
{
|
||||
bsdf_transparent_setup(sd, weight, path_flag);
|
||||
bsdf_transparent_setup(sd, rgb_to_spectrum(weight), path_flag);
|
||||
}
|
||||
};
|
||||
|
||||
@ -960,7 +962,7 @@ class VolumeAbsorptionClosure : public CBSDFClosure {
|
||||
public:
|
||||
void setup(ShaderData *sd, uint32_t path_flag, float3 weight)
|
||||
{
|
||||
volume_extinction_setup(sd, weight);
|
||||
volume_extinction_setup(sd, rgb_to_spectrum(weight));
|
||||
}
|
||||
};
|
||||
|
||||
@ -979,10 +981,10 @@ class VolumeHenyeyGreensteinClosure : public CBSDFClosure {
|
||||
|
||||
void setup(ShaderData *sd, uint32_t path_flag, float3 weight)
|
||||
{
|
||||
volume_extinction_setup(sd, weight);
|
||||
volume_extinction_setup(sd, rgb_to_spectrum(weight));
|
||||
|
||||
HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume *)bsdf_alloc_osl(
|
||||
sd, sizeof(HenyeyGreensteinVolume), weight, ¶ms);
|
||||
sd, sizeof(HenyeyGreensteinVolume), rgb_to_spectrum(weight), ¶ms);
|
||||
if (!volume) {
|
||||
return;
|
||||
}
|
||||
|
@ -115,7 +115,8 @@ class CBSDFClosure : public CClosurePrimitive {
|
||||
{ \
|
||||
if (!skip(sd, path_flag, TYPE)) { \
|
||||
params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); \
|
||||
structname *bsdf = (structname *)bsdf_alloc_osl(sd, sizeof(structname), weight, ¶ms); \
|
||||
structname *bsdf = (structname *)bsdf_alloc_osl( \
|
||||
sd, sizeof(structname), rgb_to_spectrum(weight), ¶ms); \
|
||||
sd->flag |= (bsdf) ? bsdf_##lower##_setup(bsdf) : 0; \
|
||||
} \
|
||||
} \
|
||||
|
@ -14,9 +14,13 @@
|
||||
|
||||
// clang-format off
|
||||
#include "kernel/device/cpu/compat.h"
|
||||
#include "kernel/device/cpu/globals.h"
|
||||
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/emissive.h"
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
// clang-format on
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@ -34,7 +38,7 @@ class GenericEmissiveClosure : public CClosurePrimitive {
|
||||
public:
|
||||
void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight)
|
||||
{
|
||||
emission_setup(sd, weight);
|
||||
emission_setup(sd, rgb_to_spectrum(weight));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/util/color.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Closure Nodes */
|
||||
@ -183,7 +185,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
}
|
||||
float3 subsurface_radius = stack_valid(data_cn_ssr.y) ?
|
||||
stack_load_float3(stack, data_cn_ssr.y) :
|
||||
make_float3(1.0f, 1.0f, 1.0f);
|
||||
one_float3();
|
||||
float subsurface_ior = stack_valid(data_cn_ssr.z) ? stack_load_float(stack, data_cn_ssr.z) :
|
||||
1.4f;
|
||||
float subsurface_anisotropy = stack_valid(data_cn_ssr.w) ?
|
||||
@ -198,12 +200,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
__uint_as_float(data_subsurface_color.z),
|
||||
__uint_as_float(data_subsurface_color.w));
|
||||
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
|
||||
# ifdef __SUBSURFACE__
|
||||
float3 mixed_ss_base_color = subsurface_color * subsurface +
|
||||
base_color * (1.0f - subsurface);
|
||||
float3 subsurf_weight = weight * mixed_ss_base_color * diffuse_weight;
|
||||
Spectrum subsurf_weight = weight * rgb_to_spectrum(mixed_ss_base_color) * diffuse_weight;
|
||||
|
||||
/* disable in case of diffuse ancestor, can't see it well then and
|
||||
* adds considerably noise due to probabilities of continuing path
|
||||
@ -220,7 +222,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
/* diffuse */
|
||||
if (fabsf(average(mixed_ss_base_color)) > CLOSURE_WEIGHT_CUTOFF) {
|
||||
if (subsurface <= CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight;
|
||||
Spectrum diff_weight = weight * rgb_to_spectrum(base_color) * diffuse_weight;
|
||||
|
||||
ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)
|
||||
bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
|
||||
@ -237,8 +239,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, subsurf_weight);
|
||||
|
||||
if (bssrdf) {
|
||||
bssrdf->radius = subsurface_radius * subsurface;
|
||||
bssrdf->albedo = mixed_ss_base_color;
|
||||
bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface);
|
||||
bssrdf->albedo = rgb_to_spectrum(mixed_ss_base_color);
|
||||
bssrdf->N = N;
|
||||
bssrdf->roughness = roughness;
|
||||
|
||||
@ -254,7 +256,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
# else
|
||||
/* diffuse */
|
||||
if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 diff_weight = weight * base_color * diffuse_weight;
|
||||
Spectrum diff_weight = weight * rgb_to_spectrum(base_color) * diffuse_weight;
|
||||
|
||||
ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
|
||||
@ -272,15 +274,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
/* sheen */
|
||||
if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float m_cdlum = linear_rgb_to_gray(kg, base_color);
|
||||
float3 m_ctint = m_cdlum > 0.0f ?
|
||||
base_color / m_cdlum :
|
||||
make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
|
||||
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum :
|
||||
one_float3(); // normalize lum. to isolate hue+sat
|
||||
|
||||
/* color of the sheen component */
|
||||
float3 sheen_color = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sheen_tint) +
|
||||
m_ctint * sheen_tint;
|
||||
float3 sheen_color = make_float3(1.0f - sheen_tint) + m_ctint * sheen_tint;
|
||||
|
||||
float3 sheen_weight = weight * sheen * sheen_color * diffuse_weight;
|
||||
Spectrum sheen_weight = weight * sheen * rgb_to_spectrum(sheen_color) * diffuse_weight;
|
||||
|
||||
ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc(
|
||||
sd, sizeof(PrincipledSheenBsdf), sheen_weight);
|
||||
@ -299,7 +299,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
# endif
|
||||
if (specular_weight > CLOSURE_WEIGHT_CUTOFF &&
|
||||
(specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) {
|
||||
float3 spec_weight = weight * specular_weight;
|
||||
Spectrum spec_weight = weight * specular_weight;
|
||||
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), spec_weight);
|
||||
@ -322,16 +322,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y +
|
||||
0.1f * base_color.z; // luminance approx.
|
||||
float3 m_ctint = m_cdlum > 0.0f ?
|
||||
base_color / m_cdlum :
|
||||
make_float3(
|
||||
1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
|
||||
float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) +
|
||||
m_ctint * specular_tint;
|
||||
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum :
|
||||
one_float3(); // normalize lum. to isolate hue+sat
|
||||
float3 tmp_col = make_float3(1.0f - specular_tint) + m_ctint * specular_tint;
|
||||
|
||||
bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) +
|
||||
base_color * metallic;
|
||||
bsdf->extra->color = base_color;
|
||||
bsdf->extra->cspec0 = rgb_to_spectrum(
|
||||
(specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic);
|
||||
bsdf->extra->color = rgb_to_spectrum(base_color);
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
|
||||
/* setup bsdf */
|
||||
@ -352,9 +349,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
|
||||
# endif
|
||||
if (final_transmission > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 glass_weight = weight * final_transmission;
|
||||
float3 cspec0 = base_color * specular_tint +
|
||||
make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint);
|
||||
Spectrum glass_weight = weight * final_transmission;
|
||||
float3 cspec0 = base_color * specular_tint + make_float3(1.0f - specular_tint);
|
||||
|
||||
if (roughness <= 5e-2f ||
|
||||
distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) { /* use single-scatter GGX */
|
||||
@ -374,15 +370,15 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
if (bsdf && extra) {
|
||||
bsdf->N = N;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->extra = extra;
|
||||
|
||||
bsdf->alpha_x = refl_roughness * refl_roughness;
|
||||
bsdf->alpha_y = refl_roughness * refl_roughness;
|
||||
bsdf->ior = ior;
|
||||
|
||||
bsdf->extra->color = base_color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
bsdf->extra->color = rgb_to_spectrum(base_color);
|
||||
bsdf->extra->cspec0 = rgb_to_spectrum(cspec0);
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
|
||||
/* setup bsdf */
|
||||
@ -398,10 +394,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
/* This is to prevent MNEE from receiving a null BSDF. */
|
||||
float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel);
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), base_color * glass_weight * refraction_fresnel);
|
||||
sd,
|
||||
sizeof(MicrofacetBsdf),
|
||||
rgb_to_spectrum(base_color) * glass_weight * refraction_fresnel);
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->extra = NULL;
|
||||
|
||||
if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
|
||||
@ -430,14 +428,14 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
if (bsdf && extra) {
|
||||
bsdf->N = N;
|
||||
bsdf->extra = extra;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
|
||||
bsdf->alpha_x = roughness * roughness;
|
||||
bsdf->alpha_y = roughness * roughness;
|
||||
bsdf->ior = ior;
|
||||
|
||||
bsdf->extra->color = base_color;
|
||||
bsdf->extra->cspec0 = cspec0;
|
||||
bsdf->extra->color = rgb_to_spectrum(base_color);
|
||||
bsdf->extra->cspec0 = rgb_to_spectrum(cspec0);
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
|
||||
/* setup bsdf */
|
||||
@ -463,15 +461,15 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
if (bsdf && extra) {
|
||||
bsdf->N = clearcoat_normal;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->ior = 1.5f;
|
||||
bsdf->extra = extra;
|
||||
|
||||
bsdf->alpha_x = clearcoat_roughness * clearcoat_roughness;
|
||||
bsdf->alpha_y = clearcoat_roughness * clearcoat_roughness;
|
||||
|
||||
bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
|
||||
bsdf->extra->color = zero_spectrum();
|
||||
bsdf->extra->cspec0 = make_spectrum(0.04f);
|
||||
bsdf->extra->clearcoat = clearcoat;
|
||||
|
||||
/* setup bsdf */
|
||||
@ -486,7 +484,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
}
|
||||
#endif /* __PRINCIPLED__ */
|
||||
case CLOSURE_BSDF_DIFFUSE_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private OrenNayarBsdf *bsdf = (ccl_private OrenNayarBsdf *)bsdf_alloc(
|
||||
sd, sizeof(OrenNayarBsdf), weight);
|
||||
|
||||
@ -506,7 +504,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
|
||||
sd, sizeof(DiffuseBsdf), weight);
|
||||
|
||||
@ -517,7 +515,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_TRANSPARENT_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
bsdf_transparent_setup(sd, weight, path_flag);
|
||||
break;
|
||||
}
|
||||
@ -530,7 +528,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
||||
break;
|
||||
#endif
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), weight);
|
||||
|
||||
@ -545,7 +543,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
bsdf->extra = NULL;
|
||||
|
||||
if (data_node.y == SVM_STACK_INVALID) {
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->alpha_x = roughness;
|
||||
bsdf->alpha_y = roughness;
|
||||
}
|
||||
@ -581,8 +579,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
bsdf->extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(sd,
|
||||
sizeof(MicrofacetExtra));
|
||||
if (bsdf->extra) {
|
||||
bsdf->extra->color = stack_load_float3(stack, data_node.w);
|
||||
bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->extra->color = rgb_to_spectrum(stack_load_float3(stack, data_node.w));
|
||||
bsdf->extra->cspec0 = zero_spectrum();
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
|
||||
}
|
||||
@ -600,13 +598,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
if (!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
|
||||
break;
|
||||
#endif
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->extra = NULL;
|
||||
|
||||
float eta = fmaxf(param2, 1e-5f);
|
||||
@ -644,7 +642,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
|
||||
/* index of refraction */
|
||||
float eta = fmaxf(param2, 1e-5f);
|
||||
@ -665,7 +663,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->extra = NULL;
|
||||
svm_node_glass_setup(sd, bsdf, type, eta, roughness, false);
|
||||
}
|
||||
@ -683,7 +681,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
bsdf->extra = NULL;
|
||||
svm_node_glass_setup(sd, bsdf, type, eta, roughness, true);
|
||||
}
|
||||
@ -697,7 +695,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
|
||||
break;
|
||||
#endif
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(MicrofacetBsdf), weight);
|
||||
if (!bsdf) {
|
||||
@ -712,7 +710,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
|
||||
bsdf->N = N;
|
||||
bsdf->extra = extra;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->T = zero_float3();
|
||||
|
||||
float roughness = sqr(param1);
|
||||
bsdf->alpha_x = roughness;
|
||||
@ -721,8 +719,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
|
||||
|
||||
kernel_assert(stack_valid(data_node.z));
|
||||
bsdf->extra->color = stack_load_float3(stack, data_node.z);
|
||||
bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->extra->color = rgb_to_spectrum(stack_load_float3(stack, data_node.z));
|
||||
bsdf->extra->cspec0 = zero_spectrum();
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
|
||||
/* setup bsdf */
|
||||
@ -730,7 +728,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private VelvetBsdf *bsdf = (ccl_private VelvetBsdf *)bsdf_alloc(
|
||||
sd, sizeof(VelvetBsdf), weight);
|
||||
|
||||
@ -749,7 +747,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
ATTR_FALLTHROUGH;
|
||||
#endif
|
||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private ToonBsdf *bsdf = (ccl_private ToonBsdf *)bsdf_alloc(
|
||||
sd, sizeof(ToonBsdf), weight);
|
||||
|
||||
@ -771,7 +769,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
uint4 data_node3 = read_node(kg, &offset);
|
||||
uint4 data_node4 = read_node(kg, &offset);
|
||||
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
|
||||
uint offset_ofs, ior_ofs, color_ofs, parametrization;
|
||||
svm_unpack_node_uchar4(data_node.y, &offset_ofs, &ior_ofs, &color_ofs, ¶metrization);
|
||||
@ -829,7 +827,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
switch (parametrization) {
|
||||
case NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION: {
|
||||
float3 absorption_coefficient = stack_load_float3(stack, absorption_coefficient_ofs);
|
||||
bsdf->sigma = absorption_coefficient;
|
||||
bsdf->sigma = rgb_to_spectrum(absorption_coefficient);
|
||||
break;
|
||||
}
|
||||
case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION: {
|
||||
@ -849,20 +847,21 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
/* Benedikt Bitterli's melanin ratio remapping. */
|
||||
float eumelanin = melanin * (1.0f - melanin_redness);
|
||||
float pheomelanin = melanin * melanin_redness;
|
||||
float3 melanin_sigma = bsdf_principled_hair_sigma_from_concentration(eumelanin,
|
||||
pheomelanin);
|
||||
Spectrum melanin_sigma = bsdf_principled_hair_sigma_from_concentration(eumelanin,
|
||||
pheomelanin);
|
||||
|
||||
/* Optional tint. */
|
||||
float3 tint = stack_load_float3(stack, tint_ofs);
|
||||
float3 tint_sigma = bsdf_principled_hair_sigma_from_reflectance(tint,
|
||||
radial_roughness);
|
||||
Spectrum tint_sigma = bsdf_principled_hair_sigma_from_reflectance(
|
||||
rgb_to_spectrum(tint), radial_roughness);
|
||||
|
||||
bsdf->sigma = melanin_sigma + tint_sigma;
|
||||
break;
|
||||
}
|
||||
case NODE_PRINCIPLED_HAIR_REFLECTANCE: {
|
||||
float3 color = stack_load_float3(stack, color_ofs);
|
||||
bsdf->sigma = bsdf_principled_hair_sigma_from_reflectance(color, radial_roughness);
|
||||
bsdf->sigma = bsdf_principled_hair_sigma_from_reflectance(rgb_to_spectrum(color),
|
||||
radial_roughness);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -879,7 +878,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
}
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
|
||||
ccl_private HairBsdf *bsdf = (ccl_private HairBsdf *)bsdf_alloc(
|
||||
sd, sizeof(HairBsdf), weight);
|
||||
@ -916,7 +915,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
case CLOSURE_BSSRDF_BURLEY_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
Spectrum weight = sd->svm_closure_weight * mix_weight;
|
||||
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
|
||||
|
||||
if (bssrdf) {
|
||||
@ -926,7 +925,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
|
||||
if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
|
||||
param1 = 0.0f;
|
||||
|
||||
bssrdf->radius = stack_load_float3(stack, data_node.z) * param1;
|
||||
bssrdf->radius = rgb_to_spectrum(stack_load_float3(stack, data_node.z) * param1);
|
||||
bssrdf->albedo = sd->svm_closure_weight;
|
||||
bssrdf->N = N;
|
||||
bssrdf->roughness = FLT_MAX;
|
||||
@ -976,10 +975,10 @@ ccl_device_noinline void svm_node_closure_volume(KernelGlobals kg,
|
||||
density = mix_weight * fmaxf(density, 0.0f);
|
||||
|
||||
/* Compute scattering coefficient. */
|
||||
float3 weight = sd->svm_closure_weight;
|
||||
Spectrum weight = sd->svm_closure_weight;
|
||||
|
||||
if (type == CLOSURE_VOLUME_ABSORPTION_ID) {
|
||||
weight = make_float3(1.0f, 1.0f, 1.0f) - weight;
|
||||
weight = one_spectrum() - weight;
|
||||
}
|
||||
|
||||
weight *= density;
|
||||
@ -1047,11 +1046,11 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg,
|
||||
|
||||
if (density > CLOSURE_WEIGHT_CUTOFF) {
|
||||
/* Compute scattering color. */
|
||||
float3 color = sd->svm_closure_weight;
|
||||
Spectrum color = sd->svm_closure_weight;
|
||||
|
||||
const AttributeDescriptor attr_color = find_attribute(kg, sd, attr_node.y);
|
||||
if (attr_color.offset != ATTR_STD_NOT_FOUND) {
|
||||
color *= primitive_volume_attribute_float3(kg, sd, attr_color);
|
||||
color *= rgb_to_spectrum(primitive_volume_attribute_float3(kg, sd, attr_color));
|
||||
}
|
||||
|
||||
/* Add closure for volume scattering. */
|
||||
@ -1066,10 +1065,13 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg,
|
||||
}
|
||||
|
||||
/* Add extinction weight. */
|
||||
float3 zero = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float3 one = make_float3(1.0f, 1.0f, 1.0f);
|
||||
float3 absorption_color = max(sqrt(stack_load_float3(stack, absorption_color_offset)), zero);
|
||||
float3 absorption = max(one - color, zero) * max(one - absorption_color, zero);
|
||||
float3 absorption_color = max(sqrt(stack_load_float3(stack, absorption_color_offset)),
|
||||
zero_float3());
|
||||
|
||||
Spectrum zero = zero_spectrum();
|
||||
Spectrum one = one_spectrum();
|
||||
Spectrum absorption = max(one - color, zero) *
|
||||
max(one - rgb_to_spectrum(absorption_color), zero);
|
||||
volume_extinction_setup(sd, (color + absorption) * density);
|
||||
}
|
||||
|
||||
@ -1089,7 +1091,7 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg,
|
||||
|
||||
if (emission > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 emission_color = stack_load_float3(stack, emission_color_offset);
|
||||
emission_setup(sd, emission * emission_color);
|
||||
emission_setup(sd, rgb_to_spectrum(emission * emission_color));
|
||||
}
|
||||
|
||||
if (blackbody > CLOSURE_WEIGHT_CUTOFF) {
|
||||
@ -1113,7 +1115,7 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg,
|
||||
float3 blackbody_tint = stack_load_float3(stack, node.w);
|
||||
float3 bb = blackbody_tint * intensity *
|
||||
rec709_to_rgb(kg, svm_math_blackbody_color_rec709(T));
|
||||
emission_setup(sd, bb);
|
||||
emission_setup(sd, rgb_to_spectrum(bb));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1125,7 +1127,7 @@ ccl_device_noinline void svm_node_closure_emission(ccl_private ShaderData *sd,
|
||||
uint4 node)
|
||||
{
|
||||
uint mix_weight_offset = node.y;
|
||||
float3 weight = sd->svm_closure_weight;
|
||||
Spectrum weight = sd->svm_closure_weight;
|
||||
|
||||
if (stack_valid(mix_weight_offset)) {
|
||||
float mix_weight = stack_load_float(stack, mix_weight_offset);
|
||||
@ -1144,7 +1146,7 @@ ccl_device_noinline void svm_node_closure_background(ccl_private ShaderData *sd,
|
||||
uint4 node)
|
||||
{
|
||||
uint mix_weight_offset = node.y;
|
||||
float3 weight = sd->svm_closure_weight;
|
||||
Spectrum weight = sd->svm_closure_weight;
|
||||
|
||||
if (stack_valid(mix_weight_offset)) {
|
||||
float mix_weight = stack_load_float(stack, mix_weight_offset);
|
||||
@ -1181,14 +1183,15 @@ ccl_device_noinline void svm_node_closure_holdout(ccl_private ShaderData *sd,
|
||||
|
||||
/* Closure Nodes */
|
||||
|
||||
ccl_device_inline void svm_node_closure_store_weight(ccl_private ShaderData *sd, float3 weight)
|
||||
ccl_device_inline void svm_node_closure_store_weight(ccl_private ShaderData *sd, Spectrum weight)
|
||||
{
|
||||
sd->svm_closure_weight = weight;
|
||||
}
|
||||
|
||||
ccl_device void svm_node_closure_set_weight(ccl_private ShaderData *sd, uint r, uint g, uint b)
|
||||
{
|
||||
float3 weight = make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b));
|
||||
Spectrum weight = rgb_to_spectrum(
|
||||
make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b)));
|
||||
svm_node_closure_store_weight(sd, weight);
|
||||
}
|
||||
|
||||
@ -1196,7 +1199,7 @@ ccl_device void svm_node_closure_weight(ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
uint weight_offset)
|
||||
{
|
||||
float3 weight = stack_load_float3(stack, weight_offset);
|
||||
Spectrum weight = rgb_to_spectrum(stack_load_float3(stack, weight_offset));
|
||||
svm_node_closure_store_weight(sd, weight);
|
||||
}
|
||||
|
||||
@ -1209,7 +1212,7 @@ ccl_device_noinline void svm_node_emission_weight(KernelGlobals kg,
|
||||
uint strength_offset = node.z;
|
||||
|
||||
float strength = stack_load_float(stack, strength_offset);
|
||||
float3 weight = stack_load_float3(stack, color_offset) * strength;
|
||||
Spectrum weight = rgb_to_spectrum(stack_load_float3(stack, color_offset)) * strength;
|
||||
|
||||
svm_node_closure_store_weight(sd, weight);
|
||||
}
|
||||
|
@ -413,9 +413,9 @@ typedef enum CryptomatteType {
|
||||
} CryptomatteType;
|
||||
|
||||
typedef struct BsdfEval {
|
||||
float3 diffuse;
|
||||
float3 glossy;
|
||||
float3 sum;
|
||||
Spectrum diffuse;
|
||||
Spectrum glossy;
|
||||
Spectrum sum;
|
||||
} BsdfEval;
|
||||
|
||||
/* Closure Filter */
|
||||
@ -709,7 +709,7 @@ typedef struct AttributeMap {
|
||||
* padded to be 16 bytes, while it's only 12 bytes on the GPU. */
|
||||
|
||||
#define SHADER_CLOSURE_BASE \
|
||||
float3 weight; \
|
||||
Spectrum weight; \
|
||||
ClosureType type; \
|
||||
float sample_weight; \
|
||||
float3 N
|
||||
@ -718,10 +718,9 @@ typedef struct ccl_align(16) ShaderClosure
|
||||
{
|
||||
SHADER_CLOSURE_BASE;
|
||||
|
||||
#ifndef __KERNEL_GPU__
|
||||
float pad[2];
|
||||
#endif
|
||||
float data[10];
|
||||
/* Extra space for closures to store data, somewhat arbitrary but closures
|
||||
* assert that their size fits. */
|
||||
char pad[sizeof(Spectrum) * 2 + sizeof(float) * 4];
|
||||
}
|
||||
ShaderClosure;
|
||||
|
||||
@ -912,12 +911,12 @@ typedef struct ccl_align(16) ShaderData
|
||||
/* Closure data, we store a fixed array of closures */
|
||||
int num_closure;
|
||||
int num_closure_left;
|
||||
float3 svm_closure_weight;
|
||||
Spectrum svm_closure_weight;
|
||||
|
||||
/* Closure weights summed directly, so we can evaluate
|
||||
* emission and shadow transparency with MAX_CLOSURE 0. */
|
||||
float3 closure_emission_background;
|
||||
float3 closure_transparent_extinction;
|
||||
Spectrum closure_emission_background;
|
||||
Spectrum closure_transparent_extinction;
|
||||
|
||||
/* At the end so we can adjust size in ShaderDataTinyStorage. */
|
||||
struct ShaderClosure closure[MAX_CLOSURE];
|
||||
@ -948,7 +947,7 @@ ShaderDataCausticsStorage;
|
||||
* Used for decoupled direct/indirect light closure storage. */
|
||||
|
||||
typedef struct ShaderVolumeClosure {
|
||||
float3 weight;
|
||||
Spectrum weight;
|
||||
float sample_weight;
|
||||
float g;
|
||||
} ShaderVolumeClosure;
|
||||
|
@ -33,4 +33,19 @@ ccl_device float linear_rgb_to_gray(KernelGlobals kg, float3 c)
|
||||
return dot(c, float4_to_float3(kernel_data.film.rgb_to_y));
|
||||
}
|
||||
|
||||
ccl_device_inline Spectrum rgb_to_spectrum(float3 rgb)
|
||||
{
|
||||
return rgb;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 spectrum_to_rgb(Spectrum s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
ccl_device float spectrum_to_gray(KernelGlobals kg, Spectrum c)
|
||||
{
|
||||
return linear_rgb_to_gray(kg, spectrum_to_rgb(c));
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -116,6 +116,7 @@ set(SRC_HEADERS
|
||||
types_int3_impl.h
|
||||
types_int4.h
|
||||
types_int4_impl.h
|
||||
types_spectrum.h
|
||||
types_uchar2.h
|
||||
types_uchar2_impl.h
|
||||
types_uchar3.h
|
||||
|
@ -136,4 +136,7 @@ template<typename T> static inline T decltype_helper(T x)
|
||||
# define util_assert(statement)
|
||||
#endif
|
||||
|
||||
#define CONCAT_HELPER(a, ...) a##__VA_ARGS__
|
||||
#define CONCAT(a, ...) CONCAT_HELPER(a, __VA_ARGS__)
|
||||
|
||||
#endif /* __UTIL_DEFINES_H__ */
|
||||
|
@ -595,26 +595,26 @@ ccl_device_inline void make_orthonormals(const float3 N,
|
||||
|
||||
/* Color division */
|
||||
|
||||
ccl_device_inline float3 safe_invert_color(float3 a)
|
||||
ccl_device_inline Spectrum safe_invert_color(Spectrum a)
|
||||
{
|
||||
float x, y, z;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
GET_SPECTRUM_CHANNEL(a, i) = (GET_SPECTRUM_CHANNEL(a, i) != 0.0f) ?
|
||||
1.0f / GET_SPECTRUM_CHANNEL(a, i) :
|
||||
0.0f;
|
||||
}
|
||||
|
||||
x = (a.x != 0.0f) ? 1.0f / a.x : 0.0f;
|
||||
y = (a.y != 0.0f) ? 1.0f / a.y : 0.0f;
|
||||
z = (a.z != 0.0f) ? 1.0f / a.z : 0.0f;
|
||||
|
||||
return make_float3(x, y, z);
|
||||
return a;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 safe_divide_color(float3 a, float3 b)
|
||||
ccl_device_inline Spectrum safe_divide_color(Spectrum a, Spectrum b)
|
||||
{
|
||||
float x, y, z;
|
||||
FOREACH_SPECTRUM_CHANNEL (i) {
|
||||
GET_SPECTRUM_CHANNEL(a, i) = (GET_SPECTRUM_CHANNEL(b, i) != 0.0f) ?
|
||||
GET_SPECTRUM_CHANNEL(a, i) / GET_SPECTRUM_CHANNEL(b, i) :
|
||||
0.0f;
|
||||
}
|
||||
|
||||
x = (b.x != 0.0f) ? a.x / b.x : 0.0f;
|
||||
y = (b.y != 0.0f) ? a.y / b.y : 0.0f;
|
||||
z = (b.z != 0.0f) ? a.z / b.z : 0.0f;
|
||||
|
||||
return make_float3(x, y, z);
|
||||
return a;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 safe_divide_even_color(float3 a, float3 b)
|
||||
|
@ -109,6 +109,8 @@ ccl_device_inline void print_float(ccl_private const char *label, const float a)
|
||||
#include "util/types_float4.h"
|
||||
#include "util/types_float8.h"
|
||||
|
||||
#include "util/types_spectrum.h"
|
||||
|
||||
/* Vectorized types implementation. */
|
||||
#include "util/types_uchar2_impl.h"
|
||||
#include "util/types_uchar3_impl.h"
|
||||
|
34
intern/cycles/util/types_spectrum.h
Normal file
34
intern/cycles/util/types_spectrum.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#ifndef __UTIL_TYPES_SPECTRUM_H__
|
||||
#define __UTIL_TYPES_SPECTRUM_H__
|
||||
|
||||
#ifndef __UTIL_TYPES_H__
|
||||
# error "Do not include this file directly, include util/types.h instead."
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#define SPECTRUM_CHANNELS 3
|
||||
#define SPECTRUM_DATA_TYPE float3
|
||||
#define PACKED_SPECTRUM_DATA_TYPE packed_float3
|
||||
|
||||
using Spectrum = SPECTRUM_DATA_TYPE;
|
||||
using PackedSpectrum = PACKED_SPECTRUM_DATA_TYPE;
|
||||
|
||||
#define make_spectrum(f) CONCAT(make_, SPECTRUM_DATA_TYPE(f))
|
||||
#define load_spectrum(f) CONCAT(load_, SPECTRUM_DATA_TYPE(f))
|
||||
#define store_spectrum(s, f) CONCAT(store_, SPECTRUM_DATA_TYPE((s), (f)))
|
||||
|
||||
#define zero_spectrum CONCAT(zero_, SPECTRUM_DATA_TYPE)
|
||||
#define one_spectrum CONCAT(one_, SPECTRUM_DATA_TYPE)
|
||||
|
||||
#define FOREACH_SPECTRUM_CHANNEL(counter) \
|
||||
for (int counter = 0; counter < SPECTRUM_CHANNELS; counter++)
|
||||
|
||||
#define GET_SPECTRUM_CHANNEL(v, i) (((ccl_private float *)(&(v)))[i])
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __UTIL_TYPES_SPECTRUM_H__ */
|
Loading…
Reference in New Issue
Block a user