Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format1
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/bake/bake.h12
-rw-r--r--intern/cycles/kernel/closure/alloc.h6
-rw-r--r--intern/cycles/kernel/closure/bsdf.h6
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h20
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h32
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse.h52
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse_ramp.h27
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair.h52
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair_principled.h131
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h98
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h89
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h58
-rw-r--r--intern/cycles/kernel/closure/bsdf_oren_nayar.h34
-rw-r--r--intern/cycles/kernel/closure/bsdf_phong_ramp.h20
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_diffuse.h30
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_sheen.h30
-rw-r--r--intern/cycles/kernel/closure/bsdf_reflection.h26
-rw-r--r--intern/cycles/kernel/closure/bsdf_refraction.h26
-rw-r--r--intern/cycles/kernel/closure/bsdf_toon.h70
-rw-r--r--intern/cycles/kernel/closure/bsdf_transparent.h26
-rw-r--r--intern/cycles/kernel/closure/bsdf_util.h6
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h119
-rw-r--r--intern/cycles/kernel/closure/emissive.h8
-rw-r--r--intern/cycles/kernel/closure/volume.h59
-rw-r--r--intern/cycles/kernel/film/accumulate.h125
-rw-r--r--intern/cycles/kernel/film/passes.h48
-rw-r--r--intern/cycles/kernel/film/write_passes.h8
-rw-r--r--intern/cycles/kernel/integrator/mnee.h10
-rw-r--r--intern/cycles/kernel/integrator/path_state.h4
-rw-r--r--intern/cycles/kernel/integrator/shade_background.h20
-rw-r--r--intern/cycles/kernel/integrator/shade_light.h4
-rw-r--r--intern/cycles/kernel/integrator/shade_shadow.h14
-rw-r--r--intern/cycles/kernel/integrator/shade_surface.h30
-rw-r--r--intern/cycles/kernel/integrator/shade_volume.h125
-rw-r--r--intern/cycles/kernel/integrator/shader_eval.h87
-rw-r--r--intern/cycles/kernel/integrator/shadow_catcher.h2
-rw-r--r--intern/cycles/kernel/integrator/shadow_state_template.h8
-rw-r--r--intern/cycles/kernel/integrator/state_template.h12
-rw-r--r--intern/cycles/kernel/integrator/subsurface.h8
-rw-r--r--intern/cycles/kernel/integrator/subsurface_disk.h14
-rw-r--r--intern/cycles/kernel/integrator/subsurface_random_walk.h87
-rw-r--r--intern/cycles/kernel/light/sample.h7
-rw-r--r--intern/cycles/kernel/osl/background.cpp8
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp7
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp7
-rw-r--r--intern/cycles/kernel/osl/bssrdf.cpp9
-rw-r--r--intern/cycles/kernel/osl/closures.cpp52
-rw-r--r--intern/cycles/kernel/osl/closures.h3
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp6
-rw-r--r--intern/cycles/kernel/svm/closure.h167
-rw-r--r--intern/cycles/kernel/types.h23
-rw-r--r--intern/cycles/kernel/util/color.h15
-rw-r--r--intern/cycles/util/CMakeLists.txt1
-rw-r--r--intern/cycles/util/defines.h3
-rw-r--r--intern/cycles/util/math.h28
-rw-r--r--intern/cycles/util/types.h2
-rw-r--r--intern/cycles/util/types_spectrum.h34
59 files changed, 1068 insertions, 949 deletions
diff --git a/.clang-format b/.clang-format
index 7b8e0ef8eba..7e88e6d1cb1 100644
--- a/.clang-format
+++ b/.clang-format
@@ -266,6 +266,7 @@ ForEachMacros:
- MAP_SLOT_PROBING_BEGIN
- VECTOR_SET_SLOT_PROBING_BEGIN
- WL_ARRAY_FOR_EACH
+ - FOREACH_SPECTRUM_CHANNEL
StatementMacros:
- PyObject_HEAD
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 3f857be0dfa..8b8ad1758ca 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -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
diff --git a/intern/cycles/kernel/bake/bake.h b/intern/cycles/kernel/bake/bake.h
index ec87990b699..9d53d71b431 100644
--- a/intern/cycles/kernel/bake/bake.h
+++ b/intern/cycles/kernel/bake/bake.h
@@ -8,6 +8,8 @@
#include "kernel/geom/geom.h"
+#include "kernel/util/color.h"
+
CCL_NAMESPACE_BEGIN
ccl_device void kernel_displace_evaluate(KernelGlobals kg,
@@ -65,7 +67,7 @@ ccl_device void kernel_background_evaluate(KernelGlobals kg,
shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT &
~(KERNEL_FEATURE_NODE_RAYTRACE | KERNEL_FEATURE_NODE_LIGHT_PATH)>(
kg, INTEGRATOR_STATE_NULL, &sd, NULL, path_flag);
- float3 color = shader_background_eval(&sd);
+ Spectrum color = shader_background_eval(&sd);
#ifdef __KERNEL_DEBUG_NAN__
if (!isfinite_safe(color)) {
@@ -76,10 +78,12 @@ ccl_device void kernel_background_evaluate(KernelGlobals kg,
/* Ensure finite color, avoiding possible numerical instabilities in the path tracing kernels. */
color = ensure_finite(color);
+ float3 color_rgb = spectrum_to_rgb(color);
+
/* Write output. */
- output[offset * 3 + 0] += color.x;
- output[offset * 3 + 1] += color.y;
- output[offset * 3 + 2] += color.z;
+ output[offset * 3 + 0] += color_rgb.x;
+ output[offset * 3 + 1] += color_rgb.y;
+ output[offset * 3 + 2] += color_rgb.z;
}
ccl_device void kernel_curve_shadow_transparency_evaluate(
diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h
index 933c07a5102..9847898ee89 100644
--- a/intern/cycles/kernel/closure/alloc.h
+++ b/intern/cycles/kernel/closure/alloc.h
@@ -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));
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 4feb21c43e3..7b28018afad 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -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) {
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index 47066542122..2f6ac2dceb0 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -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 {
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
index 3d7906eef7d..ee58bd50aa1 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
@@ -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;
}
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h
index 759ad03f8e8..2a082796043 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse.h
@@ -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;
}
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
index aa4c091f587..8b88edb37f7 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
@@ -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;
}
diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index a136ed05800..4179f73e22c 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -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)
+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 make_float3(0.0f, 0.0f, 0.0f);
+ return zero_spectrum();
}
-ccl_device float3 bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc,
- const float3 I,
- const float3 omega_in,
- ccl_private float *pdf)
+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.
diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
index e7f24b89458..f78a05ea212 100644
--- a/intern/cycles/kernel/closure/bsdf_hair_principled.h
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -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
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index c6cbd1ffae7..091fbde5585 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -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;
}
}
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
index b2e068daf17..e6ab116519b 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -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__
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
index e4fcf0e6ba3..91fb9158050 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
@@ -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
diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
index 56c7ec869c7..fcfeb9257f1 100644
--- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h
+++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
@@ -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;
diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
index 74a1f7ae090..d010e74cb65 100644
--- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
@@ -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;
diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
index 5a7020e82d2..90ef252b3b9 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
@@ -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;
}
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
index 3a96a93db73..42a776299eb 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
@@ -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;
diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h
index c8db2b7cf13..40d02b13b46 100644
--- a/intern/cycles/kernel/closure/bsdf_reflection.h
+++ b/intern/cycles/kernel/closure/bsdf_reflection.h
@@ -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;
}
diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h
index 862e774da87..3faa51025d6 100644
--- a/intern/cycles/kernel/closure/bsdf_refraction.h
+++ b/intern/cycles/kernel/closure/bsdf_refraction.h
@@ -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;
}
diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h
index 0400fc61860..f2f48417319 100644
--- a/intern/cycles/kernel/closure/bsdf_toon.h
+++ b/intern/cycles/kernel/closure/bsdf_toon.h
@@ -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();
}
}
diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h
index 636d9d664f2..89b36c709e4 100644
--- a/intern/cycles/kernel/closure/bsdf_transparent.h
+++ b/intern/cycles/kernel/closure/bsdf_transparent.h
@@ -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;
}
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index e3b24d487f1..10f2643721e 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -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)
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index b87790f5f8a..47df0c5533a 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -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;
-
- 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;
+ sampled_radius = 0.0f;
+
+ 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);
-
- 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--;
+ int bssrdf_channels = SPECTRUM_CHANNELS;
+ Spectrum diffuse_weight = zero_spectrum();
+
+ 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) {
diff --git a/intern/cycles/kernel/closure/emissive.h b/intern/cycles/kernel/closure/emissive.h
index 03e19cbde21..d896721f77b 100644
--- a/intern/cycles/kernel/closure/emissive.h
+++ b/intern/cycles/kernel/closure/emissive.h
@@ -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
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index ef414c7b821..10494be87cb 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -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
diff --git a/intern/cycles/kernel/film/accumulate.h b/intern/cycles/kernel/film/accumulate.h
index 33c35a68ad0..97ec915a8ad 100644
--- a/intern/cycles/kernel/film/accumulate.h
+++ b/intern/cycles/kernel/film/accumulate.h
@@ -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);
diff --git a/intern/cycles/kernel/film/passes.h b/intern/cycles/kernel/film/passes.h
index 1f5cf2048f1..bea23411000 100644
--- a/intern/cycles/kernel/film/passes.h
+++ b/intern/cycles/kernel/film/passes.h
@@ -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,
diff --git a/intern/cycles/kernel/film/write_passes.h b/intern/cycles/kernel/film/write_passes.h
index 9148d73518f..c78116cedc6 100644
--- a/intern/cycles/kernel/film/write_passes.h
+++ b/intern/cycles/kernel/film/write_passes.h
@@ -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)
{
diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h
index aa72b93c9d2..98968400d0a 100644
--- a/intern/cycles/kernel/integrator/mnee.h
+++ b/intern/cycles/kernel/integrator/mnee.h
@@ -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);
}
diff --git a/intern/cycles/kernel/integrator/path_state.h b/intern/cycles/kernel/integrator/path_state.h
index b09bc117d78..5ec94b934ca 100644
--- a/intern/cycles/kernel/integrator/path_state.h
+++ b/intern/cycles/kernel/integrator/path_state.h
@@ -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
}
diff --git a/intern/cycles/kernel/integrator/shade_background.h b/intern/cycles/kernel/integrator/shade_background.h
index a7edfffd175..57d060d58df 100644
--- a/intern/cycles/kernel/integrator/shade_background.h
+++ b/intern/cycles/kernel/integrator/shade_background.h
@@ -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);
}
diff --git a/intern/cycles/kernel/integrator/shade_light.h b/intern/cycles/kernel/integrator/shade_light.h
index 910e3383f51..ac9d1415abb 100644
--- a/intern/cycles/kernel/integrator/shade_light.h
+++ b/intern/cycles/kernel/integrator/shade_light.h
@@ -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);
}
diff --git a/intern/cycles/kernel/integrator/shade_shadow.h b/intern/cycles/kernel/integrator/shade_shadow.h
index 4b002a47bee..a52706a77f1 100644
--- a/intern/cycles/kernel/integrator/shade_shadow.h
+++ b/intern/cycles/kernel/integrator/shade_shadow.h
@@ -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;
}
diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h
index 70b20a93b6a..986f7f622fb 100644
--- a/intern/cycles/kernel/integrator/shade_surface.h
+++ b/intern/cycles/kernel/integrator/shade_surface.h
@@ -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);
diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h
index 4aab097a7d8..0d35011c359 100644
--- a/intern/cycles/kernel/integrator/shade_volume.h
+++ b/intern/cycles/kernel/integrator/shade_volume.h
@@ -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 */
diff --git a/intern/cycles/kernel/integrator/shader_eval.h b/intern/cycles/kernel/integrator/shader_eval.h
index ed4d973e864..d9c14b25a4b 100644
--- a/intern/cycles/kernel/integrator/shader_eval.h
+++ b/intern/cycles/kernel/integrator/shader_eval.h
@@ -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);
diff --git a/intern/cycles/kernel/integrator/shadow_catcher.h b/intern/cycles/kernel/integrator/shadow_catcher.h
index ff63625aceb..7103b6032ac 100644
--- a/intern/cycles/kernel/integrator/shadow_catcher.h
+++ b/intern/cycles/kernel/integrator/shadow_catcher.h
@@ -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));
}
diff --git a/intern/cycles/kernel/integrator/shadow_state_template.h b/intern/cycles/kernel/integrator/shadow_state_template.h
index c340467606d..3b490ecffdd 100644
--- a/intern/cycles/kernel/integrator/shadow_state_template.h
+++ b/intern/cycles/kernel/integrator/shadow_state_template.h
@@ -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. */
diff --git a/intern/cycles/kernel/integrator/state_template.h b/intern/cycles/kernel/integrator/state_template.h
index 5c2af131945..f4e280e4cb2 100644
--- a/intern/cycles/kernel/integrator/state_template.h
+++ b/intern/cycles/kernel/integrator/state_template.h
@@ -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)
diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h
index 2f96f215d8a..ee3a619f968 100644
--- a/intern/cycles/kernel/integrator/subsurface.h
+++ b/intern/cycles/kernel/integrator/subsurface.h
@@ -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) {
diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h
index 60b63c075a0..77763f702d8 100644
--- a/intern/cycles/kernel/integrator/subsurface_disk.h
+++ b/intern/cycles/kernel/integrator/subsurface_disk.h
@@ -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;
diff --git a/intern/cycles/kernel/integrator/subsurface_random_walk.h b/intern/cycles/kernel/integrator/subsurface_random_walk.h
index e43bbb3c50a..9c67d909bd4 100644
--- a/intern/cycles/kernel/integrator/subsurface_random_walk.h
+++ b/intern/cycles/kernel/integrator/subsurface_random_walk.h
@@ -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;
- }
- 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;
+ 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;
+ }
}
-
- *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;
}
diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h
index 2e309cee43f..4195675dd13 100644
--- a/intern/cycles/kernel/light/sample.h
+++ b/intern/cycles/kernel/light/sample.h
@@ -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;
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index 865ff4ddc6d..4b5a2686117 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -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;
}
};
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index 39fcee1ac0d..667207ec6bf 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -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);
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index 972ed7e4a6d..6f54a96e542 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -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);
diff --git a/intern/cycles/kernel/osl/bssrdf.cpp b/intern/cycles/kernel/osl/bssrdf.cpp
index 4b282fddad3..3054946ba5a 100644
--- a/intern/cycles/kernel/osl/bssrdf.cpp
+++ b/intern/cycles/kernel/osl/bssrdf.cpp
@@ -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 */
diff --git a/intern/cycles/kernel/osl/closures.cpp b/intern/cycles/kernel/osl/closures.cpp
index 7c6b48154e4..8766fb73dbb 100644
--- a/intern/cycles/kernel/osl/closures.cpp
+++ b/intern/cycles/kernel/osl/closures.cpp
@@ -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;
}
diff --git a/intern/cycles/kernel/osl/closures.h b/intern/cycles/kernel/osl/closures.h
index e10a3d88a04..97666be7a1e 100644
--- a/intern/cycles/kernel/osl/closures.h
+++ b/intern/cycles/kernel/osl/closures.h
@@ -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; \
} \
} \
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index 1a01b215836..8d1928d0126 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -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));
}
};
diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h
index 99a8fdd3be9..5e8ef69fd15 100644
--- a/intern/cycles/kernel/svm/closure.h
+++ b/intern/cycles/kernel/svm/closure.h
@@ -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;
-
- bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) +
- base_color * metallic;
- bsdf->extra->color = base_color;
+ 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 = 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);
}
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 7762c95275e..252c27a40f0 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -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;
diff --git a/intern/cycles/kernel/util/color.h b/intern/cycles/kernel/util/color.h
index c85ef262d88..4983b9048d4 100644
--- a/intern/cycles/kernel/util/color.h
+++ b/intern/cycles/kernel/util/color.h
@@ -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
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index b33bad79e6c..e70f65e124c 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -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
diff --git a/intern/cycles/util/defines.h b/intern/cycles/util/defines.h
index d0df1a221fc..c7118ca09c9 100644
--- a/intern/cycles/util/defines.h
+++ b/intern/cycles/util/defines.h
@@ -136,4 +136,7 @@ template<typename T> static inline T decltype_helper(T x)
# define util_assert(statement)
#endif
+#define CONCAT_HELPER(a, ...) a##__VA_ARGS__
+#define CONCAT(a, ...) CONCAT_HELPER(a, __VA_ARGS__)
+
#endif /* __UTIL_DEFINES_H__ */
diff --git a/intern/cycles/util/math.h b/intern/cycles/util/math.h
index f6400cb879f..0585dcc8ad5 100644
--- a/intern/cycles/util/math.h
+++ b/intern/cycles/util/math.h
@@ -595,26 +595,26 @@ ccl_device_inline void make_orthonormals(const float3 N,
/* Color division */
-ccl_device_inline float3 safe_invert_color(float3 a)
+ccl_device_inline Spectrum safe_invert_color(Spectrum a)
{
- float x, y, z;
-
- 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;
+ 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;
+ }
- 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;
-
- 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;
+ 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;
+ }
- return make_float3(x, y, z);
+ return a;
}
ccl_device_inline float3 safe_divide_even_color(float3 a, float3 b)
diff --git a/intern/cycles/util/types.h b/intern/cycles/util/types.h
index d0d8c2941d7..1ab6f76f9bc 100644
--- a/intern/cycles/util/types.h
+++ b/intern/cycles/util/types.h
@@ -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"
diff --git a/intern/cycles/util/types_spectrum.h b/intern/cycles/util/types_spectrum.h
new file mode 100644
index 00000000000..c59230b83ae
--- /dev/null
+++ b/intern/cycles/util/types_spectrum.h
@@ -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__ */