Blender V4.3
kernel/closure/volume.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
8
13
15
16/* VOLUME EXTINCTION */
17
19{
20 if (sd->flag & SD_EXTINCTION) {
21 sd->closure_transparent_extinction += weight;
22 }
23 else {
24 sd->flag |= SD_EXTINCTION;
25 sd->closure_transparent_extinction = weight;
26 }
27}
28
29/* VOLUME SCATTERING */
30
33 float3 wo,
34 ccl_private float *pdf)
35{
36 switch (svc->type) {
38 return volume_fournier_forand_eval(sd, svc, wo, pdf);
40 return volume_rayleigh_eval(sd, wo, pdf);
42 return volume_draine_eval(sd, svc, wo, pdf);
44 return volume_henyey_greenstein_eval(sd, svc, wo, pdf);
45 default:
46 kernel_assert(false);
47 *pdf = 0.0f;
48 return zero_spectrum();
49 }
50}
51
54 float2 rand,
57 ccl_private float *pdf)
58{
59 switch (svc->type) {
61 return volume_fournier_forand_sample(sd, svc, rand, eval, wo, pdf);
63 return volume_rayleigh_sample(sd, rand, eval, wo, pdf);
65 return volume_draine_sample(sd, svc, rand, eval, wo, pdf);
67 return volume_henyey_greenstein_sample(sd, svc, rand, eval, wo, pdf);
68 default:
69 kernel_assert(false);
70 *pdf = 0.0f;
71 return 0;
72 }
73}
74
76 ccl_private const ShaderClosure *c2)
77{
78 if (c1->type != c2->type) {
79 return false;
80 }
81 switch (c1->type) {
85 return v1->c1 == v2->c1 && v1->c2 == v2->c2 && v1->c3 == v2->c3;
86 }
88 return true;
92 return v1->g == v2->g && v1->alpha == v2->alpha;
93 }
97 return v1->g == v2->g;
98 }
99 default:
100 return false;
101 }
102 return false;
103}
104
105/* Approximate phase functions as Henyey-Greenstein for volume guiding.
106 * TODO: This is not ideal, we should use RIS guiding for non-HG phase functions. */
108{
109 switch (svc->type) {
111 /* TODO */
112 return 1.0f;
114 /* Approximate as isotropic */
115 return 0.0f;
117 /* Approximate as HG, TODO */
118 return ((ccl_private DraineVolume *)svc)->g;
120 return ((ccl_private HenyeyGreensteinVolume *)svc)->g;
121 default:
122 return 0.0f;
123 }
124}
125
126/* Volume sampling utilities. */
127
128/* todo: this value could be tweaked or turned into a probability to avoid
129 * unnecessary work in volumes and subsurface scattering. */
130#define VOLUME_THROUGHPUT_EPSILON 1e-6f
131
133{
134 return exp(-sigma * t);
135}
136
137ccl_device float volume_channel_get(Spectrum value, int channel)
138{
139 return GET_SPECTRUM_CHANNEL(value, channel);
140}
141
143 Spectrum throughput,
144 ccl_private float *rand,
146{
147 /* Sample color channel proportional to throughput and single scattering
148 * albedo, to significantly reduce noise with many bounce, following:
149 *
150 * "Practical and Controllable Subsurface Scattering for Production Path
151 * Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */
152 Spectrum weights = fabs(throughput * albedo);
153 float sum_weights = reduce_add(weights);
154
155 if (sum_weights > 0.0f) {
156 *pdf = weights / sum_weights;
157 }
158 else {
159 *pdf = make_spectrum(1.0f / SPECTRUM_CHANNELS);
160 }
161
162 float pdf_sum = 0.0f;
164 const float channel_pdf = GET_SPECTRUM_CHANNEL(*pdf, i);
165 if (*rand < pdf_sum + channel_pdf) {
166 /* Rescale to reuse. */
167 *rand = (*rand - pdf_sum) / channel_pdf;
168 return i;
169 }
170 pdf_sum += channel_pdf;
171 }
172 return SPECTRUM_CHANNELS - 1;
173}
174
ATTR_WARN_UNUSED_RESULT const BMVert * v2
#define kernel_assert(cond)
#define ccl_device
#define ccl_private
#define CCL_NAMESPACE_END
CCL_NAMESPACE_BEGIN ccl_device void volume_extinction_setup(ccl_private ShaderData *sd, Spectrum weight)
ccl_device bool volume_phase_equal(ccl_private const ShaderClosure *c1, ccl_private const ShaderClosure *c2)
ccl_device int volume_sample_channel(Spectrum albedo, Spectrum throughput, ccl_private float *rand, ccl_private Spectrum *pdf)
ccl_device int volume_phase_sample(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device Spectrum volume_phase_eval(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float3 wo, ccl_private float *pdf)
ccl_device float volume_phase_get_g(ccl_private const ShaderVolumeClosure *svc)
ccl_device float volume_channel_get(Spectrum value, int channel)
ccl_device Spectrum volume_color_transmittance(Spectrum sigma, float t)
@ CLOSURE_VOLUME_RAYLEIGH_ID
@ CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID
@ CLOSURE_VOLUME_DRAINE_ID
@ CLOSURE_VOLUME_FOURNIER_FORAND_ID
@ SD_EXTINCTION
ShaderData
ShaderClosure
ccl_device_inline float reduce_add(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float3 exp(float3 v)
#define SPECTRUM_CHANNELS
#define zero_spectrum
#define make_spectrum(f)
#define FOREACH_SPECTRUM_CHANNEL(counter)
#define GET_SPECTRUM_CHANNEL(v, i)
SPECTRUM_DATA_TYPE Spectrum
ccl_device Spectrum volume_draine_eval(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float3 wo, ccl_private float *pdf)
ccl_device int volume_draine_sample(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device int volume_fournier_forand_sample(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device Spectrum volume_fournier_forand_eval(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float3 wo, ccl_private float *pdf)
ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device Spectrum volume_henyey_greenstein_eval(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float3 wo, ccl_private float *pdf)
ccl_device int volume_rayleigh_sample(ccl_private const ShaderData *sd, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device Spectrum volume_rayleigh_eval(ccl_private const ShaderData *sd, float3 wo, ccl_private float *pdf)