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:
Andrii Symkin 2022-07-29 13:41:37 +02:00 committed by Brecht Van Lommel
parent 7921faa651
commit d832d993c5
59 changed files with 1066 additions and 947 deletions

View File

@ -266,6 +266,7 @@ ForEachMacros:
- MAP_SLOT_PROBING_BEGIN
- VECTOR_SET_SLOT_PROBING_BEGIN
- WL_ARRAY_FOR_EACH
- FOREACH_SPECTRUM_CHANNEL
StatementMacros:
- PyObject_HEAD

View File

@ -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

View File

@ -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(

View File

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

View File

@ -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) {

View File

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

View File

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

View File

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

View File

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

View File

@ -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.

View File

@ -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

View File

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

View File

@ -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__

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

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

View File

@ -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,

View File

@ -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)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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. */

View File

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

View File

@ -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) {

View File

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

View File

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

View File

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

View File

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

View File

@ -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, &params);
sd, sizeof(DiffuseRampBsdf), rgb_to_spectrum(weight), &params);
if (bsdf) {
bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);

View File

@ -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, &params);
sd, sizeof(PhongRampBsdf), rgb_to_spectrum(weight), &params);
if (bsdf) {
bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);

View File

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

View File

@ -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, &params);
sd, sizeof(PrincipledSheenBsdf), rgb_to_spectrum(weight), &params);
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, &params);
sd, sizeof(PrincipledHairBSDF), rgb_to_spectrum(weight), &params);
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, &params);
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), &params);
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, &params);
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), &params);
if (!bsdf) {
return;
@ -586,7 +588,7 @@ class MicrofacetFresnelClosure : public CBSDFClosure {
}
MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
sd, sizeof(MicrofacetBsdf), weight, &params);
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), &params);
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, &params);
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), &params);
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, &params);
sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), &params);
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, &params);
sd, sizeof(HenyeyGreensteinVolume), rgb_to_spectrum(weight), &params);
if (!volume) {
return;
}

View File

@ -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, &params); \
structname *bsdf = (structname *)bsdf_alloc_osl( \
sd, sizeof(structname), rgb_to_spectrum(weight), &params); \
sd->flag |= (bsdf) ? bsdf_##lower##_setup(bsdf) : 0; \
} \
} \

View File

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

View File

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

View File

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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -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"

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