Blender V4.3
bsdf_ashikhmin_velvet.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
2 * SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Adapted code from Open Shading Language. */
7
8#pragma once
9
11
13
20
21static_assert(sizeof(ShaderClosure) >= sizeof(VelvetBsdf), "VelvetBsdf is too large!");
22
24{
25 float sigma = fmaxf(bsdf->sigma, 0.01f);
26 bsdf->invsigma2 = 1.0f / (sigma * sigma);
27
29
31}
32
34 const float3 wi,
35 const float3 wo,
36 ccl_private float *pdf)
37{
38 ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc;
39 float m_invsigma2 = bsdf->invsigma2;
40 float3 N = bsdf->N;
41
42 float cosNI = dot(N, wi);
43 float cosNO = dot(N, wo);
44 if (!(cosNI > 0 && cosNO > 0)) {
45 *pdf = 0.0f;
46 return zero_spectrum();
47 }
48
49 float3 H = normalize(wi + wo);
50
51 float cosNH = dot(N, H);
52 float cosHI = fabsf(dot(wi, H));
53
54 if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHI > 1e-5f)) {
55 *pdf = 0.0f;
56 return zero_spectrum();
57 }
58 float cosNHdivHI = cosNH / cosHI;
59 cosNHdivHI = fmaxf(cosNHdivHI, 1e-5f);
60
61 float fac1 = 2 * fabsf(cosNHdivHI * cosNI);
62 float fac2 = 2 * fabsf(cosNHdivHI * cosNO);
63
64 float sinNH2 = 1 - cosNH * cosNH;
65 float sinNH4 = sinNH2 * sinNH2;
66 float cotangent2 = (cosNH * cosNH) / sinNH2;
67
68 float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
69 float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
70
71 float out = 0.25f * (D * G) / cosNI;
72
73 *pdf = 0.5f * M_1_PI_F;
74 return make_spectrum(out);
75}
76
78 float3 Ng,
79 float3 wi,
80 const float2 rand,
83 ccl_private float *pdf)
84{
85 ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc;
86 float m_invsigma2 = bsdf->invsigma2;
87 float3 N = bsdf->N;
88
89 // we are viewing the surface from above - send a ray out with uniform
90 // distribution over the hemisphere
91 sample_uniform_hemisphere(N, rand, wo, pdf);
92
93 if (!(dot(Ng, *wo) > 0)) {
94 *pdf = 0.0f;
95 *eval = zero_spectrum();
96 return LABEL_NONE;
97 }
98
99 float3 H = normalize(wi + *wo);
100
101 float cosNI = dot(N, wi);
102 float cosNO = dot(N, *wo);
103 float cosHI = fabsf(dot(wi, H));
104 float cosNH = dot(N, H);
105
106 if (!(cosNI > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHI > 1e-5f)) {
107 *pdf = 0.0f;
108 *eval = zero_spectrum();
109 return LABEL_NONE;
110 }
111
112 float cosNHdivHI = cosNH / cosHI;
113 cosNHdivHI = fmaxf(cosNHdivHI, 1e-5f);
114
115 float fac1 = 2 * fabsf(cosNHdivHI * cosNI);
116 float fac2 = 2 * fabsf(cosNHdivHI * cosNO);
117
118 float sinNH2 = 1 - cosNH * cosNH;
119 float sinNH4 = sinNH2 * sinNH2;
120 float cotangent2 = (cosNH * cosNH) / sinNH2;
121
122 float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
123 float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
124
125 float power = 0.25f * (D * G) / cosNI;
126
127 *eval = make_spectrum(power);
128
130}
131
ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 wi, const float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf)
ccl_device Spectrum bsdf_ashikhmin_velvet_eval(ccl_private const ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
CCL_NAMESPACE_BEGIN struct VelvetBsdf VelvetBsdf
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define ccl_device
#define expf(x)
#define ccl_private
#define CCL_NAMESPACE_END
#define fmaxf(x, y)
#define fminf(x, y)
#define fabsf(x)
@ CLOSURE_BSDF_ASHIKHMIN_VELVET_ID
@ SD_BSDF_HAS_EVAL
@ SD_BSDF
@ LABEL_DIFFUSE
@ LABEL_NONE
@ LABEL_REFLECT
ShaderClosure
ccl_device_inline float2 power(float2 v, float e)
#define N
#define G(x, y, z)
#define H(x, y, z)
ccl_device_inline void sample_uniform_hemisphere(const float3 N, const float2 rand, ccl_private float3 *wo, ccl_private float *pdf)
#define zero_spectrum
#define make_spectrum(f)
SPECTRUM_DATA_TYPE Spectrum