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--intern/cycles/app/CMakeLists.txt1
-rw-r--r--intern/cycles/app/cycles_precompute.cpp400
-rw-r--r--intern/cycles/app/cycles_standalone.cpp6
-rw-r--r--intern/cycles/blender/shader.cpp3
-rw-r--r--intern/cycles/kernel/CMakeLists.txt9
-rw-r--r--intern/cycles/kernel/closure/bsdf.h71
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair_principled.h1
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h1179
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_beckmann.h527
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_glass.h283
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h686
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h262
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_util.h158
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_sheen.h92
-rw-r--r--intern/cycles/kernel/closure/bsdf_util.h61
-rw-r--r--intern/cycles/kernel/film/denoising_passes.h2
-rw-r--r--intern/cycles/kernel/film/passes.h302
-rw-r--r--intern/cycles/kernel/integrator/mnee.h1
-rw-r--r--intern/cycles/kernel/osl/closures_setup.h81
-rw-r--r--intern/cycles/kernel/svm/closure.h427
-rw-r--r--intern/cycles/kernel/svm/closure_principled.h843
-rw-r--r--intern/cycles/kernel/svm/types.h33
-rw-r--r--intern/cycles/kernel/types.h8
-rw-r--r--intern/cycles/kernel/util/lookup_table.h25
-rw-r--r--intern/cycles/scene/shader.cpp33
-rw-r--r--intern/cycles/scene/shader.h1
-rw-r--r--intern/cycles/scene/shader.tables1264
-rw-r--r--intern/cycles/scene/shader_graph.cpp4
-rw-r--r--intern/cycles/scene/shader_nodes.cpp209
-rw-r--r--intern/cycles/scene/shader_nodes.h25
-rw-r--r--intern/cycles/util/math_float2.h6
-rw-r--r--source/blender/blenloader/intern/versioning_280.c2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl4
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc56
36 files changed, 4534 insertions, 2547 deletions
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 1c7a861ea93..b8523d917a7 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -62,6 +62,7 @@ include_directories(SYSTEM ${INC_SYS})
if(WITH_CYCLES_STANDALONE)
set(SRC
cycles_standalone.cpp
+ cycles_precompute.cpp
cycles_xml.cpp
cycles_xml.h
oiio_output_driver.cpp
diff --git a/intern/cycles/app/cycles_precompute.cpp b/intern/cycles/app/cycles_precompute.cpp
new file mode 100644
index 00000000000..6f9d9601b1e
--- /dev/null
+++ b/intern/cycles/app/cycles_precompute.cpp
@@ -0,0 +1,400 @@
+#include "util/math.h"
+#include "util/string.h"
+#include "util/system.h"
+
+#include "util/hash.h"
+#include "util/task.h"
+
+#include "kernel/device/cpu/compat.h"
+#include "kernel/device/cpu/globals.h"
+
+#include "kernel/sample/lcg.h"
+#include "kernel/sample/mapping.h"
+
+#include "kernel/closure/bsdf_microfacet.h"
+#include "kernel/closure/bsdf_microfacet_glass.h"
+#include "kernel/closure/bsdf_principled_sheen.h"
+
+#include <iostream>
+
+CCL_NAMESPACE_BEGIN
+
+/* From PBRT: core/montecarlo.h */
+inline float VanDerCorput(uint32_t n, uint32_t scramble)
+{
+ n = (n << 16) | (n >> 16);
+ n = ((n & 0x00ff00ff) << 8) | ((n & 0xff00ff00) >> 8);
+ n = ((n & 0x0f0f0f0f) << 4) | ((n & 0xf0f0f0f0) >> 4);
+ n = ((n & 0x33333333) << 2) | ((n & 0xcccccccc) >> 2);
+ n = ((n & 0x55555555) << 1) | ((n & 0xaaaaaaaa) >> 1);
+ n ^= scramble;
+ return ((n >> 8) & 0xffffff) / float(1 << 24);
+}
+inline float Sobol2(uint32_t n, uint32_t scramble)
+{
+ for (uint32_t v = 1 << 31; n != 0; n >>= 1, v ^= v >> 1)
+ if (n & 0x1)
+ scramble ^= v;
+ return ((scramble >> 8) & 0xffffff) / float(1 << 24);
+}
+
+static float precompute_sheen_E(float rough, float mu, float u1, float u2)
+{
+ PrincipledSheenBsdf bsdf;
+ bsdf.weight = one_float3();
+ bsdf.type = CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID;
+ bsdf.sample_weight = 1.0f;
+ bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+ bsdf.roughness = sqr(rough);
+
+ float3 eval, omega_in, domega_in_dx, domega_in_dy;
+ float pdf = 0.0f;
+ bsdf_principled_sheen_sample((ShaderClosure *)&bsdf,
+ make_float3(0.0f, 0.0f, 1.0f),
+ make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+ zero_float3(),
+ zero_float3(),
+ u1,
+ u2,
+ &eval,
+ &omega_in,
+ &domega_in_dx,
+ &domega_in_dy,
+ &pdf);
+ if (pdf != 0.0f) {
+ return clamp(average(eval) / pdf, 0.0f, 1e5f);
+ }
+ return 0.0f;
+}
+
+static float precompute_clearcoat_E(float rough, float mu, float u1, float u2)
+{
+ MicrofacetBsdf bsdf;
+ bsdf.weight = one_float3();
+ bsdf.type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID;
+ bsdf.sample_weight = 1.0f;
+ bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+ bsdf.alpha_x = bsdf.alpha_y = sqr(rough);
+ bsdf.ior = 1.5f;
+ bsdf.extra = nullptr;
+ bsdf.T = make_float3(1.0f, 0.0f, 0.0f);
+
+ /* Account for the albedo scaling that the closure performs.
+ * Dependency warning - this relies on the ggx_E and ggx_E_avg lookup tables! */
+ float E = microfacet_ggx_E(mu, rough), E_avg = microfacet_ggx_E_avg(rough);
+ float Fss = dielectric_fresnel_Fss(1.5f);
+ float Fms = Fss * E_avg / (1.0f - Fss * (1.0f - E_avg));
+ float albedo_scale = 1.0f + Fms * ((1.0f - E) / E);
+
+ float3 eval, omega_in, domega_in_dx, domega_in_dy;
+ float pdf = 0.0f;
+ bsdf_microfacet_ggx_sample((ShaderClosure *)&bsdf,
+ make_float3(0.0f, 0.0f, 1.0f),
+ make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+ zero_float3(),
+ zero_float3(),
+ u1,
+ u2,
+ &eval,
+ &omega_in,
+ &domega_in_dx,
+ &domega_in_dy,
+ &pdf);
+ if (pdf != 0.0f) {
+ /* Encode relative to macrosurface Fresnel, saves resolution.
+ * TODO: Worth the extra evaluation? */
+ return albedo_scale * (average(eval) / pdf) / fresnel_dielectric_cos(mu, 1.5f);
+ }
+ return 0.0f;
+}
+
+static float precompute_ggx_E(float rough, float mu, float u1, float u2)
+{
+ MicrofacetBsdf bsdf;
+ bsdf.weight = one_float3();
+ bsdf.type = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ bsdf.sample_weight = 1.0f;
+ bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+ bsdf.alpha_x = bsdf.alpha_y = sqr(rough);
+ bsdf.ior = 1.0f;
+ bsdf.extra = nullptr;
+ bsdf.T = make_float3(1.0f, 0.0f, 0.0f);
+
+ float3 eval, omega_in, domega_in_dx, domega_in_dy;
+ float pdf = 0.0f;
+ bsdf_microfacet_ggx_sample((ShaderClosure *)&bsdf,
+ make_float3(0.0f, 0.0f, 1.0f),
+ make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+ zero_float3(),
+ zero_float3(),
+ u1,
+ u2,
+ &eval,
+ &omega_in,
+ &domega_in_dx,
+ &domega_in_dy,
+ &pdf);
+ if (pdf != 0.0f) {
+ return average(eval) / pdf;
+ }
+ return 0.0f;
+}
+
+static float precompute_ggx_refract_E(float rough, float mu, float eta, float u1, float u2)
+{
+ MicrofacetBsdf bsdf;
+ bsdf.weight = one_float3();
+ bsdf.type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ bsdf.sample_weight = 1.0f;
+ bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+ bsdf.alpha_x = bsdf.alpha_y = sqr(rough);
+ bsdf.ior = eta;
+ bsdf.extra = nullptr;
+ bsdf.T = make_float3(1.0f, 0.0f, 0.0f);
+
+ float3 eval, omega_in, domega_in_dx, domega_in_dy;
+ float pdf = 0.0f;
+ bsdf_microfacet_ggx_sample((ShaderClosure *)&bsdf,
+ make_float3(0.0f, 0.0f, 1.0f),
+ make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+ zero_float3(),
+ zero_float3(),
+ u1,
+ u2,
+ &eval,
+ &omega_in,
+ &domega_in_dx,
+ &domega_in_dy,
+ &pdf);
+ if (pdf != 0.0f) {
+ return average(eval) / pdf;
+ }
+ return 0.0f;
+}
+
+static float precompute_ggx_glass_E(float rough, float mu, float eta, float u1, float u2)
+{
+ MicrofacetBsdf bsdf;
+ bsdf.weight = one_float3();
+ bsdf.type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ bsdf.sample_weight = 1.0f;
+ bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+ bsdf.alpha_x = bsdf.alpha_y = sqr(rough);
+ bsdf.ior = eta;
+ bsdf.extra = nullptr;
+ bsdf.T = make_float3(1.0f, 0.0f, 0.0f);
+
+ float3 eval, omega_in, domega_in_dx, domega_in_dy;
+ float pdf = 0.0f;
+ bsdf_microfacet_ggx_glass_sample((ShaderClosure *)&bsdf,
+ make_float3(0.0f, 0.0f, 1.0f),
+ make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+ zero_float3(),
+ zero_float3(),
+ u1,
+ u2,
+ &eval,
+ &omega_in,
+ &domega_in_dx,
+ &domega_in_dy,
+ &pdf);
+ if (pdf != 0.0f) {
+ return average(eval) / pdf;
+ }
+ return 0.0f;
+}
+
+static float precompute_ggx_dielectric_E(float rough, float mu, float eta, float u1, float u2)
+{
+ {
+ /* Reparametrize based on macrosurface fresnel to get more resolution into areas where
+ * the Fresnel curve is rapidly changing. Particularly important for eta<1 due to the TIR edge.
+ * However, in the eta<1 case, the entire TIR area would be compressed down to a point, which
+ * is an issue since there are changes in that range at higher roughnesses.
+ * Therefore, the remapping is blended with the identity function for a compromise.
+ */
+ float F0 = fresnel_dielectric_cos(1.0f, eta);
+ auto get_remap = [eta, F0](float x) {
+ return mix(x, inverse_lerp(1.0f, F0, fresnel_dielectric_cos(x, eta)), 0.5f);
+ };
+
+ float remap_target = mu;
+ float start = 0.0f, end = 1.0f;
+ while (end - start > 1e-7f) {
+ mu = (end + start) * 0.5f;
+ if (get_remap(mu) > remap_target) {
+ end = mu;
+ }
+ else {
+ start = mu;
+ }
+ }
+ }
+
+ MicrofacetExtrav2 extra;
+ MicrofacetBsdf bsdf;
+ bsdf.weight = one_float3();
+ bsdf.type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID;
+ bsdf.sample_weight = 1.0f;
+ bsdf.N = make_float3(0.0f, 0.0f, 1.0f);
+ bsdf.alpha_x = bsdf.alpha_y = sqr(rough);
+ bsdf.ior = eta;
+ bsdf.extra = (MicrofacetExtra *)&extra;
+ bsdf.T = make_float3(1.0f, 0.0f, 0.0f);
+ extra.metallic = extra.metal_base = extra.metal_edge_factor = zero_float3();
+
+ /* Dependency warning - this relies on the ggx_E and ggx_E_avg lookup tables! */
+ float E = microfacet_ggx_E(mu, rough), E_avg = microfacet_ggx_E_avg(rough);
+ float Fss = dielectric_fresnel_Fss(eta);
+ float Fms = Fss * E_avg / (1.0f - Fss * (1.0f - E_avg));
+ extra.dielectric = 1.0f + Fms * ((1.0f - E) / E);
+
+ float3 eval, omega_in, domega_in_dx, domega_in_dy;
+ float pdf = 0.0f;
+ bsdf_microfacet_ggx_sample((ShaderClosure *)&bsdf,
+ make_float3(0.0f, 0.0f, 1.0f),
+ make_float3(sqrtf(1.0f - sqr(mu)), 0.0f, mu),
+ zero_float3(),
+ zero_float3(),
+ u1,
+ u2,
+ &eval,
+ &omega_in,
+ &domega_in_dx,
+ &domega_in_dy,
+ &pdf);
+ if (pdf != 0.0f) {
+ return average(eval) / pdf;
+ }
+ return 0.0f;
+}
+
+struct PrecomputeTerm {
+ int dim, samples, res;
+ std::function<float(float, float, float, float, float)> evaluation;
+};
+
+bool cycles_precompute(std::string name);
+bool cycles_precompute(std::string name)
+{
+ std::map<string, PrecomputeTerm> precompute_terms;
+ precompute_terms["sheen_E"] = {
+ 2, 1 << 23, 32, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_sheen_E(rough, mu, u1, u2);
+ }};
+ precompute_terms["clearcoat_E"] = {
+ 2, 1 << 23, 16, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_clearcoat_E(rough, mu, u1, u2);
+ }};
+ precompute_terms["ggx_E"] = {
+ 2, 1 << 23, 32, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_ggx_E(rough, mu, u1, u2);
+ }};
+ precompute_terms["ggx_E_avg"] = {
+ 1, 1 << 23, 32, [](float rough, float mu, float ior, float u1, float u2) {
+ return 2.0f * mu * precompute_ggx_E(rough, mu, u1, u2);
+ }};
+ precompute_terms["ggx_glass_E"] = {
+ 3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_ggx_glass_E(rough, mu, ior, u1, u2);
+ }};
+ precompute_terms["ggx_glass_inv_E"] = {
+ 3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_ggx_glass_E(rough, mu, 1.0f / ior, u1, u2);
+ }};
+ precompute_terms["ggx_refract_E"] = {
+ 3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_ggx_refract_E(rough, mu, ior, u1, u2);
+ }};
+ precompute_terms["ggx_refract_inv_E"] = {
+ 3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_ggx_refract_E(rough, mu, 1.0f / ior, u1, u2);
+ }};
+ precompute_terms["ggx_dielectric_E"] = {
+ 3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_ggx_dielectric_E(rough, mu, ior, u1, u2);
+ }};
+ // TODO: Consider more X resolution for this table.
+ precompute_terms["ggx_dielectric_inv_E"] = {
+ 3, 1 << 20, 16, [](float rough, float mu, float ior, float u1, float u2) {
+ return precompute_ggx_dielectric_E(rough, mu, 1.0f / ior, u1, u2);
+ }};
+
+ if (precompute_terms.count(name) == 0) {
+ return false;
+ }
+
+ const PrecomputeTerm &term = precompute_terms[name];
+
+ const int samples = term.samples;
+ const int res = term.res;
+ const int nz = (term.dim > 2) ? res : 1, ny = res, nx = (term.dim > 1) ? res : 1;
+
+ if (nz > 1) {
+ std::cout << "static const float table_" << name << "[" << nz << "][" << ny << "][" << nx
+ << "] = {" << std::endl;
+ }
+ for (int z = 0; z < nz; z++) {
+ float *data = new float[nx * ny];
+ parallel_for(0, ny, [&](int64_t y) {
+ for (int x = 0; x < nx; x++) {
+ uint rng = hash_uint2(x, y);
+ uint scramble1 = lcg_step_uint(&rng), scramble2 = lcg_step_uint(&rng);
+ double sum = 0.0;
+ for (int i = 0; i < samples; i++) {
+ float rough = 1.0f - (float(y) + lcg_step_float(&rng)) / float(ny);
+ float mu = (float(x) + lcg_step_float(&rng)) / float(nx);
+ float ior = (float(z) + lcg_step_float(&rng)) / float(nz);
+ /* Encode IOR remapped as sqrt(0.5*(IOR-1)) for more resolution at the start, where most
+ * of the changes happen (also places the most common range around 1.5 in the center) */
+ ior = 1.0f + 2.0f * sqr(ior);
+ float u1 = VanDerCorput(i, scramble1);
+ float u2 = Sobol2(i, scramble2);
+
+ float value = term.evaluation(rough, mu, ior, u1, u2);
+ if (isnan(value)) {
+ value = 0.0f;
+ }
+ sum += (double)value;
+ }
+ data[y * nx + x] = float(sum / double(samples));
+ }
+ });
+
+ string filename = name;
+ if (nz > 1) {
+ filename += string_printf("_%02d", z);
+ std::cout << " {" << std::endl;
+ }
+ else {
+ std::cout << "static const float table_" << name << "[" << ny << "][" << nx << "] = {"
+ << std::endl;
+ }
+
+ for (int y = 0; y < ny; y++) {
+ std::cout << " {";
+ for (int x = 0; x < nx; x++) {
+ std::cout << data[y * nx + x] << ((x + 1 == nx) ? "f" : "f, ");
+ }
+ std::cout << ((y + 1 == ny) ? "}" : "},") << std::endl;
+ }
+ if (nz > 1) {
+ std::cout << ((z + 1 == nz) ? " }" : " },") << std::endl;
+ }
+ else {
+ std::cout << "};" << std::endl;
+ }
+
+ FILE *f = fopen((filename + ".pfm").c_str(), "w");
+ fprintf(f, "Pf\n%d %d\n-1.0\n", nx, ny);
+ fwrite(data, sizeof(float), nx * ny, f);
+ fclose(f);
+ }
+ if (nz > 1) {
+ std::cout << "};" << std::endl;
+ }
+
+ return true;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index 8b40adc8d92..6184b4ad445 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -37,6 +37,8 @@
CCL_NAMESPACE_BEGIN
+bool cycles_precompute(std::string name);
+
struct Options {
Session *session;
Scene *scene;
@@ -536,6 +538,10 @@ int main(int argc, const char **argv)
path_init();
options_parse(argc, argv);
+ if (cycles_precompute(options.filepath)) {
+ return 0;
+ }
+
#ifdef WITH_CYCLES_STANDALONE_GUI
if (options.session_params.background) {
#endif
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index dbc49df7f22..d749686d449 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -662,6 +662,9 @@ static ShaderNode *add_node(Scene *scene,
principled->set_distribution(CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
break;
case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX:
+ principled->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+ break;
+ case BL::ShaderNodeBsdfPrincipled::distribution_V2:
principled->set_distribution(CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
break;
}
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 81c5f593974..e7a94f00ffb 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -103,8 +103,9 @@ set(SRC_KERNEL_CLOSURE_HEADERS
closure/bsdf_diffuse.h
closure/bsdf_diffuse_ramp.h
closure/bsdf_microfacet.h
- closure/bsdf_microfacet_multi.h
- closure/bsdf_microfacet_multi_impl.h
+ closure/bsdf_microfacet_beckmann.h
+ closure/bsdf_microfacet_glass.h
+ closure/bsdf_microfacet_util.h
closure/bsdf_oren_nayar.h
closure/bsdf_phong_ramp.h
closure/bsdf_reflection.h
@@ -133,6 +134,7 @@ set(SRC_KERNEL_SVM_HEADERS
svm/camera.h
svm/clamp.h
svm/closure.h
+ svm/closure_principled.h
svm/convert.h
svm/checker.h
svm/color_util.h
@@ -547,7 +549,8 @@ endif()
# HIP module
-if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
+# TODO: Re-enable HIP and figure out compiler crash
+if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP AND FALSE)
# build for each arch
set(hip_sources device/hip/kernel.cpp
${SRC_KERNEL_HEADERS}
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 71af68aa80e..fbda52d74c4 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -10,7 +10,8 @@
#include "kernel/closure/bsdf_phong_ramp.h"
#include "kernel/closure/bsdf_diffuse_ramp.h"
#include "kernel/closure/bsdf_microfacet.h"
-#include "kernel/closure/bsdf_microfacet_multi.h"
+#include "kernel/closure/bsdf_microfacet_beckmann.h"
+#include "kernel/closure/bsdf_microfacet_glass.h"
#include "kernel/closure/bsdf_reflection.h"
#include "kernel/closure/bsdf_refraction.h"
#include "kernel/closure/bsdf_transparent.h"
@@ -168,40 +169,17 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
label = bsdf_microfacet_ggx_sample(
- kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- label = bsdf_microfacet_multi_ggx_sample(kg,
- sc,
- Ng,
- sd->I,
- randu,
- randv,
- eval,
- omega_in,
- pdf,
- &sd->lcg_state,
- sampled_roughness,
- eta);
+ sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- label = bsdf_microfacet_multi_ggx_glass_sample(kg,
- sc,
- Ng,
- sd->I,
- randu,
- randv,
- eval,
- omega_in,
- pdf,
- &sd->lcg_state,
- sampled_roughness,
- eta);
+ label = bsdf_microfacet_ggx_glass_sample(
+ sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
@@ -249,6 +227,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
*eta = 1.0f;
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
label = bsdf_principled_sheen_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
*sampled_roughness = one_float2();
*eta = 1.0f;
@@ -343,7 +322,9 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
@@ -351,13 +332,6 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
*eta = refractive ? 1.0f / bsdf->ior : bsdf->ior;
break;
}
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: {
- ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
- *roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
- *eta = bsdf->ior;
- break;
- }
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
@@ -411,6 +385,7 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
*eta = 1.0f;
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
*roughness = one_float2();
*eta = 1.0f;
break;
@@ -462,9 +437,9 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_REFLECT | LABEL_SINGULAR :
@@ -511,6 +486,7 @@ ccl_device_inline int bsdf_label(const KernelGlobals kg,
label = LABEL_REFLECT | LABEL_DIFFUSE;
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
label = LABEL_REFLECT | LABEL_DIFFUSE;
break;
#endif
@@ -576,17 +552,15 @@ ccl_device_inline
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval(sc, sd->I, omega_in, pdf);
break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_glass_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ eval = bsdf_microfacet_ggx_glass_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
@@ -617,6 +591,7 @@ ccl_device_inline
eval = bsdf_principled_diffuse_eval(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID:
eval = bsdf_principled_sheen_eval(sc, sd->I, omega_in, pdf);
break;
#endif
@@ -652,16 +627,14 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float
/* TODO: do we want to blur volume closures? */
#if defined(__SVM__) || defined(__OSL__)
switch (sc->type) {
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- bsdf_microfacet_multi_ggx_blur(sc, roughness);
- break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
bsdf_microfacet_ggx_blur(sc, roughness);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
index 857b3fbf3a6..f5651d82aae 100644
--- a/intern/cycles/kernel/closure/bsdf_hair_principled.h
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -7,6 +7,7 @@
# include <fenv.h>
#endif
+#include "kernel/sample/lcg.h"
#include "kernel/util/color.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 4eb7cd5df22..e0b513b69f1 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -8,20 +8,27 @@
#pragma once
-#include "kernel/closure/bsdf_util.h"
-
-#include "kernel/sample/pattern.h"
-
-#include "kernel/util/lookup_table.h"
+#include "kernel/closure/bsdf_microfacet_util.h"
CCL_NAMESPACE_BEGIN
typedef struct MicrofacetExtra {
Spectrum color, cspec0;
Spectrum fresnel_color;
- float clearcoat;
} MicrofacetExtra;
+typedef struct MicrofacetExtrav2 {
+ /* Metallic fresnel control */
+ Spectrum metal_base, metal_edge_factor;
+ Spectrum metallic;
+ float dielectric;
+} MicrofacetExtrav2;
+
+// TODO probably remove this for the final code
+static_assert(sizeof(MicrofacetExtra) <= sizeof(ShaderClosure), "Try to shrink MicrofacetExtra!");
+static_assert(sizeof(MicrofacetExtrav2) <= sizeof(ShaderClosure),
+ "Try to shrink MicrofacetExtra!");
+
typedef struct MicrofacetBsdf {
SHADER_CLOSURE_BASE;
@@ -32,200 +39,6 @@ typedef struct MicrofacetBsdf {
static_assert(sizeof(ShaderClosure) >= sizeof(MicrofacetBsdf), "MicrofacetBsdf is too large!");
-/* Beckmann and GGX microfacet importance sampling. */
-
-ccl_device_inline void microfacet_beckmann_sample_slopes(KernelGlobals kg,
- const float cos_theta_i,
- const float sin_theta_i,
- float randu,
- float randv,
- ccl_private float *slope_x,
- ccl_private float *slope_y,
- ccl_private float *G1i)
-{
- /* special case (normal incidence) */
- if (cos_theta_i >= 0.99999f) {
- const float r = sqrtf(-logf(randu));
- const float phi = M_2PI_F * randv;
- *slope_x = r * cosf(phi);
- *slope_y = r * sinf(phi);
- *G1i = 1.0f;
- return;
- }
-
- /* precomputations */
- const float tan_theta_i = sin_theta_i / cos_theta_i;
- const float inv_a = tan_theta_i;
- const float cot_theta_i = 1.0f / tan_theta_i;
- const float erf_a = fast_erff(cot_theta_i);
- const float exp_a2 = expf(-cot_theta_i * cot_theta_i);
- const float SQRT_PI_INV = 0.56418958354f;
- const float Lambda = 0.5f * (erf_a - 1.0f) + (0.5f * SQRT_PI_INV) * (exp_a2 * inv_a);
- const float G1 = 1.0f / (1.0f + Lambda); /* masking */
-
- *G1i = G1;
-
-#if defined(__KERNEL_GPU__)
- /* Based on paper from Wenzel Jakob
- * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
- *
- * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
- *
- * Reformulation from OpenShadingLanguage which avoids using inverse
- * trigonometric functions.
- */
-
- /* Sample slope X.
- *
- * Compute a coarse approximation using the approximation:
- * exp(-ierf(x)^2) ~= 1 - x * x
- * solve y = 1 + b + K * (1 - b * b)
- */
- float K = tan_theta_i * SQRT_PI_INV;
- float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
- float y_exact = randu * (1.0f + erf_a + K * exp_a2);
- float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
-
- /* Perform newton step to refine toward the true root. */
- float inv_erf = fast_ierff(b);
- float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
- /* Check if we are close enough already,
- * this also avoids NaNs as we get close to the root.
- */
- if (fabsf(value) > 1e-6f) {
- b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
- inv_erf = fast_ierff(b);
- value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
- b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
- /* Compute the slope from the refined value. */
- *slope_x = fast_ierff(b);
- }
- else {
- /* We are close enough already. */
- *slope_x = inv_erf;
- }
- *slope_y = fast_ierff(2.0f * randv - 1.0f);
-#else
- /* Use precomputed table on CPU, it gives better performance. */
- int beckmann_table_offset = kernel_data.tables.beckmann_offset;
-
- *slope_x = lookup_table_read_2D(
- kg, randu, cos_theta_i, beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
- *slope_y = fast_ierff(2.0f * randv - 1.0f);
-#endif
-}
-
-/* GGX microfacet importance sampling from:
- *
- * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals.
- * E. Heitz and E. d'Eon, EGSR 2014
- */
-
-ccl_device_inline void microfacet_ggx_sample_slopes(const float cos_theta_i,
- const float sin_theta_i,
- float randu,
- float randv,
- ccl_private float *slope_x,
- ccl_private float *slope_y,
- ccl_private float *G1i)
-{
- /* special case (normal incidence) */
- if (cos_theta_i >= 0.99999f) {
- const float r = sqrtf(randu / (1.0f - randu));
- const float phi = M_2PI_F * randv;
- *slope_x = r * cosf(phi);
- *slope_y = r * sinf(phi);
- *G1i = 1.0f;
-
- return;
- }
-
- /* precomputations */
- const float tan_theta_i = sin_theta_i / cos_theta_i;
- const float G1_inv = 0.5f * (1.0f + safe_sqrtf(1.0f + tan_theta_i * tan_theta_i));
-
- *G1i = 1.0f / G1_inv;
-
- /* sample slope_x */
- const float A = 2.0f * randu * G1_inv - 1.0f;
- const float AA = A * A;
- const float tmp = 1.0f / (AA - 1.0f);
- const float B = tan_theta_i;
- const float BB = B * B;
- const float D = safe_sqrtf(BB * (tmp * tmp) - (AA - BB) * tmp);
- const float slope_x_1 = B * tmp - D;
- const float slope_x_2 = B * tmp + D;
- *slope_x = (A < 0.0f || slope_x_2 * tan_theta_i > 1.0f) ? slope_x_1 : slope_x_2;
-
- /* sample slope_y */
- float S;
-
- if (randv > 0.5f) {
- S = 1.0f;
- randv = 2.0f * (randv - 0.5f);
- }
- else {
- S = -1.0f;
- randv = 2.0f * (0.5f - randv);
- }
-
- const float z = (randv * (randv * (randv * 0.27385f - 0.73369f) + 0.46341f)) /
- (randv * (randv * (randv * 0.093073f + 0.309420f) - 1.000000f) + 0.597999f);
- *slope_y = S * z * safe_sqrtf(1.0f + (*slope_x) * (*slope_x));
-}
-
-ccl_device_forceinline float3 microfacet_sample_stretched(KernelGlobals kg,
- const float3 omega_i,
- const float alpha_x,
- const float alpha_y,
- const float randu,
- const float randv,
- bool beckmann,
- ccl_private float *G1i)
-{
- /* 1. stretch omega_i */
- float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z);
- omega_i_ = normalize(omega_i_);
-
- /* get polar coordinates of omega_i_ */
- float costheta_ = 1.0f;
- float sintheta_ = 0.0f;
- float cosphi_ = 1.0f;
- float sinphi_ = 0.0f;
-
- if (omega_i_.z < 0.99999f) {
- costheta_ = omega_i_.z;
- sintheta_ = safe_sqrtf(1.0f - costheta_ * costheta_);
-
- float invlen = 1.0f / sintheta_;
- cosphi_ = omega_i_.x * invlen;
- sinphi_ = omega_i_.y * invlen;
- }
-
- /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */
- float slope_x, slope_y;
-
- if (beckmann) {
- microfacet_beckmann_sample_slopes(
- kg, costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
- }
- else {
- microfacet_ggx_sample_slopes(costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
- }
-
- /* 3. rotate */
- float tmp = cosphi_ * slope_x - sinphi_ * slope_y;
- slope_y = sinphi_ * slope_x + cosphi_ * slope_y;
- slope_x = tmp;
-
- /* 4. unstretch */
- slope_x = alpha_x * slope_x;
- slope_y = alpha_y * slope_y;
-
- /* 5. compute normal */
- return normalize(make_float3(-slope_x, -slope_y, 1.0f));
-}
-
/* Calculate the reflection color
*
* If fresnel is used, the color is an interpolation of the F0 color and white
@@ -237,55 +50,77 @@ ccl_device_forceinline Spectrum reflection_color(ccl_private const MicrofacetBsd
float3 L,
float3 H)
{
- 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) {
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
-
- F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID) {
+ return interpolate_fresnel_color(L, H, bsdf->ior, bsdf->extra->cspec0);
+ }
+ else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ return interpolate_fresnel_color(L, H, bsdf->ior, make_spectrum(0.04f));
+ }
+ else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID) {
+ float f = fresnel_dielectric_cos(dot(H, L), bsdf->ior);
+ return make_spectrum(f);
+ }
+ else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID) {
+ MicrofacetExtrav2 *extra = (MicrofacetExtrav2 *)bsdf->extra;
+ float cosHL = dot(H, L);
+ /* Metallic Fresnel: Kinda Schlick-Fresnel-like with configurable F0 and F90
+ * as well as falloff control. F90=white and falloff=0.2 gives classic Schlick Fresnel.
+ * Metallic factor and albedo scaling is baked into the F0 and F90 parameters. */
+ Spectrum metallic = extra->metallic *
+ fresnel_metallic(extra->metal_base, extra->metal_edge_factor, cosHL);
+ /* Dielectric Fresnel, just basic IOR control. */
+ float dielectric = extra->dielectric * fresnel_dielectric_cos(cosHL, bsdf->ior);
+
+ return metallic + make_spectrum(dielectric);
+ }
+ else {
+ return one_spectrum();
}
-
- return F;
-}
-
-ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
-{
- if (alpha >= 1.0f)
- return M_1_PI_F;
- float alpha2 = alpha * alpha;
- float t = 1.0f + (alpha2 - 1.0f) * NdotH * NdotH;
- return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
}
ccl_device_forceinline void bsdf_microfacet_fresnel_color(ccl_private const ShaderData *sd,
ccl_private MicrofacetBsdf *bsdf)
{
- kernel_assert(CLOSURE_IS_BSDF_MICROFACET_FRESNEL(bsdf->type));
+ Spectrum average_fresnel = reflection_color(bsdf, sd->I, bsdf->N);
+ bsdf->sample_weight *= average(average_fresnel);
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- bsdf->extra->fresnel_color = interpolate_fresnel_color(
- sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0);
-
- if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- bsdf->extra->fresnel_color *= 0.25f * bsdf->extra->clearcoat;
+ if (bsdf->extra) {
+ bsdf->extra->fresnel_color = average_fresnel;
}
+}
- bsdf->sample_weight *= average(bsdf->extra->fresnel_color);
+ccl_device_inline Spectrum microfacet_ggx_albedo_scaling(KernelGlobals kg,
+ ccl_private const MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd,
+ const Spectrum Fss)
+{
+ float mu = dot(sd->I, bsdf->N);
+ float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
+ float E = microfacet_ggx_E(kg, mu, rough);
+
+ float E_avg = microfacet_ggx_E_avg(kg, rough);
+ /* Fms here is based on the appendix of
+ * https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf,
+ * with one Fss cancelled out since this is just a multiplier on top of
+ * the single-scattering BSDF, which already contains one bounce of Fresnel. */
+ Spectrum Fms = Fss * E_avg / (one_spectrum() - Fss * (1.0f - E_avg));
+
+ return one_spectrum() + Fms * ((1.0f - E) / E);
+ /* TODO: Ensure that increase in weight does not mess up glossy color, albedo etc. passes */
}
-/* GGX microfacet with Smith shadow-masking from:
- *
- * Microfacet Models for Refraction through Rough Surfaces
- * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007
- *
- * Anisotropic from:
- *
- * Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs
- * E. Heitz, Research Report 2014
- *
- * Anisotropy is only supported for reflection currently, but adding it for
- * transmission is just a matter of copying code from reflection if needed. */
+ccl_device_inline float microfacet_ggx_albedo_scaling_float(KernelGlobals kg,
+ ccl_private const MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd,
+ const float Fss)
+{
+ // TOOD: Deduplicate somehow?
+ float mu = dot(sd->I, bsdf->N);
+ float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
+ float E = microfacet_ggx_E(kg, mu, rough), E_avg = microfacet_ggx_E_avg(kg, rough);
+ float Fms = Fss * E_avg / (1.0f - Fss * (1.0f - E_avg));
+ return 1.0f + Fms * ((1.0f - E) / E);
+}
ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
{
@@ -299,11 +134,12 @@ ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-/* Required to maintain OSL interface. */
-ccl_device int bsdf_microfacet_ggx_isotropic_setup(ccl_private MicrofacetBsdf *bsdf)
+ccl_device int bsdf_microfacet_multi_ggx_setup(KernelGlobals kg,
+ ccl_private MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd,
+ const Spectrum color)
{
- bsdf->alpha_y = bsdf->alpha_x;
-
+ bsdf->weight *= microfacet_ggx_albedo_scaling(kg, bsdf, sd, saturate(color));
return bsdf_microfacet_ggx_setup(bsdf);
}
@@ -322,11 +158,55 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsd
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
+ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(KernelGlobals kg,
+ ccl_private MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd)
+{
+ Spectrum Fss = schlick_fresnel_Fss(bsdf->extra->cspec0);
+ bsdf->weight *= microfacet_ggx_albedo_scaling(kg, bsdf, sd, Fss);
+ return bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
+}
+
+ccl_device int bsdf_microfacet_ggx_fresnel_v2_setup(KernelGlobals kg,
+ ccl_private MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd,
+ float metallic,
+ float dielectric)
+{
+ bsdf->alpha_x = saturatef(bsdf->alpha_x);
+ bsdf->alpha_y = saturatef(bsdf->alpha_y);
+
+ MicrofacetExtrav2 *extra = (MicrofacetExtrav2 *)bsdf->extra;
+
+ if (metallic > 0.0f) {
+ Spectrum metal_Fss = fresnel_metallic_Fss(extra->metal_base, extra->metal_edge_factor);
+ extra->metallic = metallic * microfacet_ggx_albedo_scaling(kg, bsdf, sd, metal_Fss);
+ }
+ else {
+ extra->metallic = zero_spectrum();
+ extra->metal_base = zero_spectrum();
+ extra->metal_edge_factor = zero_spectrum();
+ }
+
+ if (dielectric > 0.0f) {
+ float dielectric_Fss = dielectric_fresnel_Fss(bsdf->ior);
+ extra->dielectric = dielectric *
+ microfacet_ggx_albedo_scaling_float(kg, bsdf, sd, dielectric_Fss);
+ }
+ else {
+ extra->dielectric = 0.0f;
+ }
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID;
+
+ // bsdf_microfacet_fresnel_color(sd, bsdf); // TODO
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *bsdf,
ccl_private const ShaderData *sd)
{
- bsdf->extra->cspec0 = saturate(bsdf->extra->cspec0);
-
bsdf->alpha_x = saturatef(bsdf->alpha_x);
bsdf->alpha_y = bsdf->alpha_x;
@@ -337,6 +217,23 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *b
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
+ccl_device int bsdf_microfacet_ggx_clearcoat_v2_setup(KernelGlobals kg,
+ ccl_private MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd)
+{
+ bsdf->alpha_x = saturatef(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID;
+
+ float Fss = dielectric_fresnel_Fss(bsdf->ior);
+ bsdf->weight *= microfacet_ggx_albedo_scaling_float(kg, bsdf, sd, Fss);
+
+ bsdf_microfacet_fresnel_color(sd, bsdf);
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
{
bsdf->extra = NULL;
@@ -367,99 +264,77 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const Microface
const float cosNO,
const float cosNI)
{
+ float alpha2 = alpha_x * alpha_y;
if (!(cosNI > 0 && cosNO > 0)) {
*pdf = 0.0f;
return zero_spectrum();
}
- /* get half vector */
+ /* Ensure that both direction are in the upper hemisphere */
+ if (cosNI <= 0 || cosNO <= 0) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ /* Compute half vector */
float3 m = normalize(omega_in + I);
- float alpha2 = alpha_x * alpha_y;
- float D, G1o, G1i;
+ float D, lambdaO, lambdaI;
if (alpha_x == alpha_y) {
- /* isotropic
- * eq. 20: (F*G*D)/(4*in*on)
- * eq. 33: first we calculate D(m) */
- float cosThetaM = dot(N, m);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ /* Isotropic case */
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
/* use GTR1 for clearcoat */
- D = D_GTR1(cosThetaM, bsdf->alpha_x);
+ D = microfacet_GTR1_D(dot(N, m), alpha2);
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
alpha2 = 0.0625f;
}
else {
/* use GTR2 otherwise */
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ D = microfacet_ggx_D(dot(N, m), alpha2);
}
- /* eq. 34: now calculate G1(i,m) and G1(o,m) */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+ lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
}
else {
- /* anisotropic */
+ /* Anisotropic case */
float3 X, Y, Z = N;
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- /* distribution */
+ /* Transform vectors into local coordinate space */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x / (local_m.z * alpha_x);
- float slope_y = -local_m.y / (local_m.z * alpha_y);
- float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) and G1(o,m) */
- float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
- float cosPhiO = dot(I, X);
- float sinPhiO = dot(I, Y);
-
- float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
- (sinPhiO * sinPhiO) * (alpha_y * alpha_y);
- alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
-
- G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
-
- float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
- float cosPhiI = dot(omega_in, X);
- float sinPhiI = dot(omega_in, Y);
-
- float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
- (sinPhiI * sinPhiI) * (alpha_y * alpha_y);
- alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
+ float3 local_O = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_I = make_float3(dot(X, omega_in), dot(Y, omega_in), cosNI);
- G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
+ D = microfacet_ggx_D_aniso(local_m, alpha_x, alpha_y);
+ lambdaO = microfacet_ggx_lambda_aniso(local_O, alpha_x, alpha_y);
+ lambdaI = microfacet_ggx_lambda_aniso(local_I, alpha_x, alpha_y);
}
- float G = G1o * G1i;
+ /* The full BSDF is (see e.g. eq. 20 in Walter et al. 2007):
+ * f(i, o) = F(i, m) * G(i, o) * D(m) / (4*cosNI*cosNO).
+ *
+ * Here, F is the fresnel reflection term, G is the masking-shadowing term,
+ * D is the microfacet distribution and cosNI/cosNO are cosines of angles.
+ *
+ * For G, this implementation uses the non-separable form of the Smith
+ * masking-shadowing term, so G is defined in terms of a function Lambda:
+ * G(i, o) = 1 / (1 + Lambda(i) + Lambda(o)).
+ *
+ * In Cycles, BSDF evaluation actually returns f(i, o)*cosNI, so one term
+ * in the BSDFs denominator cancels out.
+ *
+ * The PDF of VNDF sampling is D(m) * G1(o) / (4*cosNO), where G1(o) is
+ * 1 / (1 + Lambda(o)).
+ */
- /* eq. 20 */
+ /* Evaluate BSDF */
float common = D * 0.25f / cosNO;
-
Spectrum F = reflection_color(bsdf, omega_in, m);
- if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- F *= 0.25f * bsdf->extra->clearcoat;
- }
-
- Spectrum out = F * G * common;
-
- /* eq. 2 in distribution of visible normals sampling
- * `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */
-
- /* eq. 38 - but see also:
- * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
- * `pdf = pm * 0.25 / dot(m, I);` */
- *pdf = G1o * common;
+ Spectrum out = F * common / (1 + lambdaO + lambdaI);
+ *pdf = common / (1 + lambdaO);
return out;
}
@@ -474,44 +349,29 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const Microfac
const float cosNO,
const float cosNI)
{
+ float alpha2 = alpha_x * alpha_y;
if (cosNO <= 0 || cosNI >= 0) {
*pdf = 0.0f;
- return zero_spectrum(); /* vectors on same side -- not possible */
+ return zero_spectrum();
}
- /* compute half-vector of the refraction (eq. 16) */
+
+ /* Compute half vector */
float m_eta = bsdf->ior;
float3 ht = -(m_eta * omega_in + I);
- float3 Ht = normalize(ht);
- float cosHO = dot(Ht, I);
- float cosHI = dot(Ht, omega_in);
-
- float D, G1o, G1i;
-
- /* eq. 33: first we calculate D(m) with m=Ht: */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM = dot(N, Ht);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ float3 m = normalize(ht);
+ float cosMO = dot(m, I);
+ float cosMI = dot(m, omega_in);
- /* eq. 34: now calculate G1(i,m) and G1(o,m) */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ /* Evaluate microfacet model */
+ float D = microfacet_ggx_D(dot(N, m), alpha2);
+ float lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+ float lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
- float G = G1o * G1i;
-
- /* probability */
+ /* Evaluate BSDF */
float Ht2 = dot(ht, ht);
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
- * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * fabsf(cosHO * cosHI) * common;
+ float common = fabsf(cosMI * cosMO) * D * sqr(m_eta) / (cosNO * Ht2);
+ float out = common / (1 + lambdaO + lambdaI);
+ *pdf = common / (1 + lambdaO);
return make_spectrum(out);
}
@@ -540,8 +400,7 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval(ccl_private const ShaderClosure *sc
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
}
-ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
- ccl_private const ShaderClosure *sc,
+ccl_device int bsdf_microfacet_ggx_sample(ccl_private const ShaderClosure *sc,
float3 Ng,
float3 I,
float randu,
@@ -555,585 +414,135 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
float alpha_x = bsdf->alpha_x;
float alpha_y = bsdf->alpha_y;
+ float alpha2 = alpha_x * alpha_y;
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
*sampled_roughness = make_float2(alpha_x, alpha_y);
*eta = m_refractive ? 1.0f / bsdf->ior : bsdf->ior;
float3 N = bsdf->N;
- int label;
+ /* Ensure that the view direction is in the upper hemisphere. */
float cosNO = dot(N, I);
- if (cosNO > 0) {
- float3 X, Y, Z = N;
-
- if (alpha_x == alpha_y)
- make_orthonormals(Z, &X, &Y);
- else
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* importance sampling with distribution of visible normals. vectors are
- * transformed to local space before and after */
- float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
- float3 local_m;
- float G1o;
-
- local_m = microfacet_sample_stretched(
- kg, local_I, alpha_x, alpha_y, randu, randv, false, &G1o);
-
- float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
- float cosThetaM = local_m.z;
-
- /* reflection or refraction? */
- if (!m_refractive) {
- float cosMO = dot(m, I);
- label = LABEL_REFLECT | LABEL_GLOSSY;
-
- if (cosMO > 0) {
- /* eq. 39 - compute actual reflected direction */
- *omega_in = 2 * cosMO * m - I;
-
- if (dot(Ng, *omega_in) > 0) {
- if (alpha_x * alpha_y <= 1e-7f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_spectrum(1e6f);
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
- bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
-
- /* if fresnel is used, calculate the color with reflection_color(...) */
- if (use_fresnel) {
- *eval *= reflection_color(bsdf, *omega_in, m);
- }
-
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* microfacet normal is visible to this ray */
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float D, G1i;
-
- if (alpha_x == alpha_y) {
- /* isotropic */
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1 / (cosThetaM2)-1;
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- /* use GTR1 for clearcoat */
- D = D_GTR1(cosThetaM, bsdf->alpha_x);
-
- /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
- alpha2 = 0.0625f;
-
- /* recalculate G1o */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- }
- else {
- /* use GTR2 otherwise */
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- }
-
- /* eq. 34: now calculate G1(i,m) */
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
- }
- else {
- /* anisotropic distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x / (local_m.z * alpha_x);
- float slope_y = -local_m.y / (local_m.z * alpha_y);
- float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
-
- /* calculate G1(i,m) */
- float cosNI = dot(N, *omega_in);
-
- float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
- float cosPhiI = dot(*omega_in, X);
- float sinPhiI = dot(*omega_in, Y);
-
- float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
- (sinPhiI * sinPhiI) * (alpha_y * alpha_y);
- alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
-
- G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
- }
-
- /* see eval function for derivation */
- float common = (G1o * D) * 0.25f / cosNO;
- *pdf = common;
-
- Spectrum F = reflection_color(bsdf, *omega_in, m);
-
- *eval = G1i * common * F;
- }
-
- if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- *eval *= 0.25f * bsdf->extra->clearcoat;
- }
- }
- else {
- *eval = zero_spectrum();
- *pdf = 0.0f;
- }
- }
- }
- else {
- label = LABEL_TRANSMIT | LABEL_GLOSSY;
-
- /* CAUTION: the i and o variables are inverted relative to the paper
- * eq. 39 - compute actual refractive direction */
- float3 R, T;
- float m_eta = bsdf->ior, fresnel;
- bool inside;
-
- fresnel = fresnel_dielectric(m_eta, m, I, &R, &T, &inside);
-
- if (!inside && fresnel != 1.0f) {
- *omega_in = T;
-
- if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_spectrum(1e6f);
- label = LABEL_TRANSMIT | LABEL_SINGULAR;
- }
- else {
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1 / (cosThetaM2)-1;
- float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 34: now calculate G1(i,m) */
- float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
-
- /* eq. 21 */
- float cosHI = dot(m, *omega_in);
- float cosHO = dot(m, I);
- float Ht2 = m_eta * cosHI + cosHO;
- Ht2 *= Ht2;
-
- /* see eval function for derivation */
- float common = (G1o * D) * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G1i * fabsf(cosHI * cosHO) * common;
- *pdf = cosHO * fabsf(cosHI) * common;
-
- *eval = make_spectrum(out);
- }
- }
- else {
- *eval = zero_spectrum();
- *pdf = 0.0f;
- }
- }
- }
- else {
- label = (m_refractive) ? LABEL_TRANSMIT | LABEL_GLOSSY : LABEL_REFLECT | LABEL_GLOSSY;
- }
- return label;
-}
-
-/* Beckmann microfacet with Smith shadow-masking from:
- *
- * Microfacet Models for Refraction through Rough Surfaces
- * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007 */
-
-ccl_device int bsdf_microfacet_beckmann_setup(ccl_private MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_x = saturatef(bsdf->alpha_x);
- bsdf->alpha_y = saturatef(bsdf->alpha_y);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL;
-}
-
-/* Required to maintain OSL interface. */
-ccl_device int bsdf_microfacet_beckmann_isotropic_setup(ccl_private MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_y = bsdf->alpha_x;
-
- return bsdf_microfacet_beckmann_setup(bsdf);
-}
-
-ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_x = saturatef(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- return SD_BSDF | SD_BSDF_HAS_EVAL;
-}
-
-ccl_device void bsdf_microfacet_beckmann_blur(ccl_private ShaderClosure *sc, float roughness)
-{
- ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
-
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
-}
-
-ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n)
-{
- cos_n *= cos_n;
- float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n);
- if (invA < 0.625f) {
- return 1.0f;
- }
-
- float a = 1.0f / invA;
- return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
-}
-
-ccl_device_inline float bsdf_beckmann_aniso_G1(
- float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi)
-{
- cos_n *= cos_n;
- sin_phi *= sin_phi;
- cos_phi *= cos_phi;
- alpha_x *= alpha_x;
- alpha_y *= alpha_y;
-
- float alphaO2 = (cos_phi * alpha_x + sin_phi * alpha_y) / (cos_phi + sin_phi);
- float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n);
- if (invA < 0.625f) {
- return 1.0f;
- }
-
- float a = 1.0f / invA;
- return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
-}
-
-ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
- const float3 N,
- const float3 I,
- const float3 omega_in,
- ccl_private float *pdf,
- const float alpha_x,
- const float alpha_y,
- const float cosNO,
- const float cosNI)
-{
- if (!(cosNO > 0 && cosNI > 0)) {
+ if (cosNO <= 0) {
*pdf = 0.0f;
- return zero_spectrum();
+ return LABEL_NONE;
}
- /* get half vector */
- float3 m = normalize(omega_in + I);
-
- float alpha2 = alpha_x * alpha_y;
- float D, G1o, G1i;
-
- if (alpha_x == alpha_y) {
- /* isotropic
- * eq. 20: (F*G*D)/(4*in*on)
- * eq. 25: first we calculate D(m) */
- float cosThetaM = dot(N, m);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- G1o = bsdf_beckmann_G1(alpha_x, cosNO);
- G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- }
- else {
- /* anisotropic */
- float3 X, Y, Z = N;
+ /* Form local coordinate frame */
+ float3 X, Y, Z = N;
+ if (alpha_x == alpha_y)
+ make_orthonormals(Z, &X, &Y);
+ else
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- /* distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x / (local_m.z * alpha_x);
- float slope_y = -local_m.y / (local_m.z * alpha_y);
+ /* Sample distribution of visible normals to find the microfacet normal.
+ * Sampling happens in the local frame. */
+ float3 local_O = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_m = microfacet_ggx_sample_vndf(local_O, alpha_x, alpha_y, randu, randv);
+ float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
+ float cosThetaM = local_m.z;
+
+ /* Reflection or refraction? */
+ if (!m_refractive) {
+ /* Compute reflected direction and ensure that it is in the upper hemisphere.
+ * Also check if the microfacet is masked (in that case, we'd hit it from the backside). */
+ float cosMO = dot(m, I);
+ *omega_in = 2 * cosMO * m - I;
+ if (cosMO <= 0 || dot(Ng, *omega_in) <= 0) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ Spectrum F = reflection_color(bsdf, *omega_in, m);
+ if (alpha2 <= 1e-7f) {
+ /* Specular case, just return some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_spectrum(1e6f) * F;
+ return LABEL_REFLECT | LABEL_SINGULAR;
+ }
- D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
+ /* Evaluate microfacet model. */
+ float D, lambdaO, lambdaI;
+ if (alpha_x == alpha_y) {
+ /* Isotropic case */
- /* G1(i,m) and G1(o,m) */
- G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
- G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
- }
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ /* use GTR1 for clearcoat */
+ D = microfacet_GTR1_D(cosThetaM, alpha2);
- float G = G1o * G1i;
+ /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+ alpha2 = 0.0625f;
- /* eq. 20 */
- float common = D * 0.25f / cosNO;
- float out = G * common;
+ /* recalculate lambdaO */
+ lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+ }
+ else {
+ /* use GTR2 otherwise */
+ D = microfacet_ggx_D(cosThetaM, alpha2);
+ }
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+ float cosNI = dot(N, *omega_in);
+ lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+ lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
+ }
+ else {
+ /* Anisotropic case */
+ D = microfacet_ggx_D_aniso(local_m, alpha_x, alpha_y);
- /* eq. 38 - but see also:
- * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
- * pdf = pm * 0.25 / dot(m, I); */
- *pdf = G1o * common;
+ float3 local_I = make_float3(dot(X, *omega_in), dot(Y, *omega_in), dot(N, *omega_in));
+ lambdaO = microfacet_ggx_lambda_aniso(local_O, alpha_x, alpha_y);
+ lambdaI = microfacet_ggx_lambda_aniso(local_I, alpha_x, alpha_y);
+ }
- return make_spectrum(out);
-}
+ /* See bsdf_microfacet_ggx_eval_reflect for derivation. */
+ float common = D * 0.25f / cosNO;
+ *pdf = common / (1 + lambdaO);
+ *eval = common * F / (1 + lambdaO + lambdaI);
-ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const MicrofacetBsdf *bsdf,
- const float3 N,
- const float3 I,
- const float3 omega_in,
- ccl_private float *pdf,
- const float alpha_x,
- const float alpha_y,
- const float cosNO,
- const float cosNI)
-{
- if (cosNO <= 0 || cosNI >= 0) {
- *pdf = 0.0f;
- return zero_spectrum();
+ return LABEL_REFLECT | LABEL_GLOSSY;
}
+ else {
+ /* Compute refracted direction */
+ float3 R, T;
+ float m_eta = bsdf->ior, fresnel;
+ bool inside;
- const float m_eta = bsdf->ior;
- /* compute half-vector of the refraction (eq. 16) */
- float3 ht = -(m_eta * omega_in + I);
- float3 Ht = normalize(ht);
- float cosHO = dot(Ht, I);
- float cosHI = dot(Ht, omega_in);
-
- /* eq. 25: first we calculate D(m) with m=Ht: */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM = min(dot(N, Ht), 1.0f);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
- float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- float G = G1o * G1i;
-
- /* probability */
- float Ht2 = dot(ht, ht);
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
- * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * fabsf(cosHO * cosHI) * common;
-
- return make_spectrum(out);
-}
+ fresnel = fresnel_dielectric(m_eta, m, I, &R, &T, &inside);
-ccl_device Spectrum bsdf_microfacet_beckmann_eval(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;
- const float alpha_x = bsdf->alpha_x;
- const float alpha_y = bsdf->alpha_y;
- const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- const float3 N = bsdf->N;
- const float cosNO = dot(N, I);
- const float cosNI = dot(N, omega_in);
+ /* Ensure that the microfacet is nor masked and that we don't encounter TIR */
+ if (inside || fresnel == 1.0f) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
- if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
- *pdf = 0.0f;
- return zero_spectrum();
- }
+ *omega_in = T;
- return (cosNI < 0.0f) ? bsdf_microfacet_beckmann_eval_transmit(
- bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
- bsdf_microfacet_beckmann_eval_reflect(
- bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
-}
+ if (alpha2 <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_spectrum(1e6f);
+ return LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
-ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
- ccl_private const ShaderClosure *sc,
- float3 Ng,
- float3 I,
- float randu,
- float randv,
- ccl_private Spectrum *eval,
- ccl_private float3 *omega_in,
- ccl_private float *pdf,
- ccl_private float2 *sampled_roughness,
- ccl_private float *eta)
-{
- ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = bsdf->N;
- int label;
+ /* Evaluate microfacet model */
+ float D = microfacet_ggx_D(cosThetaM, alpha2);
+ float cosNI = dot(N, *omega_in);
+ float lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+ float lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
- *sampled_roughness = make_float2(alpha_x, alpha_y);
- *eta = m_refractive ? 1.0f / bsdf->ior : bsdf->ior;
+ /* Evaluate BSDF */
+ float cosMI = dot(m, *omega_in);
+ float cosMO = dot(m, I);
+ float Ht2 = sqr(m_eta * cosMI + cosMO);
+ float common = fabsf(cosMI * cosMO) * D * sqr(m_eta) / (cosNO * Ht2);
+ float out = common / (1 + lambdaO + lambdaI);
+ *pdf = common / (1 + lambdaO);
- float cosNO = dot(N, I);
- if (cosNO > 0) {
- float3 X, Y, Z = N;
+ *eval = make_spectrum(out);
- if (alpha_x == alpha_y)
- make_orthonormals(Z, &X, &Y);
- else
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* importance sampling with distribution of visible normals. vectors are
- * transformed to local space before and after */
- float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
- float3 local_m;
- float G1o;
-
- local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_x, randu, randv, true, &G1o);
-
- float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
- float cosThetaM = local_m.z;
-
- /* reflection or refraction? */
- if (!m_refractive) {
- label = LABEL_REFLECT | LABEL_GLOSSY;
- float cosMO = dot(m, I);
-
- if (cosMO > 0) {
- /* eq. 39 - compute actual reflected direction */
- *omega_in = 2 * cosMO * m - I;
-
- if (dot(Ng, *omega_in) > 0) {
- if (alpha_x * alpha_y <= 1e-7f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_spectrum(1e6f);
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* microfacet normal is visible to this ray
- * eq. 25 */
- float alpha2 = alpha_x * alpha_y;
- float D, G1i;
-
- if (alpha_x == alpha_y) {
- /* Isotropic distribution. */
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1 / (cosThetaM2)-1;
- D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 26, 27: now calculate G1(i,m) */
- G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- }
- else {
- /* anisotropic distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x / (local_m.z * alpha_x);
- float slope_y = -local_m.y / (local_m.z * alpha_y);
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) */
- G1i = bsdf_beckmann_aniso_G1(
- alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y));
- }
-
- float G = G1o * G1i;
-
- /* see eval function for derivation */
- float common = D * 0.25f / cosNO;
- float out = G * common;
- *pdf = G1o * common;
-
- *eval = make_spectrum(out);
- }
- }
- else {
- *eval = zero_spectrum();
- *pdf = 0.0f;
- }
- }
- }
- else {
- label = LABEL_TRANSMIT | LABEL_GLOSSY;
-
- /* CAUTION: the i and o variables are inverted relative to the paper
- * eq. 39 - compute actual refractive direction */
- float3 R, T;
- float m_eta = bsdf->ior, fresnel;
- bool inside;
-
- fresnel = fresnel_dielectric(m_eta, m, I, &R, &T, &inside);
-
- if (!inside && fresnel != 1.0f) {
- *omega_in = T;
-
- if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_spectrum(1e6f);
- label = LABEL_TRANSMIT | LABEL_SINGULAR;
- }
- else {
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1 / (cosThetaM2)-1;
- float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 26, 27: now calculate G1(i,m) */
- float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- float G = G1o * G1i;
-
- /* eq. 21 */
- float cosHI = dot(m, *omega_in);
- float cosHO = dot(m, I);
- float Ht2 = m_eta * cosHI + cosHO;
- Ht2 *= Ht2;
-
- /* see eval function for derivation */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * cosHO * fabsf(cosHI) * common;
-
- *eval = make_spectrum(out);
- }
- }
- else {
- *eval = zero_spectrum();
- *pdf = 0.0f;
- }
- }
- }
- else {
- label = (m_refractive) ? LABEL_TRANSMIT | LABEL_GLOSSY : LABEL_REFLECT | LABEL_GLOSSY;
+ return LABEL_TRANSMIT | LABEL_GLOSSY;
}
- return label;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_beckmann.h b/intern/cycles/kernel/closure/bsdf_microfacet_beckmann.h
new file mode 100644
index 00000000000..4fabbcfc1eb
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_beckmann.h
@@ -0,0 +1,527 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Adapted from Open Shading Language
+ * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
+ * All Rights Reserved.
+ *
+ * Modifications Copyright 2011-2022 Blender Foundation. */
+
+#pragma once
+
+#include "kernel/closure/bsdf_util.h"
+
+#include "kernel/util/lookup_table.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Beckmann microfacet with Smith shadow-masking from:
+ *
+ * Microfacet Models for Refraction through Rough Surfaces
+ * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007
+ *
+ * Microfacet importance sampling from:
+ * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals.
+ * E. Heitz and E. d'Eon, EGSR 2014
+ */
+
+ccl_device_inline void microfacet_beckmann_sample_slopes(KernelGlobals kg,
+ const float cos_theta_i,
+ const float sin_theta_i,
+ float randu,
+ float randv,
+ ccl_private float *slope_x,
+ ccl_private float *slope_y,
+ ccl_private float *G1i)
+{
+ /* special case (normal incidence) */
+ if (cos_theta_i >= 0.99999f) {
+ const float r = sqrtf(-logf(randu));
+ const float phi = M_2PI_F * randv;
+ *slope_x = r * cosf(phi);
+ *slope_y = r * sinf(phi);
+ *G1i = 1.0f;
+ return;
+ }
+
+ /* precomputations */
+ const float tan_theta_i = sin_theta_i / cos_theta_i;
+ const float inv_a = tan_theta_i;
+ const float cot_theta_i = 1.0f / tan_theta_i;
+ const float erf_a = fast_erff(cot_theta_i);
+ const float exp_a2 = expf(-cot_theta_i * cot_theta_i);
+ const float SQRT_PI_INV = 0.56418958354f;
+ const float Lambda = 0.5f * (erf_a - 1.0f) + (0.5f * SQRT_PI_INV) * (exp_a2 * inv_a);
+ const float G1 = 1.0f / (1.0f + Lambda); /* masking */
+
+ *G1i = G1;
+
+#if defined(__KERNEL_GPU__)
+ /* Based on paper from Wenzel Jakob
+ * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
+ *
+ * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
+ *
+ * Reformulation from OpenShadingLanguage which avoids using inverse
+ * trigonometric functions.
+ */
+
+ /* Sample slope X.
+ *
+ * Compute a coarse approximation using the approximation:
+ * exp(-ierf(x)^2) ~= 1 - x * x
+ * solve y = 1 + b + K * (1 - b * b)
+ */
+ float K = tan_theta_i * SQRT_PI_INV;
+ float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
+ float y_exact = randu * (1.0f + erf_a + K * exp_a2);
+ float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
+
+ /* Perform newton step to refine toward the true root. */
+ float inv_erf = fast_ierff(b);
+ float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ /* Check if we are close enough already,
+ * this also avoids NaNs as we get close to the root.
+ */
+ if (fabsf(value) > 1e-6f) {
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
+ inv_erf = fast_ierff(b);
+ value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
+ /* Compute the slope from the refined value. */
+ *slope_x = fast_ierff(b);
+ }
+ else {
+ /* We are close enough already. */
+ *slope_x = inv_erf;
+ }
+ *slope_y = fast_ierff(2.0f * randv - 1.0f);
+#else
+ /* Use precomputed table on CPU, it gives better performance. */
+ int beckmann_table_offset = kernel_data.tables.beckmann_offset;
+
+ *slope_x = lookup_table_read_2D(
+ kg, randu, cos_theta_i, beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
+ *slope_y = fast_ierff(2.0f * randv - 1.0f);
+#endif
+}
+
+ccl_device_forceinline float3 microfacet_sample_stretched(KernelGlobals kg,
+ const float3 omega_i,
+ const float alpha_x,
+ const float alpha_y,
+ const float randu,
+ const float randv,
+ ccl_private float *G1i)
+{
+ /* 1. stretch omega_i */
+ float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z);
+ omega_i_ = normalize(omega_i_);
+
+ /* get polar coordinates of omega_i_ */
+ float costheta_ = 1.0f;
+ float sintheta_ = 0.0f;
+ float cosphi_ = 1.0f;
+ float sinphi_ = 0.0f;
+
+ if (omega_i_.z < 0.99999f) {
+ costheta_ = omega_i_.z;
+ sintheta_ = safe_sqrtf(1.0f - costheta_ * costheta_);
+
+ float invlen = 1.0f / sintheta_;
+ cosphi_ = omega_i_.x * invlen;
+ sinphi_ = omega_i_.y * invlen;
+ }
+
+ /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */
+ float slope_x, slope_y;
+ microfacet_beckmann_sample_slopes(
+ kg, costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
+
+ /* 3. rotate */
+ float tmp = cosphi_ * slope_x - sinphi_ * slope_y;
+ slope_y = sinphi_ * slope_x + cosphi_ * slope_y;
+ slope_x = tmp;
+
+ /* 4. unstretch */
+ slope_x = alpha_x * slope_x;
+ slope_y = alpha_y * slope_y;
+
+ /* 5. compute normal */
+ return normalize(make_float3(-slope_x, -slope_y, 1.0f));
+}
+
+ccl_device int bsdf_microfacet_beckmann_setup(ccl_private MicrofacetBsdf *bsdf)
+{
+ bsdf->alpha_x = saturatef(bsdf->alpha_x);
+ bsdf->alpha_y = saturatef(bsdf->alpha_y);
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
+ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
+{
+ bsdf->alpha_x = saturatef(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
+ccl_device void bsdf_microfacet_beckmann_blur(ccl_private ShaderClosure *sc, float roughness)
+{
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
+
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+}
+
+ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n)
+{
+ cos_n *= cos_n;
+ float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n);
+ if (invA < 0.625f) {
+ return 1.0f;
+ }
+
+ float a = 1.0f / invA;
+ return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
+}
+
+ccl_device_inline float bsdf_beckmann_aniso_G1(
+ float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi)
+{
+ cos_n *= cos_n;
+ sin_phi *= sin_phi;
+ cos_phi *= cos_phi;
+ alpha_x *= alpha_x;
+ alpha_y *= alpha_y;
+
+ float alphaO2 = (cos_phi * alpha_x + sin_phi * alpha_y) / (cos_phi + sin_phi);
+ float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n);
+ if (invA < 0.625f) {
+ return 1.0f;
+ }
+
+ float a = 1.0f / invA;
+ return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
+}
+
+ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
+ const float3 N,
+ const float3 I,
+ const float3 omega_in,
+ ccl_private float *pdf,
+ const float alpha_x,
+ const float alpha_y,
+ const float cosNO,
+ const float cosNI)
+{
+ if (!(cosNO > 0 && cosNI > 0)) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ /* get half vector */
+ float3 m = normalize(omega_in + I);
+
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1o, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* isotropic
+ * eq. 20: (F*G*D)/(4*in*on)
+ * eq. 25: first we calculate D(m) */
+ float cosThetaM = dot(N, m);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
+ G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+ G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ }
+ else {
+ /* anisotropic */
+ float3 X, Y, Z = N;
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) and G1(o,m) */
+ G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
+ G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
+ }
+
+ float G = G1o * G1i;
+
+ /* eq. 20 */
+ float common = D * 0.25f / cosNO;
+ float out = G * common;
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* eq. 38 - but see also:
+ * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
+ * pdf = pm * 0.25 / dot(m, I); */
+ *pdf = G1o * common;
+
+ return make_spectrum(out);
+}
+
+ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const MicrofacetBsdf *bsdf,
+ const float3 N,
+ const float3 I,
+ const float3 omega_in,
+ ccl_private float *pdf,
+ const float alpha_x,
+ const float alpha_y,
+ const float cosNO,
+ const float cosNI)
+{
+ const float m_eta = bsdf->ior;
+ if (cosNO <= 0 || cosNI >= 0) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+ /* compute half-vector of the refraction (eq. 16) */
+ float3 ht = -(m_eta * omega_in + I);
+ float3 Ht = normalize(ht);
+ float cosHO = dot(Ht, I);
+ float cosHI = dot(Ht, omega_in);
+
+ /* eq. 25: first we calculate D(m) with m=Ht: */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM = min(dot(N, Ht), 1.0f);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
+ float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ float G = G1o * G1i;
+
+ /* probability */
+ float Ht2 = dot(ht, ht);
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
+ * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * fabsf(cosHO * cosHI) * common;
+
+ return make_spectrum(out);
+}
+
+ccl_device Spectrum bsdf_microfacet_beckmann_eval(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;
+ const float alpha_x = bsdf->alpha_x;
+ const float alpha_y = bsdf->alpha_y;
+ const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ const float3 N = bsdf->N;
+ const float cosNO = dot(N, I);
+ const float cosNI = dot(N, omega_in);
+
+ if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ return (cosNI < 0.0f) ? bsdf_microfacet_beckmann_eval_transmit(
+ bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
+ bsdf_microfacet_beckmann_eval_reflect(
+ bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
+}
+
+ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
+ ccl_private const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float randu,
+ float randv,
+ ccl_private Spectrum *eval,
+ ccl_private float3 *omega_in,
+ ccl_private float *pdf,
+ ccl_private float2 *sampled_roughness,
+ ccl_private float *eta)
+{
+ ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float3 N = bsdf->N;
+ int label;
+
+ *sampled_roughness = make_float2(alpha_x, alpha_y);
+ *eta = m_refractive ? 1.0f / bsdf->ior : bsdf->ior;
+
+ float cosNO = dot(N, I);
+ if (cosNO > 0) {
+ float3 X, Y, Z = N;
+
+ if (alpha_x == alpha_y)
+ make_orthonormals(Z, &X, &Y);
+ else
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* importance sampling with distribution of visible normals. vectors are
+ * transformed to local space before and after */
+ float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_m;
+ float G1o;
+
+ local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_x, randu, randv, &G1o);
+
+ float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
+ float cosThetaM = local_m.z;
+
+ /* reflection or refraction? */
+ if (!m_refractive) {
+ label = LABEL_REFLECT | LABEL_GLOSSY;
+ float cosMO = dot(m, I);
+
+ if (cosMO > 0) {
+ /* eq. 39 - compute actual reflected direction */
+ *omega_in = 2 * cosMO * m - I;
+
+ if (dot(Ng, *omega_in) > 0) {
+ if (alpha_x * alpha_y <= 1e-7f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_spectrum(1e6f);
+ label = LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ /* microfacet normal is visible to this ray
+ * eq. 25 */
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* Isotropic distribution. */
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 26, 27: now calculate G1(i,m) */
+ G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ }
+ else {
+ /* anisotropic distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) */
+ G1i = bsdf_beckmann_aniso_G1(
+ alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y));
+ }
+
+ float G = G1o * G1i;
+
+ /* see eval function for derivation */
+ float common = D * 0.25f / cosNO;
+ float out = G * common;
+ *pdf = G1o * common;
+
+ *eval = make_spectrum(out);
+ }
+ }
+ else {
+ *eval = zero_spectrum();
+ *pdf = 0.0f;
+ }
+ }
+ }
+ else {
+ label = LABEL_TRANSMIT | LABEL_GLOSSY;
+
+ /* CAUTION: the i and o variables are inverted relative to the paper
+ * eq. 39 - compute actual refractive direction */
+ float3 R, T;
+ float m_eta = bsdf->ior, fresnel;
+ bool inside;
+
+ fresnel = fresnel_dielectric(m_eta, m, I, &R, &T, &inside);
+
+ if (!inside && fresnel != 1.0f) {
+ *omega_in = T;
+
+ if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_spectrum(1e6f);
+ label = LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
+ else {
+ /* eq. 33 */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 26, 27: now calculate G1(i,m) */
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ float G = G1o * G1i;
+
+ /* eq. 21 */
+ float cosHI = dot(m, *omega_in);
+ float cosHO = dot(m, I);
+ float Ht2 = m_eta * cosHI + cosHO;
+ Ht2 *= Ht2;
+
+ /* see eval function for derivation */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * cosHO * fabsf(cosHI) * common;
+
+ *eval = make_spectrum(out);
+ }
+ }
+ else {
+ *eval = zero_spectrum();
+ *pdf = 0.0f;
+ }
+ }
+ }
+ else {
+ label = (m_refractive) ? LABEL_TRANSMIT | LABEL_GLOSSY : LABEL_REFLECT | LABEL_GLOSSY;
+ }
+ return label;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_glass.h b/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
new file mode 100644
index 00000000000..3c0ea32447b
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_glass.h
@@ -0,0 +1,283 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#pragma once
+
+#include "kernel/sample/lcg.h"
+
+#include "util/hash.h"
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device_inline Spectrum
+microfacet_ggx_glass_albedo_scaling(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private const MicrofacetBsdf *bsdf,
+ const Spectrum Fss)
+{
+ float mu = dot(sd->I, bsdf->N);
+ float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
+ float E = microfacet_ggx_glass_E(kg, mu, rough, bsdf->ior);
+
+ /* Close enough for glass, coloring here is unphysical anyways and it's unclear how to
+ * approximate it better. */
+ Spectrum Fms = Fss;
+
+ return one_spectrum() + Fms * ((1.0f - E) / E);
+ /* TODO: Ensure that increase in weight does not mess up glossy color, albedo etc. passes */
+}
+
+/* Currently no non-albedo-scaled version is implemented, could easily be added
+ * but would still break compatibility with the old glass due to the microfacet Fresnel. */
+
+ccl_device int bsdf_microfacet_multi_ggx_glass_setup(KernelGlobals kg,
+ ccl_private MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd,
+ const Spectrum color)
+{
+ bsdf->extra = NULL;
+
+ bsdf->alpha_x = saturatef(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+
+ bsdf->weight *= microfacet_ggx_glass_albedo_scaling(kg, sd, bsdf, saturate(color));
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(KernelGlobals kg,
+ ccl_private MicrofacetBsdf *bsdf,
+ ccl_private const ShaderData *sd)
+{
+ bsdf->extra->cspec0 = saturate(bsdf->extra->cspec0);
+
+ bsdf->alpha_x = saturatef(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
+
+ bsdf_microfacet_fresnel_color(sd, bsdf);
+
+ Spectrum Fss = schlick_fresnel_Fss(bsdf->extra->cspec0);
+ bsdf->weight *= microfacet_ggx_glass_albedo_scaling(kg, sd, bsdf, Fss);
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
+ccl_device Spectrum bsdf_microfacet_ggx_glass_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
+ const float3 N,
+ const float3 I,
+ const float3 omega_in,
+ ccl_private float *pdf,
+ const float alpha_x,
+ const float alpha_y,
+ const float cosNO,
+ const float cosNI)
+{
+ if (cosNI <= 0 || cosNO <= 0) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ float alpha2 = alpha_x * alpha_y;
+ float3 m = normalize(omega_in + I);
+ float D = microfacet_ggx_D(dot(N, m), alpha2);
+ float lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+ float lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
+
+ float common = D * 0.25f / cosNO;
+
+ float F = fresnel_dielectric_cos(dot(m, I), bsdf->ior);
+ float out = F * common / (1 + lambdaO + lambdaI);
+ *pdf = common / (1 + lambdaO);
+
+ Spectrum eval = make_spectrum(out);
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
+ eval *= reflection_color(bsdf, omega_in, m);
+ }
+ return eval;
+}
+
+ccl_device Spectrum bsdf_microfacet_ggx_glass_eval_transmit(ccl_private const MicrofacetBsdf *bsdf,
+ const float3 N,
+ const float3 I,
+ const float3 omega_in,
+ ccl_private float *pdf,
+ const float alpha_x,
+ const float alpha_y,
+ const float cosNO,
+ const float cosNI)
+{
+
+ if (cosNO <= 0 || cosNI >= 0) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ float eta = bsdf->ior;
+ float3 ht = -(eta * omega_in + I);
+ float3 m = normalize(ht);
+ float cosMO = dot(m, I);
+ float cosMI = dot(m, omega_in);
+
+ float F = fresnel_dielectric_cos(cosMO, eta);
+ if (F == 1.0f) {
+ /* TIR */
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ float alpha2 = alpha_x * alpha_y;
+ float D = microfacet_ggx_D(dot(N, m), alpha2);
+ float lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+ float lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
+
+ float Ht2 = dot(ht, ht);
+
+ float common = fabsf(cosMI * cosMO) * D * sqr(eta) / (cosNO * Ht2);
+ float out = (1.0f - F) * common / (1 + lambdaO + lambdaI);
+ *pdf = common / (1 + lambdaO);
+
+ Spectrum eval = make_spectrum(out);
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
+ eval *= bsdf->extra->color;
+ }
+ return eval;
+}
+
+ccl_device Spectrum bsdf_microfacet_ggx_glass_eval(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;
+ const float alpha_x = bsdf->alpha_x;
+ const float alpha_y = bsdf->alpha_y;
+ const float3 N = bsdf->N;
+ const float cosNO = dot(N, I);
+ const float cosNI = dot(N, omega_in);
+
+ if (alpha_x * alpha_y <= 1e-7f) {
+ *pdf = 0.0f;
+ return zero_spectrum();
+ }
+
+ return (cosNI < 0.0f) ? bsdf_microfacet_ggx_glass_eval_transmit(
+ bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
+ bsdf_microfacet_ggx_glass_eval_reflect(
+ bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
+}
+
+ccl_device int bsdf_microfacet_ggx_glass_sample(ccl_private const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float randu,
+ float randv,
+ ccl_private Spectrum *eval,
+ ccl_private float3 *omega_in,
+ ccl_private float *pdf,
+ ccl_private float2 *sampled_roughness,
+ ccl_private float *eta)
+{
+ ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ float3 N = bsdf->N;
+ int label;
+
+ *sampled_roughness = make_float2(alpha_x, alpha_y);
+ *eta = bsdf->ior; // TODO: Do we need to invert in case of refraction?
+
+ float cosNO = dot(N, I);
+ if (cosNO <= 0) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+
+ float3 X, Y, Z = N;
+ make_orthonormals(Z, &X, &Y);
+
+ /* importance sampling with distribution of visible normals. vectors are
+ * transformed to local space before and after */
+ float3 local_O = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_m = microfacet_ggx_sample_vndf(local_O, alpha_x, alpha_y, randu, randv);
+
+ float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
+ float cosThetaM = local_m.z;
+
+ float cosMO = dot(m, I);
+ if (cosMO <= 0.0f) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+
+ float3 R, T;
+ bool inside; /* Will never be inside, we already checked cosMO */
+ float fresnel = fresnel_dielectric(bsdf->ior, m, I, &R, &T, &inside);
+
+ // TODO: Somehow get a properly stratified value here, this causes considerable noise
+ float randw = hash_float2_to_float(make_float2(randu, randv));
+ bool do_reflect = randw < fresnel;
+
+ float alpha2 = alpha_x * alpha_y;
+ if (alpha2 <= 1e-7f) {
+ /* Specular case, just return some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+
+ *omega_in = do_reflect ? R : T;
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
+ *eval *= do_reflect ? reflection_color(bsdf, *omega_in, m) : bsdf->extra->color;
+ }
+
+ return LABEL_SINGULAR | (do_reflect ? LABEL_REFLECT : LABEL_TRANSMIT);
+ }
+
+ /* Common microfacet model terms. */
+ float D = microfacet_ggx_D(cosThetaM, alpha2);
+ float lambdaO = microfacet_ggx_lambda(cosNO, alpha2);
+
+ float cosNI, common;
+ if (do_reflect) {
+ cosNI = dot(N, R);
+ if (cosNI <= 0.0f || dot(Ng, R) <= 0.0f) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+
+ label = LABEL_REFLECT | LABEL_GLOSSY;
+ *omega_in = R;
+
+ common = fresnel * D * 0.25f / cosNO;
+ }
+ else {
+ cosNI = dot(N, T);
+ if (cosNI >= 0.0f || dot(Ng, T) >= 0.0f) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+
+ label = LABEL_TRANSMIT | LABEL_GLOSSY;
+ *omega_in = T;
+
+ float cosMI = dot(m, *omega_in);
+ float Ht2 = sqr(bsdf->ior * cosMI + cosMO);
+
+ common = (1.0f - fresnel) * D * fabsf(cosMI * cosMO) * sqr(bsdf->ior) / (cosNO * Ht2);
+ }
+
+ float lambdaI = microfacet_ggx_lambda(cosNI, alpha2);
+ float out = common / (1 + lambdaO + lambdaI);
+ *pdf = common / (1 + lambdaO);
+ *eval = make_spectrum(out);
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID) {
+ *eval *= do_reflect ? reflection_color(bsdf, *omega_in, m) : bsdf->extra->color;
+ }
+ return label;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
deleted file mode 100644
index 73cc0d292a1..00000000000
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ /dev/null
@@ -1,686 +0,0 @@
-/* SPDX-License-Identifier: Apache-2.0
- * Copyright 2011-2022 Blender Foundation */
-
-#pragma once
-
-#include "kernel/sample/lcg.h"
-#include "kernel/sample/mapping.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Most of the code is based on the supplemental implementations from
- * https://eheitzresearch.wordpress.com/240-2/. */
-
-/* === GGX Microfacet distribution functions === */
-
-/* Isotropic GGX microfacet distribution */
-ccl_device_forceinline float D_ggx(float3 wm, float alpha)
-{
- wm.z *= wm.z;
- alpha *= alpha;
- float tmp = (1.0f - wm.z) + alpha * wm.z;
- return alpha / max(M_PI_F * tmp * tmp, 1e-7f);
-}
-
-/* Anisotropic GGX microfacet distribution */
-ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
-{
- float slope_x = -wm.x / alpha.x;
- float slope_y = -wm.y / alpha.y;
- float tmp = wm.z * wm.z + slope_x * slope_x + slope_y * slope_y;
-
- return 1.0f / max(M_PI_F * tmp * tmp * alpha.x * alpha.y, 1e-7f);
-}
-
-/* Sample slope distribution (based on page 14 of the supplemental implementation). */
-ccl_device_forceinline float2 mf_sampleP22_11(const float cosI,
- const float randx,
- const float randy)
-{
- if (cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
- const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
- const float phi = M_2PI_F * randy;
- return make_float2(r * cosf(phi), r * sinf(phi));
- }
-
- const float sinI = safe_sqrtf(1.0f - cosI * cosI);
- const float tanI = sinI / cosI;
- const float projA = 0.5f * (cosI + 1.0f);
- if (projA < 0.0001f)
- return make_float2(0.0f, 0.0f);
- const float A = 2.0f * randx * projA / cosI - 1.0f;
- float tmp = A * A - 1.0f;
- if (fabsf(tmp) < 1e-7f)
- return make_float2(0.0f, 0.0f);
- tmp = 1.0f / tmp;
- const float D = safe_sqrtf(tanI * tanI * tmp * tmp - (A * A - tanI * tanI) * tmp);
-
- const float slopeX2 = tanI * tmp + D;
- const float slopeX = (A < 0.0f || slopeX2 > 1.0f / tanI) ? (tanI * tmp - D) : slopeX2;
-
- float U2;
- if (randy >= 0.5f)
- U2 = 2.0f * (randy - 0.5f);
- else
- U2 = 2.0f * (0.5f - randy);
- const float z = (U2 * (U2 * (U2 * 0.27385f - 0.73369f) + 0.46341f)) /
- (U2 * (U2 * (U2 * 0.093073f + 0.309420f) - 1.0f) + 0.597999f);
- const float slopeY = z * sqrtf(1.0f + slopeX * slopeX);
-
- if (randy >= 0.5f)
- return make_float2(slopeX, slopeY);
- else
- return make_float2(slopeX, -slopeY);
-}
-
-/* Visible normal sampling for the GGX distribution
- * (based on page 7 of the supplemental implementation). */
-ccl_device_forceinline float3 mf_sample_vndf(const float3 wi,
- const float2 alpha,
- const float randx,
- const float randy)
-{
- const float3 wi_11 = normalize(make_float3(alpha.x * wi.x, alpha.y * wi.y, wi.z));
- const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
-
- const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
- const float slope_x = alpha.x * (cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
- const float slope_y = alpha.y * (cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
-
- kernel_assert(isfinite(slope_x));
- return normalize(make_float3(-slope_x, -slope_y, 1.0f));
-}
-
-/* === Phase functions: Glossy and Glass === */
-
-/* Phase function for reflective materials. */
-ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi,
- ccl_private Spectrum *weight,
- const float3 wm)
-{
- return -wi + 2.0f * wm * dot(wi, wm);
-}
-
-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 zero_spectrum();
-
- const float3 wh = normalize(wo - w);
- if (wh.z < 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 zero_spectrum();
-
- float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
- if (alpha.x == alpha.y)
- phase *= D_ggx(wh, alpha.x);
- else
- phase *= D_ggx_aniso(wh, alpha);
-
- return make_spectrum(phase);
-}
-
-/* Phase function for dielectric transmissive materials, including both reflection and refraction
- * according to the dielectric fresnel term. */
-ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi,
- const float eta,
- const float3 wm,
- const float randV,
- ccl_private bool *outside)
-{
- float cosI = dot(wi, wm);
- float f = fresnel_dielectric_cos(cosI, eta);
- if (randV < f) {
- *outside = true;
- return -wi + 2.0f * wm * cosI;
- }
- *outside = false;
- float inv_eta = 1.0f / eta;
- float cosT = -safe_sqrtf(1.0f - (1.0f - cosI * cosI) * inv_eta * inv_eta);
- return normalize(wm * (cosI * inv_eta + cosT) - wi * inv_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 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 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 /
- (pArea * dotW_WH);
- }
- else {
- float3 wh = normalize(wo * eta - w);
- if (wh.z < 0.0f)
- wh = -wh;
- const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
- if (dotW_WH < 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_spectrum(v);
-}
-
-/* === Utility functions for the random walks === */
-
-/* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
-ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha)
-{
- if (w.z > 0.9999f)
- return 0.0f;
- else if (w.z < -0.9999f)
- return -0.9999f;
-
- const float inv_wz2 = 1.0f / max(w.z * w.z, 1e-7f);
- const float2 wa = make_float2(w.x, w.y) * alpha;
- float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
- if (w.z <= 0.0f)
- v = -v;
-
- return 0.5f * (v - 1.0f);
-}
-
-/* Height distribution CDF (based on page 4 of the supplemental implementation). */
-ccl_device_forceinline float mf_invC1(const float h)
-{
- return 2.0f * saturatef(h) - 1.0f;
-}
-
-ccl_device_forceinline float mf_C1(const float h)
-{
- return saturatef(0.5f * (h + 1.0f));
-}
-
-/* Masking function (based on page 16 of the supplemental implementation). */
-ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
-{
- if (w.z > 0.9999f)
- return 1.0f;
- if (w.z < 1e-5f)
- return 0.0f;
- return powf(C1, lambda);
-}
-
-/* Sampling from the visible height distribution (based on page 17 of the supplemental
- * implementation). */
-ccl_device_forceinline bool mf_sample_height(const float3 w,
- ccl_private float *h,
- ccl_private float *C1,
- ccl_private float *G1,
- ccl_private float *lambda,
- const float U)
-{
- if (w.z > 0.9999f)
- return false;
- if (w.z < -0.9999f) {
- *C1 *= U;
- *h = mf_invC1(*C1);
- *G1 = mf_G1(w, *C1, *lambda);
- }
- else if (fabsf(w.z) >= 0.0001f) {
- if (U > 1.0f - *G1)
- return false;
- if (*lambda >= 0.0f) {
- *C1 = 1.0f;
- }
- else {
- *C1 *= powf(1.0f - U, -1.0f / *lambda);
- }
- *h = mf_invC1(*C1);
- *G1 = mf_G1(w, *C1, *lambda);
- }
- return true;
-}
-
-/* === PDF approximations for the different phase functions. ===
- * As explained in bsdf_microfacet_multi_impl.h, using approximations with MIS still produces an
- * unbiased result. */
-
-/* Approximation for the albedo of the single-scattering GGX distribution,
- * the missing energy is then approximated as a diffuse reflection for the PDF. */
-ccl_device_forceinline float mf_ggx_albedo(float r)
-{
- float albedo = 0.806495f * expf(-1.98712f * r * r) + 0.199531f;
- albedo -= ((((((1.76741f * r - 8.43891f) * r + 15.784f) * r - 14.398f) * r + 6.45221f) * r -
- 1.19722f) *
- r +
- 0.027803f) *
- r +
- 0.00568739f;
- return saturatef(albedo);
-}
-
-ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior)
-{
- if (ior < 1.0f) {
- ior = 1.0f / ior;
- }
- a = saturatef(a);
- ior = clamp(ior, 1.0f, 3.0f);
- float I_1 = 0.0476898f * expf(-0.978352f * (ior - 0.65657f) * (ior - 0.65657f)) -
- 0.033756f * ior + 0.993261f;
- float R_1 = (((0.116991f * a - 0.270369f) * a + 0.0501366f) * a - 0.00411511f) * a + 1.00008f;
- float I_2 = (((-2.08704f * ior + 26.3298f) * ior - 127.906f) * ior + 292.958f) * ior - 287.946f +
- 199.803f / (ior * ior) - 101.668f / (ior * ior * ior);
- float R_2 = ((((5.3725f * a - 24.9307f) * a + 22.7437f) * a - 3.40751f) * a + 0.0986325f) * a +
- 0.00493504f;
-
- return saturatef(1.0f + I_2 * R_2 * 0.0019127f - (1.0f - I_1) * (1.0f - R_1) * 9.3205f);
-}
-
-ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
-{
- float D = D_ggx(normalize(wi + wo), alpha);
- float lambda = mf_lambda(wi, make_float2(alpha, alpha));
- float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
-
- float multiscatter = wo.z * M_1_PI_F;
-
- float albedo = mf_ggx_albedo(alpha);
- return albedo * singlescatter + (1.0f - albedo) * multiscatter;
-}
-
-ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
-{
- float D = D_ggx_aniso(normalize(wi + wo), alpha);
- float lambda = mf_lambda(wi, alpha);
- float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
-
- float multiscatter = wo.z * M_1_PI_F;
-
- float albedo = mf_ggx_albedo(sqrtf(alpha.x * alpha.y));
- return albedo * singlescatter + (1.0f - albedo) * multiscatter;
-}
-
-ccl_device_forceinline float mf_glass_pdf(const float3 wi,
- const float3 wo,
- const float alpha,
- const float eta)
-{
- bool reflective = (wi.z * wo.z > 0.0f);
-
- float wh_len;
- float3 wh = normalize_len(wi + (reflective ? wo : (wo * eta)), &wh_len);
- if (wh.z < 0.0f)
- wh = -wh;
- float3 r_wi = (wi.z < 0.0f) ? -wi : wi;
- float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
- float D = D_ggx(wh, alpha);
- float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
-
- float multiscatter = fabsf(wo.z * M_1_PI_F);
- if (reflective) {
- float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
- float albedo = mf_ggx_albedo(alpha);
- return fresnel * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
- }
- else {
- float singlescatter = fabsf(dot(r_wi, wh) * dot(wo, wh) * D * eta * eta /
- max((1.0f + lambda) * r_wi.z * wh_len * wh_len, 1e-7f));
- float albedo = mf_ggx_transmission_albedo(alpha, eta);
- return (1.0f - fresnel) * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
- }
-}
-
-/* === Actual random walk implementations === */
-/* One version of mf_eval and mf_sample per phase function. */
-
-#define MF_NAME_JOIN(x, y) x##_##y
-#define MF_NAME_EVAL(x, y) MF_NAME_JOIN(x, y)
-#define MF_FUNCTION_FULL_NAME(prefix) MF_NAME_EVAL(prefix, MF_PHASE_FUNCTION)
-
-#define MF_PHASE_FUNCTION glass
-#define MF_MULTI_GLASS
-#include "kernel/closure/bsdf_microfacet_multi_impl.h"
-
-#define MF_PHASE_FUNCTION glossy
-#define MF_MULTI_GLOSSY
-#include "kernel/closure/bsdf_microfacet_multi_impl.h"
-
-ccl_device void bsdf_microfacet_multi_ggx_blur(ccl_private ShaderClosure *sc, float roughness)
-{
- ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
-
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
-}
-
-/* === Closure implementations === */
-
-/* Multi-scattering GGX Glossy closure */
-
-ccl_device int bsdf_microfacet_multi_ggx_common_setup(ccl_private MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
- bsdf->extra->color = saturate(bsdf->extra->color);
- bsdf->extra->cspec0 = saturate(bsdf->extra->cspec0);
-
- return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
-{
- if (is_zero(bsdf->T))
- bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
-
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsdf,
- ccl_private const ShaderData *sd)
-{
- if (is_zero(bsdf->T))
- bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
-
- bsdf_microfacet_fresnel_color(sd, bsdf);
-
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_y = bsdf->alpha_x;
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
-
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
-}
-
-ccl_device Spectrum bsdf_microfacet_multi_ggx_eval(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 zero_spectrum();
- }
-
- float3 X, Y, Z;
- Z = bsdf->N;
-
- /* 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 zero_spectrum();
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
-
- bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
- if (is_aniso)
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- else
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- if (is_aniso)
- *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
- else
- *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
-
- if (*pdf <= 0.f) {
- *pdf = 0.f;
- return make_float3(0.f, 0.f, 0.f);
- }
-
- return mf_eval_glossy(localI,
- localO,
- true,
- bsdf->extra->color,
- bsdf->alpha_x,
- bsdf->alpha_y,
- lcg_state,
- bsdf->ior,
- use_fresnel,
- bsdf->extra->cspec0);
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
- ccl_private const ShaderClosure *sc,
- float3 Ng,
- float3 I,
- float randu,
- float randv,
- ccl_private Spectrum *eval,
- ccl_private float3 *omega_in,
- ccl_private float *pdf,
- ccl_private uint *lcg_state,
- ccl_private float2 *sampled_roughness,
- ccl_private float *eta)
-{
- ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
-
- float3 X, Y, Z;
- Z = bsdf->N;
-
- /* Ensure that the view direction is on the outside w.r.t. the shading normal. */
- if (dot(Z, I) <= 0.0f) {
- *pdf = 0.0f;
- return LABEL_NONE;
- }
-
- /* Special case: Extremely low roughness.
- * Don't bother with microfacets, just do specular reflection. */
- if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
- *omega_in = 2 * dot(Z, I) * Z - I;
- if (dot(Ng, *omega_in) <= 0.0f) {
- *pdf = 0.0f;
- return LABEL_NONE;
- }
- *pdf = 1e6f;
- *eval = make_spectrum(1e6f);
- return LABEL_REFLECT | LABEL_SINGULAR;
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
-
- *eta = bsdf->ior;
- *sampled_roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
-
- bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
- if (is_aniso)
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- else
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO;
-
- *eval = mf_sample_glossy(localI,
- &localO,
- bsdf->extra->color,
- bsdf->alpha_x,
- bsdf->alpha_y,
- lcg_state,
- bsdf->ior,
- use_fresnel,
- bsdf->extra->cspec0);
- *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
-
- /* Ensure that the light direction is on the outside w.r.t. the geometry normal. */
- if (dot(Ng, *omega_in) <= 0.0f) {
- *pdf = 0.0f;
- return LABEL_NONE;
- }
-
- if (is_aniso)
- *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
- else
- *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
- *pdf = fmaxf(0.f, *pdf);
- *eval *= *pdf;
-
- return LABEL_REFLECT | LABEL_GLOSSY;
-}
-
-/* Multi-scattering GGX Glass closure */
-
-ccl_device int bsdf_microfacet_multi_ggx_glass_setup(ccl_private MicrofacetBsdf *bsdf)
-{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- bsdf->ior = max(0.0f, bsdf->ior);
- bsdf->extra->color = saturate(bsdf->extra->color);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
-
- return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private MicrofacetBsdf *bsdf,
- ccl_private const ShaderData *sd)
-{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- bsdf->ior = max(0.0f, bsdf->ior);
- bsdf->extra->color = saturate(bsdf->extra->color);
- bsdf->extra->cspec0 = saturate(bsdf->extra->cspec0);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
-
- bsdf_microfacet_fresnel_color(sd, bsdf);
-
- return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
-}
-
-ccl_device Spectrum bsdf_microfacet_multi_ggx_glass_eval(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 zero_spectrum();
- }
-
- float3 X, Y, Z;
- Z = bsdf->N;
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- const bool is_transmission = localO.z < 0.0f;
- const bool use_fresnel = !is_transmission &&
- (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
-
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- kernel_assert(*pdf >= 0.f);
- return mf_eval_glass(localI,
- localO,
- !is_transmission,
- bsdf->extra->color,
- bsdf->alpha_x,
- bsdf->alpha_y,
- lcg_state,
- bsdf->ior,
- use_fresnel,
- (is_transmission) ? bsdf->extra->color : bsdf->extra->cspec0);
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
- ccl_private const ShaderClosure *sc,
- float3 Ng,
- float3 I,
- float randu,
- float randv,
- ccl_private Spectrum *eval,
- ccl_private float3 *omega_in,
- ccl_private float *pdf,
- ccl_private uint *lcg_state,
- ccl_private float2 *sampled_roughness,
- ccl_private float *eta)
-{
- ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
-
- float3 X, Y, Z;
- Z = bsdf->N;
-
- *eta = bsdf->ior;
- *sampled_roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
-
- if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
- float3 R, T;
- bool inside;
- float fresnel = fresnel_dielectric(bsdf->ior, Z, I, &R, &T, &inside);
-
- *pdf = 1e6f;
- *eval = make_spectrum(1e6f);
- if (randu < fresnel) {
- *omega_in = R;
- return LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- *omega_in = T;
- return LABEL_TRANSMIT | LABEL_SINGULAR;
- }
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
-
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO;
-
- *eval = mf_sample_glass(localI,
- &localO,
- bsdf->extra->color,
- bsdf->alpha_x,
- bsdf->alpha_y,
- lcg_state,
- bsdf->ior,
- use_fresnel,
- bsdf->extra->cspec0);
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- kernel_assert(*pdf >= 0.f);
- *eval *= *pdf;
-
- *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
- if (localO.z * localI.z > 0.0f) {
- return LABEL_REFLECT | LABEL_GLOSSY;
- }
- else {
- return LABEL_TRANSMIT | LABEL_GLOSSY;
- }
-}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
deleted file mode 100644
index 91fb9158050..00000000000
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/* SPDX-License-Identifier: Apache-2.0
- * Copyright 2011-2022 Blender Foundation */
-
-/* Evaluate the BSDF from wi to wo.
- * Evaluation is split into the analytical single-scattering BSDF and the multi-scattering BSDF,
- * which is evaluated stochastically through a random walk. At each bounce (except for the first
- * one), the amount of reflection from here towards wo is evaluated before bouncing again.
- *
- * Because of the random walk, the evaluation is not deterministic, but its expected value is equal
- * to the correct BSDF, which is enough for Monte-Carlo rendering. The PDF also can't be determined
- * analytically, so the single-scattering PDF plus a diffuse term to account for the
- * 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 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. */
- bool swapped = false;
-#ifdef MF_MULTI_GLASS
- if (wi.z * wo.z < 0.0f) {
- /* Glass transmission is a special case and requires the directions to change hemisphere. */
- if (-wo.z < wi.z) {
- swapped = true;
- float3 tmp = -wo;
- wo = -wi;
- wi = tmp;
- }
- }
- else
-#endif
- if (wo.z < wi.z) {
- swapped = true;
- float3 tmp = wo;
- wo = wi;
- wi = tmp;
- }
-
- if (wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
- return zero_spectrum();
-
- const float2 alpha = make_float2(alpha_x, alpha_y);
-
- float lambda_r = mf_lambda(-wi, alpha);
- float shadowing_lambda = mf_lambda(wo_outside ? wo : -wo, alpha);
-
- /* Analytically compute single scattering for lower noise. */
- 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);
- if (wo_outside)
- eval *= -lambda_r / (shadowing_lambda - lambda_r);
- else
- eval *= -lambda_r * beta(-lambda_r, shadowing_lambda + 1.0f);
-#else /* MF_MULTI_GLOSSY */
- const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
- float val = G2 * 0.25f / wi.z;
- if (alpha.x == alpha.y)
- val *= D_ggx(wh, alpha.x);
- else
- val *= D_ggx_aniso(wh, alpha);
- eval = make_spectrum(val);
-#endif
-
- float F0 = fresnel_dielectric_cos(1.0f, eta);
- if (use_fresnel) {
- throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
-
- eval *= throughput;
- }
-
- float3 wr = -wi;
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
-
- for (int order = 0; order < 10; order++) {
- /* Sample microfacet height. */
- float height_rand = lcg_step_float(lcg_state);
- if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
- break;
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float(lcg_state);
- float vndf_rand_x = lcg_step_float(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
-
-#ifdef MF_MULTI_GLASS
- if (order == 0 && use_fresnel) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- Spectrum phase;
- if (outside)
- phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
- else
- phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
-
- eval = throughput * phase *
- mf_G1(wo_outside ? wo : -wo,
- mf_C1((outside == wo_outside) ? hr : -hr),
- shadowing_lambda);
- }
-#endif
- if (order > 0) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- Spectrum phase;
-#ifdef MF_MULTI_GLASS
- if (outside)
- phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
- else
- phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
-#else /* MF_MULTI_GLOSSY */
- phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
-#endif
- eval += throughput * phase *
- mf_G1(wo_outside ? wo : -wo,
- mf_C1((outside == wo_outside) ? hr : -hr),
- shadowing_lambda);
- }
- if (order + 1 < 10) {
- /* Bounce from the microfacet. */
-#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
- if (!next_outside) {
- outside = !outside;
- wr = -wr;
- hr = -hr;
- }
-
- if (use_fresnel && !next_outside) {
- throughput *= color;
- }
- else if (use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
- }
-#else /* MF_MULTI_GLOSSY */
- if (use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
-#endif
-
- lambda_r = mf_lambda(wr, alpha);
-
- if (!use_fresnel)
- throughput *= color;
-
- C1_r = mf_C1(hr);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- }
-
- if (swapped)
- eval *= fabsf(wi.z / wo.z);
- return eval;
-}
-
-/* Perform a random walk on the microsurface starting from wi, returning the direction in which the
- * 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 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);
-
- Spectrum throughput = one_spectrum();
- float3 wr = -wi;
- float lambda_r = mf_lambda(wr, alpha);
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
-
- float F0 = fresnel_dielectric_cos(1.0f, eta);
-
- int order;
- for (order = 0; order < 10; order++) {
- /* Sample microfacet height. */
- float height_rand = lcg_step_float(lcg_state);
- if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
- /* The random walk has left the surface. */
- *wo = outside ? wr : -wr;
- return throughput;
- }
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float(lcg_state);
- float vndf_rand_x = lcg_step_float(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
-
- /* First-bounce color is already accounted for in mix weight. */
- if (!use_fresnel && order > 0)
- throughput *= color;
-
- /* Bounce from the microfacet. */
-#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
- if (!next_outside) {
- hr = -hr;
- wr = -wr;
- outside = !outside;
- }
-
- if (use_fresnel) {
- if (!next_outside) {
- throughput *= color;
- }
- else {
- Spectrum t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
-
- if (order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- }
-#else /* MF_MULTI_GLOSSY */
- if (use_fresnel) {
- Spectrum t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
-
- if (order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
-#endif
-
- /* Update random walk parameters. */
- lambda_r = mf_lambda(wr, alpha);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- *wo = make_float3(0.0f, 0.0f, 1.0f);
- return zero_spectrum();
-}
-
-#undef MF_MULTI_GLASS
-#undef MF_MULTI_GLOSSY
-#undef MF_PHASE_FUNCTION
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_util.h b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
new file mode 100644
index 00000000000..b531c192e03
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_util.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#pragma once
+
+#include "kernel/closure/bsdf_util.h"
+
+#include "kernel/util/lookup_table.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* GGX microfacet with Smith shadow-masking from:
+ *
+ * Microfacet Models for Refraction through Rough Surfaces
+ * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007
+ *
+ * VNDF sampling as well as D and lambda terms from:
+ *
+ * Sampling the GGX Distribution of Visible Normals.
+ * E. Heitz and E. d'Eon, JCGT Vol. 7, No. 4, 2018.
+ * https://jcgt.org/published/0007/04/01/
+ *
+ * Also see for more details on marking-shadowing:
+ * Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs.
+ * E. Heitz, JCGT Vol. 3, No. 2, 2014.
+ * https://jcgt.org/published/0003/02/03/ */
+
+ccl_device_forceinline float microfacet_ggx_lambda(const float cosTheta, const float alpha2)
+{
+ float tanTheta2 = (1 - sqr(cosTheta)) / sqr(cosTheta);
+ return 0.5f * (safe_sqrtf(1 + alpha2 * tanTheta2) - 1);
+}
+
+ccl_device_forceinline float microfacet_ggx_lambda_aniso(const float3 w,
+ const float alpha_x,
+ const float alpha_y)
+{
+ return 0.5f * (safe_sqrtf(1 + (sqr(w.x * alpha_x) + sqr(w.y * alpha_y)) / sqr(w.z)) - 1);
+}
+
+ccl_device_forceinline float microfacet_ggx_D(const float cosThetaM, const float alpha2)
+{
+ float cosThetaM2 = sqr(cosThetaM);
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ return alpha2 / (M_PI_F * sqr(cosThetaM2 * (alpha2 + tanThetaM2)));
+}
+
+ccl_device_forceinline float microfacet_ggx_D_aniso(const float3 m,
+ const float alpha_x,
+ const float alpha_y)
+{
+ return 1 /
+ (M_PI_F * alpha_x * alpha_y * sqr(sqr(m.x / alpha_x) + sqr(m.y / alpha_y) + sqr(m.z)));
+}
+
+ccl_device_forceinline float microfacet_GTR1_D(const float cosThetaM, const float alpha2)
+{
+ if (alpha2 >= 1.0f)
+ return M_1_PI_F;
+ float t = 1.0f + (alpha2 - 1.0f) * sqr(cosThetaM);
+ return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
+}
+
+ccl_device_forceinline float3 microfacet_ggx_sample_vndf(
+ const float3 V, const float alpha_x, const float alpha_y, const float U1, const float U2)
+{
+ /* Section 3.2: Transforming the view direction to the hemisphere configuration. */
+ float3 Vh = normalize(make_float3(alpha_x * V.x, alpha_y * V.y, V.z));
+ /* Section 4.1: Orthonormal basis (with special case if cross product is zero). */
+ float lensq = sqr(Vh.x) + sqr(Vh.y);
+ float3 T1 = lensq > 1e-7f ? make_float3(-Vh.y, Vh.x, 0.0f) / sqrtf(lensq) :
+ make_float3(1.0f, 0.0f, 0.0f);
+ float3 T2 = cross(Vh, T1);
+ /* Section 4.2: Parameterization of the projected area. */
+ float2 t = concentric_sample_disk(U1, U2);
+ t.y = mix(safe_sqrtf(1.0f - sqr(t.x)), t.y, 0.5f * (1.0f + Vh.z));
+ /* Section 4.3: Reprojection onto hemisphere. */
+ float3 Mh = t.x * T1 + t.y * T2 + safe_sqrtf(1.0f - len_squared(t)) * Vh;
+ /* Section 3.4: Transforming the normal back to the ellipsoid configuration. */
+ return normalize(make_float3(alpha_x * Mh.x, alpha_y * Mh.y, max(0.0f, Mh.z)));
+}
+
+/* Albedo correction. */
+
+ccl_device_forceinline float microfacet_ggx_glass_E(KernelGlobals kg,
+ float mu,
+ float rough,
+ float ior)
+{
+ bool inv_table = (ior < 1.0f);
+ int offset = inv_table ? kernel_data.tables.ggx_glass_inv_E_offset :
+ kernel_data.tables.ggx_glass_E_offset;
+
+ float x = mu, y = 1 - rough;
+ float z = sqrtf(0.5f * ((inv_table ? 1.0f / ior : ior) - 1.0f));
+ return lookup_table_read_3D(kg, x, y, z, offset, 16, 16, 16);
+}
+
+ccl_device_forceinline float microfacet_ggx_dielectric_E(KernelGlobals kg,
+ float mu,
+ float rough,
+ float ior)
+{
+ bool inv_table = (ior < 1.0f);
+ int offset = inv_table ? kernel_data.tables.ggx_dielectric_inv_E_offset :
+ kernel_data.tables.ggx_dielectric_E_offset;
+
+ float macro_fresnel = fresnel_dielectric_cos(mu, ior);
+ float F0 = fresnel_dielectric_cos(1.0f, ior);
+ float x = mix(mu, inverse_lerp(1.0f, F0, macro_fresnel), 0.5f);
+ float y = 1 - rough;
+ float z = sqrtf(0.5f * ((inv_table ? 1.0f / ior : ior) - 1.0f));
+
+ return lookup_table_read_3D(kg, x, y, z, offset, 16, 16, 16);
+}
+
+ccl_device_forceinline float microfacet_ggx_E(KernelGlobals kg, float mu, float rough)
+{
+ return lookup_table_read_2D(kg, mu, 1 - rough, kernel_data.tables.ggx_E_offset, 32, 32);
+}
+
+ccl_device_forceinline float microfacet_ggx_E_avg(KernelGlobals kg, float rough)
+{
+ return lookup_table_read(kg, 1 - rough, kernel_data.tables.ggx_E_avg_offset, 32);
+}
+
+ccl_device_forceinline float clearcoat_E(KernelGlobals kg, float mu, float rough)
+{
+ float x = mu, y = 1 - rough;
+ float table = lookup_table_read_2D(kg, x, y, kernel_data.tables.ggx_clearcoat_E_offset, 16, 16);
+ return table * fresnel_dielectric_cos(mu, 1.5f);
+}
+
+ccl_device_inline Spectrum fresnel_metallic_Fss(Spectrum F0, Spectrum B)
+{
+ return saturate(mix(F0, one_spectrum(), 1.0f / 21.0f) - B * (1.0f / 126.0f));
+}
+
+ccl_device_inline Spectrum schlick_fresnel_Fss(Spectrum F0)
+{
+ return saturate(mix(F0, one_spectrum(), 1.0f / 21.0f));
+}
+
+/* TODO Imageworks source */
+ccl_device_inline float dielectric_fresnel_Fss(float eta)
+{
+ /* TODO validate using multiGGX code */
+ float f;
+ if (eta < 1.0f) {
+ f = 0.997118f + eta * (0.1014f - eta * (0.965241f + eta * 0.130607f));
+ }
+ else {
+ f = (eta - 1.0f) / (4.08567f + 1.00071f * eta);
+ }
+ return f;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
index f6499cc437c..949a6f8f567 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
@@ -15,6 +15,7 @@ CCL_NAMESPACE_BEGIN
typedef struct PrincipledSheenBsdf {
SHADER_CLOSURE_BASE;
float avg_value;
+ float roughness;
} PrincipledSheenBsdf;
static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledSheenBsdf),
@@ -50,6 +51,64 @@ calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_priv
return make_spectrum(value);
}
+/* Based on
+ * https://dassaultsystemes-technology.github.io/EnterprisePBRShadingModel/spec-2022x.md.html#components/sheen.
+ */
+ccl_device_inline float sheen_v2_lambda(float mu, float w)
+{
+ float a = mix(11.9095f, 13.7000f, w);
+ float b = mix(4.68753f, 2.92754f, w);
+ float c = mix(0.33467f, 0.28670f, w);
+ float d = mix(-2.22664f, -0.81757f, w);
+ float e = mix(-1.76591f, -1.22466f, w);
+
+ float exponent;
+ if (mu < 0.5f) {
+ exponent = a / (1 + b * powf(mu, c)) + d * mu + e;
+ }
+ else {
+ exponent = 2 * a / (1 + b * exp2(-c)) - a / (1 + b * powf(1 - mu, c)) + d * mu + e;
+ }
+ return expf(exponent);
+}
+
+ccl_device_inline Spectrum
+sheen_v2_eval(float3 N, float3 V, float3 L, float3 H, float r, float *pdf)
+{
+ float cosNH = dot(N, H), cosNV = dot(N, V), cosNL = dot(N, L);
+
+ if (cosNH < 0 || cosNV < 0 || cosNL < 0) {
+ *pdf = 0.0f;
+ return zero_float3();
+ }
+
+ /* Evaluate microfacet distribution. */
+ float sinTheta2 = 1 - sqr(cosNH);
+ float invR = 1 / r;
+ float D = M_1_2PI_F * (2 + invR) * powf(sinTheta2, 0.5f * invR);
+
+ /* Evaluate shadowing-masking terms. */
+ float w = -1.59612f / (1 + 0.20375f * fast_safe_powf(r, -0.55825f)) + 1.32805f;
+ float lambdaV = sheen_v2_lambda(cosNV, w);
+ float lambdaL = sheen_v2_lambda(cosNL, w);
+
+ /* Soften shadow terminator. */
+ lambdaL = fast_safe_powf(lambdaL, 1 + 2 * sqr(sqr(sqr(1 - cosNL))));
+
+ /* Combined microfacet BSDF.
+ * Usual form is F*D*G/(4*cosNL*cosNV), but here we have no Fresnel, we skip dividing by cosNL
+ * since Cycles convention is returning BSDF*cosNL, and we use the combined shadowing-masking
+ * term G=1/(1+lambdaV+lambdaL).
+ */
+ float val = D / (4 * cosNV * (1 + lambdaV + lambdaL));
+ return make_spectrum(val);
+}
+
+ccl_device_forceinline float sheen_v2_E(KernelGlobals kg, float mu, float rough)
+{
+ return lookup_table_read_2D(kg, mu, 1 - sqrtf(rough), kernel_data.tables.sheen_E_offset, 32, 32);
+}
+
ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
ccl_private PrincipledSheenBsdf *bsdf)
{
@@ -59,6 +118,21 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
return SD_BSDF | SD_BSDF_HAS_EVAL;
}
+ccl_device int bsdf_principled_sheen_v2_setup(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private PrincipledSheenBsdf *bsdf)
+{
+ // TODO: Also expose as separate node. Add enum to Velvet BSDF maybe?
+ bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID;
+
+ bsdf->roughness = clamp(bsdf->roughness, 1e-3f, 1.0f);
+
+ bsdf->avg_value = sheen_v2_E(kg, dot(bsdf->N, sd->I), bsdf->roughness);
+ bsdf->sample_weight *= bsdf->avg_value;
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
+}
+
ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *sc,
const float3 I,
const float3 omega_in,
@@ -72,8 +146,13 @@ ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *
const float3 L = omega_in; // incoming
const float3 H = normalize(L + V);
- *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- return calculate_principled_sheen_brdf(N, V, L, H, pdf);
+ *pdf = M_1_2PI_F;
+ if (bsdf->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID) {
+ return sheen_v2_eval(N, V, L, H, bsdf->roughness, pdf);
+ }
+ else {
+ return calculate_principled_sheen_brdf(N, V, L, H, pdf);
+ }
}
else {
*pdf = 0.0f;
@@ -94,12 +173,17 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
float3 N = bsdf->N;
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+ sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
if (dot(Ng, *omega_in) > 0) {
float3 H = normalize(I + *omega_in);
- *eval = calculate_principled_sheen_brdf(N, I, *omega_in, H, pdf);
+ if (bsdf->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID) {
+ *eval = sheen_v2_eval(N, I, *omega_in, H, bsdf->roughness, pdf);
+ }
+ else {
+ *eval = calculate_principled_sheen_brdf(N, I, *omega_in, H, pdf);
+ }
}
else {
*eval = zero_spectrum();
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index 3c48b98fed9..13de4ac15b0 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -71,14 +71,14 @@ ccl_device float fresnel_dielectric_cos(float cosi, float eta)
return 1.0f; // TIR(no refracted component)
}
-ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k)
+ccl_device Spectrum fresnel_conductor(float cosi, const Spectrum eta, const Spectrum k)
{
- float3 cosi2 = make_float3(cosi * cosi, cosi * cosi, cosi * cosi);
- float3 one = make_float3(1.0f, 1.0f, 1.0f);
- float3 tmp_f = eta * eta + k * k;
- float3 tmp = tmp_f * cosi2;
- float3 Rparl2 = (tmp - (2.0f * eta * cosi) + one) / (tmp + (2.0f * eta * cosi) + one);
- float3 Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) / (tmp_f + (2.0f * eta * cosi) + cosi2);
+ Spectrum cosi2 = make_spectrum(sqr(cosi));
+ Spectrum one = make_spectrum(1.0f);
+ Spectrum tmp_f = eta * eta + k * k;
+ Spectrum tmp = tmp_f * cosi2;
+ Spectrum Rparl2 = (tmp - (2.0f * eta * cosi) + one) / (tmp + (2.0f * eta * cosi) + one);
+ Spectrum Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) / (tmp_f + (2.0f * eta * cosi) + cosi2);
return (Rparl2 + Rperp2) * 0.5f;
}
@@ -89,19 +89,46 @@ ccl_device float schlick_fresnel(float u)
return m2 * m2 * m; // pow(m, 5)
}
-/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
-ccl_device_forceinline Spectrum
-interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, Spectrum cspec0)
+/* Metallic Fresnel term with edge color control.
+ * Based on Schlick Fresnel, but with an optional F82 input that adds the dip at
+ * near-grazing angles that is characteristic for conductors.
+ *
+ * Source:
+ * https://substance3d.adobe.com/documentation/s3d/files/225969599/225969601/1/1647019577092/Adobe+Standard+Material+-+Technical+Documentation.pdf
+ */
+ccl_device Spectrum metallic_edge_factor(Spectrum F0, Spectrum F82)
{
- /* Calculate the fresnel interpolation factor
- * The value from fresnel_dielectric_cos(...) has to be normalized because
- * the cspec0 keeps the F0 color
+ if (F82 == one_spectrum()) {
+ return zero_spectrum();
+ }
+
+ /* Precompute the B factor of the F82 model, which scales an additional term around cosI == 1/7.
*/
- float F0_norm = 1.0f / (1.0f - F0);
- float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
+ const float f = 6.0f / 7.0f; /* 1 - cosI_max */
+ const float f5 = sqr(sqr(f)) * f;
+ return (7.0f / (f5 * f)) * mix(F0, one_spectrum(), f5) * (one_spectrum() - F82);
+}
+
+ccl_device Spectrum fresnel_metallic(Spectrum F0, Spectrum B, float cosi)
+{
+ float s = saturatef(1.0f - cosi);
+ float s5 = sqr(sqr(s)) * s;
+ return saturate(mix(F0, one_spectrum(), s5) - B * cosi * s5 * s);
+}
+
+/* Calculate the fresnel color which is a blend between white and the F0 color */
+ccl_device_forceinline Spectrum interpolate_fresnel_color(Spectrum L,
+ Spectrum H,
+ float ior,
+ Spectrum F0)
+{
+ /* Compute the real Fresnel term and remap it from real_F0...1 to F0...1.
+ * We could also just use actual Schlick fresnel (mix(F0, 1, (1-cosI)^5)) here. */
+ float real_F0 = fresnel_dielectric_cos(1.0f, ior);
+ float F0_norm = 1.0f / (1.0f - real_F0);
+ float FH = (fresnel_dielectric_cos(dot(L, H), ior) - real_F0) * F0_norm;
- /* Blend between white and a specular color with respect to the fresnel */
- return cspec0 * (1.0f - FH) + make_spectrum(FH);
+ return mix(F0, one_spectrum(), FH);
}
ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N)
diff --git a/intern/cycles/kernel/film/denoising_passes.h b/intern/cycles/kernel/film/denoising_passes.h
index dfc21d787f2..11672235b06 100644
--- a/intern/cycles/kernel/film/denoising_passes.h
+++ b/intern/cycles/kernel/film/denoising_passes.h
@@ -60,7 +60,7 @@ ccl_device_forceinline void film_write_denoising_features_surface(KernelGlobals
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
closure_albedo *= bsdf->extra->fresnel_color;
}
- else if (sc->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID) {
+ else if (CLOSURE_IS_BSDF_SHEEN(sc->type)) {
ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)sc;
closure_albedo *= bsdf->avg_value;
}
diff --git a/intern/cycles/kernel/film/passes.h b/intern/cycles/kernel/film/passes.h
new file mode 100644
index 00000000000..d6562a32cc4
--- /dev/null
+++ b/intern/cycles/kernel/film/passes.h
@@ -0,0 +1,302 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#pragma once
+
+#include "kernel/geom/geom.h"
+
+#include "kernel/film/id_passes.h"
+#include "kernel/film/write_passes.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Get pointer to pixel in render buffer. */
+ccl_device_forceinline ccl_global float *kernel_pass_pixel_render_buffer(
+ KernelGlobals kg, ConstIntegratorState state, ccl_global float *ccl_restrict render_buffer)
+{
+ const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
+ const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
+ kernel_data.film.pass_stride;
+ return render_buffer + render_buffer_offset;
+}
+
+#ifdef __DENOISING_FEATURES__
+
+ccl_device_forceinline void kernel_write_denoising_features_surface(
+ KernelGlobals kg,
+ IntegratorState state,
+ ccl_private const ShaderData *sd,
+ ccl_global float *ccl_restrict render_buffer)
+{
+ if (!(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_DENOISING_FEATURES)) {
+ return;
+ }
+
+ /* Skip implicitly transparent surfaces. */
+ if (sd->flag & SD_HAS_ONLY_VOLUME) {
+ return;
+ }
+
+ 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(
+ state, path, denoising_feature_throughput);
+ const float denoising_depth = ensure_finite(average(denoising_feature_throughput) *
+ sd->ray_length);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_denoising_depth, denoising_depth);
+ }
+
+ float3 normal = zero_float3();
+ float3 diffuse_albedo = zero_float3();
+ float3 specular_albedo = zero_float3();
+ float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f;
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ ccl_private const ShaderClosure *sc = &sd->closure[i];
+
+ if (!CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ continue;
+ }
+
+ /* All closures contribute to the normal feature, but only diffuse-like ones to the albedo. */
+ normal += sc->N * sc->sample_weight;
+ sum_weight += sc->sample_weight;
+
+ float3 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
+ * done for the sample weight in the BSDF setup, so we don't need to scale that here). */
+ if (CLOSURE_IS_BSDF_MICROFACET_FRESNEL(sc->type)) {
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)sc;
+ closure_albedo *= bsdf->extra->fresnel_color;
+ }
+ else if (CLOSURE_IS_BSDF_SHEEN(sc->type)) {
+ ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)sc;
+ closure_albedo *= bsdf->avg_value;
+ }
+ else if (sc->type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
+ closure_albedo *= bsdf_principled_hair_albedo(sc);
+ }
+ else if (sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
+ /* BSSRDF already accounts for weight, retro-reflection would double up. */
+ ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)
+ sc;
+ if (bsdf->components == PRINCIPLED_DIFFUSE_RETRO_REFLECTION) {
+ continue;
+ }
+ }
+
+ if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) {
+ diffuse_albedo += closure_albedo;
+ sum_nonspecular_weight += sc->sample_weight;
+ }
+ else {
+ specular_albedo += closure_albedo;
+ }
+ }
+
+ /* Wait for next bounce if 75% or more sample weight belongs to specular-like closures. */
+ if ((sum_weight == 0.0f) || (sum_nonspecular_weight * 4.0f > sum_weight)) {
+ if (sum_weight != 0.0f) {
+ normal /= sum_weight;
+ }
+
+ if (kernel_data.film.pass_denoising_normal != PASS_UNUSED) {
+ /* Transform normal into camera space. */
+ const Transform worldtocamera = kernel_data.cam.worldtocamera;
+ normal = transform_direction(&worldtocamera, normal);
+
+ const float3 denoising_normal = ensure_finite(normal);
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_normal, denoising_normal);
+ }
+
+ if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) {
+ const float3 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);
+ }
+
+ INTEGRATOR_STATE_WRITE(state, path, flag) &= ~PATH_RAY_DENOISING_FEATURES;
+ }
+ else {
+ INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) *= specular_albedo;
+ }
+}
+
+ccl_device_forceinline void kernel_write_denoising_features_volume(KernelGlobals kg,
+ IntegratorState state,
+ const float3 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(
+ state, path, denoising_feature_throughput);
+
+ if (scatter && kernel_data.film.pass_denoising_normal != PASS_UNUSED) {
+ /* Assume scatter is sufficiently diffuse to stop writing denoising features. */
+ INTEGRATOR_STATE_WRITE(state, path, flag) &= ~PATH_RAY_DENOISING_FEATURES;
+
+ /* Write view direction as normal. */
+ const float3 denoising_normal = make_float3(0.0f, 0.0f, -1.0f);
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_normal, denoising_normal);
+ }
+
+ 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);
+ }
+}
+#endif /* __DENOISING_FEATURES__ */
+
+ccl_device_inline size_t kernel_write_id_pass(ccl_global float *ccl_restrict buffer,
+ size_t depth,
+ float id,
+ float matte_weight)
+{
+ kernel_write_id_slots(buffer, depth * 2, id, matte_weight);
+ return depth * 4;
+}
+
+ccl_device_inline void kernel_write_data_passes(KernelGlobals kg,
+ IntegratorState state,
+ ccl_private const ShaderData *sd,
+ ccl_global float *ccl_restrict render_buffer)
+{
+#ifdef __PASSES__
+ const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
+
+ if (!(path_flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
+ return;
+ }
+
+ const int flag = kernel_data.film.pass_flag;
+
+ if (!(flag & PASS_ANY)) {
+ return;
+ }
+
+ ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer);
+
+ if (!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
+ if (!(sd->flag & SD_TRANSPARENT) || kernel_data.film.pass_alpha_threshold == 0.0f ||
+ average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) {
+ if (INTEGRATOR_STATE(state, path, sample) == 0) {
+ if (flag & PASSMASK(DEPTH)) {
+ const float depth = camera_z_depth(kg, sd->P);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth);
+ }
+ if (flag & PASSMASK(OBJECT_ID)) {
+ const float id = object_pass_id(kg, sd->object);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, id);
+ }
+ if (flag & PASSMASK(MATERIAL_ID)) {
+ const float id = shader_pass_id(kg, sd);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, id);
+ }
+ if (flag & PASSMASK(POSITION)) {
+ const float3 position = sd->P;
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_position, position);
+ }
+ }
+
+ if (flag & PASSMASK(NORMAL)) {
+ const float3 normal = shader_bsdf_average_normal(kg, sd);
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, normal);
+ }
+ if (flag & PASSMASK(ROUGHNESS)) {
+ const float roughness = shader_bsdf_average_roughness(sd);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_roughness, roughness);
+ }
+ if (flag & PASSMASK(UV)) {
+ const float3 uv = primitive_uv(kg, sd);
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, uv);
+ }
+ if (flag & PASSMASK(MOTION)) {
+ const float4 speed = primitive_motion_vector(kg, sd);
+ kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, speed);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, 1.0f);
+ }
+
+ INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SINGLE_PASS_DONE;
+ }
+ }
+
+ if (kernel_data.film.cryptomatte_passes) {
+ const float3 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) {
+ ccl_global float *cryptomatte_buffer = buffer + kernel_data.film.pass_cryptomatte;
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ const float id = object_cryptomatte_id(kg, sd->object);
+ cryptomatte_buffer += kernel_write_id_pass(
+ cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ const float id = shader_cryptomatte_id(kg, sd->shader);
+ cryptomatte_buffer += kernel_write_id_pass(
+ cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ const float id = object_cryptomatte_asset_id(kg, sd->object);
+ cryptomatte_buffer += kernel_write_id_pass(
+ cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight);
+ }
+ }
+ }
+
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ if (flag & PASSMASK(MIST)) {
+ /* Bring depth into 0..1 range. */
+ const float mist_start = kernel_data.film.mist_start;
+ const float mist_inv_depth = kernel_data.film.mist_inv_depth;
+
+ const float depth = camera_distance(kg, sd->P);
+ float mist = saturatef((depth - mist_start) * mist_inv_depth);
+
+ /* Falloff */
+ const float mist_falloff = kernel_data.film.mist_falloff;
+
+ if (mist_falloff == 1.0f)
+ ;
+ else if (mist_falloff == 2.0f)
+ mist = mist * mist;
+ else if (mist_falloff == 0.5f)
+ mist = sqrtf(mist);
+ else
+ 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 float mist_output = (1.0f - mist) * average(throughput * alpha);
+
+ /* Note that the final value in the render buffer we want is 1 - mist_output,
+ * to avoid having to tracking this in the Integrator state we do the negation
+ * after rendering. */
+ kernel_write_pass_float(buffer + kernel_data.film.pass_mist, mist_output);
+ }
+#endif
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h
index 23885306885..142977f1ac7 100644
--- a/intern/cycles/kernel/integrator/mnee.h
+++ b/intern/cycles/kernel/integrator/mnee.h
@@ -658,6 +658,7 @@ ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderCl
float cosThetaM = dot(bsdf->N, Ht);
float G;
+ /* TODO: Use bsdf_microfacet_util.h */
if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
/* Eq. 26, 27: now calculate G1(i,m) and G1(o,m). */
G = bsdf_beckmann_G1(bsdf->alpha_x, cosNO) * bsdf_beckmann_G1(bsdf->alpha_x, cosNI);
diff --git a/intern/cycles/kernel/osl/closures_setup.h b/intern/cycles/kernel/osl/closures_setup.h
index 96c551b9951..23f62ec2f3d 100644
--- a/intern/cycles/kernel/osl/closures_setup.h
+++ b/intern/cycles/kernel/osl/closures_setup.h
@@ -14,7 +14,8 @@
#include "kernel/closure/bsdf_ashikhmin_velvet.h"
#include "kernel/closure/bsdf_diffuse.h"
#include "kernel/closure/bsdf_microfacet.h"
-#include "kernel/closure/bsdf_microfacet_multi.h"
+#include "kernel/closure/bsdf_microfacet_beckmann.h"
+#include "kernel/closure/bsdf_microfacet_glass.h"
#include "kernel/closure/bsdf_oren_nayar.h"
#include "kernel/closure/bsdf_reflection.h"
#include "kernel/closure/bsdf_refraction.h"
@@ -216,14 +217,7 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
/* GGX */
if (closure->distribution == u_ggx || closure->distribution == u_default) {
if (!closure->refract) {
- if (closure->alpha_x == closure->alpha_y) {
- /* Isotropic */
- sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf);
- }
- else {
- /* Anisotropic */
- sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
- }
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
}
else {
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
@@ -232,14 +226,7 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
/* Beckmann */
else {
if (!closure->refract) {
- if (closure->alpha_x == closure->alpha_y) {
- /* Isotropic */
- sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf);
- }
- else {
- /* Anisotropic */
- sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
- }
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
else {
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
@@ -267,7 +254,7 @@ ccl_device void osl_closure_microfacet_ggx_setup(
bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
bsdf->alpha_x = closure->alpha_x;
- sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
}
ccl_device void osl_closure_microfacet_ggx_aniso_setup(
@@ -352,7 +339,6 @@ ccl_device void osl_closure_microfacet_ggx_fresnel_setup(
bsdf->extra = extra;
bsdf->extra->color = rgb_to_spectrum(closure->color);
bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
- bsdf->extra->clearcoat = 0.0f;
bsdf->T = zero_float3();
@@ -390,7 +376,6 @@ ccl_device void osl_closure_microfacet_ggx_aniso_fresnel_setup(
bsdf->extra = extra;
bsdf->extra->color = rgb_to_spectrum(closure->color);
bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
- bsdf->extra->clearcoat = 0.0f;
bsdf->T = closure->T;
@@ -419,25 +404,14 @@ ccl_device void osl_closure_microfacet_multi_ggx_setup(
return;
}
- ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
- sd, sizeof(MicrofacetExtra));
- if (!extra) {
- return;
- }
-
bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = bsdf->alpha_x;
bsdf->ior = 1.0f;
- bsdf->extra = extra;
- bsdf->extra->color = rgb_to_spectrum(closure->color);
- bsdf->extra->cspec0 = zero_spectrum();
- bsdf->extra->clearcoat = 0.0f;
-
bsdf->T = zero_float3();
- sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(kg, bsdf, sd, rgb_to_spectrum(closure->color));
}
ccl_device void osl_closure_microfacet_multi_ggx_glass_setup(
@@ -460,25 +434,14 @@ ccl_device void osl_closure_microfacet_multi_ggx_glass_setup(
return;
}
- ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
- sd, sizeof(MicrofacetExtra));
- if (!extra) {
- return;
- }
-
bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = bsdf->alpha_x;
bsdf->ior = closure->ior;
- bsdf->extra = extra;
- bsdf->extra->color = rgb_to_spectrum(closure->color);
- bsdf->extra->cspec0 = zero_spectrum();
- bsdf->extra->clearcoat = 0.0f;
-
bsdf->T = zero_float3();
- sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(kg, bsdf, sd, rgb_to_spectrum(closure->color));
}
ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup(
@@ -512,14 +475,9 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup(
bsdf->alpha_y = closure->alpha_y;
bsdf->ior = 1.0f;
- bsdf->extra = extra;
- bsdf->extra->color = rgb_to_spectrum(closure->color);
- bsdf->extra->cspec0 = zero_spectrum();
- bsdf->extra->clearcoat = 0.0f;
-
bsdf->T = closure->T;
- sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(kg, bsdf, sd, rgb_to_spectrum(closure->color));
}
/* Multi-scattering GGX closures with Fresnel */
@@ -558,11 +516,10 @@ ccl_device void osl_closure_microfacet_multi_ggx_fresnel_setup(
bsdf->extra = extra;
bsdf->extra->color = rgb_to_spectrum(closure->color);
bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
- bsdf->extra->clearcoat = 0.0f;
bsdf->T = zero_float3();
- sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(kg, bsdf, sd);
}
ccl_device void osl_closure_microfacet_multi_ggx_glass_fresnel_setup(
@@ -599,11 +556,10 @@ ccl_device void osl_closure_microfacet_multi_ggx_glass_fresnel_setup(
bsdf->extra = extra;
bsdf->extra->color = rgb_to_spectrum(closure->color);
bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
- bsdf->extra->clearcoat = 0.0f;
bsdf->T = zero_float3();
- sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(kg, bsdf, sd);
}
ccl_device void osl_closure_microfacet_multi_ggx_aniso_fresnel_setup(
@@ -640,11 +596,10 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_fresnel_setup(
bsdf->extra = extra;
bsdf->extra->color = rgb_to_spectrum(closure->color);
bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0);
- bsdf->extra->clearcoat = 0.0f;
bsdf->T = closure->T;
- sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(kg, bsdf, sd);
}
/* Beckmann closures */
@@ -669,7 +624,7 @@ ccl_device void osl_closure_microfacet_beckmann_setup(
bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
bsdf->alpha_x = closure->alpha_x;
- sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf);
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
ccl_device void osl_closure_microfacet_beckmann_aniso_setup(
@@ -873,26 +828,16 @@ ccl_device void osl_closure_principled_clearcoat_setup(
ccl_private const PrincipledClearcoatClosure *closure)
{
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
- sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight));
+ sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight) * closure->clearcoat);
if (!bsdf) {
return;
}
- MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if (!extra) {
- return;
- }
-
bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N);
bsdf->alpha_x = closure->clearcoat_roughness;
bsdf->alpha_y = closure->clearcoat_roughness;
bsdf->ior = 1.5f;
- bsdf->extra = extra;
- bsdf->extra->color = zero_spectrum();
- bsdf->extra->cspec0 = make_spectrum(0.04f);
- bsdf->extra->clearcoat = closure->clearcoat;
-
bsdf->T = zero_float3();
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h
index d18f2cc0854..82274adeea8 100644
--- a/intern/cycles/kernel/svm/closure.h
+++ b/intern/cycles/kernel/svm/closure.h
@@ -10,6 +10,8 @@
#include "kernel/util/color.h"
+#include "kernel/svm/closure_principled.h"
+
CCL_NAMESPACE_BEGIN
/* Closure Nodes */
@@ -57,19 +59,6 @@ ccl_device void svm_node_glass_setup(ccl_private ShaderData *sd,
}
}
-ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, uint type)
-{
- if (type == CLOSURE_BSDF_PRINCIPLED_ID) {
- /* Read all principled BSDF extra data to get the right offset. */
- read_node(kg, &offset);
- read_node(kg, &offset);
- read_node(kg, &offset);
- read_node(kg, &offset);
- }
-
- return offset;
-}
-
template<uint node_feature_mask, ShaderType shader_type>
ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
ccl_private ShaderData *sd,
@@ -92,12 +81,18 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
IF_KERNEL_NODES_FEATURE(BSDF)
{
if ((shader_type != SHADER_TYPE_SURFACE) || mix_weight == 0.0f) {
- return svm_node_closure_bsdf_skip(kg, offset, type);
+ return offset;
}
}
else
{
- return svm_node_closure_bsdf_skip(kg, offset, type);
+ return offset;
+ }
+
+ if (type == CLOSURE_BSDF_PRINCIPLED_ID) {
+ /* Principled BSDF uses different parameter packing. */
+ svm_node_closure_principled(kg, sd, stack, node, data_node, mix_weight, path_flag, &offset);
+ return offset;
}
float3 N = stack_valid(data_node.x) ? stack_load_float3(stack, data_node.x) : sd->N;
@@ -111,381 +106,6 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
__uint_as_float(node.w);
switch (type) {
- case CLOSURE_BSDF_PRINCIPLED_ID: {
- uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset,
- sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset,
- eta_offset, transmission_offset, anisotropic_rotation_offset,
- transmission_roughness_offset;
- uint4 data_node2 = read_node(kg, &offset);
-
- float3 T = stack_load_float3(stack, data_node.y);
- svm_unpack_node_uchar4(data_node.z,
- &specular_offset,
- &roughness_offset,
- &specular_tint_offset,
- &anisotropic_offset);
- svm_unpack_node_uchar4(data_node.w,
- &sheen_offset,
- &sheen_tint_offset,
- &clearcoat_offset,
- &clearcoat_roughness_offset);
- svm_unpack_node_uchar4(data_node2.x,
- &eta_offset,
- &transmission_offset,
- &anisotropic_rotation_offset,
- &transmission_roughness_offset);
-
- // get Disney principled parameters
- float metallic = param1;
- float subsurface = param2;
- float specular = stack_load_float(stack, specular_offset);
- float roughness = stack_load_float(stack, roughness_offset);
- float specular_tint = stack_load_float(stack, specular_tint_offset);
- float anisotropic = stack_load_float(stack, anisotropic_offset);
- float sheen = stack_load_float(stack, sheen_offset);
- float sheen_tint = stack_load_float(stack, sheen_tint_offset);
- float clearcoat = stack_load_float(stack, clearcoat_offset);
- float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset);
- float transmission = stack_load_float(stack, transmission_offset);
- float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
- float transmission_roughness = stack_load_float(stack, transmission_roughness_offset);
- float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
-
- ClosureType distribution = (ClosureType)data_node2.y;
- ClosureType subsurface_method = (ClosureType)data_node2.z;
-
- /* rotate tangent */
- if (anisotropic_rotation != 0.0f)
- T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
-
- /* calculate ior */
- float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
-
- // calculate fresnel for refraction
- float cosNO = dot(N, sd->I);
- float fresnel = fresnel_dielectric_cos(cosNO, ior);
-
- // calculate weights of the diffuse and specular part
- float diffuse_weight = (1.0f - saturatef(metallic)) * (1.0f - saturatef(transmission));
-
- float final_transmission = saturatef(transmission) * (1.0f - saturatef(metallic));
- float specular_weight = (1.0f - final_transmission);
-
- // get the base color
- uint4 data_base_color = read_node(kg, &offset);
- float3 base_color = stack_valid(data_base_color.x) ?
- stack_load_float3(stack, data_base_color.x) :
- make_float3(__uint_as_float(data_base_color.y),
- __uint_as_float(data_base_color.z),
- __uint_as_float(data_base_color.w));
-
- // get the additional clearcoat normal and subsurface scattering radius
- uint4 data_cn_ssr = read_node(kg, &offset);
- float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ?
- stack_load_float3(stack, data_cn_ssr.x) :
- sd->N;
- if (!(sd->type & PRIMITIVE_CURVE)) {
- clearcoat_normal = ensure_valid_reflection(sd->Ng, sd->I, clearcoat_normal);
- }
- float3 subsurface_radius = stack_valid(data_cn_ssr.y) ?
- stack_load_float3(stack, data_cn_ssr.y) :
- 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) ?
- stack_load_float(stack, data_cn_ssr.w) :
- 0.0f;
-
- // get the subsurface color
- uint4 data_subsurface_color = read_node(kg, &offset);
- float3 subsurface_color = stack_valid(data_subsurface_color.x) ?
- stack_load_float3(stack, data_subsurface_color.x) :
- make_float3(__uint_as_float(data_subsurface_color.y),
- __uint_as_float(data_subsurface_color.z),
- __uint_as_float(data_subsurface_color.w));
-
- Spectrum weight = sd->svm_closure_weight * mix_weight;
-
-#ifdef __SUBSURFACE__
- float3 mixed_ss_base_color = subsurface_color * subsurface +
- base_color * (1.0f - subsurface);
- 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
- * getting lower and lower */
- if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
- subsurface = 0.0f;
-
- /* need to set the base color in this case such that the
- * rays get the correctly mixed color after transmitting
- * the object */
- base_color = mixed_ss_base_color;
- }
-
- /* diffuse */
- if (fabsf(average(mixed_ss_base_color)) > CLOSURE_WEIGHT_CUTOFF) {
- if (subsurface <= CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
- 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);
-
- if (bsdf) {
- bsdf->N = N;
- bsdf->roughness = roughness;
-
- /* setup bsdf */
- sd->flag |= bsdf_principled_diffuse_setup(bsdf, PRINCIPLED_DIFFUSE_FULL);
- }
- }
- else if (subsurface > CLOSURE_WEIGHT_CUTOFF) {
- ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, subsurf_weight);
-
- if (bssrdf) {
- bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface);
- bssrdf->albedo = rgb_to_spectrum(mixed_ss_base_color);
- bssrdf->N = N;
- bssrdf->roughness = roughness;
-
- /* Clamps protecting against bad/extreme and non physical values. */
- subsurface_ior = clamp(subsurface_ior, 1.01f, 3.8f);
- bssrdf->anisotropy = clamp(subsurface_anisotropy, 0.0f, 0.9f);
-
- /* setup bsdf */
- sd->flag |= bssrdf_setup(sd, bssrdf, subsurface_method, subsurface_ior);
- }
- }
- }
-#else
- /* diffuse */
- if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
- 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);
-
- if (bsdf) {
- bsdf->N = N;
- bsdf->roughness = roughness;
-
- /* setup bsdf */
- sd->flag |= bsdf_principled_diffuse_setup(bsdf, PRINCIPLED_DIFFUSE_FULL);
- }
- }
-#endif
-
- /* 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 :
- one_float3(); // normalize lum. to isolate hue+sat
-
- /* color of the sheen component */
- float3 sheen_color = make_float3(1.0f - sheen_tint) + m_ctint * sheen_tint;
-
- 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);
-
- if (bsdf) {
- bsdf->N = N;
-
- /* setup bsdf */
- sd->flag |= bsdf_principled_sheen_setup(sd, bsdf);
- }
- }
-
- /* specular reflection */
-#ifdef __CAUSTICS_TRICKS__
- if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
-#endif
- if (specular_weight > CLOSURE_WEIGHT_CUTOFF &&
- (specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) {
- Spectrum spec_weight = weight * specular_weight;
-
- ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
- sd, sizeof(MicrofacetBsdf), spec_weight);
- ccl_private MicrofacetExtra *extra =
- (bsdf != NULL) ?
- (ccl_private MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)) :
- NULL;
-
- if (bsdf && extra) {
- bsdf->N = N;
- bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
- bsdf->T = T;
- bsdf->extra = extra;
-
- float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
- float r2 = roughness * roughness;
-
- bsdf->alpha_x = r2 / aspect;
- bsdf->alpha_y = r2 * aspect;
-
- 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 :
- 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 */
- if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID ||
- roughness <= 0.075f) /* use single-scatter GGX */
- sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
- else /* use multi-scatter GGX */
- sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
- }
- }
-#ifdef __CAUSTICS_TRICKS__
- }
-#endif
-
- /* BSDF */
-#ifdef __CAUSTICS_TRICKS__
- if (kernel_data.integrator.caustics_reflective ||
- kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
-#endif
- if (final_transmission > CLOSURE_WEIGHT_CUTOFF) {
- 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 */
- float refl_roughness = roughness;
-
- /* reflection */
-#ifdef __CAUSTICS_TRICKS__
- if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
-#endif
- {
- ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
- sd, sizeof(MicrofacetBsdf), glass_weight * fresnel);
- ccl_private MicrofacetExtra *extra =
- (bsdf != NULL) ? (ccl_private MicrofacetExtra *)closure_alloc_extra(
- sd, sizeof(MicrofacetExtra)) :
- NULL;
-
- if (bsdf && extra) {
- bsdf->N = N;
- 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 = rgb_to_spectrum(base_color);
- bsdf->extra->cspec0 = rgb_to_spectrum(cspec0);
- bsdf->extra->clearcoat = 0.0f;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
- }
- }
-
- /* refraction */
-#ifdef __CAUSTICS_TRICKS__
- if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
-#endif
- {
- /* 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),
- rgb_to_spectrum(base_color) * glass_weight * refraction_fresnel);
- if (bsdf) {
- bsdf->N = N;
- bsdf->T = zero_float3();
- bsdf->extra = NULL;
-
- if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
- transmission_roughness = 1.0f - (1.0f - refl_roughness) *
- (1.0f - transmission_roughness);
- else
- transmission_roughness = refl_roughness;
-
- bsdf->alpha_x = transmission_roughness * transmission_roughness;
- bsdf->alpha_y = transmission_roughness * transmission_roughness;
- bsdf->ior = ior;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
- }
- }
- }
- else { /* use multi-scatter GGX */
- ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
- sd, sizeof(MicrofacetBsdf), glass_weight);
- ccl_private MicrofacetExtra *extra =
- (bsdf != NULL) ? (ccl_private MicrofacetExtra *)closure_alloc_extra(
- sd, sizeof(MicrofacetExtra)) :
- NULL;
-
- if (bsdf && extra) {
- bsdf->N = N;
- bsdf->extra = extra;
- bsdf->T = zero_float3();
-
- bsdf->alpha_x = roughness * roughness;
- bsdf->alpha_y = roughness * roughness;
- bsdf->ior = ior;
-
- bsdf->extra->color = rgb_to_spectrum(base_color);
- bsdf->extra->cspec0 = rgb_to_spectrum(cspec0);
- bsdf->extra->clearcoat = 0.0f;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
- }
- }
- }
-#ifdef __CAUSTICS_TRICKS__
- }
-#endif
-
- /* clearcoat */
-#ifdef __CAUSTICS_TRICKS__
- if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
-#endif
- if (clearcoat > CLOSURE_WEIGHT_CUTOFF) {
- ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
- sd, sizeof(MicrofacetBsdf), weight);
- ccl_private MicrofacetExtra *extra =
- (bsdf != NULL) ?
- (ccl_private MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)) :
- NULL;
-
- if (bsdf && extra) {
- bsdf->N = clearcoat_normal;
- 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 = zero_spectrum();
- bsdf->extra->cspec0 = make_spectrum(0.04f);
- bsdf->extra->clearcoat = clearcoat;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
- }
- }
-#ifdef __CAUSTICS_TRICKS__
- }
-#endif
-
- break;
- }
case CLOSURE_BSDF_DIFFUSE_ID: {
Spectrum weight = sd->svm_closure_weight * mix_weight;
ccl_private OrenNayarBsdf *bsdf = (ccl_private OrenNayarBsdf *)bsdf_alloc(
@@ -579,14 +199,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
else if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
kernel_assert(stack_valid(data_node.w));
- bsdf->extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(sd,
- sizeof(MicrofacetExtra));
- if (bsdf->extra) {
- 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);
- }
+ Spectrum color = rgb_to_spectrum(stack_load_float3(stack, data_node.w));
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(kg, bsdf, sd, color);
}
else {
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
@@ -677,7 +291,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
- /* This is to prevent MNEE from receiving a null BSDF. */
+ /* This is to prevent MNEE from receiving a null BSDF.
+ * TODO: Doesn't this always enable the closure? */
float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel);
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
sd, sizeof(MicrofacetBsdf), weight * refraction_fresnel);
@@ -705,14 +320,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
break;
}
- ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
- sd, sizeof(MicrofacetExtra));
- if (!extra) {
- break;
- }
+ /* TODO: Detect sharp, fallback. */
bsdf->N = N;
- bsdf->extra = extra;
+ bsdf->extra = NULL;
bsdf->T = zero_float3();
float roughness = sqr(param1);
@@ -722,12 +333,10 @@ 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 = rgb_to_spectrum(stack_load_float3(stack, data_node.z));
- bsdf->extra->cspec0 = zero_spectrum();
- bsdf->extra->clearcoat = 0.0f;
+ Spectrum color = rgb_to_spectrum(stack_load_float3(stack, data_node.z));
/* setup bsdf */
- sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(kg, bsdf, sd, color);
break;
}
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
diff --git a/intern/cycles/kernel/svm/closure_principled.h b/intern/cycles/kernel/svm/closure_principled.h
new file mode 100644
index 00000000000..fd6df508e12
--- /dev/null
+++ b/intern/cycles/kernel/svm/closure_principled.h
@@ -0,0 +1,843 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#pragma once
+
+CCL_NAMESPACE_BEGIN
+
+/* Principled v1 components */
+
+ccl_device_inline void principled_v1_diffuse(ccl_private ShaderData *sd,
+ Spectrum weight,
+ Spectrum base_color,
+ float diffuse_weight,
+ float3 N,
+ float roughness)
+{
+ if (diffuse_weight <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+ ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledDiffuseBsdf), diffuse_weight * base_color * weight);
+
+ if (bsdf == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+ bsdf->roughness = roughness;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_principled_diffuse_setup(bsdf, PRINCIPLED_DIFFUSE_FULL);
+}
+
+ccl_device_inline void principled_v1_diffuse_sss(ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ int path_flag,
+ uint data_1,
+ uint data_2,
+ Spectrum base_color,
+ float diffuse_weight,
+ float3 N,
+ float roughness)
+{
+#ifdef __SUBSURFACE__
+ uint method, subsurface_offset, aniso_offset, radius_offset;
+ uint color_offset, ior_offset, dummy;
+ svm_unpack_node_uchar4(data_1, &method, &subsurface_offset, &aniso_offset, &radius_offset);
+ svm_unpack_node_uchar4(data_2, &color_offset, &ior_offset, &dummy, &dummy);
+
+ float subsurface = stack_load_float(stack, subsurface_offset);
+ float subsurface_anisotropy = stack_load_float(stack, aniso_offset);
+ float subsurface_ior = stack_load_float(stack, ior_offset);
+ Spectrum subsurface_color = rgb_to_spectrum(stack_load_float3(stack, color_offset));
+ Spectrum subsurface_radius = rgb_to_spectrum(stack_load_float3(stack, radius_offset));
+
+ Spectrum mixed_ss_base_color = mix(base_color, subsurface_color, subsurface);
+
+ /* 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) {
+ subsurface = 0.0f;
+ }
+
+ /* diffuse */
+ if (fabsf(average(mixed_ss_base_color)) > CLOSURE_WEIGHT_CUTOFF) {
+ if (subsurface > CLOSURE_WEIGHT_CUTOFF) {
+ Spectrum subsurf_weight = weight * mixed_ss_base_color * diffuse_weight;
+ ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, subsurf_weight);
+
+ if (bssrdf == NULL) {
+ return;
+ }
+
+ bssrdf->radius = subsurface_radius * subsurface;
+ bssrdf->albedo = mixed_ss_base_color;
+ bssrdf->N = N;
+ bssrdf->roughness = roughness;
+
+ /* Clamps protecting against bad/extreme and non physical values. */
+ subsurface_ior = clamp(subsurface_ior, 1.01f, 3.8f);
+ bssrdf->anisotropy = clamp(subsurface_anisotropy, 0.0f, 0.9f);
+
+ /* setup bsdf */
+ sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)method, subsurface_ior);
+ }
+ else {
+ principled_v1_diffuse(sd, weight, mixed_ss_base_color, diffuse_weight, N, roughness);
+ }
+ }
+#else
+ /* diffuse */
+ principled_v1_diffuse(sd, weight, base_color, diffuse_weight, N, roughness);
+#endif
+}
+
+ccl_device_inline void principled_v1_specular(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ int path_flag,
+ ClosureType distribution,
+ uint data,
+ Spectrum base_color,
+ float3 N,
+ float specular_weight,
+ float metallic,
+ float roughness,
+ float specular_tint)
+{
+#ifdef __CAUSTICS_TRICKS__
+ if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) {
+ return;
+ }
+#endif
+
+ uint specular_offset, aniso_offset, rotation_offset, tangent_offset;
+ svm_unpack_node_uchar4(data, &specular_offset, &aniso_offset, &rotation_offset, &tangent_offset);
+
+ float specular = stack_load_float(stack, specular_offset);
+
+ if ((specular_weight <= CLOSURE_WEIGHT_CUTOFF) ||
+ (specular + metallic <= CLOSURE_WEIGHT_CUTOFF)) {
+ return;
+ }
+
+ float anisotropic = stack_load_float(stack, aniso_offset);
+ float3 T = zero_float3();
+ if (stack_valid(tangent_offset)) {
+ T = stack_load_float3(stack, tangent_offset);
+ T = rotate_around_axis(T, N, stack_load_float(stack, rotation_offset) * M_2PI_F);
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), specular_weight * weight);
+ if (bsdf == NULL) {
+ return;
+ }
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (extra == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+ bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
+ bsdf->T = T;
+ bsdf->extra = extra;
+
+ float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
+
+ bsdf->alpha_x = sqr(roughness) / aspect;
+ bsdf->alpha_y = sqr(roughness) * aspect;
+
+ // normalize lum. to isolate hue+sat
+ float m_cdlum = linear_rgb_to_gray(kg, base_color);
+ Spectrum m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : one_spectrum();
+ Spectrum specular_color = mix(one_spectrum(), m_ctint, specular_tint);
+
+ bsdf->extra->cspec0 = mix(specular * 0.08f * specular_color, base_color, metallic);
+ bsdf->extra->color = base_color;
+
+ /* setup bsdf */
+ if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID ||
+ roughness <= 0.075f) /* use single-scatter GGX */
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
+ else /* use multi-scatter GGX */
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(kg, bsdf, sd);
+}
+
+ccl_device_inline void principled_v1_glass_refl(ccl_private ShaderData *sd,
+ Spectrum weight,
+ Spectrum base_color,
+ float reflection_weight,
+ float3 N,
+ float roughness,
+ float ior,
+ float specular_tint)
+{
+ if (reflection_weight <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), reflection_weight * weight);
+ if (bsdf == NULL) {
+ return;
+ }
+
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (extra == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = extra;
+
+ bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
+ bsdf->ior = ior;
+
+ bsdf->extra->color = base_color;
+ bsdf->extra->cspec0 = mix(one_spectrum(), base_color, specular_tint);
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
+}
+
+ccl_device_inline void principled_v1_glass_refr(ccl_private ShaderData *sd,
+ Spectrum weight,
+ Spectrum base_color,
+ float refraction_weight,
+ float3 N,
+ float roughness,
+ float ior)
+{
+ if (refraction_weight <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), base_color * weight * refraction_weight);
+ if (bsdf == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = NULL;
+
+ bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
+ bsdf->ior = ior;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+}
+
+ccl_device_inline void principled_v1_glass_single(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ int path_flag,
+ ClosureType distribution,
+ uint data,
+ Spectrum base_color,
+ float glass_weight,
+ float3 N,
+ float roughness,
+ float specular_tint)
+{
+ if (glass_weight <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+ uint transmission_roughness_offset, eta_offset, dummy;
+ svm_unpack_node_uchar4(data, &eta_offset, &dummy, &dummy, &transmission_roughness_offset);
+ float transmission_roughness = stack_load_float(stack, transmission_roughness_offset);
+ float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
+
+ /* calculate ior */
+ float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
+
+ // calculate fresnel for refraction
+ float fresnel = fresnel_dielectric_cos(dot(N, sd->I), ior);
+
+ /* reflection */
+ float reflection_weight = glass_weight * fresnel;
+#ifdef __CAUSTICS_TRICKS__
+ if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) {
+ reflection_weight = 0.0f;
+ }
+#endif
+ principled_v1_glass_refl(
+ sd, weight, base_color, reflection_weight, N, roughness, ior, specular_tint);
+
+ /* refraction */
+ /* TODO: MNEE ensured that this is always >0, is that correct?? */
+ float refraction_weight = glass_weight * (1.0f - fresnel);
+#ifdef __CAUSTICS_TRICKS__
+ if (!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) {
+ refraction_weight = 0.0f;
+ }
+#endif
+ if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
+ transmission_roughness = 1.0f - (1.0f - roughness) * (1.0f - transmission_roughness);
+ else
+ transmission_roughness = roughness;
+ principled_v1_glass_refr(
+ sd, weight, base_color, refraction_weight, N, transmission_roughness, ior);
+}
+
+ccl_device_inline void principled_v1_glass_multi(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ int path_flag,
+ uint data,
+ Spectrum base_color,
+ float glass_weight,
+ float3 N,
+ float roughness,
+ float specular_tint)
+{
+#ifdef __CAUSTICS_TRICKS__
+ if (!kernel_data.integrator.caustics_reflective && !kernel_data.integrator.caustics_refractive &&
+ (path_flag & PATH_RAY_DIFFUSE)) {
+ return;
+ }
+#endif
+
+ if (glass_weight <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+ uint eta_offset, dummy;
+ svm_unpack_node_uchar4(data, &eta_offset, &dummy, &dummy, &dummy);
+ float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), glass_weight * weight);
+ if (bsdf == NULL) {
+ return;
+ }
+ ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra));
+ if (extra == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+ bsdf->extra = extra;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+
+ bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
+ bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
+
+ bsdf->extra->color = base_color;
+ bsdf->extra->cspec0 = mix(one_spectrum(), base_color, specular_tint);
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(kg, bsdf, sd);
+}
+
+ccl_device_inline void principled_v1_sheen(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ uint data,
+ Spectrum base_color,
+ float diffuse_weight,
+ float3 N)
+{
+ uint sheen_offset, sheen_tint_offset, dummy;
+ svm_unpack_node_uchar4(data, &dummy, &sheen_offset, &sheen_tint_offset, &dummy);
+ float sheen = stack_load_float(stack, sheen_offset);
+
+ float sheen_weight = diffuse_weight * sheen;
+ if (sheen_weight <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+ // normalize lum. to isolate hue+sat
+ float m_cdlum = linear_rgb_to_gray(kg, base_color);
+ Spectrum m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : one_spectrum();
+
+ /* color of the sheen component */
+ float sheen_tint = stack_load_float(stack, sheen_tint_offset);
+ Spectrum sheen_color = mix(one_spectrum(), m_ctint, sheen_tint);
+
+ ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledSheenBsdf), sheen_weight * sheen_color * weight);
+
+ if (bsdf == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_principled_sheen_setup(sd, bsdf);
+}
+
+ccl_device_inline void principled_v1_clearcoat(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ int path_flag,
+ uint data)
+{
+#ifdef __CAUSTICS_TRICKS__
+ if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) {
+ return;
+ }
+#endif
+
+ uint clearcoat_offset, roughness_offset, normal_offset, dummy;
+ svm_unpack_node_uchar4(data, &clearcoat_offset, &roughness_offset, &normal_offset, &dummy);
+ float clearcoat = stack_load_float(stack, clearcoat_offset);
+
+ if (clearcoat <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+ float roughness = stack_load_float(stack, roughness_offset);
+ float3 N = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
+ if (!(sd->type & PRIMITIVE_CURVE)) {
+ N = ensure_valid_reflection(sd->Ng, sd->I, N);
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), 0.25f * weight * clearcoat);
+
+ if (bsdf == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->ior = 1.5f;
+ bsdf->extra = NULL;
+
+ bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
+}
+
+/* Principled v2 components */
+
+ccl_device_inline void principled_v2_diffuse_sss(ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ int path_flag,
+ uint data,
+ Spectrum base_color,
+ float ior,
+ float3 N)
+{
+ if (reduce_max(weight * base_color) <= CLOSURE_WEIGHT_CUTOFF) {
+ return;
+ }
+
+#ifdef __SUBSURFACE__
+ uint method, scale_offset, aniso_offset, radius_offset;
+ svm_unpack_node_uchar4(data, &scale_offset, &aniso_offset, &radius_offset, &method);
+
+ float aniso = stack_load_float(stack, aniso_offset);
+ Spectrum radius = rgb_to_spectrum(stack_load_float3(stack, radius_offset)) *
+ stack_load_float(stack, scale_offset);
+
+ /* Fall back to diffuse if there has been a diffuse bounce before or the radius is too small. */
+ if ((path_flag & PATH_RAY_DIFFUSE_ANCESTOR) == 0 && reduce_max(radius) > 1e-7f) {
+ ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, base_color * weight);
+
+ if (bssrdf == NULL) {
+ return;
+ }
+
+ bssrdf->radius = radius;
+ bssrdf->albedo = base_color;
+ bssrdf->N = N;
+ bssrdf->roughness = FLT_MAX;
+
+ /* Clamps protecting against bad/extreme and non physical values. */
+ bssrdf->anisotropy = clamp(aniso, 0.0f, 0.9f);
+
+ /* setup bsdf */
+ sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)method, clamp(ior, 1.01f, 3.8f));
+
+ return;
+ }
+#endif
+
+ ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(DiffuseBsdf), base_color * weight);
+
+ if (bsdf == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_diffuse_setup(bsdf);
+}
+
+ccl_device_inline Spectrum principled_v2_clearcoat(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ int path_flag,
+ uint data)
+{
+ uint clearcoat_offset, roughness_offset, tint_offset, normal_offset;
+ svm_unpack_node_uchar4(data, &clearcoat_offset, &roughness_offset, &tint_offset, &normal_offset);
+
+ float3 N = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
+ Spectrum tint = saturate(rgb_to_spectrum(stack_load_float3(stack, tint_offset)));
+ if (tint != one_spectrum()) {
+ /* Tint is normalized to perpendicular incidence.
+ * Therefore, if we define the coating thickness as length 1, the length along the ray is
+ * t = sqrt(1+tan^2(angle(N, I))) = sqrt(1+tan^2(acos(dotNI))) = 1 / dotNI.
+ * From Beer's law, we have T = exp(-sigma_e * t).
+ * Therefore, tint = exp(-sigma_e * 1) (per def.), so -sigma_e = log(tint).
+ * From this, T = exp(log(tint) * t) = exp(log(tint)) ^ t = tint ^ t;
+ *
+ * Note that this is only an approximation - in particular, the exit path of the
+ * light that bounces off the main layer is not accounted for.
+ * Ideally, we should be attenuating by sqrt(tint) both ways. Currently, the model
+ * is accurate for perfect mirrors since both entry and exit have the same cosNI there,
+ * but if e.g. the base is diffuse and we look at it from a grazing angle, in reality
+ * the cosNI of the exit bounce will be much higher on average, so the tint would be
+ * less extreme.
+ * TODO: Maybe account for this by setting
+ * OD := 0.5*OD + 0.5*mix(1.59, OD, metallic * (1 - roughness)),
+ * where 1.59 is the closest numerical fit for average optical depth on lambertian reflectors.
+ * That way, mirrors preserve their look, but diffuse-ish objects have a more natural behavior.
+ */
+ float cosNI = dot(sd->I, N);
+ /* Refract incoming direction into clearcoat material, which has a fixed IOR of 1.5.
+ * TIR is no concern here since we're always coming from the outside. */
+ float cosNT = sqrtf(1.0f - sqr(1.0f / 1.5f) * (1 - sqr(cosNI)));
+ float optical_depth = 1.0f / cosNT;
+ tint = pow(tint, optical_depth);
+ }
+
+ float clearcoat = saturatef(stack_load_float(stack, clearcoat_offset));
+ if (clearcoat <= CLOSURE_WEIGHT_CUTOFF) {
+ return tint;
+ }
+
+#ifdef __CAUSTICS_TRICKS__
+ if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) {
+ return tint;
+ }
+#endif
+
+ float roughness = saturatef(stack_load_float(stack, roughness_offset));
+ if (!(sd->type & PRIMITIVE_CURVE)) {
+ N = ensure_valid_reflection(sd->Ng, sd->I, N);
+ }
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), clearcoat * weight);
+
+ if (bsdf == NULL) {
+ return tint;
+ }
+
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->ior = 1.5f;
+ bsdf->extra = NULL;
+
+ bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_ggx_clearcoat_v2_setup(kg, bsdf, sd);
+
+ return tint * (1.0f - clearcoat_E(kg, dot(sd->I, N), roughness) * clearcoat);
+}
+
+ccl_device_inline float principled_v2_sheen(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ Spectrum N,
+ uint data)
+{
+ uint sheen_offset, sheen_tint_offset, sheen_roughness_offset, dummy;
+ svm_unpack_node_uchar4(data, &dummy, &sheen_offset, &sheen_tint_offset, &sheen_roughness_offset);
+
+ float sheen = stack_load_float(stack, sheen_offset);
+ if (sheen <= CLOSURE_WEIGHT_CUTOFF) {
+ return 1.0f;
+ }
+
+ float roughness = stack_load_float(stack, sheen_roughness_offset);
+ ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledSheenBsdf), sheen * weight); // TODO include tint
+
+ if (bsdf == NULL) {
+ return 1.0f;
+ }
+
+ bsdf->N = N;
+ bsdf->roughness = sqr(roughness);
+
+ /* setup bsdf */
+ sd->flag |= bsdf_principled_sheen_v2_setup(kg, sd, bsdf);
+
+ return 1.0f - sheen * bsdf->avg_value; // TODO include tint
+}
+
+ccl_device_inline float principled_v2_specular(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ Spectrum weight,
+ Spectrum base_color,
+ float roughness,
+ float metallic,
+ float ior,
+ float transmission,
+ float3 N,
+ uint data1,
+ uint data2)
+{
+ // TODO Handle caustics flag
+
+ if (metallic + (1.0f - transmission) <= CLOSURE_WEIGHT_CUTOFF) {
+ return 0.0f;
+ }
+
+ uint edge_offset, dummy;
+ uint aniso_offset, rotation_offset, tangent_offset;
+ svm_unpack_node_uchar4(data1, &dummy, &edge_offset, &dummy, &dummy);
+ svm_unpack_node_uchar4(data2, &aniso_offset, &rotation_offset, &tangent_offset, &dummy);
+
+ /* This function handles two specular components:
+ * 1. Metallic: The overall energy is given by the metallic input
+ * 2. Dielectric opaque: The overall energy is given by (1-metallic)*(1-transmission)
+ * Both of these are handled by one closure, which adds up two Fresnel terms.
+ * On top of that, there is also the transmissive component, that is handled by the glass code.
+ */
+
+ float anisotropic = stack_load_float(stack, aniso_offset);
+ float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
+ float3 T = zero_float3();
+ if (stack_valid(tangent_offset)) {
+ T = stack_load_float3(stack, tangent_offset);
+ T = rotate_around_axis(T, N, stack_load_float(stack, rotation_offset) * M_2PI_F);
+ }
+ Spectrum edge_color = rgb_to_spectrum(stack_load_float3(stack, edge_offset));
+
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), weight);
+ if (bsdf == NULL) {
+ return 0.0f;
+ }
+ ccl_private MicrofacetExtrav2 *extra = (ccl_private MicrofacetExtrav2 *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtrav2));
+ if (extra == NULL) {
+ return 0.0f;
+ }
+
+ bsdf->N = N;
+ bsdf->ior = ior;
+ bsdf->T = T;
+ bsdf->extra = (MicrofacetExtra *)extra;
+
+ bsdf->alpha_x = sqr(roughness) / aspect;
+ bsdf->alpha_y = sqr(roughness) * aspect;
+
+ extra->metal_base = base_color;
+ extra->metal_edge_factor = metallic_edge_factor(base_color, edge_color);
+
+ float dielectric = (1.0f - metallic) * (1.0f - transmission);
+ sd->flag |= bsdf_microfacet_ggx_fresnel_v2_setup(kg, bsdf, sd, metallic, dielectric);
+
+ return microfacet_ggx_dielectric_E(kg, dot(sd->I, N), roughness, ior);
+}
+
+ccl_device_inline void principled_v2_glass(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ Spectrum weight,
+ float transmission,
+ float roughness,
+ float ior,
+ float3 N)
+{
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), transmission * weight);
+ if (bsdf == NULL) {
+ return;
+ }
+
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+
+ bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
+ bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / ior : ior;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(kg, bsdf, sd, one_spectrum());
+}
+
+ccl_device void svm_node_closure_principled_v2(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ uint4 node_1,
+ uint4 node_2,
+ float mix_weight,
+ int path_flag,
+ int *offset)
+{
+ Spectrum weight = sd->svm_closure_weight * mix_weight;
+
+ /* Load shared parameter data. */
+ uint base_color_offset, normal_offset, dummy;
+ uint roughness_offset, metallic_offset, ior_offset, transmission_offset;
+ svm_unpack_node_uchar4(node_1.y, &dummy, &base_color_offset, &normal_offset, &dummy);
+ svm_unpack_node_uchar4(
+ node_1.z, &roughness_offset, &metallic_offset, &ior_offset, &transmission_offset);
+
+ Spectrum base_color = rgb_to_spectrum(stack_load_float3(stack, base_color_offset));
+ float3 N = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
+ if (!(sd->type & PRIMITIVE_CURVE)) {
+ N = ensure_valid_reflection(sd->Ng, sd->I, N);
+ }
+ float roughness = saturatef(stack_load_float(stack, roughness_offset));
+ float metallic = saturatef(stack_load_float(stack, metallic_offset));
+ float ior = fmaxf(stack_load_float(stack, ior_offset), 1e-5f);
+ float transmission = saturatef(stack_load_float(stack, transmission_offset));
+
+ weight *= principled_v2_clearcoat(kg, sd, stack, weight, path_flag, node_2.w);
+ weight *= principled_v2_sheen(kg, sd, stack, weight, N, node_2.z);
+
+ float dielectric_albedo = principled_v2_specular(kg,
+ sd,
+ stack,
+ weight,
+ base_color,
+ roughness,
+ metallic,
+ ior,
+ transmission,
+ N,
+ node_2.x,
+ node_2.y);
+ weight *= 1.0f - metallic;
+
+ principled_v2_glass(kg, sd, weight, transmission, roughness, ior, N);
+
+ weight *= (1.0f - transmission) * (1.0f - dielectric_albedo);
+
+ principled_v2_diffuse_sss(sd, stack, weight, path_flag, node_1.w, base_color, ior, N);
+}
+
+ccl_device void svm_node_closure_principled(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ ccl_private float *stack,
+ uint4 node_1,
+ uint4 node_2,
+ float mix_weight,
+ int path_flag,
+ int *offset)
+{
+ /* Load distribution type. */
+ uint packed_distribution, dummy;
+ svm_unpack_node_uchar4(node_2.x, &dummy, &dummy, &dummy, &packed_distribution);
+ ClosureType distribution = (ClosureType)packed_distribution;
+
+ if (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) {
+ svm_node_closure_principled_v2(kg, sd, stack, node_1, node_2, mix_weight, path_flag, offset);
+ return;
+ }
+
+ /* Load shared parameter data. */
+ uint base_color_offset, normal_offset;
+ uint roughness_offset, metallic_offset, transmission_offset, specular_tint_offset;
+ svm_unpack_node_uchar4(node_1.y, &dummy, &base_color_offset, &normal_offset, &dummy);
+ svm_unpack_node_uchar4(
+ node_1.z, &roughness_offset, &metallic_offset, &transmission_offset, &specular_tint_offset);
+
+ Spectrum base_color = rgb_to_spectrum(stack_load_float3(stack, base_color_offset));
+ float3 N = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
+ if (!(sd->type & PRIMITIVE_CURVE)) {
+ N = ensure_valid_reflection(sd->Ng, sd->I, N);
+ }
+ float roughness = saturatef(stack_load_float(stack, roughness_offset));
+ float metallic = saturatef(stack_load_float(stack, metallic_offset));
+ float transmission = saturatef(stack_load_float(stack, transmission_offset));
+ float specular_tint = saturatef(stack_load_float(stack, specular_tint_offset));
+
+ /* Calculate closure mix weights.
+ * The combined BSDF is mix(mix(Diffuse+SSS, Glass, transmission), Metal, metallic). */
+ float diffuse_weight = (1.0f - metallic) * (1.0f - transmission);
+ transmission *= 1.0f - metallic;
+ /* NOTE: The mixing here is incorrect, the specular lobe should be metallic + (1 - transmission)
+ * since it models both the metallic specular as well as the non-glass dielectric specular.
+ * This only affects materials mixing diffuse, glass AND metal though. */
+ float specular_weight = (1.0f - transmission);
+ Spectrum weight = sd->svm_closure_weight * mix_weight;
+
+ /* Diffuse and subsurface */
+ principled_v1_diffuse_sss(
+ sd, stack, weight, path_flag, node_1.w, node_2.x, base_color, diffuse_weight, N, roughness);
+
+ /* sheen */
+ principled_v1_sheen(kg, sd, stack, weight, node_2.z, base_color, diffuse_weight, N);
+
+ /* specular reflection */
+ principled_v1_specular(kg,
+ sd,
+ stack,
+ weight,
+ path_flag,
+ distribution,
+ node_2.y,
+ base_color,
+ N,
+ specular_weight,
+ metallic,
+ roughness,
+ specular_tint);
+
+ /* glass */
+ if (roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) {
+ principled_v1_glass_single(kg,
+ sd,
+ stack,
+ weight,
+ path_flag,
+ distribution,
+ node_2.z,
+ base_color,
+ transmission,
+ N,
+ roughness,
+ specular_tint);
+ }
+ else {
+ principled_v1_glass_multi(kg,
+ sd,
+ stack,
+ weight,
+ path_flag,
+ node_2.z,
+ base_color,
+ transmission,
+ N,
+ roughness,
+ specular_tint);
+ }
+
+ /* clearcoat */
+ principled_v1_clearcoat(kg, sd, stack, weight, path_flag, node_2.w);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h
index 9dd8f196e0f..bce403a2df5 100644
--- a/intern/cycles/kernel/svm/types.h
+++ b/intern/cycles/kernel/svm/types.h
@@ -414,17 +414,25 @@ typedef enum ClosureType {
CLOSURE_BSDF_DIFFUSE_RAMP_ID,
CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID,
CLOSURE_BSDF_PRINCIPLED_SHEEN_ID,
+ CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID,
CLOSURE_BSDF_DIFFUSE_TOON_ID,
CLOSURE_BSDF_TRANSLUCENT_ID,
/* Glossy */
CLOSURE_BSDF_REFLECTION_ID,
+ /* GGX without Fresnel term (baked into closure weight) */
CLOSURE_BSDF_MICROFACET_GGX_ID,
+ /* GGX with legacy Principled Fresnel term */
CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID,
+ /* GGX with v2 Principled Fresnel term */
+ CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_V2_ID,
+ /* GTR1 for Clearcoat (TODO: Rename, is not really GGX) */
CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID,
- CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
+ /* GGX with dielectric Fresnel term (used for Clearcoat for v2) */
+ CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_V2_ID,
+ /* Virtual closure, gets turned into regular GGX with adjusted weight */
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID,
+ CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_PHONG_RAMP_ID,
@@ -434,11 +442,15 @@ typedef enum ClosureType {
/* Transmission */
CLOSURE_BSDF_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
+ /* GGX without Fresnel term (baked into closure weight) */
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
+ /* GGX with microfacet-Fresnel-based reflection and refraction */
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
+ /* Same as above, but with additional legacy Principled Fresnel term */
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
+ /* Virtual closure, gets turned into reflection and refraction closures */
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
CLOSURE_BSDF_SHARP_GLASS_ID,
CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
@@ -477,19 +489,16 @@ typedef enum ClosureType {
(type == CLOSURE_BSDF_REFLECTION_ID || type == CLOSURE_BSDF_REFRACTION_ID || \
type == CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
-#define CLOSURE_IS_BSDF_MULTISCATTER(type) \
- (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID || \
- type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
#define CLOSURE_IS_BSDF_MICROFACET(type) \
((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
- type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \
- (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
+ type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
#define CLOSURE_IS_BSDF_MICROFACET_FRESNEL(type) \
- (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \
- type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \
- type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \
- type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID)
+ (type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \
+ type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID)
+// TODO Fresnel v2
+#define CLOSURE_IS_BSDF_SHEEN(type) \
+ (type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID || type == CLOSURE_BSDF_PRINCIPLED_SHEEN_V2_ID)
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
#define CLOSURE_IS_BSSRDF(type) \
(type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID)
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 24c5a6a4540..b0d1992738d 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1153,6 +1153,14 @@ typedef enum KernelBVHLayout {
typedef struct KernelTables {
int beckmann_offset;
int filter_table_offset;
+ int ggx_E_offset;
+ int ggx_E_avg_offset;
+ int ggx_clearcoat_E_offset;
+ int ggx_glass_E_offset;
+ int ggx_glass_inv_E_offset;
+ int ggx_dielectric_E_offset;
+ int ggx_dielectric_inv_E_offset;
+ int sheen_E_offset;
int pad1, pad2;
} KernelTables;
static_assert_align(KernelTables, 16);
diff --git a/intern/cycles/kernel/util/lookup_table.h b/intern/cycles/kernel/util/lookup_table.h
index 4db4dadab0e..d090626ab94 100644
--- a/intern/cycles/kernel/util/lookup_table.h
+++ b/intern/cycles/kernel/util/lookup_table.h
@@ -9,7 +9,7 @@ CCL_NAMESPACE_BEGIN
ccl_device float lookup_table_read(KernelGlobals kg, float x, int offset, int size)
{
- x = saturatef(x) * (size - 1);
+ x = clamp(x * size - 0.5f, 0.0f, (float)size);
int index = min(float_to_int(x), size - 1);
int nindex = min(index + 1, size - 1);
@@ -20,13 +20,13 @@ ccl_device float lookup_table_read(KernelGlobals kg, float x, int offset, int si
return data0;
float data1 = kernel_data_fetch(lookup_table, nindex + offset);
- return (1.0f - t) * data0 + t * data1;
+ return mix(data0, data1, t);
}
ccl_device float lookup_table_read_2D(
KernelGlobals kg, float x, float y, int offset, int xsize, int ysize)
{
- y = saturatef(y) * (ysize - 1);
+ y = clamp(y * ysize - 0.5f, 0.0f, (float)ysize);
int index = min(float_to_int(y), ysize - 1);
int nindex = min(index + 1, ysize - 1);
@@ -37,7 +37,24 @@ ccl_device float lookup_table_read_2D(
return data0;
float data1 = lookup_table_read(kg, x, offset + xsize * nindex, xsize);
- return (1.0f - t) * data0 + t * data1;
+ return mix(data0, data1, t);
+}
+
+ccl_device float lookup_table_read_3D(
+ KernelGlobals kg, float x, float y, float z, int offset, int xsize, int ysize, int zsize)
+{
+ z = clamp(z * zsize - 0.5f, 0.0f, (float)zsize);
+
+ int index = min(float_to_int(z), zsize - 1);
+ int nindex = min(index + 1, zsize - 1);
+ float t = z - index;
+
+ float data0 = lookup_table_read_2D(kg, x, y, offset + xsize * ysize * index, xsize, ysize);
+ if (t == 0.0f)
+ return data0;
+
+ float data1 = lookup_table_read_2D(kg, x, y, offset + xsize * ysize * nindex, xsize, ysize);
+ return mix(data0, data1, t);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp
index 56670c6e4e3..bef1ce0df4b 100644
--- a/intern/cycles/scene/shader.cpp
+++ b/intern/cycles/scene/shader.cpp
@@ -31,6 +31,8 @@ namespace OCIO = OCIO_NAMESPACE;
CCL_NAMESPACE_BEGIN
+#include "scene/shader.tables"
+
thread_mutex ShaderManager::lookup_table_mutex;
vector<float> ShaderManager::beckmann_table;
bool ShaderManager::beckmann_table_ready = false;
@@ -566,6 +568,33 @@ void ShaderManager::device_update_common(Device * /*device*/,
}
ktables->beckmann_offset = (int)beckmann_table_offset;
+ auto bsdf_table = [&](int *offset_entry, const float *data, size_t size, string name) {
+ if (!(bsdf_lookup_tables.count(name))) {
+ vector<float> entries(data, data + size);
+ bsdf_lookup_tables[name] = scene->lookup_tables->add_table(dscene, entries);
+ }
+ *offset_entry = bsdf_lookup_tables[name];
+ };
+ bsdf_table(&ktables->ggx_E_offset, &table_ggx_E[0][0], 32 * 32, "ggx_E");
+ bsdf_table(&ktables->ggx_E_avg_offset, &table_ggx_E_avg[0], 32, "ggx_E_avg");
+ bsdf_table(
+ &ktables->ggx_clearcoat_E_offset, &table_clearcoat_E[0][0], 16 * 16, "ggx_clearcoat_E");
+ bsdf_table(
+ &ktables->ggx_glass_E_offset, &table_ggx_glass_E[0][0][0], 16 * 16 * 16, "ggx_glass_E");
+ bsdf_table(&ktables->ggx_glass_inv_E_offset,
+ &table_ggx_glass_inv_E[0][0][0],
+ 16 * 16 * 16,
+ "ggx_glass_inv_E");
+ bsdf_table(&ktables->ggx_dielectric_E_offset,
+ &table_ggx_dielectric_E[0][0][0],
+ 16 * 16 * 16,
+ "ggx_dielectric_E");
+ bsdf_table(&ktables->ggx_dielectric_inv_E_offset,
+ &table_ggx_dielectric_inv_E[0][0][0],
+ 16 * 16 * 16,
+ "ggx_dielectric_inv_E");
+ bsdf_table(&ktables->sheen_E_offset, &table_sheen_E[0][0], 32 * 32, "sheen_E");
+
/* integrator */
KernelIntegrator *kintegrator = &dscene->data.integrator;
kintegrator->use_volumes = has_volumes;
@@ -588,6 +617,10 @@ void ShaderManager::device_update_common(Device * /*device*/,
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
{
scene->lookup_tables->remove_table(&beckmann_table_offset);
+ for (auto &entry : bsdf_lookup_tables) {
+ scene->lookup_tables->remove_table(&entry.second);
+ }
+ bsdf_lookup_tables.clear();
dscene->shaders.free();
}
diff --git a/intern/cycles/scene/shader.h b/intern/cycles/scene/shader.h
index 2670776aca4..6f48c2da618 100644
--- a/intern/cycles/scene/shader.h
+++ b/intern/cycles/scene/shader.h
@@ -231,6 +231,7 @@ class ShaderManager {
static bool beckmann_table_ready;
size_t beckmann_table_offset;
+ unordered_map<string, size_t> bsdf_lookup_tables;
uint get_graph_kernel_features(ShaderGraph *graph);
diff --git a/intern/cycles/scene/shader.tables b/intern/cycles/scene/shader.tables
new file mode 100644
index 00000000000..9a2d97a40af
--- /dev/null
+++ b/intern/cycles/scene/shader.tables
@@ -0,0 +1,1264 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+/* Note: this file has a non-standard extension so it is skipped by clang-format. */
+
+/* Precomputed BSDF albedo tables for various microfacet distributions. */
+
+static const float table_ggx_E[32][32] = {
+ {0.938993f, 0.858736f, 0.800571f, 0.753374f, 0.713238f, 0.678442f, 0.647723f, 0.620302f, 0.595405f, 0.573038f, 0.552392f, 0.533285f, 0.515945f, 0.499677f, 0.484473f, 0.470426f, 0.457164f, 0.444816f, 0.433116f, 0.422004f, 0.411722f, 0.401847f, 0.392444f, 0.383611f, 0.375193f, 0.367147f, 0.359387f, 0.352163f, 0.345223f, 0.338525f, 0.332036f, 0.325866f},
+ {0.942738f, 0.866279f, 0.811134f, 0.766195f, 0.727883f, 0.694788f, 0.665388f, 0.639283f, 0.615624f, 0.594017f, 0.574515f, 0.556419f, 0.539656f, 0.524166f, 0.509889f, 0.496369f, 0.483729f, 0.471968f, 0.460875f, 0.450365f, 0.440542f, 0.431178f, 0.422252f, 0.41389f, 0.405924f, 0.398354f, 0.391047f, 0.384224f, 0.377665f, 0.371384f, 0.365363f, 0.359468f},
+ {0.946178f, 0.873743f, 0.821452f, 0.778574f, 0.742257f, 0.710809f, 0.682893f, 0.657944f, 0.635623f, 0.615179f, 0.596415f, 0.579404f, 0.56365f, 0.548923f, 0.535197f, 0.522582f, 0.510837f, 0.499666f, 0.489196f, 0.479435f, 0.470211f, 0.461503f, 0.4532f, 0.445456f, 0.438062f, 0.431058f, 0.424383f, 0.418092f, 0.412088f, 0.406399f, 0.40087f, 0.39569f},
+ {0.949756f, 0.881149f, 0.831485f, 0.790608f, 0.756361f, 0.726391f, 0.7001f, 0.676466f, 0.655176f, 0.636031f, 0.618395f, 0.602169f, 0.587374f, 0.573694f, 0.560934f, 0.549078f, 0.537966f, 0.52764f, 0.518107f, 0.509184f, 0.500732f, 0.492642f, 0.485138f, 0.478096f, 0.471514f, 0.465218f, 0.459228f, 0.453642f, 0.448353f, 0.443399f, 0.438603f, 0.434138f},
+ {0.953417f, 0.888246f, 0.840978f, 0.802406f, 0.770036f, 0.741652f, 0.716727f, 0.694556f, 0.674474f, 0.656312f, 0.639932f, 0.624841f, 0.610947f, 0.598109f, 0.586429f, 0.575584f, 0.565512f, 0.556085f, 0.547336f, 0.539137f, 0.531419f, 0.524487f, 0.517923f, 0.511844f, 0.506034f, 0.500635f, 0.495476f, 0.49075f, 0.486239f, 0.482136f, 0.478268f, 0.474605f},
+ {0.956708f, 0.895075f, 0.849858f, 0.813821f, 0.783021f, 0.756452f, 0.732847f, 0.711996f, 0.6933f, 0.67629f, 0.660854f, 0.646985f, 0.634265f, 0.622532f, 0.61175f, 0.601824f, 0.592715f, 0.584454f, 0.576767f, 0.569631f, 0.563046f, 0.556973f, 0.551345f, 0.546069f, 0.541248f, 0.536783f, 0.532655f, 0.528942f, 0.525551f, 0.52244f, 0.519561f, 0.516886f},
+ {0.959787f, 0.901339f, 0.858526f, 0.824767f, 0.795491f, 0.770587f, 0.748376f, 0.728728f, 0.71134f, 0.695646f, 0.681395f, 0.6685f, 0.656868f, 0.646354f, 0.636793f, 0.628025f, 0.620035f, 0.612715f, 0.606052f, 0.599955f, 0.594453f, 0.589562f, 0.585089f, 0.581059f, 0.577338f, 0.574072f, 0.5711f, 0.568439f, 0.566075f, 0.563943f, 0.562054f, 0.560442f},
+ {0.962795f, 0.906868f, 0.866905f, 0.835062f, 0.807402f, 0.783716f, 0.763213f, 0.744831f, 0.728521f, 0.714133f, 0.701219f, 0.689528f, 0.679048f, 0.669662f, 0.661165f, 0.653617f, 0.646934f, 0.640853f, 0.635463f, 0.630651f, 0.626301f, 0.622531f, 0.619196f, 0.616271f, 0.613734f, 0.611499f, 0.609711f, 0.608151f, 0.606875f, 0.605871f, 0.605133f, 0.604569f},
+ {0.965348f, 0.911877f, 0.87486f, 0.844371f, 0.818636f, 0.796204f, 0.77703f, 0.760093f, 0.745008f, 0.731726f, 0.719978f, 0.709726f, 0.700525f, 0.692423f, 0.68525f, 0.678907f, 0.673372f, 0.668563f, 0.664407f, 0.660819f, 0.657808f, 0.655239f, 0.653235f, 0.651498f, 0.65022f, 0.649273f, 0.648646f, 0.648209f, 0.648093f, 0.648143f, 0.648444f, 0.648997f},
+ {0.967272f, 0.916721f, 0.882236f, 0.852898f, 0.829009f, 0.807843f, 0.789712f, 0.774205f, 0.76051f, 0.748502f, 0.738002f, 0.728893f, 0.721084f, 0.714364f, 0.708633f, 0.703726f, 0.699584f, 0.696126f, 0.693243f, 0.691071f, 0.689301f, 0.688063f, 0.687214f, 0.686732f, 0.686602f, 0.686769f, 0.68723f, 0.687961f, 0.688866f, 0.689989f, 0.691226f, 0.692645f},
+ {0.968586f, 0.921257f, 0.88888f, 0.860793f, 0.838269f, 0.81852f, 0.80152f, 0.787156f, 0.77494f, 0.764349f, 0.755223f, 0.747519f, 0.741015f, 0.735657f, 0.731289f, 0.727743f, 0.725038f, 0.722978f, 0.721559f, 0.720651f, 0.720252f, 0.720234f, 0.720618f, 0.721337f, 0.722343f, 0.723618f, 0.725022f, 0.726747f, 0.728463f, 0.730413f, 0.732549f, 0.734727f},
+ {0.96923f, 0.925381f, 0.894794f, 0.867815f, 0.846234f, 0.828091f, 0.812338f, 0.799121f, 0.788072f, 0.779052f, 0.77153f, 0.765368f, 0.760397f, 0.756556f, 0.753644f, 0.751631f, 0.750357f, 0.749694f, 0.749655f, 0.750052f, 0.75089f, 0.7521f, 0.75363f, 0.755437f, 0.757483f, 0.759655f, 0.762073f, 0.764543f, 0.767111f, 0.769751f, 0.772424f, 0.775168f},
+ {0.969888f, 0.929051f, 0.899625f, 0.873925f, 0.853099f, 0.8364f, 0.822071f, 0.810155f, 0.800452f, 0.792754f, 0.786807f, 0.782287f, 0.779027f, 0.776843f, 0.775539f, 0.775069f, 0.775222f, 0.775969f, 0.777249f, 0.778874f, 0.78081f, 0.783044f, 0.785524f, 0.78813f, 0.790932f, 0.793787f, 0.79679f, 0.799823f, 0.802886f, 0.806013f, 0.809039f, 0.812126f},
+ {0.970458f, 0.93208f, 0.903415f, 0.878958f, 0.858946f, 0.843321f, 0.830534f, 0.82017f, 0.812067f, 0.806002f, 0.801686f, 0.798794f, 0.797162f, 0.796612f, 0.796887f, 0.797904f, 0.799518f, 0.801557f, 0.804076f, 0.806862f, 0.809902f, 0.813101f, 0.816464f, 0.819846f, 0.823393f, 0.826865f, 0.830303f, 0.833696f, 0.837071f, 0.840289f, 0.843405f, 0.846271f},
+ {0.97093f, 0.934339f, 0.906008f, 0.882733f, 0.863623f, 0.849053f, 0.837939f, 0.829376f, 0.823131f, 0.818944f, 0.816482f, 0.815457f, 0.815624f, 0.816719f, 0.818588f, 0.8211f, 0.824063f, 0.827308f, 0.830801f, 0.83448f, 0.838211f, 0.841892f, 0.845532f, 0.849179f, 0.852736f, 0.856301f, 0.859794f, 0.863242f, 0.866589f, 0.869835f, 0.872989f, 0.87607f},
+ {0.97133f, 0.935814f, 0.907571f, 0.885251f, 0.867183f, 0.853836f, 0.844417f, 0.837916f, 0.833826f, 0.831748f, 0.83136f, 0.832276f, 0.834192f, 0.836898f, 0.840127f, 0.843696f, 0.847553f, 0.851545f, 0.855775f, 0.85999f, 0.864261f, 0.868476f, 0.872636f, 0.876703f, 0.880618f, 0.884471f, 0.888169f, 0.891631f, 0.894991f, 0.898211f, 0.90118f, 0.903876f},
+ {0.971498f, 0.936194f, 0.907977f, 0.886424f, 0.869635f, 0.857961f, 0.850455f, 0.846173f, 0.844434f, 0.844569f, 0.846203f, 0.84897f, 0.852535f, 0.856708f, 0.861232f, 0.866047f, 0.870964f, 0.875868f, 0.880772f, 0.885482f, 0.890095f, 0.894455f, 0.89851f, 0.902212f, 0.905444f, 0.908352f, 0.911154f, 0.91382f, 0.916322f, 0.918733f, 0.921009f, 0.923178f},
+ {0.971515f, 0.935335f, 0.907242f, 0.886387f, 0.871259f, 0.861767f, 0.856719f, 0.855001f, 0.855742f, 0.858309f, 0.862141f, 0.866832f, 0.872116f, 0.877706f, 0.883307f, 0.888897f, 0.894213f, 0.899182f, 0.903721f, 0.907694f, 0.911501f, 0.915135f, 0.9186f, 0.921904f, 0.92507f, 0.927995f, 0.93078f, 0.933424f, 0.935897f, 0.938226f, 0.940385f, 0.942486f},
+ {0.971233f, 0.933273f, 0.90534f, 0.885326f, 0.872522f, 0.865959f, 0.863968f, 0.865225f, 0.868804f, 0.873881f, 0.879788f, 0.886066f, 0.892447f, 0.898536f, 0.904109f, 0.909139f, 0.914005f, 0.918666f, 0.923149f, 0.927344f, 0.93132f, 0.935081f, 0.938582f, 0.941808f, 0.944912f, 0.947718f, 0.950344f, 0.952816f, 0.95506f, 0.957285f, 0.959182f, 0.961045f},
+ {0.970675f, 0.929771f, 0.902079f, 0.883688f, 0.874158f, 0.871353f, 0.873055f, 0.877692f, 0.883998f, 0.891128f, 0.898349f, 0.90501f, 0.911219f, 0.917302f, 0.923128f, 0.928714f, 0.933918f, 0.93875f, 0.943234f, 0.947359f, 0.951162f, 0.954644f, 0.957807f, 0.960532f, 0.963028f, 0.96502f, 0.966619f, 0.967709f, 0.968388f, 0.968743f, 0.968939f, 0.969107f},
+ {0.969797f, 0.924729f, 0.89772f, 0.882373f, 0.877356f, 0.879119f, 0.884863f, 0.892627f, 0.900849f, 0.908641f, 0.916223f, 0.923627f, 0.930675f, 0.937267f, 0.943249f, 0.948668f, 0.953548f, 0.957771f, 0.961262f, 0.963879f, 0.965795f, 0.967087f, 0.967986f, 0.968618f, 0.969112f, 0.969598f, 0.97003f, 0.970412f, 0.970806f, 0.971111f, 0.971429f, 0.971676f},
+ {0.968571f, 0.918364f, 0.892897f, 0.882602f, 0.883448f, 0.890303f, 0.899597f, 0.908982f, 0.91838f, 0.92749f, 0.936094f, 0.943872f, 0.950714f, 0.956491f, 0.96096f, 0.964088f, 0.966142f, 0.967554f, 0.968578f, 0.969451f, 0.970231f, 0.970983f, 0.971692f, 0.972324f, 0.972884f, 0.973405f, 0.973905f, 0.974357f, 0.974748f, 0.975061f, 0.975408f, 0.975663f},
+ {0.965173f, 0.910926f, 0.889046f, 0.886257f, 0.893902f, 0.905002f, 0.916487f, 0.928009f, 0.93872f, 0.948183f, 0.95588f, 0.961395f, 0.964914f, 0.967118f, 0.968655f, 0.969977f, 0.97117f, 0.9723f, 0.973341f, 0.97427f, 0.975106f, 0.975873f, 0.976565f, 0.977188f, 0.977768f, 0.978231f, 0.978716f, 0.979142f, 0.97947f, 0.979811f, 0.980083f, 0.980371f},
+ {0.958495f, 0.903049f, 0.888471f, 0.895308f, 0.908717f, 0.923329f, 0.937428f, 0.949533f, 0.95859f, 0.964045f, 0.967168f, 0.96929f, 0.971163f, 0.97285f, 0.974399f, 0.97577f, 0.976987f, 0.978069f, 0.979037f, 0.97987f, 0.980611f, 0.9813f, 0.981886f, 0.982413f, 0.982955f, 0.983354f, 0.983723f, 0.984063f, 0.984398f, 0.984652f, 0.984856f, 0.985063f},
+ {0.948964f, 0.895629f, 0.894262f, 0.910481f, 0.929203f, 0.946257f, 0.958732f, 0.965248f, 0.968749f, 0.971476f, 0.973909f, 0.976056f, 0.977916f, 0.979486f, 0.980913f, 0.982035f, 0.983087f, 0.983982f, 0.984791f, 0.985417f, 0.986015f, 0.98649f, 0.987023f, 0.987391f, 0.98782f, 0.988115f, 0.988375f, 0.988643f, 0.988798f, 0.989001f, 0.98932f, 0.989353f},
+ {0.937118f, 0.893165f, 0.908694f, 0.93326f, 0.954062f, 0.964852f, 0.969648f, 0.973401f, 0.976567f, 0.979253f, 0.981432f, 0.983268f, 0.984715f, 0.985961f, 0.98706f, 0.987867f, 0.988676f, 0.989308f, 0.989769f, 0.990333f, 0.990721f, 0.991062f, 0.991439f, 0.9917f, 0.991872f, 0.992123f, 0.992216f, 0.99251f, 0.992717f, 0.992757f, 0.9929f, 0.993009f},
+ {0.924708f, 0.901613f, 0.933658f, 0.959845f, 0.969049f, 0.974478f, 0.978882f, 0.982268f, 0.984778f, 0.986833f, 0.988426f, 0.989638f, 0.990686f, 0.991441f, 0.99211f, 0.992683f, 0.993142f, 0.993536f, 0.993918f, 0.994134f, 0.994405f, 0.994602f, 0.994731f, 0.994885f, 0.995065f, 0.995196f, 0.995408f, 0.995475f, 0.995622f, 0.995727f, 0.995661f, 0.995728f},
+ {0.915237f, 0.924971f, 0.962986f, 0.973159f, 0.979981f, 0.984688f, 0.987889f, 0.989996f, 0.991679f, 0.992878f, 0.993788f, 0.994514f, 0.994998f, 0.995501f, 0.995976f, 0.996148f, 0.996387f, 0.996635f, 0.996847f, 0.996874f, 0.997059f, 0.997253f, 0.997307f, 0.997327f, 0.99745f, 0.9975f, 0.997533f, 0.997708f, 0.997762f, 0.997759f, 0.997849f, 0.997848f},
+ {0.916255f, 0.96181f, 0.977531f, 0.985756f, 0.990294f, 0.992823f, 0.994433f, 0.99559f, 0.996311f, 0.996834f, 0.997191f, 0.997456f, 0.997787f, 0.997998f, 0.998229f, 0.998384f, 0.998457f, 0.998433f, 0.998494f, 0.998608f, 0.998846f, 0.998789f, 0.998969f, 0.998877f, 0.999104f, 0.999046f, 0.99894f, 0.998958f, 0.998896f, 0.999038f, 0.99902f, 0.999228f},
+ {0.938232f, 0.980496f, 0.99117f, 0.995037f, 0.996819f, 0.997623f, 0.998332f, 0.99847f, 0.998858f, 0.999061f, 0.99919f, 0.999076f, 0.999342f, 0.999446f, 0.999543f, 0.99948f, 0.999434f, 0.999576f, 0.999513f, 0.999568f, 0.999704f, 0.999605f, 0.999723f, 0.999585f, 0.999633f, 0.999681f, 0.999639f, 0.999761f, 0.999682f, 0.999801f, 0.999803f, 0.999778f},
+ {0.969782f, 0.995572f, 0.998327f, 0.999031f, 0.999409f, 0.999456f, 0.999751f, 0.999859f, 0.999893f, 0.999819f, 0.999782f, 0.999831f, 0.999837f, 0.999896f, 0.999957f, 0.999955f, 0.999955f, 0.999942f, 0.999964f, 0.999976f, 0.999957f, 0.999954f, 0.999962f, 0.999964f, 0.999982f, 0.999974f, 0.999968f, 0.999979f, 0.999807f, 0.999926f, 0.999962f, 0.99998f},
+ {0.989677f, 0.999757f, 0.999788f, 0.999983f, 0.999994f, 0.999992f, 0.999994f, 0.999994f, 0.999999f, 0.999993f, 1.0f, 1.0f, 1.0f, 1.0f, 0.999998f, 0.999998f, 1.0f, 1.0f, 1.0f, 1.0f, 0.999996f, 0.999996f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}
+};
+
+static const float table_ggx_E_avg[32] = {
+ 0.422975f, 0.451614f, 0.481159f, 0.511595f, 0.543123f, 0.575053f, 0.60744f, 0.640006f, 0.672404f, 0.704199f, 0.735225f, 0.765683f, 0.794568f, 0.821832f, 0.847303f, 0.871297f, 0.892859f, 0.912368f, 0.929627f, 0.944333f, 0.957303f, 0.968517f, 0.976663f, 0.98424f, 0.989949f, 0.993637f, 0.996464f, 0.99818f, 0.999062f, 1.00023f, 1.00014f, 1.00005f
+};
+
+static const float table_ggx_glass_E[16][16][16] = {
+ {
+ {0.546145f, 0.554928f, 0.585355f, 0.617174f, 0.649281f, 0.681332f, 0.713313f, 0.744976f, 0.776317f, 0.807153f, 0.837756f, 0.867865f, 0.897538f, 0.926556f, 0.955152f, 0.983269f},
+ {0.551645f, 0.562942f, 0.597396f, 0.633016f, 0.668497f, 0.703397f, 0.737332f, 0.77021f, 0.801938f, 0.832256f, 0.861463f, 0.889042f, 0.915358f, 0.940463f, 0.964068f, 0.986394f},
+ {0.558163f, 0.572828f, 0.611968f, 0.651944f, 0.691117f, 0.728661f, 0.764305f, 0.797737f, 0.828922f, 0.857906f, 0.88465f, 0.909353f, 0.932072f, 0.952713f, 0.971759f, 0.989101f},
+ {0.565942f, 0.584818f, 0.629791f, 0.67474f, 0.717467f, 0.757342f, 0.793846f, 0.826921f, 0.856543f, 0.883185f, 0.906937f, 0.928087f, 0.946762f, 0.963324f, 0.978089f, 0.991121f},
+ {0.575588f, 0.600003f, 0.651733f, 0.701856f, 0.748046f, 0.789334f, 0.825551f, 0.857055f, 0.884071f, 0.907377f, 0.927335f, 0.944636f, 0.959475f, 0.972171f, 0.983223f, 0.992751f},
+ {0.587534f, 0.619243f, 0.678746f, 0.734276f, 0.782725f, 0.823985f, 0.858453f, 0.886872f, 0.910116f, 0.929464f, 0.945487f, 0.958873f, 0.970007f, 0.979376f, 0.987371f, 0.994102f},
+ {0.602621f, 0.644047f, 0.712131f, 0.771979f, 0.821102f, 0.860106f, 0.890869f, 0.914867f, 0.933558f, 0.948679f, 0.960717f, 0.97046f, 0.978469f, 0.985064f, 0.990606f, 0.995082f},
+ {0.622241f, 0.675982f, 0.752631f, 0.814525f, 0.861237f, 0.89565f, 0.920899f, 0.939713f, 0.953529f, 0.964417f, 0.972942f, 0.979727f, 0.98495f, 0.989355f, 0.992982f, 0.99591f},
+ {0.647882f, 0.717283f, 0.800443f, 0.860146f, 0.900533f, 0.928044f, 0.946791f, 0.960059f, 0.969236f, 0.976488f, 0.981957f, 0.986275f, 0.989738f, 0.992396f, 0.99457f, 0.996447f},
+ {0.68242f, 0.76935f, 0.853133f, 0.904615f, 0.935514f, 0.954804f, 0.967174f, 0.975482f, 0.980791f, 0.985194f, 0.988401f, 0.990902f, 0.992909f, 0.994567f, 0.995782f, 0.996746f},
+ {0.729096f, 0.830817f, 0.905183f, 0.943073f, 0.963073f, 0.974575f, 0.981729f, 0.986219f, 0.988659f, 0.990971f, 0.992639f, 0.993905f, 0.995049f, 0.995809f, 0.996428f, 0.996998f},
+ {0.789156f, 0.895256f, 0.948956f, 0.971336f, 0.981801f, 0.987517f, 0.990816f, 0.99266f, 0.993256f, 0.994337f, 0.995166f, 0.995713f, 0.99628f, 0.99667f, 0.996902f, 0.997157f},
+ {0.859066f, 0.949326f, 0.978616f, 0.988459f, 0.99247f, 0.99464f, 0.995801f, 0.99628f, 0.995737f, 0.996129f, 0.996486f, 0.996763f, 0.996855f, 0.997043f, 0.997051f, 0.997208f},
+ {0.923198f, 0.983437f, 0.99374f, 0.996554f, 0.997289f, 0.997815f, 0.998037f, 0.997932f, 0.996729f, 0.99701f, 0.997112f, 0.997122f, 0.997151f, 0.997181f, 0.99723f, 0.997244f},
+ {0.967523f, 0.997301f, 0.998877f, 0.999232f, 0.998936f, 0.99887f, 0.998817f, 0.998544f, 0.997149f, 0.99719f, 0.997292f, 0.997176f, 0.997165f, 0.997177f, 0.997329f, 0.99722f},
+ {0.993657f, 0.999821f, 0.999725f, 0.999639f, 0.999132f, 0.998963f, 0.998883f, 0.998629f, 0.997223f, 0.997127f, 0.997255f, 0.997299f, 0.997234f, 0.997171f, 0.997179f, 0.997287f}
+ },
+ {
+ {0.631613f, 0.585535f, 0.60389f, 0.63012f, 0.658841f, 0.688715f, 0.719004f, 0.749476f, 0.779917f, 0.810074f, 0.839943f, 0.869533f, 0.898583f, 0.927148f, 0.955291f, 0.982522f},
+ {0.643297f, 0.597422f, 0.618572f, 0.647969f, 0.679661f, 0.71191f, 0.743979f, 0.775505f, 0.806121f, 0.835601f, 0.863966f, 0.891141f, 0.917079f, 0.941526f, 0.9647f, 0.98657f},
+ {0.656436f, 0.611642f, 0.636216f, 0.668916f, 0.703763f, 0.738348f, 0.771739f, 0.803497f, 0.8336f, 0.861669f, 0.887586f, 0.911674f, 0.933799f, 0.954275f, 0.97294f, 0.989745f},
+ {0.671787f, 0.628907f, 0.657412f, 0.69396f, 0.731665f, 0.767909f, 0.801987f, 0.83317f, 0.861465f, 0.887144f, 0.910067f, 0.930601f, 0.948912f, 0.965124f, 0.979652f, 0.992398f},
+ {0.689418f, 0.649953f, 0.683015f, 0.723425f, 0.763416f, 0.800574f, 0.833967f, 0.863372f, 0.889006f, 0.911341f, 0.930665f, 0.947338f, 0.961831f, 0.974299f, 0.985131f, 0.994478f},
+ {0.710308f, 0.675785f, 0.713876f, 0.757741f, 0.79883f, 0.835433f, 0.866612f, 0.892936f, 0.914899f, 0.933343f, 0.948684f, 0.961643f, 0.972544f, 0.981751f, 0.989502f, 0.996116f},
+ {0.734531f, 0.707423f, 0.750347f, 0.796438f, 0.836942f, 0.870809f, 0.898257f, 0.920374f, 0.938042f, 0.952242f, 0.963848f, 0.973335f, 0.981043f, 0.987507f, 0.992916f, 0.99742f},
+ {0.763463f, 0.745538f, 0.792477f, 0.83811f, 0.875748f, 0.904854f, 0.927199f, 0.944194f, 0.957484f, 0.967775f, 0.975886f, 0.982365f, 0.987617f, 0.991907f, 0.995436f, 0.998383f},
+ {0.797243f, 0.790409f, 0.838764f, 0.880622f, 0.912262f, 0.935119f, 0.951644f, 0.96379f, 0.972864f, 0.979631f, 0.984944f, 0.989097f, 0.992341f, 0.995011f, 0.997214f, 0.998982f},
+ {0.835707f, 0.839576f, 0.884783f, 0.919588f, 0.943649f, 0.959666f, 0.970729f, 0.978468f, 0.984043f, 0.98819f, 0.991292f, 0.993741f, 0.995631f, 0.99718f, 0.998433f, 0.9994f},
+ {0.87631f, 0.887301f, 0.926002f, 0.951959f, 0.967963f, 0.977871f, 0.984215f, 0.988547f, 0.991591f, 0.993787f, 0.995463f, 0.996735f, 0.997747f, 0.998521f, 0.999191f, 0.999696f},
+ {0.911712f, 0.927518f, 0.958425f, 0.975578f, 0.984504f, 0.989532f, 0.992666f, 0.994708f, 0.996143f, 0.997182f, 0.997949f, 0.998526f, 0.998986f, 0.999337f, 0.999623f, 0.999866f},
+ {0.933586f, 0.957793f, 0.981399f, 0.990218f, 0.994028f, 0.996008f, 0.997254f, 0.998024f, 0.998572f, 0.998947f, 0.999234f, 0.999449f, 0.999618f, 0.999754f, 0.999868f, 0.999953f},
+ {0.943785f, 0.982754f, 0.994593f, 0.997301f, 0.998376f, 0.998932f, 0.999247f, 0.999475f, 0.999609f, 0.999713f, 0.999788f, 0.999845f, 0.999898f, 0.999926f, 0.999963f, 0.999987f},
+ {0.963548f, 0.997089f, 0.999224f, 0.999595f, 0.999763f, 0.999841f, 0.99989f, 0.999923f, 0.999943f, 0.999958f, 0.99997f, 0.999978f, 0.999985f, 0.99999f, 0.999994f, 0.999997f},
+ {0.992398f, 0.999883f, 0.999938f, 0.99995f, 0.99995f, 0.999961f, 0.999968f, 0.999957f, 0.999972f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.7033f, 0.624366f, 0.628578f, 0.647018f, 0.670764f, 0.697179f, 0.724674f, 0.752952f, 0.781676f, 0.810399f, 0.838951f, 0.867394f, 0.895481f, 0.923f, 0.950124f, 0.975904f},
+ {0.71783f, 0.640314f, 0.646483f, 0.667403f, 0.693574f, 0.721948f, 0.750909f, 0.779952f, 0.808798f, 0.836672f, 0.863665f, 0.889655f, 0.914717f, 0.938198f, 0.960705f, 0.981332f},
+ {0.73379f, 0.658809f, 0.667588f, 0.691082f, 0.719766f, 0.749734f, 0.779826f, 0.808921f, 0.83682f, 0.863278f, 0.887645f, 0.910721f, 0.932106f, 0.951828f, 0.969822f, 0.985843f},
+ {0.751787f, 0.680693f, 0.692507f, 0.718771f, 0.749456f, 0.780616f, 0.810739f, 0.838952f, 0.864925f, 0.888953f, 0.910546f, 0.929958f, 0.947602f, 0.963301f, 0.977202f, 0.989426f},
+ {0.771632f, 0.706199f, 0.721422f, 0.750329f, 0.782343f, 0.813589f, 0.842857f, 0.869098f, 0.892508f, 0.913093f, 0.931231f, 0.947079f, 0.960913f, 0.972917f, 0.983348f, 0.992309f},
+ {0.794009f, 0.736069f, 0.754824f, 0.785859f, 0.817909f, 0.848151f, 0.874727f, 0.898082f, 0.917887f, 0.934733f, 0.949146f, 0.9615f, 0.971885f, 0.980801f, 0.988265f, 0.994553f},
+ {0.81858f, 0.770343f, 0.792317f, 0.823838f, 0.854519f, 0.882076f, 0.905208f, 0.924371f, 0.940351f, 0.953406f, 0.964235f, 0.973197f, 0.980488f, 0.986779f, 0.992066f, 0.996382f},
+ {0.84565f, 0.808161f, 0.832237f, 0.862468f, 0.890477f, 0.91359f, 0.93242f, 0.947124f, 0.959126f, 0.96853f, 0.976047f, 0.982215f, 0.987344f, 0.991477f, 0.994879f, 0.997734f},
+ {0.874026f, 0.847531f, 0.872048f, 0.89919f, 0.922681f, 0.940799f, 0.954911f, 0.96549f, 0.973778f, 0.980043f, 0.985121f, 0.988998f, 0.992127f, 0.994722f, 0.996887f, 0.998578f},
+ {0.901745f, 0.88446f, 0.90746f, 0.930681f, 0.949353f, 0.962582f, 0.972388f, 0.979433f, 0.984484f, 0.988402f, 0.991401f, 0.993684f, 0.995532f, 0.997017f, 0.998276f, 0.999172f},
+ {0.92477f, 0.913415f, 0.936122f, 0.956473f, 0.970167f, 0.979084f, 0.985043f, 0.989036f, 0.99183f, 0.993909f, 0.995522f, 0.996708f, 0.997708f, 0.998436f, 0.999098f, 0.999583f},
+ {0.937524f, 0.934214f, 0.959427f, 0.976221f, 0.985122f, 0.990088f, 0.993034f, 0.994956f, 0.996266f, 0.997246f, 0.997978f, 0.998526f, 0.998961f, 0.999307f, 0.999597f, 0.999814f},
+ {0.938082f, 0.95327f, 0.979643f, 0.99008f, 0.994165f, 0.996258f, 0.997424f, 0.998121f, 0.99862f, 0.998978f, 0.999263f, 0.999442f, 0.999613f, 0.999743f, 0.999853f, 0.999932f},
+ {0.937776f, 0.978551f, 0.993783f, 0.997285f, 0.998457f, 0.998989f, 0.999303f, 0.999512f, 0.999633f, 0.999719f, 0.999798f, 0.999849f, 0.999891f, 0.999916f, 0.999962f, 0.999985f},
+ {0.959602f, 0.996313f, 0.999131f, 0.999611f, 0.999778f, 0.999847f, 0.9999f, 0.999932f, 0.999941f, 0.999959f, 0.999973f, 0.999979f, 0.999985f, 0.999988f, 0.999993f, 0.999997f},
+ {0.992047f, 0.999866f, 0.999938f, 0.999952f, 0.99995f, 0.999963f, 0.999969f, 0.999957f, 0.999972f, 0.999977f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.755135f, 0.661173f, 0.653773f, 0.664733f, 0.683312f, 0.705748f, 0.730117f, 0.755903f, 0.782496f, 0.809353f, 0.836357f, 0.863372f, 0.889953f, 0.916305f, 0.942201f, 0.966181f},
+ {0.770474f, 0.680031f, 0.674374f, 0.68761f, 0.708103f, 0.732226f, 0.757874f, 0.784137f, 0.810612f, 0.836641f, 0.862026f, 0.886647f, 0.910527f, 0.932779f, 0.954265f, 0.973625f},
+ {0.787016f, 0.701255f, 0.698294f, 0.713503f, 0.736268f, 0.761355f, 0.787675f, 0.813929f, 0.839407f, 0.863906f, 0.886723f, 0.90856f, 0.928769f, 0.94772f, 0.964805f, 0.979988f},
+ {0.805089f, 0.725584f, 0.725517f, 0.743068f, 0.767051f, 0.79318f, 0.819282f, 0.84439f, 0.867851f, 0.890054f, 0.910067f, 0.928265f, 0.945076f, 0.960184f, 0.973426f, 0.984878f},
+ {0.824429f, 0.75299f, 0.756091f, 0.775729f, 0.800469f, 0.826213f, 0.851312f, 0.874399f, 0.895384f, 0.914253f, 0.931078f, 0.945795f, 0.95901f, 0.970548f, 0.980428f, 0.989062f},
+ {0.845338f, 0.783391f, 0.789807f, 0.810953f, 0.83533f, 0.859928f, 0.882298f, 0.902505f, 0.920366f, 0.935538f, 0.948974f, 0.9606f, 0.970496f, 0.979028f, 0.986278f, 0.992331f},
+ {0.867308f, 0.816128f, 0.825491f, 0.846774f, 0.869557f, 0.891891f, 0.911074f, 0.92777f, 0.942154f, 0.953901f, 0.964055f, 0.97258f, 0.97956f, 0.98555f, 0.99069f, 0.99478f},
+ {0.889951f, 0.84958f, 0.86063f, 0.880855f, 0.901829f, 0.920435f, 0.936239f, 0.94922f, 0.960077f, 0.968704f, 0.97578f, 0.981723f, 0.9867f, 0.990652f, 0.993934f, 0.996712f},
+ {0.911502f, 0.880738f, 0.892697f, 0.911203f, 0.929411f, 0.944558f, 0.956842f, 0.966517f, 0.974198f, 0.980015f, 0.984958f, 0.988685f, 0.991689f, 0.994284f, 0.99634f, 0.99798f},
+ {0.929911f, 0.906006f, 0.918487f, 0.936132f, 0.952085f, 0.963857f, 0.973151f, 0.979774f, 0.984648f, 0.988398f, 0.991266f, 0.993529f, 0.995307f, 0.996735f, 0.997922f, 0.99883f},
+ {0.941852f, 0.922287f, 0.938595f, 0.956946f, 0.970284f, 0.979251f, 0.985269f, 0.989209f, 0.991919f, 0.993943f, 0.995489f, 0.996642f, 0.997589f, 0.998321f, 0.99894f, 0.999411f},
+ {0.943856f, 0.932884f, 0.956896f, 0.974835f, 0.98458f, 0.990057f, 0.993057f, 0.995044f, 0.996328f, 0.997257f, 0.997959f, 0.998468f, 0.998932f, 0.999239f, 0.999538f, 0.99973f},
+ {0.936692f, 0.948081f, 0.976888f, 0.989024f, 0.993894f, 0.996212f, 0.997452f, 0.998183f, 0.998637f, 0.999004f, 0.999262f, 0.999414f, 0.999597f, 0.999716f, 0.999827f, 0.999902f},
+ {0.933786f, 0.975358f, 0.99277f, 0.997021f, 0.998414f, 0.999009f, 0.999327f, 0.999521f, 0.999655f, 0.99972f, 0.999794f, 0.999843f, 0.999884f, 0.999913f, 0.999955f, 0.999978f},
+ {0.957595f, 0.99572f, 0.998989f, 0.999584f, 0.999779f, 0.999853f, 0.999905f, 0.999931f, 0.999945f, 0.999959f, 0.999972f, 0.999978f, 0.999982f, 0.999987f, 0.999992f, 0.999997f},
+ {0.991893f, 0.999849f, 0.999935f, 0.999951f, 0.999951f, 0.999963f, 0.99997f, 0.999957f, 0.999972f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.791906f, 0.69219f, 0.676114f, 0.680855f, 0.694521f, 0.713153f, 0.73442f, 0.757596f, 0.78181f, 0.806742f, 0.831895f, 0.85727f, 0.882394f, 0.907418f, 0.931743f, 0.95388f},
+ {0.807178f, 0.7128f, 0.698837f, 0.7056f, 0.721143f, 0.741125f, 0.763599f, 0.78701f, 0.811022f, 0.835147f, 0.858726f, 0.881888f, 0.904514f, 0.925531f, 0.945875f, 0.963777f},
+ {0.823371f, 0.735468f, 0.724418f, 0.733205f, 0.750747f, 0.771528f, 0.794286f, 0.81766f, 0.840677f, 0.863166f, 0.884389f, 0.904885f, 0.923826f, 0.941856f, 0.958073f, 0.972386f},
+ {0.840628f, 0.760701f, 0.752903f, 0.763847f, 0.782368f, 0.803786f, 0.826433f, 0.848464f, 0.869604f, 0.890026f, 0.908455f, 0.92551f, 0.941246f, 0.955699f, 0.968406f, 0.979107f},
+ {0.858634f, 0.788152f, 0.783764f, 0.796474f, 0.815666f, 0.836682f, 0.858106f, 0.878444f, 0.897133f, 0.914273f, 0.929764f, 0.943545f, 0.956074f, 0.967169f, 0.976656f, 0.984778f},
+ {0.877468f, 0.817314f, 0.81627f, 0.830435f, 0.849078f, 0.869064f, 0.888216f, 0.905613f, 0.921754f, 0.935558f, 0.948009f, 0.95891f, 0.968269f, 0.976576f, 0.98354f, 0.989235f},
+ {0.896459f, 0.847072f, 0.848977f, 0.863348f, 0.880767f, 0.89896f, 0.915259f, 0.930031f, 0.942873f, 0.953876f, 0.963239f, 0.971341f, 0.977941f, 0.983842f, 0.988733f, 0.99273f},
+ {0.914979f, 0.875448f, 0.879065f, 0.892873f, 0.909259f, 0.92472f, 0.938542f, 0.950336f, 0.960267f, 0.968481f, 0.975098f, 0.980933f, 0.985738f, 0.989508f, 0.992699f, 0.995372f},
+ {0.931148f, 0.899453f, 0.904363f, 0.91789f, 0.932976f, 0.94634f, 0.957716f, 0.966746f, 0.974081f, 0.979724f, 0.984545f, 0.988115f, 0.991066f, 0.993629f, 0.995614f, 0.997218f},
+ {0.943403f, 0.916273f, 0.923181f, 0.937849f, 0.952534f, 0.963889f, 0.972977f, 0.979645f, 0.984447f, 0.988114f, 0.990997f, 0.993144f, 0.994956f, 0.996364f, 0.997543f, 0.998404f},
+ {0.948976f, 0.92477f, 0.93797f, 0.955598f, 0.969266f, 0.978649f, 0.984972f, 0.988992f, 0.991794f, 0.993823f, 0.995345f, 0.996493f, 0.997425f, 0.998145f, 0.99875f, 0.999192f},
+ {0.945591f, 0.930181f, 0.953883f, 0.972831f, 0.983563f, 0.989624f, 0.992798f, 0.995004f, 0.996312f, 0.99721f, 0.997915f, 0.99841f, 0.998874f, 0.999167f, 0.999462f, 0.999627f},
+ {0.935111f, 0.944096f, 0.974462f, 0.987866f, 0.993441f, 0.996016f, 0.997409f, 0.998169f, 0.998633f, 0.998991f, 0.999237f, 0.999409f, 0.999569f, 0.999698f, 0.99979f, 0.999856f},
+ {0.931369f, 0.973258f, 0.991863f, 0.996672f, 0.99832f, 0.998987f, 0.999325f, 0.999515f, 0.999664f, 0.999726f, 0.999793f, 0.999838f, 0.999886f, 0.99991f, 0.99995f, 0.999968f},
+ {0.956476f, 0.995341f, 0.998866f, 0.999534f, 0.999764f, 0.999849f, 0.999913f, 0.99993f, 0.999946f, 0.999962f, 0.999972f, 0.999976f, 0.999982f, 0.999986f, 0.999991f, 0.999997f},
+ {0.991809f, 0.999835f, 0.999933f, 0.999951f, 0.999952f, 0.999964f, 0.99997f, 0.999957f, 0.999972f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.818297f, 0.717114f, 0.694785f, 0.694342f, 0.703768f, 0.718837f, 0.73701f, 0.757527f, 0.779494f, 0.802509f, 0.825628f, 0.849226f, 0.872765f, 0.896291f, 0.918974f, 0.939604f},
+ {0.833133f, 0.73869f, 0.718909f, 0.720566f, 0.731697f, 0.748196f, 0.767401f, 0.788233f, 0.809931f, 0.831982f, 0.853779f, 0.875361f, 0.896604f, 0.916442f, 0.935584f, 0.952167f},
+ {0.848657f, 0.762005f, 0.745546f, 0.74926f, 0.762459f, 0.77941f, 0.799137f, 0.819719f, 0.8407f, 0.861063f, 0.880752f, 0.899775f, 0.91747f, 0.934615f, 0.949879f, 0.963377f},
+ {0.8649f, 0.787208f, 0.774337f, 0.780339f, 0.79444f, 0.812079f, 0.831559f, 0.850965f, 0.869981f, 0.888585f, 0.905668f, 0.921563f, 0.936315f, 0.950173f, 0.961989f, 0.972198f},
+ {0.881461f, 0.813868f, 0.804703f, 0.812521f, 0.827306f, 0.844582f, 0.862949f, 0.880905f, 0.897513f, 0.913121f, 0.927539f, 0.940462f, 0.952246f, 0.962898f, 0.971853f, 0.979696f},
+ {0.898292f, 0.841163f, 0.835515f, 0.844687f, 0.859203f, 0.875685f, 0.892135f, 0.907546f, 0.922038f, 0.934734f, 0.946206f, 0.956606f, 0.965452f, 0.973447f, 0.980231f, 0.985548f},
+ {0.914692f, 0.867788f, 0.865073f, 0.874899f, 0.88842f, 0.903681f, 0.917781f, 0.930989f, 0.942727f, 0.953001f, 0.961885f, 0.969526f, 0.975935f, 0.981647f, 0.986401f, 0.990233f},
+ {0.929949f, 0.891663f, 0.890753f, 0.900625f, 0.913808f, 0.927174f, 0.939617f, 0.950495f, 0.959815f, 0.967745f, 0.97412f, 0.979688f, 0.984353f, 0.988026f, 0.991205f, 0.99376f},
+ {0.942335f, 0.910169f, 0.911015f, 0.921508f, 0.934511f, 0.946868f, 0.957644f, 0.96641f, 0.973551f, 0.979036f, 0.983774f, 0.987343f, 0.990262f, 0.992766f, 0.994742f, 0.9963f},
+ {0.950568f, 0.921421f, 0.925018f, 0.937993f, 0.95199f, 0.963241f, 0.97238f, 0.979133f, 0.983967f, 0.987701f, 0.990597f, 0.992658f, 0.99448f, 0.99588f, 0.997082f, 0.997929f},
+ {0.952355f, 0.925186f, 0.936368f, 0.953857f, 0.967893f, 0.977715f, 0.98436f, 0.988623f, 0.991479f, 0.993643f, 0.995152f, 0.996288f, 0.9972f, 0.997897f, 0.998529f, 0.998941f},
+ {0.94611f, 0.927807f, 0.951216f, 0.970995f, 0.982455f, 0.98904f, 0.992455f, 0.994849f, 0.996185f, 0.997122f, 0.997852f, 0.998356f, 0.998788f, 0.9991f, 0.999364f, 0.999519f},
+ {0.933846f, 0.941313f, 0.972597f, 0.986844f, 0.992965f, 0.995775f, 0.997297f, 0.998112f, 0.998611f, 0.998967f, 0.99921f, 0.999397f, 0.999559f, 0.999665f, 0.999759f, 0.999818f},
+ {0.929792f, 0.971804f, 0.9912f, 0.996412f, 0.998198f, 0.998926f, 0.999303f, 0.999503f, 0.999663f, 0.999722f, 0.999787f, 0.999828f, 0.999879f, 0.999902f, 0.999943f, 0.999962f},
+ {0.955791f, 0.995089f, 0.998764f, 0.999497f, 0.999757f, 0.99984f, 0.999911f, 0.999932f, 0.999947f, 0.999961f, 0.999973f, 0.999977f, 0.999981f, 0.999986f, 0.999991f, 0.999997f},
+ {0.991759f, 0.999829f, 0.99993f, 0.999949f, 0.999952f, 0.999964f, 0.99997f, 0.999957f, 0.999973f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.837568f, 0.736764f, 0.709849f, 0.705015f, 0.710682f, 0.722521f, 0.737955f, 0.755885f, 0.775532f, 0.796539f, 0.817642f, 0.839382f, 0.861295f, 0.883276f, 0.90439f, 0.923577f},
+ {0.851897f, 0.758842f, 0.734871f, 0.73241f, 0.739817f, 0.753067f, 0.769543f, 0.787812f, 0.807201f, 0.827387f, 0.847468f, 0.867395f, 0.887248f, 0.905785f, 0.92365f, 0.939144f},
+ {0.866683f, 0.782236f, 0.762028f, 0.761779f, 0.771356f, 0.785082f, 0.802074f, 0.820286f, 0.839085f, 0.857472f, 0.875618f, 0.893432f, 0.909954f, 0.925939f, 0.940416f, 0.953019f},
+ {0.881964f, 0.80704f, 0.7908f, 0.792982f, 0.803513f, 0.81806f, 0.834788f, 0.851956f, 0.868991f, 0.886045f, 0.901641f, 0.916558f, 0.930315f, 0.943545f, 0.954579f, 0.964278f},
+ {0.89721f, 0.832614f, 0.820307f, 0.824408f, 0.835767f, 0.850102f, 0.865923f, 0.881883f, 0.896692f, 0.911183f, 0.924448f, 0.936468f, 0.947692f, 0.957893f, 0.966472f, 0.97384f},
+ {0.91236f, 0.858027f, 0.849325f, 0.855072f, 0.866327f, 0.880159f, 0.894367f, 0.908095f, 0.921258f, 0.932981f, 0.943819f, 0.953623f, 0.962047f, 0.969655f, 0.976175f, 0.981335f},
+ {0.926661f, 0.881858f, 0.876134f, 0.882654f, 0.893459f, 0.906491f, 0.919034f, 0.930944f, 0.941911f, 0.951492f, 0.960017f, 0.967281f, 0.973553f, 0.979014f, 0.983618f, 0.987414f},
+ {0.939432f, 0.902195f, 0.898327f, 0.905337f, 0.916347f, 0.928334f, 0.939728f, 0.950069f, 0.958818f, 0.966544f, 0.97279f, 0.978102f, 0.982752f, 0.986367f, 0.989486f, 0.991995f},
+ {0.94915f, 0.916778f, 0.914804f, 0.923318f, 0.934978f, 0.946658f, 0.957017f, 0.965635f, 0.972581f, 0.978128f, 0.98279f, 0.986356f, 0.989299f, 0.991747f, 0.993668f, 0.995274f},
+ {0.954756f, 0.924187f, 0.925547f, 0.937439f, 0.950997f, 0.962317f, 0.971588f, 0.978375f, 0.983398f, 0.987116f, 0.99004f, 0.992146f, 0.993989f, 0.995358f, 0.996568f, 0.997328f},
+ {0.954147f, 0.925019f, 0.934841f, 0.952223f, 0.966499f, 0.976747f, 0.983714f, 0.988143f, 0.991088f, 0.993349f, 0.994842f, 0.996048f, 0.99692f, 0.997617f, 0.998236f, 0.998646f},
+ {0.946214f, 0.925955f, 0.94916f, 0.969447f, 0.981469f, 0.988432f, 0.992094f, 0.994611f, 0.995991f, 0.99696f, 0.997723f, 0.998246f, 0.998684f, 0.999001f, 0.99924f, 0.999398f},
+ {0.932942f, 0.939385f, 0.971199f, 0.986025f, 0.99254f, 0.995547f, 0.997144f, 0.998025f, 0.998559f, 0.998917f, 0.999172f, 0.999366f, 0.999509f, 0.999617f, 0.999716f, 0.99978f},
+ {0.928768f, 0.970817f, 0.990749f, 0.996191f, 0.998091f, 0.998875f, 0.999269f, 0.999488f, 0.999653f, 0.99972f, 0.999775f, 0.999821f, 0.999874f, 0.999901f, 0.99993f, 0.999951f},
+ {0.955373f, 0.994929f, 0.998696f, 0.999463f, 0.999746f, 0.999838f, 0.999911f, 0.999931f, 0.999944f, 0.999957f, 0.999974f, 0.999975f, 0.99998f, 0.999981f, 0.99999f, 0.999995f},
+ {0.991732f, 0.999822f, 0.999925f, 0.999948f, 0.999952f, 0.999963f, 0.99997f, 0.999956f, 0.999973f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.85191f, 0.752165f, 0.721625f, 0.713215f, 0.715498f, 0.724355f, 0.737179f, 0.752576f, 0.77016f, 0.788946f, 0.808239f, 0.828107f, 0.84855f, 0.868878f, 0.88846f, 0.906357f},
+ {0.865727f, 0.774365f, 0.747303f, 0.741452f, 0.745659f, 0.755961f, 0.76993f, 0.785771f, 0.803074f, 0.82141f, 0.839566f, 0.857874f, 0.876447f, 0.893873f, 0.910485f, 0.92501f},
+ {0.879868f, 0.797708f, 0.774755f, 0.771317f, 0.777804f, 0.788724f, 0.803228f, 0.8192f, 0.836097f, 0.852658f, 0.869432f, 0.885904f, 0.901257f, 0.916297f, 0.929892f, 0.941638f},
+ {0.894244f, 0.821913f, 0.803222f, 0.802407f, 0.810018f, 0.8219f, 0.836243f, 0.851391f, 0.866821f, 0.882399f, 0.89684f, 0.91055f, 0.923487f, 0.935716f, 0.946383f, 0.955528f},
+ {0.908373f, 0.846412f, 0.831867f, 0.833086f, 0.841702f, 0.853661f, 0.867427f, 0.881556f, 0.894904f, 0.908275f, 0.920452f, 0.931773f, 0.942417f, 0.952063f, 0.960263f, 0.967193f},
+ {0.92214f, 0.870102f, 0.859242f, 0.862387f, 0.871067f, 0.882995f, 0.895399f, 0.90759f, 0.919726f, 0.930629f, 0.940753f, 0.950036f, 0.958083f, 0.965459f, 0.971662f, 0.976646f},
+ {0.934798f, 0.891635f, 0.883776f, 0.887833f, 0.89659f, 0.90792f, 0.919242f, 0.93025f, 0.940464f, 0.949541f, 0.957803f, 0.964716f, 0.970839f, 0.976081f, 0.980542f, 0.984205f},
+ {0.945751f, 0.909202f, 0.903245f, 0.908314f, 0.917707f, 0.928643f, 0.939202f, 0.949014f, 0.95737f, 0.965008f, 0.971122f, 0.976303f, 0.980901f, 0.984408f, 0.98755f, 0.989931f},
+ {0.953568f, 0.920956f, 0.917039f, 0.92407f, 0.934846f, 0.946049f, 0.956046f, 0.964541f, 0.97153f, 0.977085f, 0.981669f, 0.985233f, 0.988217f, 0.990532f, 0.992517f, 0.994095f},
+ {0.95738f, 0.925791f, 0.925588f, 0.936673f, 0.949962f, 0.961212f, 0.970718f, 0.977523f, 0.98271f, 0.986362f, 0.989429f, 0.991495f, 0.993414f, 0.994776f, 0.995943f, 0.996728f},
+ {0.955269f, 0.924717f, 0.933603f, 0.950835f, 0.965321f, 0.975741f, 0.983004f, 0.987605f, 0.990657f, 0.993001f, 0.994559f, 0.995741f, 0.99661f, 0.997318f, 0.997923f, 0.998364f},
+ {0.946206f, 0.924639f, 0.947637f, 0.968275f, 0.980654f, 0.987918f, 0.991721f, 0.994359f, 0.995761f, 0.996839f, 0.997585f, 0.998139f, 0.998558f, 0.998847f, 0.999114f, 0.999243f},
+ {0.93236f, 0.938071f, 0.970254f, 0.985425f, 0.992197f, 0.995335f, 0.997029f, 0.997938f, 0.998507f, 0.998883f, 0.999142f, 0.999319f, 0.999465f, 0.999566f, 0.999677f, 0.999732f},
+ {0.928146f, 0.970182f, 0.990407f, 0.996019f, 0.997988f, 0.998821f, 0.99923f, 0.999469f, 0.99964f, 0.999708f, 0.999764f, 0.999811f, 0.999852f, 0.999895f, 0.999915f, 0.999942f},
+ {0.955102f, 0.994825f, 0.998663f, 0.999436f, 0.999734f, 0.999831f, 0.99991f, 0.999931f, 0.999941f, 0.999956f, 0.999968f, 0.999977f, 0.999979f, 0.999978f, 0.999989f, 0.999994f},
+ {0.991717f, 0.999819f, 0.999924f, 0.999948f, 0.999952f, 0.999963f, 0.99997f, 0.999956f, 0.999973f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.862765f, 0.764131f, 0.730767f, 0.71916f, 0.718559f, 0.724679f, 0.734864f, 0.747932f, 0.763527f, 0.780125f, 0.797611f, 0.815649f, 0.834437f, 0.853295f, 0.871492f, 0.888073f},
+ {0.876161f, 0.786441f, 0.7568f, 0.748214f, 0.749576f, 0.757164f, 0.768726f, 0.782487f, 0.797808f, 0.814241f, 0.830614f, 0.847528f, 0.864641f, 0.880858f, 0.896205f, 0.909985f},
+ {0.889704f, 0.809539f, 0.784458f, 0.77839f, 0.78223f, 0.790624f, 0.802965f, 0.816864f, 0.831972f, 0.846996f, 0.862222f, 0.87733f, 0.891487f, 0.905617f, 0.918321f, 0.9293f},
+ {0.903333f, 0.833197f, 0.812552f, 0.809429f, 0.81449f, 0.824023f, 0.836431f, 0.849617f, 0.863587f, 0.877736f, 0.890918f, 0.903733f, 0.915767f, 0.927275f, 0.937303f, 0.945977f},
+ {0.916547f, 0.856672f, 0.840394f, 0.839349f, 0.845756f, 0.855676f, 0.867619f, 0.880224f, 0.892195f, 0.904545f, 0.915742f, 0.926409f, 0.936397f, 0.94549f, 0.953309f, 0.960093f},
+ {0.929187f, 0.878868f, 0.866405f, 0.867496f, 0.874109f, 0.884379f, 0.895274f, 0.906445f, 0.917646f, 0.927798f, 0.937218f, 0.945975f, 0.953684f, 0.960716f, 0.966682f, 0.971462f},
+ {0.940571f, 0.898566f, 0.889132f, 0.891334f, 0.898481f, 0.908476f, 0.918869f, 0.929053f, 0.938655f, 0.947249f, 0.955117f, 0.961841f, 0.967646f, 0.972712f, 0.977213f, 0.980699f},
+ {0.950149f, 0.914091f, 0.906597f, 0.910123f, 0.918333f, 0.928365f, 0.938377f, 0.947729f, 0.955746f, 0.963175f, 0.969199f, 0.974311f, 0.978849f, 0.982284f, 0.98537f, 0.987785f},
+ {0.956598f, 0.923775f, 0.918477f, 0.924327f, 0.93444f, 0.945162f, 0.95504f, 0.963363f, 0.970294f, 0.975916f, 0.980461f, 0.983947f, 0.986924f, 0.989259f, 0.991279f, 0.992857f},
+ {0.959154f, 0.926795f, 0.925535f, 0.935964f, 0.94903f, 0.960231f, 0.969742f, 0.976657f, 0.981907f, 0.985621f, 0.988734f, 0.990863f, 0.992689f, 0.994138f, 0.995236f, 0.996008f},
+ {0.955995f, 0.924468f, 0.932689f, 0.94973f, 0.964333f, 0.974929f, 0.982326f, 0.98703f, 0.990202f, 0.992629f, 0.994181f, 0.995418f, 0.996343f, 0.996968f, 0.997568f, 0.997996f},
+ {0.946252f, 0.923783f, 0.946605f, 0.967366f, 0.97998f, 0.987421f, 0.991385f, 0.994093f, 0.995561f, 0.996672f, 0.997433f, 0.998012f, 0.998422f, 0.998715f, 0.998984f, 0.999102f},
+ {0.932012f, 0.937248f, 0.969594f, 0.984982f, 0.991926f, 0.995169f, 0.996916f, 0.997861f, 0.998446f, 0.998839f, 0.999085f, 0.999278f, 0.999434f, 0.999522f, 0.999622f, 0.999682f},
+ {0.92778f, 0.969808f, 0.990195f, 0.995894f, 0.997922f, 0.998769f, 0.999198f, 0.999453f, 0.999629f, 0.999694f, 0.999755f, 0.999796f, 0.999837f, 0.999883f, 0.999902f, 0.999933f},
+ {0.954945f, 0.994752f, 0.99863f, 0.999412f, 0.999724f, 0.999824f, 0.999909f, 0.999931f, 0.999941f, 0.999956f, 0.999967f, 0.999976f, 0.999978f, 0.999976f, 0.999985f, 0.999991f},
+ {0.991706f, 0.999817f, 0.999923f, 0.999948f, 0.999952f, 0.999963f, 0.99997f, 0.999956f, 0.999973f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999974f}
+ },
+ {
+ {0.87117f, 0.773478f, 0.737746f, 0.723257f, 0.72006f, 0.723647f, 0.73159f, 0.742279f, 0.755881f, 0.77029f, 0.786075f, 0.802347f, 0.819384f, 0.836806f, 0.853569f, 0.869326f},
+ {0.884158f, 0.795796f, 0.764103f, 0.752993f, 0.751808f, 0.757047f, 0.766419f, 0.778018f, 0.791387f, 0.806107f, 0.820874f, 0.836148f, 0.851992f, 0.867051f, 0.881087f, 0.894105f},
+ {0.897193f, 0.818653f, 0.791824f, 0.783455f, 0.784951f, 0.791205f, 0.801575f, 0.813517f, 0.826859f, 0.840245f, 0.854066f, 0.867971f, 0.881108f, 0.894085f, 0.905971f, 0.916447f},
+ {0.910219f, 0.841752f, 0.819608f, 0.814407f, 0.817329f, 0.824996f, 0.835448f, 0.846951f, 0.85955f, 0.872219f, 0.884421f, 0.896327f, 0.907341f, 0.918095f, 0.927445f, 0.935841f},
+ {0.922657f, 0.864426f, 0.846726f, 0.843736f, 0.848332f, 0.8565f, 0.866924f, 0.878112f, 0.888836f, 0.900162f, 0.910612f, 0.920476f, 0.929843f, 0.93849f, 0.945881f, 0.952372f},
+ {0.934391f, 0.885423f, 0.871598f, 0.870985f, 0.875979f, 0.884842f, 0.894438f, 0.904629f, 0.914874f, 0.924299f, 0.933131f, 0.94145f, 0.948769f, 0.955549f, 0.961276f, 0.965885f},
+ {0.944813f, 0.903683f, 0.892907f, 0.893655f, 0.899506f, 0.908364f, 0.917845f, 0.927402f, 0.936392f, 0.944634f, 0.952183f, 0.958657f, 0.964227f, 0.969092f, 0.973609f, 0.976964f},
+ {0.953322f, 0.917611f, 0.908865f, 0.911234f, 0.918508f, 0.927746f, 0.937292f, 0.946151f, 0.954015f, 0.961192f, 0.967056f, 0.972082f, 0.97663f, 0.979991f, 0.982995f, 0.985403f},
+ {0.958765f, 0.92578f, 0.919436f, 0.924414f, 0.933929f, 0.944303f, 0.953903f, 0.962076f, 0.968977f, 0.97452f, 0.979117f, 0.982571f, 0.985534f, 0.987818f, 0.989918f, 0.991516f},
+ {0.960459f, 0.927539f, 0.925494f, 0.93535f, 0.948172f, 0.95928f, 0.968789f, 0.975776f, 0.980982f, 0.984789f, 0.987955f, 0.990108f, 0.991955f, 0.993384f, 0.994493f, 0.995297f},
+ {0.956553f, 0.924392f, 0.932135f, 0.948955f, 0.963575f, 0.974228f, 0.981718f, 0.986488f, 0.989738f, 0.992198f, 0.993817f, 0.995048f, 0.996016f, 0.996585f, 0.997211f, 0.997639f},
+ {0.946362f, 0.923322f, 0.945985f, 0.966732f, 0.979478f, 0.987009f, 0.991067f, 0.993829f, 0.995364f, 0.996483f, 0.997253f, 0.997861f, 0.998278f, 0.998575f, 0.998839f, 0.998956f},
+ {0.931879f, 0.936811f, 0.969181f, 0.984665f, 0.991706f, 0.995039f, 0.996801f, 0.997769f, 0.998383f, 0.998789f, 0.99904f, 0.999225f, 0.99938f, 0.999481f, 0.999566f, 0.999629f},
+ {0.927626f, 0.969587f, 0.990047f, 0.995803f, 0.997869f, 0.998725f, 0.99917f, 0.999432f, 0.999612f, 0.999677f, 0.999743f, 0.999784f, 0.99983f, 0.999869f, 0.999892f, 0.999909f},
+ {0.954886f, 0.994722f, 0.998604f, 0.999405f, 0.999718f, 0.999819f, 0.999901f, 0.999927f, 0.99994f, 0.999955f, 0.999963f, 0.999973f, 0.999975f, 0.999975f, 0.999984f, 0.999989f},
+ {0.991701f, 0.999816f, 0.999923f, 0.999948f, 0.999952f, 0.999962f, 0.99997f, 0.999956f, 0.999973f, 0.999978f, 0.999969f, 0.999966f, 0.999976f, 0.999972f, 0.999971f, 0.999974f}
+ },
+ {
+ {0.877747f, 0.780883f, 0.742996f, 0.725979f, 0.720276f, 0.721584f, 0.727147f, 0.73577f, 0.74746f, 0.759975f, 0.773773f, 0.78838f, 0.803892f, 0.819738f, 0.835206f, 0.849861f},
+ {0.890437f, 0.803154f, 0.769619f, 0.756273f, 0.752772f, 0.75586f, 0.763174f, 0.772737f, 0.784325f, 0.797186f, 0.810509f, 0.82418f, 0.838674f, 0.852726f, 0.865502f, 0.877691f},
+ {0.903016f, 0.825754f, 0.797396f, 0.786968f, 0.7864f, 0.790698f, 0.799182f, 0.809329f, 0.820902f, 0.832886f, 0.845313f, 0.858026f, 0.869922f, 0.881835f, 0.893135f, 0.902931f},
+ {0.915517f, 0.848335f, 0.824852f, 0.817858f, 0.818912f, 0.824792f, 0.833618f, 0.843552f, 0.854758f, 0.86613f, 0.877177f, 0.888174f, 0.89831f, 0.908404f, 0.917352f, 0.925143f},
+ {0.927334f, 0.870321f, 0.851424f, 0.846779f, 0.849725f, 0.856368f, 0.865377f, 0.875324f, 0.88497f, 0.895235f, 0.905f, 0.914069f, 0.922817f, 0.931072f, 0.938056f, 0.944178f},
+ {0.938346f, 0.890327f, 0.875427f, 0.873281f, 0.876998f, 0.884557f, 0.893063f, 0.9022f, 0.911707f, 0.920452f, 0.928671f, 0.936515f, 0.943604f, 0.949998f, 0.955491f, 0.959952f},
+ {0.947986f, 0.907455f, 0.895621f, 0.895174f, 0.899899f, 0.907895f, 0.916439f, 0.925357f, 0.933864f, 0.941756f, 0.948879f, 0.955232f, 0.960495f, 0.965329f, 0.96974f, 0.972912f},
+ {0.955697f, 0.920194f, 0.910511f, 0.911946f, 0.918341f, 0.926907f, 0.936032f, 0.94445f, 0.952065f, 0.95907f, 0.964801f, 0.969697f, 0.974137f, 0.977583f, 0.980525f, 0.982781f},
+ {0.960396f, 0.927293f, 0.92013f, 0.924394f, 0.933401f, 0.943429f, 0.952746f, 0.960788f, 0.967585f, 0.973104f, 0.977618f, 0.981119f, 0.984027f, 0.986349f, 0.988453f, 0.989993f},
+ {0.961426f, 0.928168f, 0.925529f, 0.934943f, 0.947474f, 0.958464f, 0.967918f, 0.974878f, 0.980124f, 0.983917f, 0.987153f, 0.989318f, 0.991151f, 0.992612f, 0.99371f, 0.994486f},
+ {0.957033f, 0.924479f, 0.931826f, 0.948434f, 0.962967f, 0.973631f, 0.981151f, 0.985945f, 0.989286f, 0.991776f, 0.993382f, 0.994624f, 0.995601f, 0.996179f, 0.996832f, 0.997288f},
+ {0.946532f, 0.923184f, 0.945647f, 0.966362f, 0.979097f, 0.986728f, 0.990816f, 0.993564f, 0.995129f, 0.996286f, 0.997077f, 0.997686f, 0.998115f, 0.998438f, 0.998684f, 0.998786f},
+ {0.931906f, 0.936671f, 0.968964f, 0.984479f, 0.991552f, 0.994907f, 0.996694f, 0.997677f, 0.998291f, 0.998723f, 0.998984f, 0.999165f, 0.99933f, 0.999433f, 0.999522f, 0.99958f},
+ {0.927624f, 0.969526f, 0.989973f, 0.995746f, 0.997823f, 0.998688f, 0.999141f, 0.999415f, 0.999588f, 0.999669f, 0.999731f, 0.999762f, 0.999818f, 0.999851f, 0.999879f, 0.999897f},
+ {0.954887f, 0.994707f, 0.998592f, 0.999394f, 0.999713f, 0.999817f, 0.999897f, 0.999924f, 0.999939f, 0.999954f, 0.999962f, 0.999971f, 0.999976f, 0.999973f, 0.999982f, 0.999988f},
+ {0.991702f, 0.999815f, 0.999923f, 0.999947f, 0.999952f, 0.999962f, 0.99997f, 0.999956f, 0.999973f, 0.999978f, 0.999969f, 0.999966f, 0.999976f, 0.999972f, 0.999971f, 0.999974f}
+ },
+ {
+ {0.882977f, 0.78669f, 0.746894f, 0.727572f, 0.719627f, 0.718709f, 0.722092f, 0.728754f, 0.738316f, 0.749029f, 0.761128f, 0.774097f, 0.787947f, 0.802312f, 0.816624f, 0.830502f},
+ {0.895358f, 0.808916f, 0.773799f, 0.7584f, 0.752786f, 0.753903f, 0.759079f, 0.766832f, 0.776629f, 0.787813f, 0.799613f, 0.811772f, 0.824958f, 0.83777f, 0.849522f, 0.860857f},
+ {0.907601f, 0.83135f, 0.801585f, 0.789286f, 0.786795f, 0.789243f, 0.795902f, 0.804415f, 0.814463f, 0.825046f, 0.836104f, 0.847556f, 0.858515f, 0.869251f, 0.879759f, 0.88891f},
+ {0.919673f, 0.853465f, 0.828784f, 0.820179f, 0.819573f, 0.823793f, 0.831027f, 0.83955f, 0.849394f, 0.859493f, 0.869622f, 0.879553f, 0.888914f, 0.898326f, 0.906568f, 0.914022f},
+ {0.930956f, 0.874844f, 0.854905f, 0.848788f, 0.85031f, 0.855533f, 0.863259f, 0.871986f, 0.880561f, 0.889948f, 0.898834f, 0.907374f, 0.915474f, 0.923353f, 0.929711f, 0.935547f},
+ {0.941411f, 0.89408f, 0.87826f, 0.874849f, 0.877281f, 0.883697f, 0.891194f, 0.89953f, 0.90819f, 0.916301f, 0.923914f, 0.931342f, 0.938026f, 0.944281f, 0.949469f, 0.953744f},
+ {0.950435f, 0.910324f, 0.897619f, 0.896182f, 0.899914f, 0.906985f, 0.914796f, 0.923094f, 0.931078f, 0.938664f, 0.94546f, 0.951465f, 0.956487f, 0.961276f, 0.965436f, 0.968771f},
+ {0.957518f, 0.922155f, 0.911715f, 0.912334f, 0.918047f, 0.92595f, 0.934652f, 0.942688f, 0.949951f, 0.95679f, 0.962383f, 0.967156f, 0.971493f, 0.974836f, 0.977894f, 0.980128f},
+ {0.961658f, 0.928481f, 0.920719f, 0.924333f, 0.932857f, 0.942504f, 0.951604f, 0.959438f, 0.966116f, 0.971594f, 0.976043f, 0.979541f, 0.98248f, 0.984776f, 0.986909f, 0.988461f},
+ {0.962219f, 0.928767f, 0.925655f, 0.934658f, 0.946905f, 0.957694f, 0.967021f, 0.973998f, 0.979208f, 0.983029f, 0.986244f, 0.988426f, 0.990309f, 0.991799f, 0.992883f, 0.993719f},
+ {0.957482f, 0.924727f, 0.931764f, 0.948101f, 0.962494f, 0.973132f, 0.980627f, 0.985422f, 0.988838f, 0.991293f, 0.992952f, 0.994155f, 0.995162f, 0.995793f, 0.996428f, 0.996872f},
+ {0.946771f, 0.923294f, 0.945555f, 0.96612f, 0.978828f, 0.986438f, 0.990567f, 0.993354f, 0.994904f, 0.99609f, 0.99689f, 0.997514f, 0.997931f, 0.998266f, 0.998509f, 0.998636f},
+ {0.932051f, 0.936765f, 0.968918f, 0.984371f, 0.991426f, 0.994804f, 0.996598f, 0.997592f, 0.998227f, 0.998646f, 0.998923f, 0.999101f, 0.999271f, 0.999381f, 0.999454f, 0.999517f},
+ {0.927743f, 0.969565f, 0.98996f, 0.995715f, 0.997791f, 0.998656f, 0.999114f, 0.999399f, 0.999573f, 0.999649f, 0.999718f, 0.999748f, 0.999803f, 0.999836f, 0.999861f, 0.999883f},
+ {0.954938f, 0.99471f, 0.99859f, 0.99939f, 0.999708f, 0.999814f, 0.999894f, 0.999923f, 0.999937f, 0.999951f, 0.999959f, 0.999968f, 0.999973f, 0.999971f, 0.999978f, 0.999984f},
+ {0.991707f, 0.999816f, 0.999923f, 0.999947f, 0.999951f, 0.999962f, 0.99997f, 0.999956f, 0.999973f, 0.999978f, 0.999969f, 0.999966f, 0.999976f, 0.999972f, 0.999971f, 0.999974f}
+ },
+ {
+ {0.88718f, 0.791265f, 0.749686f, 0.728275f, 0.718228f, 0.715162f, 0.716462f, 0.721278f, 0.728961f, 0.737937f, 0.748332f, 0.759736f, 0.771954f, 0.784898f, 0.797953f, 0.810917f},
+ {0.899343f, 0.813459f, 0.776874f, 0.759595f, 0.751982f, 0.751167f, 0.754454f, 0.760382f, 0.768506f, 0.778075f, 0.788391f, 0.799165f, 0.810982f, 0.82258f, 0.833486f, 0.843918f},
+ {0.911236f, 0.835741f, 0.804707f, 0.790707f, 0.786512f, 0.787057f, 0.792158f, 0.798957f, 0.807525f, 0.81683f, 0.82656f, 0.836814f, 0.846637f, 0.856566f, 0.866175f, 0.874829f},
+ {0.922975f, 0.857485f, 0.831744f, 0.821637f, 0.819443f, 0.822148f, 0.82795f, 0.83509f, 0.843705f, 0.852616f, 0.861632f, 0.87066f, 0.879052f, 0.887896f, 0.895586f, 0.902597f},
+ {0.933824f, 0.878354f, 0.857478f, 0.850105f, 0.850241f, 0.854179f, 0.860704f, 0.868262f, 0.875808f, 0.884313f, 0.892511f, 0.900266f, 0.907834f, 0.915249f, 0.921143f, 0.926654f},
+ {0.943829f, 0.897002f, 0.880335f, 0.87583f, 0.877105f, 0.882524f, 0.889055f, 0.896473f, 0.904396f, 0.911913f, 0.918998f, 0.925969f, 0.932316f, 0.938166f, 0.943144f, 0.947488f},
+ {0.95235f, 0.912517f, 0.899088f, 0.896743f, 0.899543f, 0.90584f, 0.91296f, 0.920684f, 0.928102f, 0.935284f, 0.941791f, 0.947552f, 0.952356f, 0.956925f, 0.961032f, 0.964383f},
+ {0.958953f, 0.923707f, 0.912614f, 0.912528f, 0.917563f, 0.924883f, 0.933114f, 0.940735f, 0.947724f, 0.95444f, 0.959839f, 0.964442f, 0.968741f, 0.972099f, 0.97511f, 0.977389f},
+ {0.962657f, 0.929478f, 0.92119f, 0.924276f, 0.932297f, 0.941605f, 0.95047f, 0.958f, 0.964579f, 0.969996f, 0.974393f, 0.977923f, 0.980772f, 0.983108f, 0.985188f, 0.986875f},
+ {0.96288f, 0.929335f, 0.925846f, 0.93448f, 0.946391f, 0.956989f, 0.966176f, 0.973082f, 0.978247f, 0.982056f, 0.98529f, 0.987511f, 0.989395f, 0.990923f, 0.992051f, 0.992859f},
+ {0.957907f, 0.925126f, 0.931868f, 0.947943f, 0.962145f, 0.972694f, 0.980115f, 0.984894f, 0.988325f, 0.990804f, 0.992483f, 0.993697f, 0.994771f, 0.995353f, 0.996007f, 0.996485f},
+ {0.947059f, 0.923637f, 0.945659f, 0.966036f, 0.978634f, 0.986174f, 0.990319f, 0.993109f, 0.99469f, 0.995891f, 0.996685f, 0.997324f, 0.997742f, 0.998093f, 0.998319f, 0.99846f},
+ {0.932316f, 0.937019f, 0.968993f, 0.98433f, 0.991339f, 0.994711f, 0.996512f, 0.997512f, 0.998152f, 0.998564f, 0.998851f, 0.999032f, 0.999202f, 0.999314f, 0.999398f, 0.999459f},
+ {0.927979f, 0.969703f, 0.989979f, 0.995709f, 0.997768f, 0.998636f, 0.999094f, 0.999377f, 0.999553f, 0.999636f, 0.999704f, 0.999729f, 0.999786f, 0.999821f, 0.999844f, 0.999872f},
+ {0.955042f, 0.994732f, 0.998592f, 0.999391f, 0.999705f, 0.999812f, 0.999893f, 0.999918f, 0.999934f, 0.99995f, 0.999956f, 0.999966f, 0.999973f, 0.999969f, 0.999977f, 0.999983f},
+ {0.991714f, 0.999817f, 0.999923f, 0.999947f, 0.999951f, 0.999962f, 0.999969f, 0.999956f, 0.999973f, 0.999978f, 0.999969f, 0.999966f, 0.999976f, 0.999972f, 0.999971f, 0.999974f}
+ },
+ {
+ {0.890624f, 0.794913f, 0.751595f, 0.728315f, 0.716165f, 0.711259f, 0.710489f, 0.713487f, 0.719264f, 0.72661f, 0.735377f, 0.745399f, 0.755902f, 0.767561f, 0.779444f, 0.791432f},
+ {0.902561f, 0.817053f, 0.779069f, 0.759979f, 0.750559f, 0.747973f, 0.749392f, 0.753796f, 0.760216f, 0.768113f, 0.776937f, 0.786565f, 0.797039f, 0.80733f, 0.817108f, 0.826796f},
+ {0.914196f, 0.839209f, 0.806955f, 0.791422f, 0.785544f, 0.784497f, 0.787997f, 0.793195f, 0.800421f, 0.808331f, 0.816868f, 0.826063f, 0.83466f, 0.843702f, 0.852359f, 0.860494f},
+ {0.925655f, 0.860665f, 0.83391f, 0.822388f, 0.818834f, 0.820022f, 0.824499f, 0.830276f, 0.837635f, 0.845529f, 0.853455f, 0.861507f, 0.869202f, 0.877202f, 0.884398f, 0.891023f},
+ {0.936108f, 0.881133f, 0.85936f, 0.850771f, 0.849623f, 0.852478f, 0.857742f, 0.864299f, 0.870899f, 0.878544f, 0.8859f, 0.893041f, 0.900033f, 0.906907f, 0.91244f, 0.917751f},
+ {0.945738f, 0.899317f, 0.881803f, 0.876366f, 0.876596f, 0.880928f, 0.886643f, 0.893232f, 0.90038f, 0.907277f, 0.913822f, 0.920371f, 0.926364f, 0.931915f, 0.936756f, 0.94087f},
+ {0.953892f, 0.914299f, 0.900195f, 0.897005f, 0.89897f, 0.904506f, 0.910921f, 0.918114f, 0.92501f, 0.931694f, 0.937925f, 0.943503f, 0.94808f, 0.952466f, 0.956531f, 0.959867f},
+ {0.960106f, 0.924951f, 0.913294f, 0.912564f, 0.917012f, 0.923719f, 0.931536f, 0.93876f, 0.94542f, 0.951927f, 0.957144f, 0.961631f, 0.965882f, 0.969256f, 0.972213f, 0.974584f},
+ {0.963489f, 0.930305f, 0.92158f, 0.924196f, 0.931797f, 0.940695f, 0.949222f, 0.956532f, 0.963004f, 0.968356f, 0.972664f, 0.976165f, 0.979009f, 0.981425f, 0.983548f, 0.985218f},
+ {0.963473f, 0.92992f, 0.926131f, 0.93442f, 0.946014f, 0.956334f, 0.965333f, 0.972178f, 0.977249f, 0.981065f, 0.984335f, 0.986485f, 0.9884f, 0.98998f, 0.991134f, 0.991982f},
+ {0.958326f, 0.925614f, 0.93211f, 0.947913f, 0.961902f, 0.972276f, 0.979642f, 0.984396f, 0.987816f, 0.990302f, 0.992003f, 0.993238f, 0.99431f, 0.994931f, 0.995598f, 0.996026f},
+ {0.947422f, 0.924138f, 0.945912f, 0.966055f, 0.978472f, 0.985964f, 0.990089f, 0.992852f, 0.99445f, 0.995661f, 0.9965f, 0.997122f, 0.99754f, 0.997916f, 0.998136f, 0.998282f},
+ {0.932675f, 0.937446f, 0.969148f, 0.984324f, 0.9913f, 0.994631f, 0.996427f, 0.997433f, 0.998081f, 0.998488f, 0.998776f, 0.998951f, 0.99912f, 0.999257f, 0.999339f, 0.9994f},
+ {0.928284f, 0.969893f, 0.990039f, 0.995709f, 0.997756f, 0.998618f, 0.999072f, 0.999362f, 0.999535f, 0.999619f, 0.999689f, 0.999712f, 0.999778f, 0.999807f, 0.99983f, 0.999854f},
+ {0.955178f, 0.994767f, 0.998607f, 0.999394f, 0.9997f, 0.999809f, 0.999889f, 0.999916f, 0.999933f, 0.999949f, 0.999952f, 0.999963f, 0.999969f, 0.999967f, 0.999977f, 0.999982f},
+ {0.991724f, 0.999818f, 0.999923f, 0.999947f, 0.999951f, 0.999962f, 0.999969f, 0.999955f, 0.999973f, 0.999978f, 0.999969f, 0.999966f, 0.999976f, 0.999971f, 0.999971f, 0.999974f}
+ },
+ {
+ {0.893434f, 0.797814f, 0.752922f, 0.727812f, 0.713735f, 0.706931f, 0.704372f, 0.705642f, 0.709603f, 0.715397f, 0.722403f, 0.731039f, 0.739981f, 0.750329f, 0.761289f, 0.772331f},
+ {0.905203f, 0.819884f, 0.780557f, 0.759869f, 0.748764f, 0.74445f, 0.744254f, 0.74695f, 0.751782f, 0.758117f, 0.765638f, 0.773848f, 0.783125f, 0.79231f, 0.801129f, 0.810013f},
+ {0.916605f, 0.841987f, 0.808558f, 0.791604f, 0.78415f, 0.781576f, 0.783488f, 0.787291f, 0.793066f, 0.79974f, 0.807069f, 0.815146f, 0.822749f, 0.830759f, 0.838712f, 0.846306f},
+ {0.927836f, 0.863206f, 0.835518f, 0.822659f, 0.817761f, 0.81748f, 0.820596f, 0.825366f, 0.831471f, 0.838282f, 0.845202f, 0.852335f, 0.859172f, 0.866653f, 0.873016f, 0.879285f},
+ {0.938008f, 0.883324f, 0.860708f, 0.850965f, 0.848699f, 0.850403f, 0.854568f, 0.86014f, 0.865852f, 0.872584f, 0.879233f, 0.885634f, 0.892101f, 0.898517f, 0.90361f, 0.908631f},
+ {0.947304f, 0.901111f, 0.882892f, 0.876543f, 0.875772f, 0.879161f, 0.883957f, 0.889877f, 0.896303f, 0.902553f, 0.908637f, 0.91475f, 0.920323f, 0.925431f, 0.930243f, 0.934371f},
+ {0.955132f, 0.915713f, 0.900974f, 0.896986f, 0.898208f, 0.903074f, 0.908749f, 0.915397f, 0.921827f, 0.928078f, 0.934038f, 0.939215f, 0.94377f, 0.947926f, 0.951965f, 0.955321f},
+ {0.961061f, 0.925986f, 0.913823f, 0.912456f, 0.916355f, 0.9225f, 0.929826f, 0.936681f, 0.943031f, 0.94939f, 0.954417f, 0.958823f, 0.962909f, 0.96627f, 0.969289f, 0.971649f},
+ {0.964207f, 0.931075f, 0.921945f, 0.924141f, 0.931276f, 0.939751f, 0.947996f, 0.955015f, 0.961373f, 0.96664f, 0.970834f, 0.974377f, 0.977259f, 0.979673f, 0.981779f, 0.983545f},
+ {0.963978f, 0.930519f, 0.926508f, 0.934408f, 0.945704f, 0.955672f, 0.964484f, 0.971222f, 0.976174f, 0.980013f, 0.983308f, 0.985497f, 0.987412f, 0.989029f, 0.99017f, 0.991111f},
+ {0.958762f, 0.926217f, 0.932511f, 0.94797f, 0.961684f, 0.971881f, 0.979163f, 0.983856f, 0.987279f, 0.989795f, 0.991492f, 0.992756f, 0.993819f, 0.994449f, 0.99516f, 0.995594f},
+ {0.947832f, 0.924771f, 0.946249f, 0.966141f, 0.978386f, 0.985761f, 0.989856f, 0.992601f, 0.994222f, 0.995427f, 0.996276f, 0.996921f, 0.997338f, 0.997714f, 0.997952f, 0.998097f},
+ {0.933114f, 0.93796f, 0.969371f, 0.984371f, 0.991257f, 0.994548f, 0.996345f, 0.997353f, 0.997996f, 0.998405f, 0.998696f, 0.998877f, 0.999051f, 0.999192f, 0.999279f, 0.999336f},
+ {0.928676f, 0.970165f, 0.990118f, 0.995726f, 0.997746f, 0.998599f, 0.99905f, 0.999336f, 0.999517f, 0.999599f, 0.999669f, 0.999686f, 0.999762f, 0.999791f, 0.999811f, 0.999834f},
+ {0.955348f, 0.994803f, 0.998615f, 0.999396f, 0.999697f, 0.999803f, 0.999889f, 0.999915f, 0.999931f, 0.999947f, 0.999949f, 0.999962f, 0.999966f, 0.999967f, 0.99997f, 0.999978f},
+ {0.991734f, 0.999819f, 0.999923f, 0.999947f, 0.999951f, 0.999962f, 0.999969f, 0.999955f, 0.999973f, 0.999978f, 0.999969f, 0.999966f, 0.999976f, 0.999971f, 0.999971f, 0.999974f}
+ },
+ {
+ {0.895766f, 0.800041f, 0.753664f, 0.726898f, 0.711004f, 0.702437f, 0.698171f, 0.697751f, 0.70003f, 0.704347f, 0.7097f, 0.716982f, 0.724742f, 0.733595f, 0.743427f, 0.753685f},
+ {0.907349f, 0.822096f, 0.781567f, 0.75938f, 0.746575f, 0.74062f, 0.738894f, 0.73996f, 0.743312f, 0.748194f, 0.754427f, 0.761379f, 0.769242f, 0.777495f, 0.785436f, 0.793383f},
+ {0.918598f, 0.844123f, 0.809641f, 0.791319f, 0.7824f, 0.77837f, 0.778798f, 0.781282f, 0.785739f, 0.791183f, 0.797331f, 0.804284f, 0.810899f, 0.817841f, 0.825218f, 0.832207f},
+ {0.929631f, 0.865211f, 0.836575f, 0.822486f, 0.816343f, 0.814767f, 0.816643f, 0.820147f, 0.825207f, 0.831048f, 0.837014f, 0.843117f, 0.849265f, 0.855874f, 0.861713f, 0.86756f},
+ {0.939552f, 0.885097f, 0.861661f, 0.850918f, 0.847426f, 0.848121f, 0.851277f, 0.855917f, 0.860636f, 0.86656f, 0.872519f, 0.878149f, 0.884097f, 0.890198f, 0.894954f, 0.899522f},
+ {0.948613f, 0.902507f, 0.883647f, 0.876371f, 0.874718f, 0.877191f, 0.881224f, 0.886323f, 0.892109f, 0.897762f, 0.90331f, 0.90898f, 0.914114f, 0.919126f, 0.923574f, 0.927664f},
+ {0.956161f, 0.916811f, 0.901554f, 0.89681f, 0.897271f, 0.901427f, 0.906562f, 0.91262f, 0.918545f, 0.924355f, 0.929955f, 0.935019f, 0.939407f, 0.943388f, 0.947411f, 0.950763f},
+ {0.961875f, 0.926812f, 0.914214f, 0.912295f, 0.915596f, 0.921195f, 0.928058f, 0.93455f, 0.940557f, 0.946781f, 0.951559f, 0.955916f, 0.959969f, 0.963305f, 0.966318f, 0.96869f},
+ {0.964815f, 0.931745f, 0.922315f, 0.924067f, 0.930668f, 0.938737f, 0.946705f, 0.953519f, 0.959637f, 0.964868f, 0.969074f, 0.972498f, 0.975442f, 0.977914f, 0.980016f, 0.981782f},
+ {0.964467f, 0.931144f, 0.926877f, 0.934474f, 0.945292f, 0.955041f, 0.963646f, 0.970267f, 0.975109f, 0.978975f, 0.982244f, 0.984445f, 0.9864f, 0.988078f, 0.989237f, 0.990188f},
+ {0.959202f, 0.926855f, 0.932978f, 0.948112f, 0.961503f, 0.97153f, 0.978656f, 0.983336f, 0.986739f, 0.989265f, 0.990959f, 0.992223f, 0.993323f, 0.993972f, 0.994708f, 0.995183f},
+ {0.948301f, 0.925526f, 0.946736f, 0.966259f, 0.978299f, 0.985574f, 0.989635f, 0.992358f, 0.993987f, 0.995201f, 0.996059f, 0.996718f, 0.997147f, 0.997501f, 0.997776f, 0.997928f},
+ {0.933641f, 0.938601f, 0.969659f, 0.984442f, 0.991226f, 0.994473f, 0.996258f, 0.997281f, 0.997916f, 0.998332f, 0.998633f, 0.998808f, 0.998971f, 0.999132f, 0.999212f, 0.999281f},
+ {0.929114f, 0.970469f, 0.990208f, 0.995737f, 0.997744f, 0.99858f, 0.999031f, 0.999318f, 0.999502f, 0.99958f, 0.999644f, 0.999669f, 0.999741f, 0.999768f, 0.999797f, 0.999821f},
+ {0.955539f, 0.994859f, 0.998629f, 0.999398f, 0.999695f, 0.999801f, 0.999885f, 0.999914f, 0.999925f, 0.999945f, 0.999946f, 0.999959f, 0.999961f, 0.999964f, 0.999968f, 0.999974f},
+ {0.991748f, 0.99982f, 0.999924f, 0.999947f, 0.999951f, 0.999962f, 0.999969f, 0.999955f, 0.999973f, 0.999978f, 0.999969f, 0.999965f, 0.999976f, 0.999971f, 0.999971f, 0.999972f}
+ }
+};
+
+static const float table_ggx_glass_inv_E[16][16][16] = {
+ {
+ {0.467207f, 0.538927f, 0.574659f, 0.608772f, 0.642304f, 0.675257f, 0.707957f, 0.740158f, 0.771917f, 0.803155f, 0.83407f, 0.864431f, 0.894363f, 0.923674f, 0.952321f, 0.980283f},
+ {0.464609f, 0.544532f, 0.584937f, 0.623371f, 0.660449f, 0.696496f, 0.731308f, 0.764927f, 0.797233f, 0.82808f, 0.85774f, 0.885719f, 0.912446f, 0.937796f, 0.96165f, 0.984053f},
+ {0.461956f, 0.551493f, 0.597421f, 0.640579f, 0.681798f, 0.720813f, 0.757636f, 0.792069f, 0.824053f, 0.85368f, 0.881081f, 0.906327f, 0.929485f, 0.950494f, 0.969874f, 0.987302f},
+ {0.45894f, 0.559813f, 0.612552f, 0.661377f, 0.706645f, 0.748464f, 0.786586f, 0.820906f, 0.851626f, 0.879155f, 0.903579f, 0.925338f, 0.944554f, 0.961512f, 0.976562f, 0.989744f},
+ {0.456133f, 0.570329f, 0.631129f, 0.685976f, 0.73567f, 0.779491f, 0.817903f, 0.850987f, 0.879359f, 0.903643f, 0.924492f, 0.942345f, 0.957678f, 0.970785f, 0.982122f, 0.991754f},
+ {0.453071f, 0.583454f, 0.65385f, 0.715586f, 0.768731f, 0.813542f, 0.850635f, 0.881055f, 0.905815f, 0.926283f, 0.943045f, 0.957066f, 0.968633f, 0.9783f, 0.986587f, 0.993419f},
+ {0.451459f, 0.600348f, 0.681926f, 0.750265f, 0.805757f, 0.84933f, 0.883432f, 0.909636f, 0.929928f, 0.946092f, 0.958852f, 0.969084f, 0.977468f, 0.984297f, 0.990051f, 0.994624f},
+ {0.451195f, 0.62222f, 0.716361f, 0.789977f, 0.845362f, 0.885478f, 0.914407f, 0.935464f, 0.950656f, 0.962478f, 0.971595f, 0.978785f, 0.984267f, 0.988836f, 0.992629f, 0.995593f},
+ {0.454655f, 0.650514f, 0.757753f, 0.833856f, 0.8855f, 0.91928f, 0.941692f, 0.956897f, 0.967189f, 0.975121f, 0.981058f, 0.985686f, 0.9893f, 0.992086f, 0.99434f, 0.996262f},
+ {0.466375f, 0.687794f, 0.805606f, 0.879126f, 0.922795f, 0.948203f, 0.963606f, 0.97338f, 0.979543f, 0.984405f, 0.98786f, 0.990528f, 0.992651f, 0.994388f, 0.995646f, 0.996643f},
+ {0.494072f, 0.736034f, 0.857614f, 0.922007f, 0.954045f, 0.970447f, 0.979529f, 0.985027f, 0.987903f, 0.990558f, 0.992345f, 0.993723f, 0.994905f, 0.995714f, 0.996365f, 0.996948f},
+ {0.54918f, 0.796767f, 0.91f, 0.957384f, 0.976739f, 0.985349f, 0.989745f, 0.992093f, 0.99292f, 0.994137f, 0.995029f, 0.995624f, 0.996217f, 0.996624f, 0.996871f, 0.997133f},
+ {0.643871f, 0.870216f, 0.955899f, 0.981825f, 0.990287f, 0.993789f, 0.995402f, 0.996054f, 0.995607f, 0.99605f, 0.996438f, 0.996734f, 0.996834f, 0.997026f, 0.997038f, 0.997198f},
+ {0.77505f, 0.944715f, 0.986041f, 0.994556f, 0.996691f, 0.99757f, 0.997928f, 0.997881f, 0.996692f, 0.996987f, 0.997098f, 0.997113f, 0.997145f, 0.997175f, 0.997226f, 0.997242f},
+ {0.910815f, 0.989663f, 0.997687f, 0.998948f, 0.99884f, 0.998825f, 0.998798f, 0.998538f, 0.997143f, 0.997186f, 0.997289f, 0.997175f, 0.997165f, 0.997177f, 0.997328f, 0.99722f},
+ {0.988773f, 0.999559f, 0.999684f, 0.999632f, 0.999128f, 0.998962f, 0.998883f, 0.998629f, 0.997223f, 0.997127f, 0.997255f, 0.997299f, 0.997234f, 0.997171f, 0.997179f, 0.997287f}
+ },
+
+ {
+ {0.331776f, 0.492473f, 0.54275f, 0.58052f, 0.615581f, 0.650102f, 0.683863f, 0.717645f, 0.750486f, 0.782911f, 0.814667f, 0.845786f, 0.876317f, 0.905953f, 0.934498f, 0.958563f},
+ {0.322602f, 0.492259f, 0.548848f, 0.591202f, 0.629944f, 0.667743f, 0.704394f, 0.740062f, 0.774339f, 0.807034f, 0.838191f, 0.867899f, 0.895982f, 0.922349f, 0.947096f, 0.967158f},
+ {0.313884f, 0.492341f, 0.556257f, 0.603478f, 0.646619f, 0.687837f, 0.727374f, 0.764869f, 0.799831f, 0.832292f, 0.862188f, 0.889588f, 0.914668f, 0.937611f, 0.958241f, 0.974788f},
+ {0.306584f, 0.492486f, 0.564964f, 0.618144f, 0.665772f, 0.710574f, 0.752767f, 0.791556f, 0.826674f, 0.858133f, 0.886068f, 0.910543f, 0.93235f, 0.951393f, 0.967994f, 0.980979f},
+ {0.302228f, 0.493724f, 0.575805f, 0.635368f, 0.687856f, 0.736327f, 0.780757f, 0.820176f, 0.854453f, 0.883836f, 0.908819f, 0.930057f, 0.948134f, 0.963338f, 0.97616f, 0.986112f},
+ {0.302604f, 0.497132f, 0.589276f, 0.65601f, 0.713326f, 0.764997f, 0.810677f, 0.849865f, 0.882233f, 0.908671f, 0.930141f, 0.947615f, 0.961814f, 0.973482f, 0.983032f, 0.990239f},
+ {0.311866f, 0.503628f, 0.606047f, 0.680282f, 0.742333f, 0.796606f, 0.842505f, 0.880074f, 0.909306f, 0.931619f, 0.949066f, 0.962478f, 0.973166f, 0.981543f, 0.988346f, 0.993396f},
+ {0.334117f, 0.51637f, 0.627737f, 0.708995f, 0.775339f, 0.83081f, 0.87527f, 0.909366f, 0.933935f, 0.951815f, 0.964865f, 0.974633f, 0.982087f, 0.98786f, 0.992355f, 0.995724f},
+ {0.37616f, 0.540195f, 0.656277f, 0.743628f, 0.812714f, 0.86728f, 0.907718f, 0.936156f, 0.955518f, 0.968451f, 0.977528f, 0.98398f, 0.988883f, 0.992473f, 0.995349f, 0.997396f},
+ {0.444909f, 0.580253f, 0.694618f, 0.785468f, 0.854731f, 0.904603f, 0.937922f, 0.959346f, 0.972722f, 0.981115f, 0.986813f, 0.990738f, 0.993523f, 0.99568f, 0.997376f, 0.99854f},
+ {0.540913f, 0.642909f, 0.747808f, 0.836981f, 0.90045f, 0.940121f, 0.963532f, 0.977101f, 0.985125f, 0.98995f, 0.993016f, 0.995111f, 0.996642f, 0.997782f, 0.99864f, 0.999226f},
+ {0.655892f, 0.730559f, 0.819629f, 0.895723f, 0.944071f, 0.969216f, 0.98198f, 0.989137f, 0.993044f, 0.995314f, 0.996787f, 0.997799f, 0.998483f, 0.998986f, 0.999396f, 0.999651f},
+ {0.767441f, 0.835319f, 0.902341f, 0.949704f, 0.976619f, 0.987855f, 0.993068f, 0.995822f, 0.997367f, 0.998242f, 0.998795f, 0.999172f, 0.999436f, 0.999621f, 0.999777f, 0.999871f},
+ {0.860268f, 0.935274f, 0.966945f, 0.984092f, 0.993497f, 0.996752f, 0.998115f, 0.998871f, 0.999308f, 0.999513f, 0.999674f, 0.999771f, 0.999844f, 0.999896f, 0.999942f, 0.999961f},
+ {0.939241f, 0.989576f, 0.994816f, 0.997406f, 0.999071f, 0.999539f, 0.999731f, 0.999832f, 0.999896f, 0.999931f, 0.999949f, 0.999969f, 0.999977f, 0.999986f, 0.99999f, 0.999995f},
+ {0.990906f, 0.999677f, 0.999807f, 0.999874f, 0.99993f, 0.999952f, 0.999963f, 0.999954f, 0.99997f, 0.999978f, 0.999968f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.256904f, 0.424754f, 0.496329f, 0.541f, 0.577161f, 0.610539f, 0.643f, 0.675636f, 0.708369f, 0.741092f, 0.773355f, 0.80506f, 0.835457f, 0.864645f, 0.89056f, 0.90455f},
+ {0.256637f, 0.421044f, 0.498777f, 0.548196f, 0.58799f, 0.624202f, 0.659399f, 0.694031f, 0.728631f, 0.762539f, 0.795678f, 0.827183f, 0.857095f, 0.884656f, 0.909124f, 0.923263f},
+ {0.260348f, 0.418234f, 0.501961f, 0.556894f, 0.600553f, 0.639889f, 0.6775f, 0.71432f, 0.750706f, 0.785707f, 0.81925f, 0.850363f, 0.878689f, 0.904429f, 0.926475f, 0.940143f},
+ {0.270219f, 0.418368f, 0.50699f, 0.567241f, 0.615318f, 0.657666f, 0.697777f, 0.736644f, 0.774409f, 0.810466f, 0.84373f, 0.873585f, 0.899967f, 0.923266f, 0.942284f, 0.954443f},
+ {0.288652f, 0.424105f, 0.515123f, 0.58019f, 0.632592f, 0.678303f, 0.720819f, 0.76136f, 0.800106f, 0.836255f, 0.868657f, 0.896684f, 0.920475f, 0.940283f, 0.956331f, 0.966379f},
+ {0.318977f, 0.436583f, 0.527232f, 0.596754f, 0.653232f, 0.701882f, 0.746601f, 0.78854f, 0.827661f, 0.863311f, 0.893631f, 0.918971f, 0.939366f, 0.955602f, 0.968137f, 0.976146f},
+ {0.363206f, 0.460856f, 0.546377f, 0.618231f, 0.677949f, 0.729701f, 0.776126f, 0.818725f, 0.857302f, 0.890705f, 0.918218f, 0.939441f, 0.955885f, 0.96848f, 0.977766f, 0.983681f},
+ {0.424515f, 0.501089f, 0.575559f, 0.646174f, 0.708432f, 0.762509f, 0.810299f, 0.852203f, 0.888208f, 0.917752f, 0.940618f, 0.957515f, 0.969877f, 0.978848f, 0.98533f, 0.989367f},
+ {0.502553f, 0.557605f, 0.618782f, 0.683938f, 0.746765f, 0.802128f, 0.849225f, 0.888143f, 0.919084f, 0.942748f, 0.960251f, 0.972378f, 0.980698f, 0.986699f, 0.990911f, 0.993465f},
+ {0.592986f, 0.631644f, 0.678726f, 0.734988f, 0.7948f, 0.848594f, 0.891821f, 0.924174f, 0.94746f, 0.964093f, 0.975778f, 0.983457f, 0.988777f, 0.992312f, 0.994813f, 0.996281f},
+ {0.687377f, 0.714248f, 0.753773f, 0.800942f, 0.852108f, 0.898733f, 0.933333f, 0.955821f, 0.97041f, 0.980304f, 0.986956f, 0.99124f, 0.994077f, 0.996003f, 0.997313f, 0.998074f},
+ {0.770882f, 0.79523f, 0.83876f, 0.87676f, 0.911536f, 0.944101f, 0.966593f, 0.978906f, 0.986079f, 0.990761f, 0.993961f, 0.995955f, 0.997319f, 0.998217f, 0.998788f, 0.999133f},
+ {0.835431f, 0.873433f, 0.92092f, 0.944318f, 0.960154f, 0.976041f, 0.987186f, 0.992157f, 0.994831f, 0.996532f, 0.997669f, 0.998502f, 0.998984f, 0.999324f, 0.999555f, 0.999681f},
+ {0.886285f, 0.948097f, 0.976424f, 0.98447f, 0.987702f, 0.992719f, 0.99661f, 0.997933f, 0.998634f, 0.999061f, 0.999395f, 0.999581f, 0.999729f, 0.999819f, 0.999886f, 0.99992f},
+ {0.944359f, 0.99137f, 0.996669f, 0.99791f, 0.998076f, 0.998807f, 0.999526f, 0.999714f, 0.999805f, 0.999864f, 0.999907f, 0.99994f, 0.999961f, 0.999967f, 0.999978f, 0.999993f},
+ {0.991143f, 0.999719f, 0.999863f, 0.999898f, 0.999893f, 0.999925f, 0.999958f, 0.999949f, 0.999969f, 0.999976f, 0.999967f, 0.999965f, 0.999976f, 0.999972f, 0.999972f, 0.999975f}
+ },
+ {
+ {0.264585f, 0.380989f, 0.454393f, 0.503716f, 0.54096f, 0.573291f, 0.602941f, 0.631997f, 0.660964f, 0.690201f, 0.719512f, 0.748977f, 0.777784f, 0.803781f, 0.821673f, 0.826875f},
+ {0.277732f, 0.383596f, 0.457525f, 0.509819f, 0.550482f, 0.585225f, 0.617104f, 0.647916f, 0.678334f, 0.708938f, 0.739772f, 0.770601f, 0.800401f, 0.827885f, 0.848226f, 0.858468f},
+ {0.297496f, 0.390598f, 0.463136f, 0.517902f, 0.56183f, 0.5992f, 0.633399f, 0.665758f, 0.697656f, 0.729799f, 0.761682f, 0.793706f, 0.824544f, 0.852764f, 0.874231f, 0.887592f},
+ {0.326267f, 0.404597f, 0.473285f, 0.529043f, 0.57572f, 0.615744f, 0.651933f, 0.685996f, 0.719357f, 0.752568f, 0.78587f, 0.818445f, 0.849566f, 0.877518f, 0.89911f, 0.912971f},
+ {0.364065f, 0.427977f, 0.489784f, 0.544678f, 0.593086f, 0.635453f, 0.673594f, 0.709267f, 0.744133f, 0.77849f, 0.812188f, 0.844951f, 0.875402f, 0.901525f, 0.921826f, 0.934905f},
+ {0.413338f, 0.462718f, 0.51532f, 0.566394f, 0.614844f, 0.658715f, 0.699065f, 0.736491f, 0.772566f, 0.807468f, 0.841022f, 0.872546f, 0.901018f, 0.9245f, 0.9418f, 0.953305f},
+ {0.47433f, 0.510329f, 0.552084f, 0.596886f, 0.643299f, 0.687754f, 0.729747f, 0.768691f, 0.80548f, 0.8399f, 0.871764f, 0.900638f, 0.925231f, 0.944736f, 0.958796f, 0.967747f},
+ {0.544959f, 0.570248f, 0.601173f, 0.637774f, 0.679581f, 0.723945f, 0.766767f, 0.806354f, 0.842948f, 0.875258f, 0.903389f, 0.927466f, 0.947312f, 0.962232f, 0.972586f, 0.978895f},
+ {0.6222f, 0.638229f, 0.661379f, 0.690631f, 0.72677f, 0.768451f, 0.810514f, 0.849477f, 0.883368f, 0.911109f, 0.93332f, 0.951218f, 0.965418f, 0.975785f, 0.982781f, 0.987031f},
+ {0.699547f, 0.708814f, 0.728904f, 0.755107f, 0.786019f, 0.821987f, 0.859796f, 0.894699f, 0.922949f, 0.943679f, 0.958869f, 0.970413f, 0.979505f, 0.98593f, 0.990077f, 0.992511f},
+ {0.770313f, 0.772954f, 0.797454f, 0.826894f, 0.854083f, 0.880596f, 0.909153f, 0.936118f, 0.956346f, 0.96926f, 0.977842f, 0.984166f, 0.989052f, 0.992586f, 0.994846f, 0.996153f},
+ {0.825324f, 0.829644f, 0.86696f, 0.898979f, 0.920101f, 0.934728f, 0.950628f, 0.967633f, 0.979593f, 0.986058f, 0.989888f, 0.992809f, 0.995032f, 0.996639f, 0.997636f, 0.998231f},
+ {0.863698f, 0.888044f, 0.93283f, 0.956652f, 0.968193f, 0.973147f, 0.978605f, 0.986924f, 0.992497f, 0.994971f, 0.996334f, 0.997324f, 0.99812f, 0.99872f, 0.999111f, 0.999357f},
+ {0.896649f, 0.951907f, 0.979323f, 0.988331f, 0.991859f, 0.992727f, 0.993374f, 0.996207f, 0.998059f, 0.998683f, 0.999045f, 0.999279f, 0.999495f, 0.999651f, 0.999771f, 0.999839f},
+ {0.946504f, 0.991866f, 0.997096f, 0.998411f, 0.998961f, 0.999007f, 0.998924f, 0.999404f, 0.999715f, 0.999807f, 0.999858f, 0.999894f, 0.999925f, 0.999948f, 0.99997f, 0.999976f},
+ {0.991229f, 0.999729f, 0.999872f, 0.99992f, 0.999927f, 0.999937f, 0.999938f, 0.999939f, 0.999966f, 0.999974f, 0.999966f, 0.999961f, 0.999976f, 0.999972f, 0.999972f, 0.999973f}
+ },
+ {
+ {0.317672f, 0.379772f, 0.434995f, 0.478433f, 0.513252f, 0.543012f, 0.569608f, 0.594619f, 0.618758f, 0.642435f, 0.665975f, 0.688625f, 0.710007f, 0.726249f, 0.732969f, 0.737468f},
+ {0.34194f, 0.393822f, 0.444657f, 0.487584f, 0.52402f, 0.555426f, 0.583729f, 0.610112f, 0.635474f, 0.660523f, 0.68545f, 0.710145f, 0.734133f, 0.754925f, 0.768756f, 0.781315f},
+ {0.372936f, 0.41426f, 0.459314f, 0.500417f, 0.53751f, 0.570438f, 0.600301f, 0.628293f, 0.654918f, 0.681319f, 0.70749f, 0.734155f, 0.760681f, 0.785337f, 0.804356f, 0.822369f},
+ {0.412386f, 0.443328f, 0.480816f, 0.518452f, 0.554844f, 0.588701f, 0.619944f, 0.649243f, 0.677332f, 0.704851f, 0.732926f, 0.761178f, 0.789821f, 0.816979f, 0.839927f, 0.860467f},
+ {0.459182f, 0.480803f, 0.510698f, 0.543466f, 0.577691f, 0.611229f, 0.643044f, 0.674001f, 0.703592f, 0.732581f, 0.761858f, 0.791634f, 0.82104f, 0.849167f, 0.873217f, 0.893996f},
+ {0.514798f, 0.528562f, 0.550377f, 0.576799f, 0.606945f, 0.638741f, 0.671324f, 0.703154f, 0.734342f, 0.764995f, 0.795377f, 0.825267f, 0.854095f, 0.880996f, 0.903836f, 0.922661f},
+ {0.576429f, 0.583964f, 0.599092f, 0.619577f, 0.644143f, 0.673295f, 0.705428f, 0.73839f, 0.77082f, 0.802373f, 0.832844f, 0.861325f, 0.887556f, 0.911092f, 0.930845f, 0.94606f},
+ {0.642323f, 0.645034f, 0.655166f, 0.670406f, 0.690854f, 0.716584f, 0.747033f, 0.780057f, 0.812784f, 0.843988f, 0.872615f, 0.897819f, 0.91928f, 0.937816f, 0.953006f, 0.964439f},
+ {0.707651f, 0.705863f, 0.713653f, 0.727617f, 0.746742f, 0.769487f, 0.796892f, 0.82727f, 0.85825f, 0.886988f, 0.911665f, 0.931306f, 0.946921f, 0.959863f, 0.970274f, 0.977884f},
+ {0.768305f, 0.761011f, 0.770667f, 0.788632f, 0.809512f, 0.830379f, 0.852541f, 0.877292f, 0.90318f, 0.926979f, 0.945545f, 0.958815f, 0.968652f, 0.976559f, 0.982819f, 0.987355f},
+ {0.819533f, 0.807633f, 0.825012f, 0.851067f, 0.874615f, 0.893058f, 0.907921f, 0.923517f, 0.941923f, 0.959031f, 0.970957f, 0.978474f, 0.983602f, 0.98763f, 0.99097f, 0.99347f},
+ {0.856481f, 0.848157f, 0.88085f, 0.911788f, 0.932947f, 0.946153f, 0.953749f, 0.959831f, 0.970164f, 0.980711f, 0.986951f, 0.99046f, 0.992739f, 0.994419f, 0.995858f, 0.996993f},
+ {0.879455f, 0.895342f, 0.938113f, 0.961698f, 0.973822f, 0.979847f, 0.982648f, 0.983368f, 0.987279f, 0.992764f, 0.995312f, 0.996578f, 0.997372f, 0.997933f, 0.998501f, 0.998916f},
+ {0.902488f, 0.953905f, 0.980707f, 0.989527f, 0.99321f, 0.994913f, 0.995672f, 0.995206f, 0.996094f, 0.998062f, 0.998778f, 0.999099f, 0.999288f, 0.999444f, 0.999577f, 0.999716f},
+ {0.947838f, 0.99217f, 0.997259f, 0.998559f, 0.999105f, 0.999327f, 0.999431f, 0.99931f, 0.999346f, 0.999717f, 0.99982f, 0.999867f, 0.999898f, 0.999922f, 0.999947f, 0.999962f},
+ {0.991276f, 0.999736f, 0.999882f, 0.999921f, 0.999937f, 0.999945f, 0.999952f, 0.999937f, 0.999953f, 0.999971f, 0.999965f, 0.99996f, 0.999975f, 0.99997f, 0.99997f, 0.999973f}
+ },
+ {
+ {0.389232f, 0.4106f, 0.441287f, 0.471024f, 0.498133f, 0.522389f, 0.544754f, 0.564854f, 0.583887f, 0.601715f, 0.61798f, 0.632338f, 0.641487f, 0.642305f, 0.642109f, 0.645058f},
+ {0.419866f, 0.433959f, 0.459285f, 0.486614f, 0.512656f, 0.537534f, 0.56031f, 0.581903f, 0.602083f, 0.621111f, 0.639131f, 0.655627f, 0.669362f, 0.677087f, 0.685536f, 0.69844f},
+ {0.457074f, 0.464442f, 0.483894f, 0.506939f, 0.531485f, 0.556034f, 0.579539f, 0.601915f, 0.623243f, 0.643633f, 0.663162f, 0.682512f, 0.700151f, 0.714379f, 0.729927f, 0.750548f},
+ {0.500718f, 0.502026f, 0.515138f, 0.534071f, 0.555887f, 0.578839f, 0.602149f, 0.625411f, 0.647713f, 0.6697f, 0.6915f, 0.713411f, 0.734647f, 0.753837f, 0.775004f, 0.799966f},
+ {0.549321f, 0.546636f, 0.554598f, 0.56844f, 0.58618f, 0.606839f, 0.62957f, 0.653197f, 0.6769f, 0.700492f, 0.724456f, 0.748843f, 0.772559f, 0.795413f, 0.819034f, 0.845355f},
+ {0.603212f, 0.59682f, 0.600127f, 0.610079f, 0.623859f, 0.641501f, 0.66259f, 0.686419f, 0.711285f, 0.736487f, 0.762277f, 0.788308f, 0.813579f, 0.837172f, 0.860793f, 0.885258f},
+ {0.659187f, 0.650636f, 0.651303f, 0.657924f, 0.668481f, 0.683561f, 0.70242f, 0.725576f, 0.751116f, 0.777973f, 0.804939f, 0.831435f, 0.855943f, 0.877751f, 0.898556f, 0.919262f},
+ {0.71551f, 0.704609f, 0.703716f, 0.708983f, 0.718526f, 0.732501f, 0.75024f, 0.771848f, 0.796942f, 0.823383f, 0.850091f, 0.875083f, 0.896821f, 0.914699f, 0.930683f, 0.946116f},
+ {0.768218f, 0.754625f, 0.753729f, 0.761135f, 0.773317f, 0.788683f, 0.80554f, 0.8244f, 0.846324f, 0.870275f, 0.894278f, 0.915623f, 0.932582f, 0.945417f, 0.956229f, 0.966498f},
+ {0.815168f, 0.796799f, 0.799071f, 0.812766f, 0.830588f, 0.848294f, 0.864463f, 0.879108f, 0.895118f, 0.913632f, 0.932964f, 0.949149f, 0.960601f, 0.968452f, 0.974828f, 0.980732f},
+ {0.852166f, 0.829841f, 0.841897f, 0.865298f, 0.888307f, 0.9063f, 0.919384f, 0.92889f, 0.937434f, 0.948938f, 0.962664f, 0.973255f, 0.979758f, 0.983791f, 0.986941f, 0.990001f},
+ {0.876614f, 0.859595f, 0.888882f, 0.918553f, 0.939569f, 0.953198f, 0.961563f, 0.966168f, 0.968709f, 0.97368f, 0.982199f, 0.988093f, 0.991157f, 0.992837f, 0.994129f, 0.995457f},
+ {0.889616f, 0.899825f, 0.941002f, 0.964038f, 0.976181f, 0.982571f, 0.986116f, 0.987916f, 0.987746f, 0.988747f, 0.993139f, 0.995725f, 0.996832f, 0.997418f, 0.997862f, 0.998328f},
+ {0.906243f, 0.95518f, 0.981506f, 0.990171f, 0.993785f, 0.995553f, 0.996545f, 0.996982f, 0.996721f, 0.996453f, 0.998093f, 0.998888f, 0.999156f, 0.999327f, 0.999409f, 0.999539f},
+ {0.948599f, 0.992358f, 0.99739f, 0.998668f, 0.999176f, 0.999406f, 0.999541f, 0.999591f, 0.999568f, 0.999408f, 0.999713f, 0.999839f, 0.999881f, 0.999901f, 0.999926f, 0.999939f},
+ {0.991309f, 0.999739f, 0.999888f, 0.999919f, 0.999936f, 0.999947f, 0.999957f, 0.999945f, 0.999963f, 0.999961f, 0.999962f, 0.99996f, 0.999975f, 0.999969f, 0.999969f, 0.999972f}
+ },
+ {
+ {0.464607f, 0.455732f, 0.464628f, 0.479669f, 0.495949f, 0.512354f, 0.528314f, 0.542978f, 0.556498f, 0.567824f, 0.576463f, 0.580128f, 0.575605f, 0.568531f, 0.562623f, 0.559205f},
+ {0.498542f, 0.485636f, 0.490143f, 0.501702f, 0.516224f, 0.531793f, 0.54759f, 0.562699f, 0.577045f, 0.589905f, 0.600538f, 0.607645f, 0.609028f, 0.609586f, 0.612334f, 0.618659f},
+ {0.537333f, 0.521767f, 0.521981f, 0.529418f, 0.541199f, 0.55568f, 0.570931f, 0.586192f, 0.601126f, 0.615273f, 0.628334f, 0.639068f, 0.646205f, 0.653576f, 0.664226f, 0.679003f},
+ {0.58039f, 0.563085f, 0.559246f, 0.563593f, 0.572154f, 0.583834f, 0.597981f, 0.613261f, 0.629026f, 0.644943f, 0.660698f, 0.675112f, 0.687528f, 0.701108f, 0.717599f, 0.738633f},
+ {0.626902f, 0.608143f, 0.602518f, 0.603236f, 0.608819f, 0.618142f, 0.63031f, 0.645141f, 0.662034f, 0.679491f, 0.697664f, 0.715681f, 0.732767f, 0.751152f, 0.771428f, 0.795163f},
+ {0.674906f, 0.656073f, 0.64876f, 0.647692f, 0.650566f, 0.657853f, 0.668736f, 0.682954f, 0.700176f, 0.719539f, 0.739842f, 0.760707f, 0.781203f, 0.802008f, 0.82361f, 0.846272f},
+ {0.723717f, 0.704351f, 0.696222f, 0.694352f, 0.696957f, 0.703334f, 0.713785f, 0.727349f, 0.744532f, 0.764707f, 0.786484f, 0.809047f, 0.830832f, 0.851582f, 0.871387f, 0.890878f},
+ {0.770417f, 0.74989f, 0.741971f, 0.741f, 0.745419f, 0.753661f, 0.764643f, 0.778067f, 0.79442f, 0.813643f, 0.835382f, 0.857523f, 0.878316f, 0.896853f, 0.912706f, 0.927042f},
+ {0.812279f, 0.789808f, 0.7826f, 0.785788f, 0.79504f, 0.807f, 0.820062f, 0.833465f, 0.847781f, 0.863701f, 0.882574f, 0.902333f, 0.920185f, 0.934458f, 0.945346f, 0.954754f},
+ {0.848046f, 0.821273f, 0.818615f, 0.829032f, 0.845226f, 0.861958f, 0.876709f, 0.88927f, 0.899701f, 0.910298f, 0.92378f, 0.939469f, 0.952959f, 0.962471f, 0.968968f, 0.974084f},
+ {0.874714f, 0.844976f, 0.852751f, 0.874465f, 0.896205f, 0.914235f, 0.927761f, 0.937383f, 0.943498f, 0.948295f, 0.955712f, 0.966655f, 0.975661f, 0.980913f, 0.984102f, 0.986657f},
+ {0.890484f, 0.867243f, 0.894007f, 0.922732f, 0.943369f, 0.956978f, 0.965632f, 0.971131f, 0.974095f, 0.975102f, 0.977362f, 0.984168f, 0.989293f, 0.99165f, 0.993033f, 0.994062f},
+ {0.896619f, 0.902953f, 0.942851f, 0.965488f, 0.977382f, 0.98389f, 0.987623f, 0.989862f, 0.9908f, 0.9906f, 0.990299f, 0.993846f, 0.996119f, 0.997008f, 0.997498f, 0.997813f},
+ {0.908873f, 0.955985f, 0.982049f, 0.990586f, 0.994125f, 0.995898f, 0.996901f, 0.997459f, 0.997764f, 0.997618f, 0.996962f, 0.998277f, 0.998985f, 0.999217f, 0.999302f, 0.999407f},
+ {0.949116f, 0.992473f, 0.997458f, 0.99872f, 0.999217f, 0.999448f, 0.999588f, 0.999656f, 0.999694f, 0.999686f, 0.999497f, 0.999741f, 0.999857f, 0.999887f, 0.999913f, 0.999924f},
+ {0.991334f, 0.999745f, 0.999889f, 0.999921f, 0.999937f, 0.999949f, 0.999954f, 0.999949f, 0.999967f, 0.999973f, 0.999954f, 0.999956f, 0.999974f, 0.999969f, 0.999969f, 0.99997f}
+ },
+ {
+ {0.535644f, 0.50519f, 0.496654f, 0.497589f, 0.503236f, 0.510989f, 0.519873f, 0.527879f, 0.535008f, 0.539309f, 0.539252f, 0.531167f, 0.519742f, 0.509007f, 0.49861f, 0.487933f},
+ {0.570331f, 0.538577f, 0.527508f, 0.525756f, 0.528668f, 0.535016f, 0.543254f, 0.551359f, 0.558994f, 0.565094f, 0.567923f, 0.56429f, 0.559234f, 0.55558f, 0.553574f, 0.551784f},
+ {0.608133f, 0.576666f, 0.563094f, 0.558455f, 0.559389f, 0.563998f, 0.570572f, 0.578631f, 0.586698f, 0.594588f, 0.59993f, 0.601645f, 0.602898f, 0.606063f, 0.611528f, 0.61833f},
+ {0.648542f, 0.617661f, 0.602755f, 0.596267f, 0.595127f, 0.597269f, 0.602791f, 0.610193f, 0.618942f, 0.628369f, 0.636854f, 0.643649f, 0.65072f, 0.660298f, 0.672199f, 0.686181f},
+ {0.690624f, 0.660779f, 0.645878f, 0.638184f, 0.634787f, 0.635821f, 0.640049f, 0.646755f, 0.656027f, 0.66701f, 0.678948f, 0.690056f, 0.70241f, 0.717372f, 0.734148f, 0.751897f},
+ {0.732596f, 0.704246f, 0.689645f, 0.68144f, 0.677921f, 0.678025f, 0.682047f, 0.689125f, 0.698744f, 0.711014f, 0.725492f, 0.74041f, 0.756919f, 0.775316f, 0.794663f, 0.813491f},
+ {0.773768f, 0.746302f, 0.731699f, 0.72453f, 0.722755f, 0.724264f, 0.729055f, 0.736672f, 0.747245f, 0.760346f, 0.776148f, 0.793309f, 0.811932f, 0.831565f, 0.850666f, 0.86747f},
+ {0.811941f, 0.784254f, 0.770546f, 0.765597f, 0.766766f, 0.772039f, 0.77987f, 0.789017f, 0.800264f, 0.813001f, 0.828234f, 0.845605f, 0.864049f, 0.882742f, 0.898867f, 0.911758f},
+ {0.845093f, 0.815462f, 0.803637f, 0.803392f, 0.810509f, 0.820776f, 0.832867f, 0.844459f, 0.855457f, 0.866203f, 0.878509f, 0.893151f, 0.909659f, 0.925137f, 0.937169f, 0.945601f},
+ {0.872363f, 0.839073f, 0.832138f, 0.8403f, 0.854991f, 0.871149f, 0.885615f, 0.897785f, 0.907383f, 0.914778f, 0.922322f, 0.932492f, 0.945472f, 0.956909f, 0.964608f, 0.969221f},
+ {0.891443f, 0.85558f, 0.860369f, 0.880426f, 0.901355f, 0.919079f, 0.932875f, 0.942666f, 0.949403f, 0.953541f, 0.956108f, 0.961355f, 0.970612f, 0.978002f, 0.982078f, 0.984329f},
+ {0.900528f, 0.872783f, 0.8976f, 0.925454f, 0.94568f, 0.959191f, 0.967968f, 0.973783f, 0.977401f, 0.979213f, 0.979158f, 0.980373f, 0.986408f, 0.990353f, 0.992219f, 0.993144f},
+ {0.901743f, 0.905093f, 0.944182f, 0.966457f, 0.978205f, 0.98465f, 0.9884f, 0.990632f, 0.992106f, 0.992708f, 0.992145f, 0.991677f, 0.994772f, 0.996532f, 0.997214f, 0.997501f},
+ {0.910784f, 0.956624f, 0.982355f, 0.990847f, 0.994321f, 0.996039f, 0.997124f, 0.997692f, 0.998021f, 0.99817f, 0.998013f, 0.997404f, 0.998577f, 0.999088f, 0.999224f, 0.999337f},
+ {0.949535f, 0.992566f, 0.99751f, 0.998743f, 0.999234f, 0.999473f, 0.999598f, 0.999686f, 0.999714f, 0.999748f, 0.99974f, 0.999573f, 0.999796f, 0.99987f, 0.999902f, 0.99991f},
+ {0.99135f, 0.999749f, 0.999893f, 0.999923f, 0.999936f, 0.999949f, 0.99996f, 0.999951f, 0.999967f, 0.999974f, 0.999963f, 0.999951f, 0.999973f, 0.999968f, 0.999969f, 0.999968f}
+ },
+ {
+ {0.59973f, 0.552818f, 0.530643f, 0.520157f, 0.516116f, 0.51552f, 0.516777f, 0.51803f, 0.518346f, 0.514724f, 0.504512f, 0.49003f, 0.476615f, 0.463236f, 0.449735f, 0.435024f},
+ {0.632997f, 0.587111f, 0.564079f, 0.55199f, 0.545828f, 0.543759f, 0.544237f, 0.545366f, 0.546202f, 0.544842f, 0.53818f, 0.529142f, 0.521583f, 0.51462f, 0.508502f, 0.501598f},
+ {0.668169f, 0.624811f, 0.601631f, 0.587864f, 0.580326f, 0.576726f, 0.576042f, 0.577016f, 0.578406f, 0.578992f, 0.57605f, 0.572798f, 0.570656f, 0.570384f, 0.571488f, 0.572872f},
+ {0.705117f, 0.664106f, 0.641318f, 0.62698f, 0.618315f, 0.613663f, 0.612384f, 0.61263f, 0.614626f, 0.617233f, 0.618782f, 0.620316f, 0.624132f, 0.630072f, 0.637842f, 0.646764f},
+ {0.742334f, 0.703971f, 0.68226f, 0.668393f, 0.658955f, 0.654337f, 0.652719f, 0.653158f, 0.656184f, 0.66065f, 0.665755f, 0.671911f, 0.680942f, 0.692708f, 0.706068f, 0.719966f},
+ {0.778325f, 0.742889f, 0.722235f, 0.70907f, 0.70122f, 0.69721f, 0.6965f, 0.698327f, 0.702251f, 0.708926f, 0.716871f, 0.727084f, 0.740321f, 0.75591f, 0.772929f, 0.789173f},
+ {0.81242f, 0.778793f, 0.759492f, 0.748279f, 0.742735f, 0.741557f, 0.743404f, 0.747793f, 0.753545f, 0.761827f, 0.771555f, 0.783946f, 0.799266f, 0.816835f, 0.83493f, 0.850679f},
+ {0.843431f, 0.810221f, 0.792039f, 0.783845f, 0.782521f, 0.78594f, 0.791957f, 0.799556f, 0.808191f, 0.817271f, 0.827202f, 0.839323f, 0.854523f, 0.87179f, 0.888237f, 0.901303f},
+ {0.869961f, 0.834643f, 0.819008f, 0.816238f, 0.821508f, 0.83095f, 0.84206f, 0.853057f, 0.863007f, 0.871636f, 0.880071f, 0.889763f, 0.902333f, 0.917331f, 0.930631f, 0.93963f},
+ {0.890577f, 0.85214f, 0.841829f, 0.848149f, 0.861853f, 0.877146f, 0.891448f, 0.903829f, 0.913532f, 0.920373f, 0.925714f, 0.931231f, 0.939873f, 0.951653f, 0.960918f, 0.966293f},
+ {0.903713f, 0.8635f, 0.866053f, 0.884673f, 0.905078f, 0.922462f, 0.936053f, 0.945959f, 0.953258f, 0.957631f, 0.960226f, 0.961587f, 0.96635f, 0.974725f, 0.980311f, 0.983058f},
+ {0.908067f, 0.876709f, 0.900129f, 0.927439f, 0.947228f, 0.960614f, 0.969409f, 0.975195f, 0.978983f, 0.981397f, 0.982261f, 0.98159f, 0.983296f, 0.988598f, 0.991442f, 0.992607f},
+ {0.905559f, 0.906706f, 0.945145f, 0.967146f, 0.978792f, 0.985152f, 0.988866f, 0.991238f, 0.992573f, 0.993521f, 0.993828f, 0.993031f, 0.992871f, 0.995809f, 0.996953f, 0.997356f},
+ {0.912211f, 0.957039f, 0.982562f, 0.990982f, 0.994478f, 0.996159f, 0.997183f, 0.997758f, 0.99816f, 0.998377f, 0.998465f, 0.998245f, 0.997787f, 0.998881f, 0.999157f, 0.999302f},
+ {0.949831f, 0.99262f, 0.997544f, 0.998773f, 0.999238f, 0.999496f, 0.999626f, 0.999703f, 0.999743f, 0.999767f, 0.999784f, 0.999767f, 0.999643f, 0.999844f, 0.999891f, 0.999905f},
+ {0.991361f, 0.999754f, 0.999893f, 0.999924f, 0.999936f, 0.999951f, 0.999959f, 0.999951f, 0.999969f, 0.999973f, 0.999964f, 0.999959f, 0.999968f, 0.999967f, 0.999968f, 0.999968f}
+ },
+ {
+ {0.654676f, 0.59532f, 0.562607f, 0.54273f, 0.530577f, 0.52264f, 0.517073f, 0.511514f, 0.504402f, 0.491501f, 0.475258f, 0.459301f, 0.444324f, 0.429177f, 0.414139f, 0.398977f},
+ {0.686151f, 0.629447f, 0.597385f, 0.577208f, 0.563557f, 0.5543f, 0.548279f, 0.542757f, 0.536421f, 0.526823f, 0.514555f, 0.503255f, 0.493831f, 0.484346f, 0.475693f, 0.46729f},
+ {0.717895f, 0.665604f, 0.635024f, 0.614131f, 0.600309f, 0.590793f, 0.583714f, 0.578272f, 0.573119f, 0.56593f, 0.558015f, 0.551866f, 0.547493f, 0.544452f, 0.542585f, 0.541624f},
+ {0.751169f, 0.702484f, 0.673297f, 0.653206f, 0.639342f, 0.62976f, 0.622743f, 0.617912f, 0.613845f, 0.609127f, 0.605943f, 0.604379f, 0.605509f, 0.608557f, 0.613293f, 0.619877f},
+ {0.783237f, 0.738911f, 0.711777f, 0.692944f, 0.679718f, 0.670958f, 0.664668f, 0.661096f, 0.658669f, 0.657331f, 0.657487f, 0.660671f, 0.666855f, 0.675339f, 0.686082f, 0.698414f},
+ {0.81389f, 0.773134f, 0.748038f, 0.730966f, 0.719877f, 0.712763f, 0.709313f, 0.707496f, 0.707847f, 0.709368f, 0.713043f, 0.719855f, 0.729735f, 0.742554f, 0.757318f, 0.773124f},
+ {0.842615f, 0.804118f, 0.780557f, 0.766424f, 0.758346f, 0.754852f, 0.75494f, 0.757283f, 0.760534f, 0.765159f, 0.771012f, 0.779851f, 0.791974f, 0.806569f, 0.823433f, 0.839688f},
+ {0.86778f, 0.829723f, 0.80825f, 0.797446f, 0.794359f, 0.796189f, 0.80129f, 0.807893f, 0.815203f, 0.822077f, 0.829476f, 0.83815f, 0.849642f, 0.864134f, 0.880192f, 0.894549f},
+ {0.888723f, 0.849193f, 0.830428f, 0.825644f, 0.829293f, 0.838161f, 0.848673f, 0.859429f, 0.868781f, 0.877112f, 0.883703f, 0.890558f, 0.899185f, 0.911532f, 0.925323f, 0.935976f},
+ {0.904265f, 0.861773f, 0.849084f, 0.853769f, 0.866609f, 0.881528f, 0.895544f, 0.907821f, 0.917513f, 0.924602f, 0.929705f, 0.933389f, 0.938068f, 0.947244f, 0.957673f, 0.964536f},
+ {0.912919f, 0.869358f, 0.870041f, 0.88768f, 0.907484f, 0.924736f, 0.938087f, 0.947975f, 0.955366f, 0.960351f, 0.963268f, 0.964553f, 0.965688f, 0.971382f, 0.97857f, 0.982323f},
+ {0.913656f, 0.879634f, 0.901988f, 0.928741f, 0.948291f, 0.961506f, 0.970343f, 0.976191f, 0.980038f, 0.982511f, 0.983914f, 0.984118f, 0.9833f, 0.986313f, 0.990643f, 0.99235f},
+ {0.908461f, 0.907873f, 0.945866f, 0.967611f, 0.979155f, 0.985489f, 0.989231f, 0.991488f, 0.992973f, 0.993936f, 0.99444f, 0.994481f, 0.993323f, 0.994502f, 0.996668f, 0.997279f},
+ {0.913294f, 0.957376f, 0.982744f, 0.991115f, 0.994583f, 0.99626f, 0.997271f, 0.997831f, 0.99826f, 0.998478f, 0.998631f, 0.998611f, 0.998137f, 0.998381f, 0.99909f, 0.999289f},
+ {0.950029f, 0.992669f, 0.997573f, 0.998792f, 0.999256f, 0.999498f, 0.99963f, 0.999708f, 0.999759f, 0.999793f, 0.999807f, 0.999807f, 0.99973f, 0.999747f, 0.999879f, 0.999903f},
+ {0.991379f, 0.999757f, 0.999895f, 0.999925f, 0.999936f, 0.999953f, 0.999958f, 0.99995f, 0.999968f, 0.999973f, 0.999967f, 0.999959f, 0.999972f, 0.999963f, 0.999968f, 0.999968f}
+ },
+ {
+ {0.701283f, 0.631609f, 0.590791f, 0.563657f, 0.544568f, 0.530369f, 0.518693f, 0.506491f, 0.491062f, 0.471977f, 0.453936f, 0.436798f, 0.420917f, 0.405036f, 0.389759f, 0.375973f},
+ {0.730196f, 0.664903f, 0.625716f, 0.598936f, 0.579934f, 0.564673f, 0.552868f, 0.541584f, 0.527948f, 0.512314f, 0.497918f, 0.485108f, 0.473825f, 0.463099f, 0.453284f, 0.445269f},
+ {0.75871f, 0.699282f, 0.662597f, 0.636558f, 0.617696f, 0.60309f, 0.591416f, 0.580311f, 0.56901f, 0.556289f, 0.54594f, 0.53783f, 0.531363f, 0.526312f, 0.522932f, 0.521629f},
+ {0.787871f, 0.733163f, 0.699089f, 0.674943f, 0.656999f, 0.643239f, 0.632021f, 0.622998f, 0.613578f, 0.604161f, 0.598042f, 0.594089f, 0.592947f, 0.59385f, 0.596666f, 0.602704f},
+ {0.815874f, 0.765978f, 0.735051f, 0.71273f, 0.69632f, 0.684541f, 0.675091f, 0.667648f, 0.661466f, 0.656148f, 0.653631f, 0.654271f, 0.657856f, 0.66402f, 0.672603f, 0.684604f},
+ {0.841934f, 0.796586f, 0.767979f, 0.748061f, 0.734541f, 0.72515f, 0.71936f, 0.715301f, 0.712778f, 0.711296f, 0.71245f, 0.716704f, 0.723992f, 0.734124f, 0.746976f, 0.762878f},
+ {0.865935f, 0.823198f, 0.796706f, 0.780209f, 0.770091f, 0.765027f, 0.763333f, 0.764378f, 0.766053f, 0.768751f, 0.773071f, 0.779501f, 0.788486f, 0.800539f, 0.815685f, 0.832755f},
+ {0.886749f, 0.844826f, 0.820477f, 0.807657f, 0.80303f, 0.803694f, 0.808046f, 0.813893f, 0.8204f, 0.826566f, 0.832809f, 0.83965f, 0.848298f, 0.85991f, 0.874561f, 0.890263f},
+ {0.903223f, 0.860252f, 0.838974f, 0.832478f, 0.835173f, 0.843307f, 0.853267f, 0.863631f, 0.872986f, 0.880853f, 0.887624f, 0.893368f, 0.899353f, 0.908364f, 0.92135f, 0.933599f},
+ {0.914895f, 0.869102f, 0.854416f, 0.857914f, 0.869986f, 0.884328f, 0.898298f, 0.910349f, 0.919873f, 0.927424f, 0.932819f, 0.936563f, 0.939487f, 0.94486f, 0.954848f, 0.963392f},
+ {0.92025f, 0.873787f, 0.873043f, 0.889895f, 0.909314f, 0.926297f, 0.939483f, 0.949355f, 0.956715f, 0.961806f, 0.965408f, 0.96719f, 0.967507f, 0.969543f, 0.976742f, 0.981854f},
+ {0.917948f, 0.881872f, 0.903407f, 0.929708f, 0.949123f, 0.962271f, 0.970883f, 0.976753f, 0.980604f, 0.983267f, 0.984823f, 0.985719f, 0.985322f, 0.984983f, 0.989636f, 0.992183f},
+ {0.910636f, 0.908797f, 0.946414f, 0.967988f, 0.979453f, 0.985659f, 0.989433f, 0.991682f, 0.99316f, 0.994164f, 0.994788f, 0.99502f, 0.994648f, 0.993706f, 0.996244f, 0.997233f},
+ {0.914078f, 0.95762f, 0.982874f, 0.991184f, 0.994643f, 0.996325f, 0.997353f, 0.997903f, 0.99829f, 0.99851f, 0.998671f, 0.99875f, 0.998692f, 0.998057f, 0.998976f, 0.999278f},
+ {0.950208f, 0.992704f, 0.997595f, 0.9988f, 0.999282f, 0.999503f, 0.999644f, 0.999721f, 0.999751f, 0.999793f, 0.999808f, 0.999814f, 0.999826f, 0.999707f, 0.999862f, 0.999902f},
+ {0.991386f, 0.999757f, 0.999895f, 0.999926f, 0.999937f, 0.999953f, 0.99996f, 0.999951f, 0.999968f, 0.999975f, 0.999967f, 0.999959f, 0.999976f, 0.999961f, 0.999967f, 0.999968f}
+ },
+ {
+ {0.739778f, 0.661981f, 0.614519f, 0.581398f, 0.557306f, 0.537236f, 0.519877f, 0.501546f, 0.47938f, 0.458089f, 0.438817f, 0.421047f, 0.404398f, 0.388427f, 0.374196f, 0.361575f},
+ {0.766009f, 0.6941f, 0.649217f, 0.617718f, 0.593578f, 0.573984f, 0.557176f, 0.539899f, 0.52048f, 0.502346f, 0.486733f, 0.472533f, 0.460112f, 0.448827f, 0.439189f, 0.431442f},
+ {0.791642f, 0.726574f, 0.684914f, 0.654938f, 0.63208f, 0.613643f, 0.597698f, 0.581789f, 0.565231f, 0.550402f, 0.538079f, 0.528682f, 0.520661f, 0.514542f, 0.5106f, 0.509097f},
+ {0.817359f, 0.757799f, 0.719905f, 0.692383f, 0.671033f, 0.654384f, 0.639872f, 0.626648f, 0.61344f, 0.601787f, 0.593969f, 0.588313f, 0.585293f, 0.584608f, 0.586594f, 0.591851f},
+ {0.841507f, 0.787679f, 0.75347f, 0.728337f, 0.70957f, 0.694878f, 0.683113f, 0.673125f, 0.663414f, 0.656921f, 0.652573f, 0.651336f, 0.652872f, 0.657233f, 0.664633f, 0.675853f},
+ {0.864067f, 0.814815f, 0.783425f, 0.761238f, 0.745584f, 0.734387f, 0.726839f, 0.720942f, 0.716462f, 0.713896f, 0.713758f, 0.716234f, 0.721376f, 0.729465f, 0.74094f, 0.756301f},
+ {0.884084f, 0.838008f, 0.808943f, 0.790538f, 0.778836f, 0.772328f, 0.769884f, 0.769473f, 0.770142f, 0.77224f, 0.776124f, 0.780973f, 0.787884f, 0.797596f, 0.811259f, 0.828174f},
+ {0.901344f, 0.856394f, 0.829732f, 0.815137f, 0.809389f, 0.809136f, 0.812727f, 0.817882f, 0.823857f, 0.830124f, 0.836163f, 0.842295f, 0.84916f, 0.858317f, 0.871217f, 0.887319f},
+ {0.914526f, 0.868599f, 0.84526f, 0.837525f, 0.839408f, 0.846857f, 0.856456f, 0.866433f, 0.875764f, 0.883618f, 0.890695f, 0.896488f, 0.901232f, 0.907641f, 0.918784f, 0.931855f},
+ {0.922982f, 0.874709f, 0.858501f, 0.861113f, 0.872533f, 0.886545f, 0.900127f, 0.911956f, 0.921509f, 0.929207f, 0.935147f, 0.939275f, 0.941776f, 0.944701f, 0.952789f, 0.962454f},
+ {0.925782f, 0.877133f, 0.875308f, 0.891519f, 0.910631f, 0.927329f, 0.940375f, 0.950293f, 0.957518f, 0.96278f, 0.966636f, 0.968953f, 0.969842f, 0.969839f, 0.975088f, 0.981411f},
+ {0.921248f, 0.883587f, 0.90448f, 0.93043f, 0.949709f, 0.962698f, 0.971276f, 0.977072f, 0.981011f, 0.983684f, 0.985523f, 0.986612f, 0.986854f, 0.985561f, 0.988429f, 0.992005f},
+ {0.912277f, 0.909461f, 0.946828f, 0.968264f, 0.979653f, 0.985861f, 0.989548f, 0.991826f, 0.993265f, 0.994305f, 0.994896f, 0.995299f, 0.995359f, 0.994336f, 0.995546f, 0.997175f},
+ {0.914709f, 0.957806f, 0.98299f, 0.99125f, 0.994695f, 0.996377f, 0.997389f, 0.997929f, 0.998325f, 0.998541f, 0.998718f, 0.998825f, 0.99885f, 0.998436f, 0.998697f, 0.999265f},
+ {0.950336f, 0.992723f, 0.99761f, 0.998802f, 0.999296f, 0.999519f, 0.999649f, 0.999722f, 0.999762f, 0.9998f, 0.999822f, 0.999833f, 0.999837f, 0.999763f, 0.999808f, 0.9999f},
+ {0.99139f, 0.999757f, 0.999897f, 0.999926f, 0.999938f, 0.999952f, 0.999961f, 0.999951f, 0.999968f, 0.999974f, 0.999967f, 0.99996f, 0.999976f, 0.999964f, 0.999965f, 0.999968f}
+ },
+ {
+ {0.770998f, 0.686931f, 0.634265f, 0.596254f, 0.567331f, 0.543185f, 0.520343f, 0.495714f, 0.470991f, 0.448555f, 0.428511f, 0.410107f, 0.393342f, 0.378156f, 0.36469f, 0.352596f},
+ {0.795015f, 0.717653f, 0.668339f, 0.632841f, 0.604974f, 0.581209f, 0.560113f, 0.537314f, 0.515121f, 0.496039f, 0.479315f, 0.464286f, 0.451354f, 0.440024f, 0.430609f, 0.422883f},
+ {0.817973f, 0.7482f, 0.702787f, 0.669535f, 0.643446f, 0.621934f, 0.602381f, 0.582128f, 0.563082f, 0.547239f, 0.533819f, 0.523213f, 0.514104f, 0.507522f, 0.503359f, 0.501306f},
+ {0.840778f, 0.777305f, 0.736223f, 0.705801f, 0.682064f, 0.662551f, 0.645414f, 0.628567f, 0.613626f, 0.601269f, 0.592265f, 0.585321f, 0.580982f, 0.57963f, 0.580866f, 0.585123f},
+ {0.8619f, 0.804678f, 0.767553f, 0.740228f, 0.719376f, 0.702886f, 0.68916f, 0.676527f, 0.665539f, 0.658178f, 0.652959f, 0.650719f, 0.650971f, 0.654012f, 0.660239f, 0.670351f},
+ {0.881182f, 0.828897f, 0.795305f, 0.771161f, 0.753987f, 0.741464f, 0.73213f, 0.724484f, 0.71928f, 0.71662f, 0.715945f, 0.71725f, 0.721061f, 0.727652f, 0.737836f, 0.752075f},
+ {0.898328f, 0.849545f, 0.818445f, 0.798279f, 0.78526f, 0.777848f, 0.774228f, 0.772896f, 0.773319f, 0.775384f, 0.778796f, 0.783347f, 0.789071f, 0.797256f, 0.809091f, 0.8251f},
+ {0.912492f, 0.865099f, 0.836682f, 0.820873f, 0.813947f, 0.813045f, 0.816107f, 0.820657f, 0.82658f, 0.832902f, 0.839364f, 0.845288f, 0.851083f, 0.858572f, 0.869737f, 0.885193f},
+ {0.923206f, 0.875112f, 0.850108f, 0.841381f, 0.842447f, 0.849294f, 0.858589f, 0.868246f, 0.877387f, 0.885927f, 0.893229f, 0.899232f, 0.903716f, 0.908704f, 0.917536f, 0.930437f},
+ {0.929416f, 0.879031f, 0.861479f, 0.863345f, 0.874394f, 0.888073f, 0.901441f, 0.913068f, 0.922679f, 0.930421f, 0.936747f, 0.94131f, 0.944077f, 0.946029f, 0.951657f, 0.961578f},
+ {0.929961f, 0.879713f, 0.877021f, 0.892717f, 0.91156f, 0.928023f, 0.940969f, 0.950753f, 0.958077f, 0.963495f, 0.967515f, 0.970119f, 0.97154f, 0.971433f, 0.973997f, 0.980923f},
+ {0.923813f, 0.88494f, 0.905293f, 0.930999f, 0.950162f, 0.963021f, 0.971522f, 0.977304f, 0.981213f, 0.984018f, 0.985846f, 0.987192f, 0.987814f, 0.986963f, 0.987549f, 0.991779f},
+ {0.913577f, 0.909968f, 0.947136f, 0.968498f, 0.979824f, 0.98596f, 0.989639f, 0.991884f, 0.993358f, 0.994389f, 0.995062f, 0.995502f, 0.995694f, 0.995242f, 0.994964f, 0.997095f},
+ {0.915225f, 0.957948f, 0.983091f, 0.991314f, 0.994726f, 0.996395f, 0.9974f, 0.997954f, 0.998351f, 0.998569f, 0.99875f, 0.998843f, 0.99892f, 0.998785f, 0.998458f, 0.999245f},
+ {0.950438f, 0.99275f, 0.997626f, 0.998808f, 0.9993f, 0.999522f, 0.999649f, 0.999722f, 0.999765f, 0.9998f, 0.999817f, 0.999832f, 0.999842f, 0.999849f, 0.999771f, 0.999898f},
+ {0.991403f, 0.999757f, 0.999897f, 0.999927f, 0.999939f, 0.999952f, 0.999961f, 0.999951f, 0.999969f, 0.999972f, 0.999966f, 0.99996f, 0.999974f, 0.999965f, 0.999964f, 0.999968f}
+ },
+ {
+ {0.79705f, 0.707087f, 0.650125f, 0.608325f, 0.575656f, 0.547339f, 0.519517f, 0.490858f, 0.465293f, 0.442303f, 0.421886f, 0.403233f, 0.38683f, 0.372037f, 0.359003f, 0.347211f},
+ {0.818406f, 0.736522f, 0.683598f, 0.644745f, 0.613662f, 0.5868f, 0.561474f, 0.535419f, 0.51204f, 0.492423f, 0.474782f, 0.459397f, 0.446089f, 0.434972f, 0.42572f, 0.417781f},
+ {0.838915f, 0.76538f, 0.71697f, 0.680901f, 0.652404f, 0.627981f, 0.604879f, 0.582095f, 0.562335f, 0.545635f, 0.53178f, 0.520098f, 0.510837f, 0.503805f, 0.499364f, 0.496573f},
+ {0.859427f, 0.792616f, 0.748843f, 0.71611f, 0.690565f, 0.66897f, 0.649153f, 0.630161f, 0.614583f, 0.601802f, 0.592015f, 0.584405f, 0.579516f, 0.577337f, 0.577881f, 0.581019f},
+ {0.877941f, 0.817762f, 0.778341f, 0.74933f, 0.726722f, 0.70854f, 0.693008f, 0.678967f, 0.667968f, 0.660119f, 0.654418f, 0.651497f, 0.650648f, 0.653018f, 0.658252f, 0.666947f},
+ {0.894946f, 0.839848f, 0.804323f, 0.778658f, 0.760117f, 0.746318f, 0.735719f, 0.727265f, 0.721936f, 0.718995f, 0.718274f, 0.719192f, 0.722341f, 0.727937f, 0.736645f, 0.749427f},
+ {0.90937f, 0.858314f, 0.825635f, 0.804151f, 0.790096f, 0.781706f, 0.777206f, 0.775328f, 0.775831f, 0.7781f, 0.781525f, 0.785871f, 0.791006f, 0.798083f, 0.808513f, 0.823113f},
+ {0.921259f, 0.871938f, 0.842067f, 0.825098f, 0.817405f, 0.815975f, 0.818193f, 0.822737f, 0.828566f, 0.83501f, 0.841897f, 0.847892f, 0.853643f, 0.860164f, 0.869398f, 0.883714f},
+ {0.930002f, 0.880092f, 0.853777f, 0.84416f, 0.844764f, 0.851092f, 0.859958f, 0.869441f, 0.878832f, 0.887484f, 0.89514f, 0.901397f, 0.906208f, 0.9106f, 0.917304f, 0.929364f},
+ {0.93434f, 0.882394f, 0.863801f, 0.865045f, 0.875658f, 0.889041f, 0.902161f, 0.913795f, 0.9235f, 0.931512f, 0.937785f, 0.942816f, 0.946137f, 0.948175f, 0.951499f, 0.960778f},
+ {0.933288f, 0.881678f, 0.878297f, 0.893636f, 0.912242f, 0.928599f, 0.9414f, 0.951132f, 0.958467f, 0.963995f, 0.968187f, 0.971034f, 0.972905f, 0.973151f, 0.973816f, 0.980384f},
+ {0.925808f, 0.885998f, 0.905907f, 0.931442f, 0.950453f, 0.963263f, 0.971733f, 0.977432f, 0.981437f, 0.984181f, 0.986101f, 0.987512f, 0.988453f, 0.988142f, 0.987422f, 0.991483f},
+ {0.914584f, 0.910362f, 0.947376f, 0.968621f, 0.979921f, 0.986048f, 0.989702f, 0.991953f, 0.993416f, 0.994454f, 0.995204f, 0.995643f, 0.995904f, 0.995802f, 0.994945f, 0.996973f},
+ {0.915627f, 0.958056f, 0.98316f, 0.991351f, 0.994752f, 0.996424f, 0.997426f, 0.997968f, 0.998351f, 0.998579f, 0.99877f, 0.998878f, 0.998955f, 0.998924f, 0.998463f, 0.999213f},
+ {0.950525f, 0.99277f, 0.997636f, 0.998811f, 0.999304f, 0.999523f, 0.999655f, 0.999724f, 0.999768f, 0.999796f, 0.999833f, 0.999839f, 0.999859f, 0.999856f, 0.999769f, 0.999893f},
+ {0.991407f, 0.999758f, 0.999897f, 0.999927f, 0.999939f, 0.999952f, 0.999961f, 0.999951f, 0.999969f, 0.999973f, 0.999967f, 0.99996f, 0.999976f, 0.999968f, 0.999965f, 0.999968f}
+ },
+ {
+ {0.817657f, 0.723241f, 0.662787f, 0.617806f, 0.581707f, 0.549774f, 0.517554f, 0.487769f, 0.461541f, 0.43842f, 0.417691f, 0.399079f, 0.383059f, 0.368634f, 0.355749f, 0.34413f},
+ {0.837002f, 0.751305f, 0.695682f, 0.653945f, 0.620295f, 0.590505f, 0.56115f, 0.534408f, 0.510693f, 0.490235f, 0.472319f, 0.45677f, 0.443685f, 0.432378f, 0.422948f, 0.414752f},
+ {0.855837f, 0.77891f, 0.727936f, 0.689818f, 0.658997f, 0.632206f, 0.606236f, 0.582562f, 0.562559f, 0.545354f, 0.530933f, 0.518986f, 0.509504f, 0.502321f, 0.497312f, 0.493854f},
+ {0.87425f, 0.804615f, 0.758634f, 0.724153f, 0.696774f, 0.673192f, 0.65101f, 0.631897f, 0.615946f, 0.602754f, 0.592606f, 0.584959f, 0.57949f, 0.57674f, 0.576506f, 0.578649f},
+ {0.890419f, 0.827886f, 0.786812f, 0.756174f, 0.732164f, 0.712579f, 0.695441f, 0.681054f, 0.669964f, 0.66197f, 0.65612f, 0.652777f, 0.651928f, 0.653243f, 0.657598f, 0.664986f},
+ {0.90543f, 0.848397f, 0.811216f, 0.784383f, 0.764677f, 0.749748f, 0.738095f, 0.729745f, 0.724129f, 0.721272f, 0.720688f, 0.721413f, 0.724267f, 0.729195f, 0.736498f, 0.747847f},
+ {0.918058f, 0.865296f, 0.831113f, 0.808539f, 0.793531f, 0.784463f, 0.779086f, 0.777031f, 0.777935f, 0.780148f, 0.783813f, 0.788206f, 0.793626f, 0.799897f, 0.808777f, 0.821865f},
+ {0.92817f, 0.877163f, 0.846146f, 0.828246f, 0.819912f, 0.81795f, 0.819629f, 0.824224f, 0.830215f, 0.836919f, 0.843879f, 0.850116f, 0.856108f, 0.862218f, 0.869877f, 0.882704f},
+ {0.935269f, 0.883777f, 0.856602f, 0.846148f, 0.846328f, 0.852397f, 0.860816f, 0.8704f, 0.880012f, 0.888671f, 0.896505f, 0.903096f, 0.908467f, 0.912619f, 0.91797f, 0.928547f},
+ {0.938124f, 0.884951f, 0.865568f, 0.866333f, 0.876638f, 0.889789f, 0.902716f, 0.914317f, 0.924097f, 0.932265f, 0.938791f, 0.943975f, 0.947756f, 0.949879f, 0.952018f, 0.960114f},
+ {0.93579f, 0.883236f, 0.879279f, 0.894274f, 0.912769f, 0.928973f, 0.941669f, 0.951429f, 0.958813f, 0.964351f, 0.968547f, 0.971721f, 0.973799f, 0.974578f, 0.974338f, 0.979852f},
+ {0.927364f, 0.886746f, 0.906354f, 0.931745f, 0.95066f, 0.963418f, 0.971877f, 0.977557f, 0.981557f, 0.984338f, 0.986312f, 0.987779f, 0.988855f, 0.989031f, 0.987891f, 0.991104f},
+ {0.915345f, 0.910666f, 0.947524f, 0.968757f, 0.980016f, 0.986115f, 0.989741f, 0.991972f, 0.993453f, 0.994511f, 0.995276f, 0.995723f, 0.996041f, 0.996168f, 0.995255f, 0.996776f},
+ {0.915938f, 0.958148f, 0.983201f, 0.991381f, 0.99478f, 0.996435f, 0.99744f, 0.997984f, 0.998355f, 0.998594f, 0.998779f, 0.998912f, 0.998993f, 0.999027f, 0.998616f, 0.99915f},
+ {0.950581f, 0.992777f, 0.997638f, 0.998817f, 0.999309f, 0.999523f, 0.999654f, 0.999726f, 0.999771f, 0.999794f, 0.999827f, 0.999842f, 0.999862f, 0.999874f, 0.999802f, 0.999884f},
+ {0.991412f, 0.999758f, 0.999897f, 0.999927f, 0.999939f, 0.999952f, 0.999961f, 0.999951f, 0.999969f, 0.999973f, 0.999967f, 0.99996f, 0.999975f, 0.999968f, 0.999966f, 0.999968f}
+ },
+ {
+ {0.834262f, 0.736081f, 0.672702f, 0.625014f, 0.586161f, 0.550531f, 0.516081f, 0.486013f, 0.459502f, 0.435917f, 0.415263f, 0.39704f, 0.38115f, 0.366798f, 0.353983f, 0.342407f},
+ {0.851862f, 0.763193f, 0.705094f, 0.661069f, 0.625188f, 0.592424f, 0.560815f, 0.533871f, 0.510054f, 0.489451f, 0.471438f, 0.455787f, 0.442738f, 0.431341f, 0.421574f, 0.413145f},
+ {0.869257f, 0.789477f, 0.736528f, 0.696478f, 0.663679f, 0.634635f, 0.606979f, 0.583289f, 0.563214f, 0.545723f, 0.531246f, 0.519275f, 0.50954f, 0.501924f, 0.496418f, 0.49241f},
+ {0.885878f, 0.814001f, 0.766181f, 0.730203f, 0.701311f, 0.675861f, 0.652699f, 0.63334f, 0.617329f, 0.604181f, 0.594001f, 0.585954f, 0.580486f, 0.577284f, 0.576186f, 0.577435f},
+ {0.900284f, 0.835873f, 0.793276f, 0.761237f, 0.736218f, 0.715139f, 0.697124f, 0.682916f, 0.671961f, 0.663839f, 0.657969f, 0.654832f, 0.65357f, 0.654377f, 0.65769f, 0.664005f},
+ {0.913773f, 0.855093f, 0.816642f, 0.78864f, 0.76792f, 0.751972f, 0.739652f, 0.731461f, 0.726004f, 0.723444f, 0.722722f, 0.723692f, 0.72628f, 0.730495f, 0.737157f, 0.747096f},
+ {0.924899f, 0.870493f, 0.835283f, 0.811765f, 0.795979f, 0.786153f, 0.780495f, 0.778662f, 0.77946f, 0.782012f, 0.785891f, 0.790644f, 0.795793f, 0.801773f, 0.809674f, 0.821251f},
+ {0.933694f, 0.881228f, 0.849145f, 0.830641f, 0.821706f, 0.819135f, 0.820668f, 0.825357f, 0.831337f, 0.838222f, 0.845529f, 0.852179f, 0.858367f, 0.864221f, 0.870816f, 0.882142f},
+ {0.939375f, 0.88676f, 0.858762f, 0.847718f, 0.847456f, 0.853243f, 0.861524f, 0.87118f, 0.880766f, 0.889638f, 0.897678f, 0.90467f, 0.910191f, 0.914583f, 0.918902f, 0.928033f},
+ {0.941125f, 0.886904f, 0.866931f, 0.867285f, 0.877266f, 0.890242f, 0.903113f, 0.914783f, 0.924603f, 0.932848f, 0.939544f, 0.944953f, 0.948932f, 0.951516f, 0.952998f, 0.959612f},
+ {0.937776f, 0.884404f, 0.880006f, 0.89478f, 0.91314f, 0.929183f, 0.94187f, 0.951681f, 0.959063f, 0.964666f, 0.968907f, 0.972145f, 0.97442f, 0.975584f, 0.975366f, 0.979376f},
+ {0.92858f, 0.887323f, 0.906695f, 0.931937f, 0.950831f, 0.963534f, 0.971975f, 0.977659f, 0.981644f, 0.984444f, 0.986487f, 0.988046f, 0.989126f, 0.989509f, 0.988619f, 0.990707f},
+ {0.915996f, 0.910913f, 0.947682f, 0.968833f, 0.98007f, 0.986144f, 0.98975f, 0.992f, 0.993487f, 0.994564f, 0.995305f, 0.995811f, 0.99615f, 0.996282f, 0.995737f, 0.996513f},
+ {0.916171f, 0.958214f, 0.983234f, 0.99141f, 0.994796f, 0.996442f, 0.997449f, 0.997982f, 0.998363f, 0.99861f, 0.998803f, 0.998928f, 0.999017f, 0.99905f, 0.998836f, 0.999022f},
+ {0.950623f, 0.992779f, 0.997641f, 0.998824f, 0.999312f, 0.999527f, 0.999656f, 0.999725f, 0.999771f, 0.999797f, 0.999835f, 0.999839f, 0.999864f, 0.999876f, 0.999835f, 0.999855f},
+ {0.991415f, 0.999758f, 0.999897f, 0.999927f, 0.999939f, 0.999952f, 0.999961f, 0.999951f, 0.999969f, 0.999973f, 0.999967f, 0.999959f, 0.999976f, 0.999967f, 0.999968f, 0.999967f}
+ }
+};
+
+static const float table_sheen_E[32][32] = {
+ {0.943446f, 0.829183f, 0.758593f, 0.701678f, 0.65437f, 0.613853f, 0.578324f, 0.546567f, 0.517736f, 0.491244f, 0.466677f, 0.443702f, 0.422089f, 0.401649f, 0.382255f, 0.363786f, 0.346264f, 0.329937f, 0.3147f, 0.300355f, 0.286744f, 0.273754f, 0.2613f, 0.249303f, 0.237713f, 0.22648f, 0.215584f, 0.204988f, 0.194684f, 0.184666f, 0.174931f, 0.165459f},
+ {0.943527f, 0.825942f, 0.755178f, 0.698084f, 0.650598f, 0.609906f, 0.574227f, 0.542291f, 0.513309f, 0.486677f, 0.461965f, 0.438862f, 0.417121f, 0.396567f, 0.377068f, 0.358499f, 0.340878f, 0.324466f, 0.309131f, 0.294691f, 0.280993f, 0.267918f, 0.255377f, 0.243296f, 0.231623f, 0.220311f, 0.209329f, 0.198659f, 0.188276f, 0.178176f, 0.168359f, 0.158801f},
+ {0.94159f, 0.822574f, 0.751611f, 0.694328f, 0.646623f, 0.60574f, 0.569858f, 0.537753f, 0.508596f, 0.481807f, 0.456942f, 0.433696f, 0.411825f, 0.391151f, 0.371534f, 0.352855f, 0.335132f, 0.318621f, 0.3032f, 0.288665f, 0.274878f, 0.261717f, 0.249088f, 0.236925f, 0.22517f, 0.213775f, 0.20272f, 0.191969f, 0.181514f, 0.171338f, 0.16144f, 0.151807f},
+ {0.947645f, 0.819075f, 0.747871f, 0.690367f, 0.642425f, 0.601337f, 0.565226f, 0.532917f, 0.503575f, 0.476605f, 0.451569f, 0.428174f, 0.406162f, 0.38536f, 0.365618f, 0.346832f, 0.329003f, 0.312389f, 0.296871f, 0.282243f, 0.268367f, 0.255119f, 0.242405f, 0.230161f, 0.218327f, 0.206862f, 0.195731f, 0.18491f, 0.174385f, 0.16414f, 0.154173f, 0.144472f},
+ {0.931949f, 0.815488f, 0.744024f, 0.6862f, 0.637992f, 0.596647f, 0.560271f, 0.527753f, 0.498193f, 0.471027f, 0.445819f, 0.42226f, 0.400092f, 0.379144f, 0.359283f, 0.340377f, 0.322447f, 0.305737f, 0.290118f, 0.275394f, 0.261429f, 0.248096f, 0.2353f, 0.222984f, 0.211078f, 0.199541f, 0.188343f, 0.177461f, 0.166877f, 0.156573f, 0.146546f, 0.136784f},
+ {0.927251f, 0.811799f, 0.739918f, 0.681784f, 0.633273f, 0.591611f, 0.554994f, 0.522205f, 0.492415f, 0.46504f, 0.439642f, 0.415899f, 0.393569f, 0.37248f, 0.35248f, 0.333463f, 0.31542f, 0.298607f, 0.282892f, 0.268086f, 0.254031f, 0.240616f, 0.227752f, 0.21536f, 0.203389f, 0.191793f, 0.180542f, 0.169607f, 0.158972f, 0.148623f, 0.138553f, 0.128751f},
+ {0.944949f, 0.807898f, 0.735619f, 0.677107f, 0.62824f, 0.586245f, 0.549329f, 0.516248f, 0.486213f, 0.458594f, 0.432987f, 0.40905f, 0.386553f, 0.365305f, 0.345168f, 0.326027f, 0.307882f, 0.290974f, 0.27516f, 0.260268f, 0.246135f, 0.232649f, 0.219716f, 0.207267f, 0.195241f, 0.183598f, 0.172308f, 0.161336f, 0.15067f, 0.140293f, 0.130202f, 0.120373f},
+ {0.926739f, 0.803886f, 0.73108f, 0.672099f, 0.622817f, 0.580449f, 0.543192f, 0.509824f, 0.479494f, 0.451625f, 0.425779f, 0.401649f, 0.378978f, 0.357567f, 0.337293f, 0.318033f, 0.299781f, 0.28278f, 0.266884f, 0.251909f, 0.237707f, 0.224155f, 0.211166f, 0.198674f, 0.186609f, 0.174943f, 0.163621f, 0.152637f, 0.141963f, 0.131588f, 0.121493f, 0.111675f},
+ {0.919685f, 0.799638f, 0.72623f, 0.666732f, 0.616988f, 0.574212f, 0.536564f, 0.502848f, 0.472221f, 0.444071f, 0.417988f, 0.393637f, 0.370768f, 0.349201f, 0.328791f, 0.30941f, 0.291068f, 0.273971f, 0.258004f, 0.242962f, 0.228693f, 0.215099f, 0.202076f, 0.189557f, 0.17748f, 0.165797f, 0.154488f, 0.143513f, 0.132859f, 0.12251f, 0.112452f, 0.102663f},
+ {0.921379f, 0.795163f, 0.720993f, 0.660933f, 0.610687f, 0.567427f, 0.529359f, 0.49527f, 0.464308f, 0.435861f, 0.409513f, 0.38494f, 0.361875f, 0.340136f, 0.319589f, 0.300094f, 0.281665f, 0.2645f, 0.248462f, 0.233371f, 0.219069f, 0.205448f, 0.192409f, 0.179886f, 0.167823f, 0.156167f, 0.144891f, 0.133964f, 0.123368f, 0.113088f, 0.103106f, 0.0934057f},
+ {0.912241f, 0.790311f, 0.715419f, 0.654675f, 0.603798f, 0.560013f, 0.521488f, 0.486989f, 0.455643f, 0.426892f, 0.400276f, 0.375458f, 0.352193f, 0.330302f, 0.309625f, 0.290033f, 0.271525f, 0.2543f, 0.238222f, 0.223103f, 0.208785f, 0.195163f, 0.182143f, 0.169651f, 0.15763f, 0.146039f, 0.134842f, 0.124007f, 0.113516f, 0.103354f, 0.0935006f, 0.0839435f},
+ {0.91345f, 0.785198f, 0.70931f, 0.64782f, 0.596253f, 0.551881f, 0.512834f, 0.477892f, 0.446165f, 0.417072f, 0.390154f, 0.365109f, 0.341651f, 0.319601f, 0.2988f, 0.279133f, 0.260575f, 0.243316f, 0.227216f, 0.212098f, 0.197803f, 0.184217f, 0.171254f, 0.158835f, 0.146906f, 0.135426f, 0.124352f, 0.113664f, 0.103339f, 0.0933538f, 0.0836994f, 0.0743491f},
+ {0.917381f, 0.779585f, 0.70264f, 0.640234f, 0.587942f, 0.542923f, 0.503322f, 0.467867f, 0.435732f, 0.406285f, 0.379066f, 0.353768f, 0.330129f, 0.307935f, 0.287036f, 0.267313f, 0.248731f, 0.231476f, 0.215402f, 0.200323f, 0.186083f, 0.172584f, 0.159726f, 0.147435f, 0.135657f, 0.124347f, 0.113469f, 0.102992f, 0.092898f, 0.0831719f, 0.0737889f, 0.0647255f},
+ {0.9016f, 0.773416f, 0.695288f, 0.631867f, 0.578743f, 0.532989f, 0.492754f, 0.456782f, 0.424198f, 0.394388f, 0.366874f, 0.341344f, 0.317524f, 0.295205f, 0.274237f, 0.254489f, 0.235933f, 0.218722f, 0.202718f, 0.187724f, 0.173608f, 0.160244f, 0.147555f, 0.135463f, 0.123904f, 0.112837f, 0.102231f, 0.0920529f, 0.0822744f, 0.072887f, 0.0638682f, 0.0551924f},
+ {0.89597f, 0.766728f, 0.687074f, 0.622508f, 0.568442f, 0.521924f, 0.481014f, 0.444465f, 0.411431f, 0.381233f, 0.353424f, 0.327669f, 0.303705f, 0.2813f, 0.260303f, 0.240585f, 0.222097f, 0.204991f, 0.189117f, 0.174291f, 0.160361f, 0.147219f, 0.134768f, 0.122952f, 0.1117f, 0.100963f, 0.0907206f, 0.0809338f, 0.0715818f, 0.0626399f, 0.0540926f, 0.0459167f},
+ {0.889611f, 0.759066f, 0.677879f, 0.612037f, 0.556915f, 0.5095f, 0.467866f, 0.43074f, 0.397213f, 0.366648f, 0.338564f, 0.312623f, 0.288544f, 0.266104f, 0.245138f, 0.225512f, 0.207174f, 0.190249f, 0.174593f, 0.160007f, 0.146351f, 0.133517f, 0.12141f, 0.10996f, 0.0991205f, 0.0888212f, 0.079053f, 0.0697677f, 0.0609446f, 0.0525649f, 0.0446104f, 0.0370559f},
+ {0.88571f, 0.750491f, 0.667413f, 0.600153f, 0.543867f, 0.495509f, 0.453121f, 0.415381f, 0.381383f, 0.350454f, 0.322136f, 0.296045f, 0.271906f, 0.249507f, 0.228655f, 0.209217f, 0.19112f, 0.17448f, 0.159124f, 0.144888f, 0.13162f, 0.119201f, 0.107552f, 0.096592f, 0.0862693f, 0.0765452f, 0.0673689f, 0.0587079f, 0.0505464f, 0.0428553f, 0.03562f, 0.0288094f},
+ {0.881187f, 0.740717f, 0.655493f, 0.586624f, 0.529056f, 0.479691f, 0.436498f, 0.398131f, 0.36368f, 0.332435f, 0.30394f, 0.277786f, 0.25368f, 0.231415f, 0.21078f, 0.191636f, 0.173914f, 0.157676f, 0.142762f, 0.129006f, 0.116246f, 0.104388f, 0.093325f, 0.0829933f, 0.0733365f, 0.064305f, 0.0558577f, 0.0479562f, 0.0405888f, 0.0337189f, 0.0273257f, 0.0213849f},
+ {0.871552f, 0.729423f, 0.641759f, 0.571064f, 0.51215f, 0.461717f, 0.417699f, 0.378747f, 0.343881f, 0.312389f, 0.28379f, 0.257688f, 0.23375f, 0.211747f, 0.191478f, 0.172789f, 0.15559f, 0.139922f, 0.125599f, 0.112475f, 0.10039f, 0.089234f, 0.078919f, 0.0693676f, 0.0605158f, 0.0523276f, 0.0447506f, 0.037752f, 0.0313042f, 0.0253749f, 0.019938f, 0.0149783f},
+ {0.862202f, 0.71629f, 0.625816f, 0.553169f, 0.492726f, 0.441201f, 0.396405f, 0.356893f, 0.321718f, 0.290114f, 0.261572f, 0.235654f, 0.212044f, 0.190491f, 0.170786f, 0.15274f, 0.136254f, 0.12133f, 0.107812f, 0.0955063f, 0.0842785f, 0.0740051f, 0.0645986f, 0.0559841f, 0.0481095f, 0.0409034f, 0.0343314f, 0.0283543f, 0.0229354f, 0.0180445f, 0.0136542f, 0.00973637f},
+ {0.854242f, 0.700808f, 0.607223f, 0.53239f, 0.470404f, 0.417759f, 0.372242f, 0.332304f, 0.296972f, 0.265426f, 0.237128f, 0.211624f, 0.188581f, 0.167724f, 0.148806f, 0.131644f, 0.116108f, 0.102177f, 0.0896697f, 0.0783904f, 0.0682186f, 0.0590272f, 0.0507134f, 0.0432071f, 0.036439f, 0.0303554f, 0.0249063f, 0.0200439f, 0.0157306f, 0.0119318f, 0.00861227f, 0.00574364f},
+ {0.849415f, 0.682471f, 0.585377f, 0.508187f, 0.444628f, 0.390946f, 0.344851f, 0.304708f, 0.269428f, 0.238205f, 0.210447f, 0.185652f, 0.163483f, 0.143608f, 0.125798f, 0.109808f, 0.0955169f, 0.0828409f, 0.0715812f, 0.0615731f, 0.052665f, 0.0447368f, 0.03769f, 0.0314372f, 0.0259102f, 0.0210422f, 0.0167823f, 0.0130802f, 0.00988758f, 0.00716571f, 0.00487594f, 0.00298292f},
+ {0.826131f, 0.66057f, 0.559653f, 0.479971f, 0.41487f, 0.360302f, 0.313872f, 0.273805f, 0.238939f, 0.208449f, 0.181598f, 0.157936f, 0.137028f, 0.11853f, 0.102173f, 0.0877084f, 0.0749816f, 0.063839f, 0.0541136f, 0.0455908f, 0.0381677f, 0.0316713f, 0.0260305f, 0.0211355f, 0.016916f, 0.0133054f, 0.0102383f, 0.0076575f, 0.00552056f, 0.00377583f, 0.00238132f, 0.00129849f},
+ {0.812095f, 0.634496f, 0.529093f, 0.44694f, 0.380486f, 0.325406f, 0.279036f, 0.239517f, 0.205614f, 0.176316f, 0.150927f, 0.128895f, 0.109726f, 0.0930842f, 0.0786069f, 0.0660483f, 0.0552158f, 0.0459069f, 0.0379652f, 0.0311522f, 0.0253495f, 0.0204161f, 0.0162403f, 0.0127359f, 0.00981095f, 0.00739878f, 0.00543373f, 0.003856f, 0.00261187f, 0.00165708f, 0.000946434f, 0.000443164f},
+ {0.794071f, 0.603171f, 0.493023f, 0.408376f, 0.340973f, 0.285893f, 0.240198f, 0.201957f, 0.169687f, 0.142314f, 0.119063f, 0.0992952f, 0.0824592f, 0.0681709f, 0.0560355f, 0.0457793f, 0.0371415f, 0.0299437f, 0.0239457f, 0.0189681f, 0.0148637f, 0.0115041f, 0.00876013f, 0.00655424f, 0.00479841f, 0.0034206f, 0.00235615f, 0.00155722f, 0.000970439f, 0.000556371f, 0.000278639f, 0.000105997f},
+ {0.763979f, 0.565522f, 0.450168f, 0.363447f, 0.295723f, 0.241536f, 0.197573f, 0.161537f, 0.131902f, 0.107384f, 0.087099f, 0.0703382f, 0.0564711f, 0.0450734f, 0.0357098f, 0.0280724f, 0.0218626f, 0.0168724f, 0.0128856f, 0.00972834f, 0.00723374f, 0.00529015f, 0.00379385f, 0.00265875f, 0.00181094f, 0.00119149f, 0.000752846f, 0.000450051f, 0.000249434f, 0.000123833f, 5.16742e-05f, 1.48307e-05f},
+ {0.736436f, 0.520102f, 0.399499f, 0.311411f, 0.244558f, 0.192643f, 0.151786f, 0.11939f, 0.0936107f, 0.0730717f, 0.0567342f, 0.0437701f, 0.0335016f, 0.0254089f, 0.0190926f, 0.0141879f, 0.0104086f, 0.0075515f, 0.00539284f, 0.00378805f, 0.00261317f, 0.00175799f, 0.00115495f, 0.000735692f, 0.000449918f, 0.00026424f, 0.000146425f, 7.54017e-05f, 3.52908e-05f, 1.42643e-05f, 4.57858e-06f, 8.81577e-07f},
+ {0.700224f, 0.465658f, 0.339632f, 0.251689f, 0.187643f, 0.140115f, 0.104474f, 0.0775548f, 0.0572586f, 0.0419565f, 0.0304561f, 0.0219111f, 0.0155727f, 0.0109402f, 0.00756375f, 0.00515542f, 0.00344945f, 0.00226989f, 0.00145839f, 0.000917069f, 0.000562676f, 0.000333521f, 0.000190339f, 0.000104056f, 5.46174e-05f, 2.66385e-05f, 1.20736e-05f, 4.9736e-06f, 1.76633e-06f, 5.29699e-07f, 1.10831e-07f, 1.21185e-08f},
+ {0.663667f, 0.399957f, 0.269205f, 0.184027f, 0.126383f, 0.086515f, 0.0589411f, 0.0397684f, 0.0265884f, 0.0175079f, 0.011371f, 0.00726631f, 0.00457177f, 0.00281099f, 0.00169641f, 0.000999952f, 0.00057396f, 0.000321279f, 0.000173225f, 9.0491e-05f, 4.5631e-05f, 2.18649e-05f, 9.83801e-06f, 4.21215e-06f, 1.68447e-06f, 6.02285e-07f, 1.97599e-07f, 5.49234e-08f, 1.23614e-08f, 2.1325e-09f, 2.28753e-10f, 9.38201e-12f},
+ {0.627924f, 0.318773f, 0.185733f, 0.109707f, 0.0645309f, 0.037627f, 0.0216008f, 0.0121971f, 0.00673593f, 0.00363777f, 0.00192611f, 0.000980903f, 0.000492178f, 0.000238301f, 0.000111442f, 5.00866e-05f, 2.15714e-05f, 8.99007e-06f, 3.42523e-06f, 1.26682e-06f, 4.34498e-07f, 1.37677e-07f, 3.95201e-08f, 1.02132e-08f, 2.45011e-09f, 4.75872e-10f, 7.71094e-11f, 9.70048e-12f, 8.28134e-13f, 4.82864e-14f, 1.24283e-15f, 6.80699e-18f},
+ {0.602571f, 0.208486f, 0.086843f, 0.0363861f, 0.0150805f, 0.00613398f, 0.00243117f, 0.000935378f, 0.000340054f, 0.000120725f, 3.98771e-05f, 1.26402e-05f, 3.65801e-06f, 1.02043e-06f, 2.51742e-07f, 5.80963e-08f, 1.22453e-08f, 2.34199e-09f, 3.72857e-10f, 5.74371e-11f, 7.22338e-12f, 6.44319e-13f, 6.22934e-14f, 3.85108e-15f, 1.89348e-16f, 8.59175e-18f, 1.95153e-19f, 2.63448e-21f, 1.71356e-23f, 5.21569e-26f, 2.13312e-29f, 4.3595e-34f},
+ {0.591225f, 0.045818f, 0.00732363f, 0.00112657f, 0.000170285f, 2.07311e-05f, 2.37514e-06f, 1.86339e-07f, 1.1563e-08f, 7.84983e-10f, 2.46995e-11f, 1.01276e-12f, 2.0924e-14f, 2.83508e-16f, 7.15504e-18f, 2.95273e-20f, 8.42547e-23f, 2.83875e-25f, 9.54702e-28f, 5.32362e-31f, 4.20998e-34f, 1.43471e-37f, 3.92305e-40f, 1.4013e-45f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}
+};
+
+static const float table_ggx_dielectric_E[16][16][16] = {
+ {
+ {0.000833139f, 0.000739042f, 0.000661531f, 0.00058659f, 0.000504253f, 0.000429894f, 0.00034459f, 0.000248786f, 0.000130008f, 4.30204e-05f, 1.54746e-05f, 7.03338e-06f, 3.85273e-06f, 2.39524e-06f, 1.67518e-06f, 1.27851e-06f},
+ {0.000971227f, 0.000870615f, 0.000791253f, 0.000703758f, 0.000616392f, 0.000533401f, 0.000428542f, 0.000310971f, 0.000162786f, 5.49843e-05f, 1.97338e-05f, 8.86372e-06f, 4.74838e-06f, 2.90918e-06f, 2.0109e-06f, 1.53578e-06f},
+ {0.00117122f, 0.00106393f, 0.000977222f, 0.00087564f, 0.000762933f, 0.000667494f, 0.000542036f, 0.000394954f, 0.000209898f, 7.17009e-05f, 2.53486e-05f, 1.11729e-05f, 5.8894e-06f, 3.51212e-06f, 2.38932e-06f, 1.82166e-06f},
+ {0.00145307f, 0.00132647f, 0.00123762f, 0.00111287f, 0.00098268f, 0.000850916f, 0.000704074f, 0.000520591f, 0.000278186f, 9.42205e-05f, 3.27689e-05f, 1.42655e-05f, 7.27467e-06f, 4.21994e-06f, 2.79021e-06f, 2.1252e-06f},
+ {0.00187665f, 0.00174242f, 0.0015913f, 0.00147f, 0.0012994f, 0.00112776f, 0.000939697f, 0.000694948f, 0.000375119f, 0.000126431f, 4.36664e-05f, 1.83223e-05f, 8.92567e-06f, 5.04081e-06f, 3.22432e-06f, 2.41999e-06f},
+ {0.00250117f, 0.00231726f, 0.00215006f, 0.00194379f, 0.00174525f, 0.00153672f, 0.00127908f, 0.000963896f, 0.000518268f, 0.000174377f, 5.81443e-05f, 2.35887e-05f, 1.10161e-05f, 5.88478e-06f, 3.6355e-06f, 2.68866e-06f},
+ {0.00344393f, 0.00321262f, 0.00297996f, 0.00275639f, 0.00248222f, 0.00219712f, 0.00181121f, 0.00136085f, 0.000733074f, 0.000241602f, 7.79961e-05f, 3.03e-05f, 1.34434e-05f, 6.78013e-06f, 4.01359e-06f, 2.90952e-06f},
+ {0.00502222f, 0.00468816f, 0.00437739f, 0.00400831f, 0.00363854f, 0.00321053f, 0.00268791f, 0.00200402f, 0.00107331f, 0.000344745f, 0.000105866f, 3.84394e-05f, 1.60633e-05f, 7.58774e-06f, 4.30163e-06f, 3.08396e-06f},
+ {0.00760919f, 0.00717899f, 0.00670281f, 0.0061924f, 0.00560971f, 0.00490708f, 0.00410922f, 0.00307884f, 0.00162484f, 0.000500342f, 0.000142486f, 4.77747e-05f, 1.83874e-05f, 8.12365e-06f, 4.43344e-06f, 3.16708e-06f},
+ {0.0123334f, 0.0115619f, 0.0108044f, 0.00999222f, 0.00902f, 0.00794271f, 0.00664624f, 0.00491208f, 0.0025462f, 0.00073129f, 0.000187547f, 5.68591e-05f, 2.01069e-05f, 8.37956e-06f, 4.43916e-06f, 3.20476e-06f},
+ {0.0210496f, 0.0198311f, 0.0185466f, 0.0170842f, 0.0154773f, 0.0135819f, 0.0112714f, 0.0082633f, 0.00412282f, 0.001059f, 0.000235039f, 6.366e-05f, 2.06888e-05f, 8.23859e-06f, 4.33161e-06f, 3.1942e-06f},
+ {0.0385231f, 0.036234f, 0.0338544f, 0.031228f, 0.0282111f, 0.0246418f, 0.0203127f, 0.0146674f, 0.00682645f, 0.00148063f, 0.00027352f, 6.59662e-05f, 2.02234e-05f, 7.8928e-06f, 4.18144e-06f, 3.16758e-06f},
+ {0.0750848f, 0.0708705f, 0.0661296f, 0.0607573f, 0.0547065f, 0.0476295f, 0.0388318f, 0.0269979f, 0.0111858f, 0.00187513f, 0.000285965f, 6.43457e-05f, 1.91992e-05f, 7.45021e-06f, 4.03854e-06f, 3.15126e-06f},
+ {0.156612f, 0.147597f, 0.13748f, 0.12619f, 0.113024f, 0.0970109f, 0.0768087f, 0.0495397f, 0.0165158f, 0.00206221f, 0.000279698f, 6.11915e-05f, 1.82972e-05f, 7.16881e-06f, 3.94998e-06f, 3.12396e-06f},
+ {0.339907f, 0.318571f, 0.297574f, 0.271907f, 0.238398f, 0.195571f, 0.142549f, 0.0791503f, 0.0199063f, 0.00204778f, 0.000270804f, 5.93819e-05f, 1.77928e-05f, 7.02194e-06f, 3.91683e-06f, 3.12036e-06f},
+ {0.716349f, 0.663103f, 0.590735f, 0.503601f, 0.407083f, 0.305267f, 0.200609f, 0.097081f, 0.0203857f, 0.00201006f, 0.000266758f, 5.87193e-05f, 1.76699e-05f, 6.99297e-06f, 3.90627e-06f, 3.11936e-06f}
+ },
+ {
+ {0.0054489f, 0.00482758f, 0.00430475f, 0.00381337f, 0.00332831f, 0.00284381f, 0.00234429f, 0.00180105f, 0.00123002f, 0.000687392f, 0.000346588f, 0.000182707f, 0.000107221f, 6.96051e-05f, 4.98454e-05f, 3.86404e-05f},
+ {0.00632047f, 0.00566836f, 0.00509984f, 0.00456772f, 0.0040243f, 0.00345987f, 0.00287984f, 0.00223329f, 0.00152974f, 0.000867574f, 0.000435897f, 0.00022754f, 0.000131303f, 8.41223e-05f, 5.97612e-05f, 4.64033e-05f},
+ {0.00751868f, 0.00683849f, 0.00621179f, 0.00557888f, 0.00494806f, 0.00430001f, 0.0035993f, 0.00281247f, 0.00194378f, 0.00110538f, 0.000552399f, 0.000284381f, 0.00016138f, 0.000101163f, 7.08287e-05f, 5.49811e-05f},
+ {0.00917018f, 0.00839765f, 0.00770217f, 0.00698923f, 0.00622979f, 0.00543909f, 0.00457211f, 0.00360984f, 0.00251132f, 0.00142492f, 0.000707093f, 0.00035873f, 0.000198194f, 0.000120952f, 8.2766e-05f, 6.40531e-05f},
+ {0.0115296f, 0.0106853f, 0.00981214f, 0.00896792f, 0.00803715f, 0.00704736f, 0.00596575f, 0.00472702f, 0.00330195f, 0.00187294f, 0.000920679f, 0.000455649f, 0.000242469f, 0.000143645f, 9.54207e-05f, 7.30283e-05f},
+ {0.0149886f, 0.0139356f, 0.0128885f, 0.0117971f, 0.0106259f, 0.00938115f, 0.00797168f, 0.00632205f, 0.00442635f, 0.00250747f, 0.00120767f, 0.000579839f, 0.00029674f, 0.000167605f, 0.000107637f, 8.1211e-05f},
+ {0.020083f, 0.0187734f, 0.0174339f, 0.0160347f, 0.0144876f, 0.0128035f, 0.0108938f, 0.00868579f, 0.00605735f, 0.00339308f, 0.00159783f, 0.000738063f, 0.000359774f, 0.000192457f, 0.000118643f, 8.79938e-05f},
+ {0.0279459f, 0.026192f, 0.0244034f, 0.0224763f, 0.0203525f, 0.0180162f, 0.0153666f, 0.0122229f, 0.00848837f, 0.00467733f, 0.00212656f, 0.000930591f, 0.000427272f, 0.000215171f, 0.000127045f, 9.31421e-05f},
+ {0.0402593f, 0.0378179f, 0.0353093f, 0.0325471f, 0.0295181f, 0.0261582f, 0.0222662f, 0.0176824f, 0.0121424f, 0.00652877f, 0.00281585f, 0.00114965f, 0.000489492f, 0.000230955f, 0.000131329f, 9.59171e-05f},
+ {0.0600786f, 0.0565731f, 0.0528449f, 0.0487969f, 0.0442528f, 0.0391631f, 0.0332573f, 0.0261877f, 0.0177251f, 0.00912576f, 0.00365579f, 0.00136535f, 0.000536541f, 0.00023833f, 0.00013182f, 9.71272e-05f},
+ {0.0926893f, 0.0874447f, 0.0816981f, 0.0754352f, 0.0684505f, 0.0603947f, 0.0510103f, 0.0397201f, 0.0261436f, 0.0125808f, 0.00453719f, 0.00153327f, 0.000555563f, 0.000235702f, 0.000129202f, 9.69834e-05f},
+ {0.147257f, 0.139052f, 0.129869f, 0.119935f, 0.108499f, 0.0953123f, 0.079793f, 0.060981f, 0.0381665f, 0.0166025f, 0.00526269f, 0.00160539f, 0.000548524f, 0.000227108f, 0.000125193f, 9.63345e-05f},
+ {0.238632f, 0.225199f, 0.210292f, 0.193614f, 0.174596f, 0.152403f, 0.125454f, 0.0919936f, 0.0528787f, 0.0200386f, 0.00558471f, 0.00158949f, 0.000526298f, 0.000216321f, 0.00012142f, 9.57553e-05f},
+ {0.387215f, 0.363624f, 0.339193f, 0.312425f, 0.279986f, 0.238885f, 0.187623f, 0.126957f, 0.064932f, 0.0216823f, 0.00558656f, 0.00153846f, 0.000505618f, 0.000208917f, 0.000118933f, 9.51526e-05f},
+ {0.601368f, 0.565664f, 0.532116f, 0.480309f, 0.410484f, 0.327764f, 0.238057f, 0.148055f, 0.0696973f, 0.0218727f, 0.00549581f, 0.00150288f, 0.000493932f, 0.000205215f, 0.000117959f, 9.50296e-05f},
+ {0.850891f, 0.788596f, 0.690268f, 0.580937f, 0.469289f, 0.358751f, 0.251714f, 0.152438f, 0.0702474f, 0.0217677f, 0.00544833f, 0.00149152f, 0.000491073f, 0.000204302f, 0.000117631f, 9.49407e-05f}
+ },
+ {
+ {0.0134773f, 0.0119334f, 0.0106402f, 0.00943146f, 0.00827477f, 0.00712604f, 0.00598572f, 0.00480555f, 0.00362505f, 0.00248347f, 0.00156394f, 0.000964066f, 0.000620601f, 0.000427409f, 0.000317538f, 0.000252033f},
+ {0.0154715f, 0.0138684f, 0.0124784f, 0.0111661f, 0.00987902f, 0.00856818f, 0.00725332f, 0.00586758f, 0.00444672f, 0.00306948f, 0.00193197f, 0.00118275f, 0.000752525f, 0.000513362f, 0.000379663f, 0.000302407f},
+ {0.018133f, 0.0164694f, 0.014946f, 0.0134629f, 0.011988f, 0.01048f, 0.00892565f, 0.00727173f, 0.00553599f, 0.0038303f, 0.00240588f, 0.00145722f, 0.000914262f, 0.000613295f, 0.000448658f, 0.000357988f},
+ {0.0217691f, 0.0199308f, 0.0182436f, 0.0165531f, 0.0148152f, 0.0130371f, 0.0111501f, 0.00914209f, 0.00699686f, 0.00483563f, 0.00302397f, 0.00180912f, 0.00111084f, 0.000728306f, 0.0005233f, 0.000416705f},
+ {0.0268022f, 0.0247771f, 0.0227878f, 0.0208044f, 0.0187235f, 0.0165533f, 0.0142274f, 0.0116998f, 0.00897598f, 0.00620667f, 0.00384934f, 0.00226023f, 0.00134572f, 0.000858441f, 0.00060167f, 0.0004751f},
+ {0.0339414f, 0.0315519f, 0.0291755f, 0.0267461f, 0.0241738f, 0.0214679f, 0.0185015f, 0.0152512f, 0.0117175f, 0.00808103f, 0.00494193f, 0.00283123f, 0.0016288f, 0.000997006f, 0.00067781f, 0.000528645f},
+ {0.0441083f, 0.0412223f, 0.0382958f, 0.0352252f, 0.0319457f, 0.0284347f, 0.0245693f, 0.0202935f, 0.0155534f, 0.0106412f, 0.00639801f, 0.00354955f, 0.00195491f, 0.00113935f, 0.000746232f, 0.000573412f},
+ {0.0590103f, 0.055343f, 0.0515593f, 0.0475658f, 0.0432285f, 0.0385148f, 0.0333405f, 0.0274946f, 0.0209867f, 0.0141888f, 0.00831519f, 0.00441743f, 0.00230368f, 0.00127026f, 0.00079906f, 0.000607241f},
+ {0.081026f, 0.0761906f, 0.071196f, 0.065735f, 0.0598391f, 0.0533955f, 0.0461258f, 0.0379552f, 0.0287092f, 0.0190676f, 0.0107546f, 0.00539737f, 0.00263185f, 0.00136538f, 0.000828535f, 0.000626811f},
+ {0.113957f, 0.107471f, 0.100498f, 0.0929509f, 0.0846462f, 0.0754061f, 0.0650015f, 0.0531292f, 0.0396794f, 0.0255514f, 0.0136604f, 0.00636976f, 0.00288726f, 0.00141338f, 0.000835217f, 0.000635768f},
+ {0.163512f, 0.154467f, 0.144593f, 0.133784f, 0.121783f, 0.10823f, 0.092816f, 0.0750354f, 0.0547318f, 0.0335873f, 0.0166494f, 0.00714922f, 0.00301045f, 0.00140856f, 0.000823361f, 0.000636303f},
+ {0.237967f, 0.224954f, 0.21048f, 0.194654f, 0.176822f, 0.156529f, 0.133013f, 0.105369f, 0.0736485f, 0.0421191f, 0.0190916f, 0.0075472f, 0.0030057f, 0.00136947f, 0.000802573f, 0.000633212f},
+ {0.347622f, 0.327749f, 0.306321f, 0.28301f, 0.256642f, 0.225294f, 0.187228f, 0.142072f, 0.0929064f, 0.0487841f, 0.0203309f, 0.00757853f, 0.0029212f, 0.00131786f, 0.000782341f, 0.00062987f},
+ {0.500004f, 0.468164f, 0.439508f, 0.40699f, 0.364072f, 0.309008f, 0.243923f, 0.173495f, 0.105729f, 0.0519279f, 0.0205797f, 0.00744622f, 0.00283547f, 0.00128046f, 0.000768588f, 0.000626691f},
+ {0.682999f, 0.650709f, 0.610607f, 0.543879f, 0.46044f, 0.36923f, 0.276602f, 0.187945f, 0.110242f, 0.0525648f, 0.0204669f, 0.00733238f, 0.00278506f, 0.00126175f, 0.000763024f, 0.000625869f},
+ {0.879889f, 0.81163f, 0.707536f, 0.598578f, 0.490206f, 0.38462f, 0.283682f, 0.190684f, 0.110882f, 0.052544f, 0.0203766f, 0.00729589f, 0.0027724f, 0.001257f, 0.000761166f, 0.000625359f}
+ },
+ {
+ {0.0238197f, 0.0211108f, 0.0188422f, 0.0167573f, 0.0147763f, 0.0128504f, 0.010956f, 0.00906967f, 0.00721569f, 0.00543793f, 0.00388576f, 0.00270171f, 0.00190172f, 0.00139396f, 0.00107937f, 0.00088027f},
+ {0.027024f, 0.0242377f, 0.0218403f, 0.0195824f, 0.0174037f, 0.0152367f, 0.0130791f, 0.0108893f, 0.00870305f, 0.00658977f, 0.00471157f, 0.00326184f, 0.00227979f, 0.00166215f, 0.00128599f, 0.00105485f},
+ {0.0312307f, 0.028357f, 0.0257586f, 0.0232631f, 0.0208073f, 0.0183345f, 0.0158315f, 0.0132536f, 0.0106309f, 0.00806245f, 0.005755f, 0.00395292f, 0.00273407f, 0.00197022f, 0.00151425f, 0.0012473f},
+ {0.0368842f, 0.0337766f, 0.0309339f, 0.028114f, 0.0252827f, 0.0224056f, 0.0194298f, 0.0163467f, 0.0131567f, 0.00996559f, 0.00708664f, 0.00481926f, 0.00327804f, 0.00232049f, 0.00176065f, 0.00145048f},
+ {0.0445504f, 0.0411596f, 0.0379045f, 0.0346566f, 0.0313193f, 0.0278805f, 0.0242788f, 0.020473f, 0.016498f, 0.0124936f, 0.00881884f, 0.00590692f, 0.00391931f, 0.00271135f, 0.00201762f, 0.00165313f},
+ {0.0551315f, 0.0512576f, 0.0474356f, 0.0435717f, 0.0395285f, 0.0353354f, 0.0308395f, 0.0260586f, 0.021011f, 0.0158556f, 0.0110624f, 0.00726079f, 0.00467893f, 0.00312695f, 0.00226797f, 0.00184002f},
+ {0.0697923f, 0.0652443f, 0.0606751f, 0.0559088f, 0.0508999f, 0.045599f, 0.0398809f, 0.033734f, 0.0271379f, 0.0203319f, 0.0139857f, 0.00893493f, 0.00554413f, 0.0035507f, 0.0024935f, 0.00199771f},
+ {0.090504f, 0.0849509f, 0.0792256f, 0.0732382f, 0.0668228f, 0.0599185f, 0.0524799f, 0.0443196f, 0.0355052f, 0.0263326f, 0.0177353f, 0.0109306f, 0.006466f, 0.00394227f, 0.00267066f, 0.00211782f},
+ {0.119864f, 0.112845f, 0.105589f, 0.0977262f, 0.089284f, 0.080165f, 0.0700984f, 0.0590518f, 0.0469187f, 0.0342734f, 0.0223816f, 0.0131589f, 0.00734204f, 0.00423762f, 0.00277741f, 0.00219115f},
+ {0.161698f, 0.152675f, 0.142986f, 0.132555f, 0.121174f, 0.108654f, 0.0948148f, 0.0793925f, 0.0623309f, 0.0443728f, 0.0277639f, 0.0153645f, 0.00804042f, 0.0044007f, 0.00281335f, 0.00222742f},
+ {0.221163f, 0.209139f, 0.19608f, 0.181832f, 0.166153f, 0.148703f, 0.129126f, 0.106964f, 0.0821502f, 0.056202f, 0.0331533f, 0.0171563f, 0.008421f, 0.0044189f, 0.00279129f, 0.00223515f},
+ {0.304872f, 0.28827f, 0.270099f, 0.250395f, 0.228592f, 0.203852f, 0.175231f, 0.142043f, 0.104966f, 0.0679245f, 0.0374763f, 0.0181623f, 0.00848426f, 0.00433705f, 0.00273886f, 0.00222901f},
+ {0.419258f, 0.394724f, 0.369774f, 0.343265f, 0.312835f, 0.275756f, 0.230938f, 0.179571f, 0.125717f, 0.0765274f, 0.0397846f, 0.0183976f, 0.0083389f, 0.00421535f, 0.00268452f, 0.00222f},
+ {0.564586f, 0.528693f, 0.500018f, 0.463913f, 0.413847f, 0.351108f, 0.280343f, 0.20718f, 0.138166f, 0.0805441f, 0.0404455f, 0.0182559f, 0.00816844f, 0.0041224f, 0.0026463f, 0.00221114f},
+ {0.724662f, 0.697084f, 0.650536f, 0.575759f, 0.487769f, 0.39564f, 0.304575f, 0.218596f, 0.142428f, 0.0815253f, 0.0404322f, 0.0180835f, 0.00806238f, 0.00407511f, 0.00263051f, 0.00220859f},
+ {0.894611f, 0.82241f, 0.718073f, 0.61173f, 0.507051f, 0.405794f, 0.309477f, 0.220748f, 0.143096f, 0.0815987f, 0.0403418f, 0.0180254f, 0.00803507f, 0.00406293f, 0.00262515f, 0.00220711f}
+ },
+ {
+ {0.0358343f, 0.0318379f, 0.0285018f, 0.025466f, 0.0225984f, 0.0198491f, 0.0171665f, 0.0145469f, 0.0120017f, 0.00957318f, 0.00738436f, 0.00557967f, 0.00422319f, 0.00327311f, 0.0026358f, 0.00220758f},
+ {0.0401601f, 0.0360909f, 0.0326095f, 0.0293522f, 0.0262432f, 0.0231857f, 0.020174f, 0.0171764f, 0.0142277f, 0.0113899f, 0.00879617f, 0.00663365f, 0.00500545f, 0.00387396f, 0.00312824f, 0.00264104f},
+ {0.0457675f, 0.0416052f, 0.0378846f, 0.0343402f, 0.0308827f, 0.0274416f, 0.0240029f, 0.0205291f, 0.0170547f, 0.0136661f, 0.010542f, 0.00790713f, 0.00592566f, 0.00455506f, 0.00366917f, 0.00311836f},
+ {0.0531949f, 0.0487785f, 0.0447594f, 0.0408071f, 0.036889f, 0.0329475f, 0.0289295f, 0.0248344f, 0.0206752f, 0.0165481f, 0.01272f, 0.00946548f, 0.00700681f, 0.00531864f, 0.0042506f, 0.00362199f},
+ {0.0631052f, 0.0583486f, 0.0538427f, 0.0493753f, 0.0448329f, 0.0401991f, 0.0354157f, 0.0304558f, 0.0253692f, 0.0202774f, 0.0154824f, 0.0113772f, 0.00825911f, 0.0061583f, 0.00485322f, 0.00412526f},
+ {0.0765093f, 0.0712044f, 0.0660153f, 0.0608039f, 0.0554114f, 0.0498659f, 0.0440226f, 0.0379064f, 0.0315586f, 0.0251239f, 0.0189796f, 0.0137102f, 0.00971429f, 0.00704499f, 0.00544079f, 0.00459175f},
+ {0.0946911f, 0.0886122f, 0.0825482f, 0.0762678f, 0.0697294f, 0.0628755f, 0.055586f, 0.0478732f, 0.039754f, 0.0314252f, 0.0234375f, 0.0165402f, 0.0113484f, 0.00794176f, 0.00597195f, 0.00498885f},
+ {0.119714f, 0.112505f, 0.105099f, 0.0974135f, 0.0892439f, 0.0805268f, 0.0712618f, 0.0612599f, 0.0506454f, 0.0396504f, 0.0290232f, 0.0198596f, 0.0130767f, 0.00877228f, 0.0063965f, 0.00529482f},
+ {0.15416f, 0.145329f, 0.13621f, 0.126403f, 0.115936f, 0.104726f, 0.0925239f, 0.0793263f, 0.0650568f, 0.0502183f, 0.0357813f, 0.0235156f, 0.0147231f, 0.00941683f, 0.00666896f, 0.00548995f},
+ {0.201638f, 0.190615f, 0.178818f, 0.166189f, 0.152515f, 0.137613f, 0.121326f, 0.103408f, 0.0838158f, 0.0632103f, 0.0434132f, 0.0271049f, 0.0160558f, 0.00980044f, 0.0067856f, 0.00559379f},
+ {0.266619f, 0.25235f, 0.236947f, 0.220278f, 0.202099f, 0.182063f, 0.15973f, 0.134658f, 0.106853f, 0.0777947f, 0.0508658f, 0.0300301f, 0.0168412f, 0.0099017f, 0.00677348f, 0.00562793f},
+ {0.354322f, 0.335062f, 0.314385f, 0.292341f, 0.268175f, 0.240684f, 0.20878f, 0.172098f, 0.131797f, 0.0915616f, 0.0567327f, 0.0317579f, 0.0170689f, 0.00979803f, 0.0066878f, 0.00562442f},
+ {0.468551f, 0.440725f, 0.414082f, 0.38617f, 0.353238f, 0.312441f, 0.263599f, 0.20898f, 0.152905f, 0.101252f, 0.0599336f, 0.0323058f, 0.0169154f, 0.00960406f, 0.00658901f, 0.00560931f},
+ {0.605581f, 0.568177f, 0.540397f, 0.501468f, 0.446818f, 0.380197f, 0.307363f, 0.233795f, 0.164861f, 0.105749f, 0.0609902f, 0.0322404f, 0.0166837f, 0.00944633f, 0.00651632f, 0.0055923f},
+ {0.750163f, 0.725931f, 0.674553f, 0.595927f, 0.506948f, 0.415919f, 0.327045f, 0.243548f, 0.168929f, 0.106952f, 0.0611084f, 0.0320564f, 0.0165289f, 0.00936413f, 0.00648574f, 0.00558712f},
+ {0.90352f, 0.829307f, 0.726325f, 0.622715f, 0.521319f, 0.423627f, 0.330922f, 0.245397f, 0.169596f, 0.107093f, 0.0610393f, 0.031989f, 0.0164881f, 0.00934261f, 0.00647503f, 0.00558409f}
+ },
+ {
+ {0.049263f, 0.0439495f, 0.039526f, 0.0355251f, 0.0317568f, 0.028172f, 0.0246975f, 0.0213342f, 0.0180912f, 0.0150024f, 0.0121741f, 0.00974301f, 0.00778936f, 0.00631804f, 0.00526283f, 0.00451406f},
+ {0.0545288f, 0.0491761f, 0.0446147f, 0.0403699f, 0.0363441f, 0.0324123f, 0.0285694f, 0.0247851f, 0.0210973f, 0.0175548f, 0.0142732f, 0.0114247f, 0.00913658f, 0.00742588f, 0.00622164f, 0.00538976f},
+ {0.0612851f, 0.0558621f, 0.0510569f, 0.0465052f, 0.0420904f, 0.0377294f, 0.0334143f, 0.0290996f, 0.0248306f, 0.0206789f, 0.0168068f, 0.0134114f, 0.0106881f, 0.008665f, 0.00726887f, 0.00635282f},
+ {0.0701276f, 0.0644691f, 0.0593445f, 0.0543413f, 0.0494218f, 0.0445061f, 0.0395415f, 0.034537f, 0.0295095f, 0.0245491f, 0.0198938f, 0.0157815f, 0.0124732f, 0.0100339f, 0.00838855f, 0.00736803f},
+ {0.0817766f, 0.0757684f, 0.070125f, 0.064561f, 0.0589476f, 0.0532648f, 0.047451f, 0.0414943f, 0.0354518f, 0.0294362f, 0.0237113f, 0.0186193f, 0.0145004f, 0.0115168f, 0.00954218f, 0.00838362f},
+ {0.0972988f, 0.0907249f, 0.084342f, 0.0779665f, 0.0714237f, 0.0647249f, 0.057753f, 0.0505347f, 0.0431154f, 0.0356457f, 0.0284353f, 0.0220085f, 0.016808f, 0.0130674f, 0.0106663f, 0.00932891f},
+ {0.118018f, 0.110635f, 0.103318f, 0.095781f, 0.0879837f, 0.0798674f, 0.0713186f, 0.0623647f, 0.0530538f, 0.0435497f, 0.0343289f, 0.0260379f, 0.0193581f, 0.0146214f, 0.0116855f, 0.0101398f},
+ {0.146f, 0.137441f, 0.128689f, 0.119648f, 0.1101f, 0.0999781f, 0.0893148f, 0.0779289f, 0.0659733f, 0.0536418f, 0.0415628f, 0.0306845f, 0.0220275f, 0.0160602f, 0.0125125f, 0.0107719f},
+ {0.183728f, 0.173487f, 0.162931f, 0.151648f, 0.139672f, 0.126919f, 0.11318f, 0.0984522f, 0.0826797f, 0.0663106f, 0.0501368f, 0.0357302f, 0.0245653f, 0.0172002f, 0.0130701f, 0.0111893f},
+ {0.234548f, 0.222029f, 0.20868f, 0.194472f, 0.179179f, 0.162651f, 0.144712f, 0.125123f, 0.103844f, 0.0814873f, 0.0596167f, 0.0406355f, 0.026637f, 0.0179185f, 0.0133483f, 0.011425f},
+ {0.302344f, 0.286446f, 0.269391f, 0.251107f, 0.231339f, 0.20967f, 0.185595f, 0.158676f, 0.128987f, 0.0979997f, 0.068685f, 0.0446287f, 0.0279229f, 0.0181857f, 0.0133941f, 0.0115223f},
+ {0.391323f, 0.370159f, 0.347859f, 0.324505f, 0.299011f, 0.269867f, 0.235947f, 0.197185f, 0.155072f, 0.113067f, 0.0757243f, 0.0470591f, 0.0283976f, 0.018111f, 0.0132954f, 0.0115375f},
+ {0.503589f, 0.473541f, 0.446217f, 0.417774f, 0.383304f, 0.340254f, 0.289226f, 0.233094f, 0.176135f, 0.123386f, 0.0796023f, 0.0479481f, 0.0283004f, 0.0178708f, 0.0131569f, 0.0115212f},
+ {0.633226f, 0.595523f, 0.568606f, 0.527724f, 0.470465f, 0.402181f, 0.328971f, 0.255944f, 0.187661f, 0.128162f, 0.0809784f, 0.0480034f, 0.028048f, 0.0176587f, 0.0130483f, 0.011496f},
+ {0.767073f, 0.74497f, 0.690584f, 0.610465f, 0.521984f, 0.432625f, 0.345964f, 0.26467f, 0.191575f, 0.129502f, 0.0812154f, 0.0478403f, 0.0278634f, 0.0175445f, 0.0130018f, 0.011488f},
+ {0.90934f, 0.834459f, 0.733265f, 0.632227f, 0.533697f, 0.438997f, 0.349256f, 0.266338f, 0.192235f, 0.129685f, 0.0811716f, 0.0477733f, 0.0278134f, 0.0175141f, 0.0129847f, 0.011483f}
+ },
+ {
+ {0.0640814f, 0.0574846f, 0.0519985f, 0.0470462f, 0.042391f, 0.0379756f, 0.03371f, 0.0295985f, 0.0256463f, 0.0218829f, 0.0184027f, 0.0153367f, 0.0127657f, 0.0107273f, 0.00918596f, 0.00803987f},
+ {0.0700642f, 0.0634915f, 0.0579038f, 0.0527207f, 0.0478182f, 0.0430505f, 0.0384107f, 0.0338681f, 0.0294587f, 0.0252286f, 0.0212803f, 0.0177715f, 0.0148381f, 0.0125294f, 0.010818f, 0.00957796f},
+ {0.0776754f, 0.0710878f, 0.0652858f, 0.0598068f, 0.0545127f, 0.0493069f, 0.0441839f, 0.0390928f, 0.034085f, 0.0292264f, 0.0246667f, 0.0205831f, 0.0171768f, 0.0145194f, 0.0125906f, 0.0112666f},
+ {0.087544f, 0.0807737f, 0.0746673f, 0.0687346f, 0.0629286f, 0.0571556f, 0.0513547f, 0.0455507f, 0.0397578f, 0.0340643f, 0.028693f, 0.0238524f, 0.0198115f, 0.0166866f, 0.0144752f, 0.0130444f},
+ {0.100415f, 0.0933282f, 0.0867113f, 0.0802169f, 0.0736964f, 0.0671269f, 0.0604465f, 0.0536521f, 0.0468096f, 0.0400272f, 0.0335458f, 0.0276704f, 0.0227425f, 0.0190003f, 0.0164058f, 0.0148235f},
+ {0.117374f, 0.10975f, 0.10239f, 0.0950646f, 0.0875875f, 0.0799596f, 0.0720803f, 0.0639825f, 0.0557144f, 0.0474366f, 0.0394149f, 0.0321278f, 0.0260095f, 0.0213924f, 0.0182838f, 0.0164845f},
+ {0.139747f, 0.131328f, 0.123023f, 0.11451f, 0.105738f, 0.0966491f, 0.0871373f, 0.0772478f, 0.067047f, 0.0566811f, 0.0465843f, 0.0373203f, 0.0295588f, 0.0237671f, 0.0199902f, 0.0179184f},
+ {0.169556f, 0.159968f, 0.150209f, 0.140156f, 0.129591f, 0.118443f, 0.106766f, 0.0944001f, 0.081508f, 0.0682636f, 0.0552209f, 0.0432074f, 0.0332304f, 0.025961f, 0.0213918f, 0.0190475f},
+ {0.209163f, 0.197897f, 0.186309f, 0.173979f, 0.160947f, 0.147134f, 0.132358f, 0.116619f, 0.0998744f, 0.0825344f, 0.06528f, 0.0495133f, 0.0367055f, 0.0277252f, 0.022373f, 0.0198138f},
+ {0.261686f, 0.248121f, 0.233706f, 0.218435f, 0.202089f, 0.18453f, 0.165568f, 0.144965f, 0.122681f, 0.0993001f, 0.0762148f, 0.0555861f, 0.0395549f, 0.0288856f, 0.0229146f, 0.0202667f},
+ {0.330562f, 0.313556f, 0.295419f, 0.276134f, 0.25544f, 0.232849f, 0.207796f, 0.179854f, 0.149148f, 0.117136f, 0.0865125f, 0.0605197f, 0.0413898f, 0.0294082f, 0.0230902f, 0.0204814f},
+ {0.419323f, 0.396875f, 0.373606f, 0.349596f, 0.323465f, 0.293472f, 0.258505f, 0.218722f, 0.175813f, 0.133044f, 0.0944332f, 0.0635843f, 0.0421678f, 0.0294277f, 0.0230191f, 0.0205425f},
+ {0.529025f, 0.497538f, 0.470052f, 0.441529f, 0.4063f, 0.362149f, 0.310225f, 0.253701f, 0.196712f, 0.143748f, 0.0988194f, 0.0648012f, 0.0421795f, 0.0291832f, 0.0228607f, 0.0205362f},
+ {0.652546f, 0.614936f, 0.588741f, 0.546853f, 0.488476f, 0.419868f, 0.347178f, 0.275177f, 0.207898f, 0.148689f, 0.100442f, 0.0649891f, 0.0419435f, 0.0289391f, 0.0227237f, 0.0205056f},
+ {0.778651f, 0.757907f, 0.702076f, 0.621855f, 0.534538f, 0.447013f, 0.362479f, 0.283235f, 0.211692f, 0.150109f, 0.100774f, 0.0648621f, 0.0417482f, 0.0288019f, 0.0226636f, 0.0204958f},
+ {0.913306f, 0.838644f, 0.73936f, 0.640683f, 0.544696f, 0.452603f, 0.365415f, 0.284779f, 0.212338f, 0.15032f, 0.100752f, 0.0648007f, 0.0416937f, 0.0287644f, 0.0226404f, 0.0204887f}
+ },
+ {
+ {0.0803585f, 0.0725536f, 0.0660569f, 0.0601876f, 0.0546685f, 0.0494325f, 0.0443772f, 0.039507f, 0.0348263f, 0.0303632f, 0.0262068f, 0.0224862f, 0.0192785f, 0.0166424f, 0.0145671f, 0.0129636f},
+ {0.0868272f, 0.0791381f, 0.0726053f, 0.066551f, 0.060827f, 0.0552656f, 0.0498625f, 0.0445833f, 0.0394648f, 0.0345559f, 0.02995f, 0.0257962f, 0.0222347f, 0.0193303f, 0.0170918f, 0.015405f},
+ {0.0949956f, 0.0873776f, 0.0806932f, 0.0743873f, 0.0683033f, 0.0623328f, 0.0564699f, 0.0506613f, 0.0449668f, 0.0394454f, 0.034247f, 0.0295345f, 0.0255088f, 0.0222636f, 0.0198192f, 0.0180796f},
+ {0.10551f, 0.0977934f, 0.0908542f, 0.0841298f, 0.077564f, 0.0710516f, 0.0645252f, 0.0580227f, 0.0515577f, 0.0452203f, 0.0392291f, 0.033774f, 0.0291231f, 0.0254156f, 0.0227025f, 0.0208908f},
+ {0.119117f, 0.111153f, 0.103748f, 0.0965002f, 0.0892401f, 0.0819454f, 0.074555f, 0.0670718f, 0.0595727f, 0.0521647f, 0.045081f, 0.0386034f, 0.0330633f, 0.0287348f, 0.02564f, 0.023703f},
+ {0.1369f, 0.128462f, 0.12035f, 0.112294f, 0.1041f, 0.0957545f, 0.0871753f, 0.0784003f, 0.0694858f, 0.0606027f, 0.0519945f, 0.0441119f, 0.0373651f, 0.0321274f, 0.0284908f, 0.026334f},
+ {0.160162f, 0.150978f, 0.141954f, 0.132734f, 0.123254f, 0.11346f, 0.103254f, 0.0926985f, 0.0818751f, 0.0709259f, 0.0602656f, 0.0503989f, 0.0419584f, 0.0354631f, 0.0310839f, 0.0286161f},
+ {0.190862f, 0.180558f, 0.170108f, 0.159361f, 0.148103f, 0.136265f, 0.123912f, 0.110906f, 0.0974297f, 0.0836426f, 0.0700573f, 0.0574097f, 0.0466516f, 0.038535f, 0.0332341f, 0.030428f},
+ {0.231255f, 0.219316f, 0.207055f, 0.194057f, 0.180354f, 0.165884f, 0.15049f, 0.134171f, 0.116903f, 0.0990739f, 0.081292f, 0.0648239f, 0.0510695f, 0.041032f, 0.0347829f, 0.031684f},
+ {0.284273f, 0.270056f, 0.254988f, 0.239084f, 0.222136f, 0.204019f, 0.184535f, 0.163455f, 0.140737f, 0.116945f, 0.0933454f, 0.0719059f, 0.0547005f, 0.0427281f, 0.0356989f, 0.0324525f},
+ {0.353047f, 0.335381f, 0.31662f, 0.296801f, 0.275672f, 0.252696f, 0.227271f, 0.198977f, 0.167965f, 0.135662f, 0.104571f, 0.0776515f, 0.0571057f, 0.0435924f, 0.0360905f, 0.0328519f},
+ {0.440703f, 0.417495f, 0.393722f, 0.369475f, 0.343199f, 0.312998f, 0.277765f, 0.237802f, 0.194883f, 0.152123f, 0.113164f, 0.0812787f, 0.0582238f, 0.0437738f, 0.0361006f, 0.0329945f},
+ {0.547713f, 0.515359f, 0.487926f, 0.459618f, 0.424305f, 0.379991f, 0.328129f, 0.272005f, 0.215612f, 0.163081f, 0.117939f, 0.0827963f, 0.0583819f, 0.0435706f, 0.0359518f, 0.0330141f},
+ {0.666307f, 0.628751f, 0.603217f, 0.561218f, 0.502851f, 0.434804f, 0.363191f, 0.292537f, 0.226539f, 0.168122f, 0.119749f, 0.0831136f, 0.0581898f, 0.0433205f, 0.0358002f, 0.0329838f},
+ {0.786583f, 0.766754f, 0.710744f, 0.631306f, 0.545511f, 0.459889f, 0.377407f, 0.300144f, 0.230236f, 0.16959f, 0.120156f, 0.0830272f, 0.0579986f, 0.0431714f, 0.0357315f, 0.0329736f},
+ {0.916039f, 0.842245f, 0.744891f, 0.648415f, 0.554738f, 0.464995f, 0.380115f, 0.301602f, 0.230869f, 0.169818f, 0.12015f, 0.0829735f, 0.0579435f, 0.0431294f, 0.0357031f, 0.0329647f}
+ },
+ {
+ {0.0981625f, 0.0892539f, 0.0818178f, 0.0750794f, 0.0687249f, 0.0626799f, 0.0568324f, 0.0511863f, 0.0457492f, 0.0405501f, 0.0356807f, 0.0312738f, 0.0274039f, 0.0241437f, 0.0214994f, 0.0193932f},
+ {0.104896f, 0.0962186f, 0.0888389f, 0.0819913f, 0.0755049f, 0.069194f, 0.0630562f, 0.0570554f, 0.051231f, 0.0456402f, 0.0403724f, 0.0355759f, 0.0313967f, 0.0279044f, 0.0251351f, 0.0229823f},
+ {0.113342f, 0.104848f, 0.0974075f, 0.090382f, 0.0836008f, 0.0769436f, 0.0704028f, 0.0639284f, 0.0575857f, 0.0514345f, 0.0456317f, 0.0403345f, 0.0357444f, 0.0319649f, 0.0290427f, 0.0269045f},
+ {0.124153f, 0.115669f, 0.108054f, 0.100678f, 0.0934787f, 0.0863385f, 0.0791883f, 0.0720757f, 0.0650182f, 0.0581114f, 0.0515791f, 0.0456044f, 0.0404544f, 0.036275f, 0.0331504f, 0.0310184f},
+ {0.138061f, 0.129426f, 0.121419f, 0.113592f, 0.105754f, 0.0978858f, 0.0899266f, 0.081886f, 0.0738524f, 0.0659413f, 0.0583869f, 0.0514633f, 0.0454908f, 0.040757f, 0.0373134f, 0.0351297f},
+ {0.15613f, 0.147112f, 0.138467f, 0.129888f, 0.121177f, 0.112308f, 0.103214f, 0.0939393f, 0.0845523f, 0.07524f, 0.0662407f, 0.0579924f, 0.0508817f, 0.0452875f, 0.0413425f, 0.0389805f},
+ {0.179631f, 0.169944f, 0.16045f, 0.150767f, 0.140822f, 0.13056f, 0.119893f, 0.108903f, 0.0976866f, 0.086396f, 0.0754428f, 0.0652944f, 0.0565412f, 0.0497014f, 0.0450084f, 0.0423321f},
+ {0.210455f, 0.199721f, 0.188863f, 0.177706f, 0.16604f, 0.153794f, 0.141052f, 0.127695f, 0.113933f, 0.0999227f, 0.0861578f, 0.0733073f, 0.0622534f, 0.0537512f, 0.0480695f, 0.0450104f},
+ {0.250765f, 0.238462f, 0.225848f, 0.212499f, 0.198453f, 0.183659f, 0.167986f, 0.151445f, 0.134035f, 0.11613f, 0.098294f, 0.0816827f, 0.0676002f, 0.0570696f, 0.0503226f, 0.0468971f},
+ {0.303357f, 0.288829f, 0.273457f, 0.257269f, 0.240081f, 0.221779f, 0.202177f, 0.181061f, 0.158392f, 0.134711f, 0.111187f, 0.08963f, 0.0720008f, 0.0593793f, 0.0517214f, 0.0480824f},
+ {0.371176f, 0.353231f, 0.334214f, 0.314218f, 0.293023f, 0.270078f, 0.244771f, 0.216682f, 0.185957f, 0.153982f, 0.123109f, 0.0960767f, 0.0749851f, 0.0606631f, 0.0524191f, 0.0487398f},
+ {0.457151f, 0.43362f, 0.409672f, 0.385472f, 0.359419f, 0.329529f, 0.294679f, 0.255218f, 0.212933f, 0.170807f, 0.132228f, 0.100208f, 0.0764683f, 0.061069f, 0.0525688f, 0.0490036f},
+ {0.561511f, 0.528708f, 0.501392f, 0.473516f, 0.4387f, 0.394994f, 0.34394f, 0.288823f, 0.233525f, 0.181949f, 0.13731f, 0.101999f, 0.0767982f, 0.0609496f, 0.0524627f, 0.0490672f},
+ {0.676168f, 0.638437f, 0.613568f, 0.572243f, 0.514769f, 0.447933f, 0.377794f, 0.308737f, 0.244268f, 0.187052f, 0.139264f, 0.102435f, 0.0766688f, 0.0607181f, 0.0523128f, 0.0490438f},
+ {0.791881f, 0.772692f, 0.71755f, 0.639511f, 0.555468f, 0.471796f, 0.391333f, 0.316044f, 0.247886f, 0.188548f, 0.139726f, 0.102389f, 0.0764923f, 0.0605677f, 0.0522415f, 0.0490355f},
+ {0.917899f, 0.845494f, 0.750079f, 0.655691f, 0.564168f, 0.476608f, 0.393894f, 0.317438f, 0.248507f, 0.188784f, 0.139733f, 0.102344f, 0.0764393f, 0.0605235f, 0.0522096f, 0.0490251f}
+ },
+ {
+ {0.11751f, 0.107624f, 0.0993338f, 0.0917856f, 0.0846319f, 0.0777925f, 0.0711485f, 0.0647043f, 0.0584743f, 0.0524925f, 0.0468619f, 0.0417259f, 0.0371605f, 0.0332496f, 0.0300086f, 0.0273659f},
+ {0.124306f, 0.114785f, 0.106666f, 0.0991106f, 0.0919247f, 0.0849085f, 0.0780616f, 0.071347f, 0.0648108f, 0.0585228f, 0.0525764f, 0.0471269f, 0.0423307f, 0.0382568f, 0.0349603f, 0.0323352f},
+ {0.132779f, 0.123572f, 0.115507f, 0.107873f, 0.100486f, 0.0932153f, 0.0860537f, 0.0789544f, 0.0719909f, 0.0652289f, 0.0588412f, 0.0529878f, 0.0478756f, 0.0436113f, 0.040256f, 0.0377502f},
+ {0.143578f, 0.134508f, 0.126371f, 0.118483f, 0.110768f, 0.103105f, 0.0954216f, 0.0877739f, 0.080187f, 0.0727685f, 0.0657556f, 0.0593361f, 0.0537804f, 0.0492324f, 0.0457926f, 0.0434156f},
+ {0.157411f, 0.148305f, 0.139872f, 0.131628f, 0.123364f, 0.115059f, 0.106656f, 0.0981693f, 0.0897029f, 0.0813887f, 0.0734711f, 0.0662311f, 0.0599818f, 0.0550111f, 0.0513753f, 0.0490691f},
+ {0.175309f, 0.165929f, 0.156949f, 0.148038f, 0.138991f, 0.129771f, 0.12032f, 0.110698f, 0.100983f, 0.091388f, 0.0821612f, 0.0737418f, 0.0664975f, 0.060792f, 0.0567621f, 0.0543656f},
+ {0.198507f, 0.18855f, 0.17881f, 0.168882f, 0.158683f, 0.148159f, 0.137228f, 0.125995f, 0.114578f, 0.103149f, 0.0921318f, 0.0819751f, 0.0732283f, 0.0663765f, 0.0616617f, 0.0589862f},
+ {0.228824f, 0.217911f, 0.206893f, 0.19557f, 0.183737f, 0.171323f, 0.158429f, 0.144959f, 0.131157f, 0.117193f, 0.103557f, 0.0908711f, 0.0799427f, 0.0714806f, 0.0657739f, 0.0626964f},
+ {0.268352f, 0.255955f, 0.243255f, 0.229826f, 0.215707f, 0.200861f, 0.185183f, 0.16871f, 0.151472f, 0.13384f, 0.116353f, 0.100071f, 0.0861941f, 0.0756888f, 0.0688507f, 0.0653426f},
+ {0.319796f, 0.305249f, 0.289862f, 0.273678f, 0.256534f, 0.238341f, 0.218941f, 0.198147f, 0.175927f, 0.1528f, 0.129853f, 0.108758f, 0.0913441f, 0.0786728f, 0.0708283f, 0.0670383f},
+ {0.386009f, 0.368111f, 0.349132f, 0.329238f, 0.308253f, 0.285658f, 0.260863f, 0.233437f, 0.203497f, 0.17237f, 0.142289f, 0.115814f, 0.0949101f, 0.0804427f, 0.0719178f, 0.0680263f},
+ {0.46989f, 0.446402f, 0.422523f, 0.398572f, 0.373009f, 0.343849f, 0.309915f, 0.271516f, 0.230398f, 0.189433f, 0.151832f, 0.120404f, 0.0967766f, 0.0811275f, 0.0722626f, 0.0684499f},
+ {0.571682f, 0.538755f, 0.511551f, 0.484265f, 0.450423f, 0.407959f, 0.358314f, 0.304695f, 0.250908f, 0.200723f, 0.157165f, 0.122444f, 0.0972951f, 0.0811272f, 0.072231f, 0.068575f},
+ {0.683197f, 0.645011f, 0.620823f, 0.580826f, 0.524971f, 0.45986f, 0.391505f, 0.324258f, 0.261537f, 0.205867f, 0.159228f, 0.122988f, 0.0972399f, 0.0809346f, 0.0720988f, 0.0685651f},
+ {0.795212f, 0.776459f, 0.723058f, 0.646906f, 0.564805f, 0.483121f, 0.40467f, 0.331375f, 0.265093f, 0.207375f, 0.159729f, 0.12298f, 0.0970849f, 0.0807918f, 0.0720306f, 0.0685604f},
+ {0.919114f, 0.848547f, 0.7551f, 0.662733f, 0.573261f, 0.487776f, 0.407142f, 0.332723f, 0.265702f, 0.207614f, 0.159746f, 0.122942f, 0.0970357f, 0.0807477f, 0.0719968f, 0.0685491f}
+ },
+ {
+ {0.138345f, 0.127624f, 0.118581f, 0.110295f, 0.102388f, 0.0947759f, 0.0873342f, 0.0800672f, 0.0730019f, 0.0661816f, 0.0597308f, 0.0538126f, 0.0485111f, 0.0439208f, 0.0400601f, 0.0368569f},
+ {0.145028f, 0.134816f, 0.126075f, 0.117903f, 0.110086f, 0.102411f, 0.0948807f, 0.0874554f, 0.0801934f, 0.0731821f, 0.0665282f, 0.0604029f, 0.0549808f, 0.0503269f, 0.0465094f, 0.0434137f},
+ {0.153312f, 0.143555f, 0.134999f, 0.126867f, 0.118965f, 0.111153f, 0.103423f, 0.0957312f, 0.088163f, 0.0807961f, 0.0738278f, 0.0674315f, 0.061826f, 0.0571178f, 0.0533733f, 0.0505359f},
+ {0.163836f, 0.154354f, 0.145843f, 0.137574f, 0.129457f, 0.121368f, 0.113231f, 0.10511f, 0.0970424f, 0.0891524f, 0.0817001f, 0.0748907f, 0.0690031f, 0.0641757f, 0.0605112f, 0.0579665f},
+ {0.177276f, 0.167883f, 0.159189f, 0.150678f, 0.142126f, 0.133503f, 0.124765f, 0.115926f, 0.107107f, 0.0984665f, 0.0902685f, 0.0828149f, 0.0764174f, 0.0713564f, 0.0676733f, 0.0653667f},
+ {0.194623f, 0.185075f, 0.175939f, 0.166865f, 0.157643f, 0.148219f, 0.138548f, 0.128702f, 0.118775f, 0.109014f, 0.0996898f, 0.0912584f, 0.0840744f, 0.0784716f, 0.0745621f, 0.0722969f},
+ {0.217071f, 0.207049f, 0.197256f, 0.187272f, 0.177003f, 0.166389f, 0.15536f, 0.144039f, 0.132574f, 0.121169f, 0.110274f, 0.100335f, 0.091865f, 0.0852916f, 0.0808225f, 0.0783506f},
+ {0.24637f, 0.235492f, 0.224522f, 0.213243f, 0.201446f, 0.18906f, 0.176208f, 0.162812f, 0.149166f, 0.135464f, 0.122211f, 0.109998f, 0.0995521f, 0.0915013f, 0.0860959f, 0.0832286f},
+ {0.284556f, 0.272287f, 0.259727f, 0.246442f, 0.23247f, 0.217788f, 0.202323f, 0.186146f, 0.169326f, 0.152253f, 0.13545f, 0.119896f, 0.106675f, 0.096646f, 0.0900913f, 0.0867407f},
+ {0.334276f, 0.31995f, 0.304786f, 0.28884f, 0.271966f, 0.254109f, 0.235156f, 0.214962f, 0.193513f, 0.171307f, 0.149356f, 0.129209f, 0.112548f, 0.100347f, 0.0927249f, 0.0890255f},
+ {0.398369f, 0.380784f, 0.362086f, 0.342515f, 0.321946f, 0.299938f, 0.275954f, 0.249555f, 0.22081f, 0.190968f, 0.162159f, 0.136797f, 0.116693f, 0.102656f, 0.094281f, 0.0904092f},
+ {0.479828f, 0.45669f, 0.433076f, 0.409521f, 0.384633f, 0.356519f, 0.323922f, 0.287045f, 0.247536f, 0.208175f, 0.17205f, 0.14181f, 0.118956f, 0.103664f, 0.0948691f, 0.0910267f},
+ {0.579117f, 0.546343f, 0.519233f, 0.492627f, 0.460121f, 0.419408f, 0.371663f, 0.319956f, 0.268029f, 0.2196f, 0.177595f, 0.144079f, 0.119673f, 0.10381f, 0.0949387f, 0.0912277f},
+ {0.688119f, 0.649231f, 0.625702f, 0.587546f, 0.533917f, 0.470966f, 0.404661f, 0.3394f, 0.278611f, 0.224776f, 0.179743f, 0.14472f, 0.119698f, 0.103671f, 0.0948371f, 0.0912364f},
+ {0.797056f, 0.778532f, 0.727609f, 0.653779f, 0.573794f, 0.494139f, 0.417701f, 0.346418f, 0.282121f, 0.226284f, 0.18027f, 0.144745f, 0.119568f, 0.103543f, 0.0947767f, 0.0912366f},
+ {0.919821f, 0.851517f, 0.760096f, 0.669722f, 0.582236f, 0.498746f, 0.420129f, 0.347736f, 0.282717f, 0.226521f, 0.180293f, 0.144714f, 0.119524f, 0.1035f, 0.0947425f, 0.0912247f}
+ },
+ {
+ {0.160543f, 0.149143f, 0.13946f, 0.130523f, 0.121924f, 0.113571f, 0.105338f, 0.0972271f, 0.0892811f, 0.0815582f, 0.074218f, 0.0674548f, 0.0613702f, 0.0560701f, 0.0515703f, 0.0477901f},
+ {0.166967f, 0.15622f, 0.146979f, 0.13829f, 0.129917f, 0.121637f, 0.113452f, 0.105319f, 0.0973119f, 0.0895414f, 0.082139f, 0.0753037f, 0.0692376f, 0.0640003f, 0.0596678f, 0.0561079f},
+ {0.174881f, 0.164734f, 0.155816f, 0.147299f, 0.138974f, 0.130692f, 0.122446f, 0.114189f, 0.106023f, 0.0980447f, 0.0904852f, 0.0835441f, 0.077461f, 0.0723396f, 0.0682445f, 0.0651114f},
+ {0.184912f, 0.17518f, 0.166435f, 0.15791f, 0.149497f, 0.141073f, 0.132556f, 0.124015f, 0.1155f, 0.107162f, 0.0992916f, 0.0921272f, 0.0859626f, 0.0809279f, 0.0771172f, 0.0744755f},
+ {0.197702f, 0.188185f, 0.179378f, 0.170733f, 0.162018f, 0.153186f, 0.14421f, 0.135094f, 0.125984f, 0.11707f, 0.108649f, 0.101058f, 0.0946137f, 0.0895836f, 0.0859776f, 0.0837792f},
+ {0.21419f, 0.204641f, 0.195505f, 0.186414f, 0.177156f, 0.167657f, 0.157881f, 0.147912f, 0.137861f, 0.128018f, 0.118694f, 0.110374f, 0.103407f, 0.0980853f, 0.0944718f, 0.0924835f},
+ {0.235531f, 0.225612f, 0.215932f, 0.206048f, 0.195863f, 0.185308f, 0.174316f, 0.163027f, 0.151631f, 0.14037f, 0.12974f, 0.120201f, 0.112229f, 0.106176f, 0.102181f, 0.100091f},
+ {0.263402f, 0.252733f, 0.241984f, 0.230921f, 0.219326f, 0.207132f, 0.194474f, 0.181295f, 0.16795f, 0.154673f, 0.142004f, 0.130514f, 0.120846f, 0.113517f, 0.108692f, 0.106236f},
+ {0.299799f, 0.287839f, 0.275601f, 0.262645f, 0.248996f, 0.23465f, 0.219562f, 0.203847f, 0.18763f, 0.171334f, 0.155486f, 0.140987f, 0.128797f, 0.119623f, 0.113672f, 0.110692f},
+ {0.347333f, 0.333422f, 0.318676f, 0.303159f, 0.286729f, 0.269377f, 0.251051f, 0.231658f, 0.211221f, 0.190226f, 0.169619f, 0.150824f, 0.13536f, 0.124064f, 0.117016f, 0.113625f},
+ {0.408889f, 0.391835f, 0.37362f, 0.35455f, 0.334547f, 0.31329f, 0.290327f, 0.265226f, 0.237998f, 0.209799f, 0.182661f, 0.158873f, 0.140076f, 0.126952f, 0.119099f, 0.115458f},
+ {0.487652f, 0.465114f, 0.441944f, 0.418893f, 0.394792f, 0.367938f, 0.336996f, 0.302003f, 0.264464f, 0.227073f, 0.192842f, 0.164283f, 0.142743f, 0.128316f, 0.119968f, 0.116296f},
+ {0.584467f, 0.55209f, 0.525082f, 0.499175f, 0.468244f, 0.429675f, 0.384234f, 0.334784f, 0.285009f, 0.238636f, 0.198574f, 0.166763f, 0.143663f, 0.128627f, 0.120159f, 0.116583f},
+ {0.691448f, 0.651687f, 0.62873f, 0.592783f, 0.541889f, 0.481483f, 0.417463f, 0.354331f, 0.295618f, 0.243842f, 0.200786f, 0.167488f, 0.14377f, 0.128552f, 0.120097f, 0.116613f},
+ {0.797777f, 0.779238f, 0.731402f, 0.660309f, 0.582619f, 0.505038f, 0.430609f, 0.361339f, 0.299099f, 0.245343f, 0.201327f, 0.167541f, 0.143667f, 0.128441f, 0.120048f, 0.116619f},
+ {0.920111f, 0.854479f, 0.765174f, 0.676798f, 0.591257f, 0.5097f, 0.433035f, 0.362639f, 0.299683f, 0.245575f, 0.201354f, 0.167517f, 0.143628f, 0.128402f, 0.120015f, 0.116607f}
+ },
+ {
+ {0.183925f, 0.172005f, 0.161812f, 0.152324f, 0.143108f, 0.134064f, 0.125061f, 0.116094f, 0.107223f, 0.0985268f, 0.0902175f, 0.0825365f, 0.0756155f, 0.0695739f, 0.0644191f, 0.0600524f},
+ {0.189968f, 0.178844f, 0.16923f, 0.16013f, 0.151287f, 0.142465f, 0.133663f, 0.124832f, 0.116057f, 0.107483f, 0.0992795f, 0.0916883f, 0.0849513f, 0.0791224f, 0.0742802f, 0.0702652f},
+ {0.19737f, 0.186983f, 0.177832f, 0.169041f, 0.160387f, 0.151712f, 0.143002f, 0.134212f, 0.125448f, 0.11684f, 0.108663f, 0.10116f, 0.0946025f, 0.0890889f, 0.0846751f, 0.0812787f},
+ {0.206737f, 0.196899f, 0.188049f, 0.179386f, 0.17078f, 0.162107f, 0.153281f, 0.144367f, 0.135428f, 0.126647f, 0.118363f, 0.110859f, 0.104453f, 0.0992669f, 0.0953736f, 0.0926945f},
+ {0.218671f, 0.209173f, 0.200386f, 0.191726f, 0.182958f, 0.174018f, 0.164887f, 0.155561f, 0.146202f, 0.137045f, 0.128433f, 0.120755f, 0.11434f, 0.109436f, 0.106007f, 0.104006f},
+ {0.234062f, 0.224649f, 0.215647f, 0.206663f, 0.197489f, 0.18803f, 0.178242f, 0.168233f, 0.158121f, 0.148249f, 0.138989f, 0.130871f, 0.124243f, 0.119344f, 0.116167f, 0.114574f},
+ {0.254017f, 0.244337f, 0.234904f, 0.225252f, 0.215279f, 0.204906f, 0.194061f, 0.182899f, 0.171649f, 0.160614f, 0.150349f, 0.141348f, 0.134049f, 0.128712f, 0.125375f, 0.12381f},
+ {0.280141f, 0.269818f, 0.259427f, 0.248721f, 0.237463f, 0.22559f, 0.213248f, 0.20039f, 0.187442f, 0.1747f, 0.162761f, 0.15219f, 0.143539f, 0.137182f, 0.133162f, 0.13128f},
+ {0.314399f, 0.302888f, 0.291117f, 0.278639f, 0.265452f, 0.251575f, 0.236983f, 0.221846f, 0.206351f, 0.190985f, 0.176299f, 0.163119f, 0.152265f, 0.144251f, 0.139164f, 0.136728f},
+ {0.359383f, 0.346035f, 0.331867f, 0.316926f, 0.30108f, 0.284357f, 0.266771f, 0.24831f, 0.229047f, 0.209477f, 0.19049f, 0.173379f, 0.159478f, 0.149438f, 0.14325f, 0.140346f},
+ {0.418061f, 0.401703f, 0.384151f, 0.365722f, 0.346395f, 0.325989f, 0.304172f, 0.280547f, 0.255071f, 0.228795f, 0.203655f, 0.181823f, 0.164748f, 0.152931f, 0.145904f, 0.14267f},
+ {0.493888f, 0.472147f, 0.449606f, 0.427134f, 0.403872f, 0.378393f, 0.349318f, 0.316475f, 0.281192f, 0.24607f, 0.214076f, 0.187605f, 0.167824f, 0.154673f, 0.147081f, 0.143746f},
+ {0.588219f, 0.55646f, 0.529618f, 0.504351f, 0.475117f, 0.438965f, 0.396153f, 0.349244f, 0.301861f, 0.257786f, 0.219979f, 0.190282f, 0.168946f, 0.155158f, 0.147405f, 0.144124f},
+ {0.693558f, 0.652854f, 0.630304f, 0.596789f, 0.549046f, 0.491535f, 0.430014f, 0.369127f, 0.312581f, 0.263028f, 0.22224f, 0.191079f, 0.169133f, 0.155151f, 0.147388f, 0.144176f},
+ {0.797663f, 0.778804f, 0.734538f, 0.666599f, 0.591398f, 0.515947f, 0.443505f, 0.376217f, 0.316055f, 0.264516f, 0.222784f, 0.191155f, 0.169056f, 0.155062f, 0.147351f, 0.144186f},
+ {0.920066f, 0.857486f, 0.770404f, 0.684067f, 0.600448f, 0.520762f, 0.445972f, 0.377513f, 0.316628f, 0.264739f, 0.222812f, 0.191135f, 0.169022f, 0.155026f, 0.147319f, 0.144174f}
+ },
+ {
+ {0.208271f, 0.195993f, 0.185429f, 0.175501f, 0.165763f, 0.1561f, 0.146368f, 0.136549f, 0.126713f, 0.116969f, 0.1076f, 0.0989169f, 0.0911003f, 0.084285f, 0.0784627f, 0.0735062f},
+ {0.213842f, 0.202487f, 0.192636f, 0.183233f, 0.174017f, 0.164733f, 0.155363f, 0.145854f, 0.136294f, 0.126867f, 0.117795f, 0.109389f, 0.101946f, 0.0955135f, 0.0901661f, 0.0857069f},
+ {0.220621f, 0.21013f, 0.200873f, 0.191919f, 0.183033f, 0.174051f, 0.164935f, 0.155647f, 0.146283f, 0.137018f, 0.128184f, 0.120088f, 0.113046f, 0.107152f, 0.102444f, 0.098812f},
+ {0.229193f, 0.219374f, 0.210544f, 0.201848f, 0.193147f, 0.184316f, 0.17525f, 0.166011f, 0.156663f, 0.147434f, 0.138717f, 0.13087f, 0.124243f, 0.118944f, 0.115017f, 0.112347f},
+ {0.240119f, 0.230755f, 0.222108f, 0.213535f, 0.204815f, 0.195861f, 0.186653f, 0.177175f, 0.167597f, 0.158209f, 0.149414f, 0.141673f, 0.135338f, 0.130631f, 0.127457f, 0.125719f},
+ {0.254234f, 0.245066f, 0.236313f, 0.227536f, 0.218549f, 0.209229f, 0.199515f, 0.189531f, 0.179402f, 0.169528f, 0.160363f, 0.152503f, 0.146303f, 0.141934f, 0.139301f, 0.13819f},
+ {0.272596f, 0.263258f, 0.254182f, 0.244863f, 0.235208f, 0.22512f, 0.214514f, 0.203551f, 0.192497f, 0.181729f, 0.171888f, 0.16352f, 0.157028f, 0.152557f, 0.150015f, 0.149082f},
+ {0.296735f, 0.286859f, 0.276936f, 0.266692f, 0.25588f, 0.244435f, 0.2325f, 0.220036f, 0.207537f, 0.195389f, 0.184273f, 0.174769f, 0.167321f, 0.162131f, 0.159086f, 0.1579f},
+ {0.328587f, 0.317627f, 0.306438f, 0.29455f, 0.281933f, 0.268629f, 0.254618f, 0.240126f, 0.225413f, 0.211065f, 0.197685f, 0.186032f, 0.176758f, 0.170146f, 0.166119f, 0.164357f},
+ {0.370739f, 0.358061f, 0.344603f, 0.330349f, 0.315192f, 0.29919f, 0.282409f, 0.264942f, 0.246937f, 0.22893f, 0.211773f, 0.196616f, 0.184572f, 0.176065f, 0.170955f, 0.168676f},
+ {0.426266f, 0.410716f, 0.393993f, 0.376311f, 0.357741f, 0.338242f, 0.317616f, 0.295552f, 0.271977f, 0.247831f, 0.224949f, 0.205387f, 0.190375f, 0.180173f, 0.174209f, 0.171518f},
+ {0.498944f, 0.478136f, 0.456429f, 0.434587f, 0.412177f, 0.388098f, 0.360993f, 0.330479f, 0.297658f, 0.265036f, 0.235563f, 0.211521f, 0.193858f, 0.182306f, 0.175709f, 0.172841f},
+ {0.590743f, 0.55979f, 0.53326f, 0.508515f, 0.480983f, 0.447398f, 0.40746f, 0.363325f, 0.318528f, 0.276934f, 0.24163f, 0.21438f, 0.195177f, 0.182969f, 0.17617f, 0.173308f},
+ {0.694721f, 0.653117f, 0.630746f, 0.599736f, 0.55546f, 0.501161f, 0.44235f, 0.383795f, 0.329462f, 0.282226f, 0.243926f, 0.215236f, 0.195439f, 0.183031f, 0.1762f, 0.173381f},
+ {0.796946f, 0.777413f, 0.737044f, 0.672694f, 0.600192f, 0.52694f, 0.456453f, 0.391079f, 0.332955f, 0.283699f, 0.244465f, 0.21533f, 0.195385f, 0.182961f, 0.176174f, 0.173394f},
+ {0.919721f, 0.860566f, 0.775828f, 0.691594f, 0.609891f, 0.532017f, 0.459009f, 0.392386f, 0.333517f, 0.283911f, 0.244491f, 0.215313f, 0.195357f, 0.182929f, 0.176145f, 0.173382f}
+ },
+ {
+ {0.233345f, 0.22086f, 0.210077f, 0.199823f, 0.189677f, 0.179491f, 0.169098f, 0.158453f, 0.147627f, 0.136759f, 0.126225f, 0.116444f, 0.107665f, 0.100043f, 0.0935449f, 0.088001f},
+ {0.238375f, 0.226926f, 0.216973f, 0.207378f, 0.197895f, 0.188246f, 0.178381f, 0.168226f, 0.157875f, 0.147538f, 0.13752f, 0.128228f, 0.120034f, 0.112982f, 0.107133f, 0.102242f},
+ {0.244451f, 0.233977f, 0.224739f, 0.215724f, 0.206708f, 0.197512f, 0.188066f, 0.178321f, 0.168365f, 0.158408f, 0.14886f, 0.140123f, 0.132574f, 0.126303f, 0.121321f, 0.117476f},
+ {0.252138f, 0.242441f, 0.233745f, 0.225111f, 0.216411f, 0.207513f, 0.198284f, 0.188768f, 0.179029f, 0.169332f, 0.160149f, 0.151936f, 0.145088f, 0.139702f, 0.135776f, 0.13315f},
+ {0.261947f, 0.252808f, 0.244407f, 0.236006f, 0.227423f, 0.21855f, 0.209337f, 0.199763f, 0.189992f, 0.180366f, 0.171372f, 0.163568f, 0.157343f, 0.152882f, 0.150014f, 0.148586f},
+ {0.274662f, 0.265818f, 0.257413f, 0.248919f, 0.240202f, 0.231116f, 0.221556f, 0.211648f, 0.201533f, 0.19166f, 0.182589f, 0.175014f, 0.169302f, 0.165539f, 0.163524f, 0.162952f},
+ {0.291286f, 0.282361f, 0.273731f, 0.264822f, 0.255567f, 0.245853f, 0.235567f, 0.224853f, 0.214024f, 0.203532f, 0.194131f, 0.186454f, 0.180866f, 0.177369f, 0.17572f, 0.175488f},
+ {0.313271f, 0.303909f, 0.294539f, 0.284834f, 0.274553f, 0.26362f, 0.252168f, 0.240141f, 0.228112f, 0.216569f, 0.206319f, 0.197982f, 0.191879f, 0.188001f, 0.18605f, 0.18564f},
+ {0.342526f, 0.332183f, 0.321664f, 0.310442f, 0.298482f, 0.28583f, 0.272465f, 0.258641f, 0.244722f, 0.231416f, 0.219425f, 0.209452f, 0.201953f, 0.196923f, 0.194098f, 0.193098f},
+ {0.381633f, 0.369694f, 0.357053f, 0.343564f, 0.329179f, 0.313965f, 0.298023f, 0.281547f, 0.264811f, 0.248428f, 0.233245f, 0.22026f, 0.210311f, 0.203547f, 0.199673f, 0.198112f},
+ {0.433793f, 0.419121f, 0.403378f, 0.386517f, 0.368769f, 0.350206f, 0.330755f, 0.310245f, 0.288629f, 0.266745f, 0.246321f, 0.229288f, 0.216617f, 0.20827f, 0.203539f, 0.201486f},
+ {0.503137f, 0.483345f, 0.462695f, 0.44151f, 0.419955f, 0.397224f, 0.372085f, 0.343987f, 0.313753f, 0.283801f, 0.257079f, 0.235752f, 0.220502f, 0.210798f, 0.205367f, 0.203058f},
+ {0.592324f, 0.56232f, 0.53634f, 0.511965f, 0.486048f, 0.45505f, 0.418131f, 0.376965f, 0.334901f, 0.295919f, 0.263309f, 0.238781f, 0.222011f, 0.211635f, 0.205965f, 0.203611f},
+ {0.695136f, 0.652781f, 0.630336f, 0.601762f, 0.561141f, 0.51034f, 0.454456f, 0.398306f, 0.346176f, 0.301288f, 0.265631f, 0.239684f, 0.222339f, 0.211762f, 0.206038f, 0.203699f},
+ {0.795819f, 0.775221f, 0.738895f, 0.67858f, 0.60902f, 0.538053f, 0.469481f, 0.40592f, 0.349727f, 0.302746f, 0.266157f, 0.239788f, 0.222307f, 0.211711f, 0.206024f, 0.203713f},
+ {0.919101f, 0.86371f, 0.781466f, 0.699412f, 0.619639f, 0.543528f, 0.472186f, 0.407257f, 0.350284f, 0.302945f, 0.266177f, 0.239773f, 0.222282f, 0.211683f, 0.205997f, 0.203701f}
+ },
+ {
+ {0.258907f, 0.246356f, 0.235502f, 0.225041f, 0.214616f, 0.204028f, 0.193072f, 0.181656f, 0.169838f, 0.157772f, 0.145956f, 0.134961f, 0.125146f, 0.116685f, 0.109506f, 0.103382f},
+ {0.263349f, 0.251927f, 0.242005f, 0.232324f, 0.222689f, 0.212789f, 0.202522f, 0.191782f, 0.180648f, 0.169348f, 0.158293f, 0.148023f, 0.139025f, 0.131334f, 0.124989f, 0.119678f},
+ {0.26867f, 0.258315f, 0.24921f, 0.240227f, 0.231186f, 0.221882f, 0.212196f, 0.202055f, 0.191523f, 0.180837f, 0.170507f, 0.16106f, 0.152972f, 0.146321f, 0.141076f, 0.137036f},
+ {0.275412f, 0.265922f, 0.257459f, 0.248968f, 0.240365f, 0.231488f, 0.222188f, 0.212457f, 0.202347f, 0.192157f, 0.182455f, 0.17383f, 0.16675f, 0.161288f, 0.157387f, 0.154826f},
+ {0.284035f, 0.27519f, 0.267124f, 0.258963f, 0.250598f, 0.241898f, 0.232756f, 0.223148f, 0.213207f, 0.203323f, 0.194092f, 0.1862f, 0.180093f, 0.175908f, 0.17338f, 0.172288f},
+ {0.295274f, 0.286808f, 0.278826f, 0.270681f, 0.262297f, 0.253533f, 0.244202f, 0.23442f, 0.224343f, 0.214453f, 0.205448f, 0.198153f, 0.192962f, 0.189855f, 0.188503f, 0.188502f},
+ {0.310069f, 0.301603f, 0.293482f, 0.285039f, 0.276244f, 0.26698f, 0.257092f, 0.246671f, 0.236076f, 0.225837f, 0.216858f, 0.209892f, 0.205272f, 0.202825f, 0.202128f, 0.202634f},
+ {0.329793f, 0.320985f, 0.312223f, 0.303105f, 0.293424f, 0.283068f, 0.272163f, 0.260612f, 0.24904f, 0.238068f, 0.228677f, 0.221566f, 0.216913f, 0.214449f, 0.213668f, 0.214076f},
+ {0.356322f, 0.346634f, 0.336842f, 0.326332f, 0.315095f, 0.303163f, 0.290492f, 0.27734f, 0.264178f, 0.251874f, 0.241298f, 0.233115f, 0.22754f, 0.224227f, 0.222693f, 0.222503f},
+ {0.392238f, 0.381076f, 0.369321f, 0.35665f, 0.343095f, 0.328732f, 0.313643f, 0.298115f, 0.282585f, 0.267806f, 0.25468f, 0.244043f, 0.236381f, 0.231516f, 0.228979f, 0.228194f},
+ {0.440867f, 0.427111f, 0.412452f, 0.396466f, 0.379608f, 0.362005f, 0.343667f, 0.324622f, 0.304928f, 0.285361f, 0.267539f, 0.253254f, 0.243153f, 0.236841f, 0.233458f, 0.232102f},
+ {0.506717f, 0.487997f, 0.468576f, 0.448089f, 0.427412f, 0.405926f, 0.382646f, 0.356947f, 0.329352f, 0.302177f, 0.278386f, 0.260022f, 0.247431f, 0.23976f, 0.23561f, 0.233916f},
+ {0.593192f, 0.564277f, 0.539059f, 0.514959f, 0.4905f, 0.461974f, 0.428121f, 0.390063f, 0.350845f, 0.314561f, 0.284786f, 0.263211f, 0.249118f, 0.240763f, 0.236337f, 0.234546f},
+ {0.69495f, 0.652106f, 0.629305f, 0.602994f, 0.566049f, 0.518994f, 0.466269f, 0.4126f, 0.362632f, 0.320051f, 0.287129f, 0.264149f, 0.249505f, 0.240948f, 0.23645f, 0.234644f},
+ {0.79443f, 0.77234f, 0.740076f, 0.684182f, 0.617848f, 0.549283f, 0.482602f, 0.420725f, 0.366297f, 0.321495f, 0.287634f, 0.264256f, 0.249489f, 0.240914f, 0.236443f, 0.234657f},
+ {0.918215f, 0.866875f, 0.787313f, 0.707521f, 0.62971f, 0.555326f, 0.485537f, 0.42212f, 0.36685f, 0.321679f, 0.287645f, 0.264241f, 0.249468f, 0.240889f, 0.236419f, 0.234644f}
+ }
+};
+
+static const float table_ggx_dielectric_inv_E[16][16][16] = {
+ {
+ {0.00235046f, 0.000951943f, 0.000961408f, 0.000944843f, 0.000942617f, 0.000910931f, 0.000859474f, 0.000767562f, 0.000483162f, 0.000109375f, 2.0597e-05f, 8.06816e-06f, 4.16443e-06f, 2.50755e-06f, 1.72255e-06f, 1.30155e-06f},
+ {0.00292426f, 0.00126262f, 0.00125521f, 0.00125754f, 0.00122733f, 0.00121732f, 0.00114463f, 0.000989368f, 0.000632914f, 0.000142431f, 2.66276e-05f, 1.02422e-05f, 5.15253e-06f, 3.05061e-06f, 2.06668e-06f, 1.56083e-06f},
+ {0.00379196f, 0.00171564f, 0.00171269f, 0.00165289f, 0.00165397f, 0.00163529f, 0.00152361f, 0.00136859f, 0.000883173f, 0.000198944f, 3.48297e-05f, 1.30138e-05f, 6.42139e-06f, 3.68929e-06f, 2.45527e-06f, 1.84825e-06f},
+ {0.00489294f, 0.00234044f, 0.00235165f, 0.00228443f, 0.00231354f, 0.0022399f, 0.00210313f, 0.00188593f, 0.00122852f, 0.000277262f, 4.53518e-05f, 1.67627e-05f, 7.96693e-06f, 4.44151e-06f, 2.86604e-06f, 2.15288e-06f},
+ {0.00654822f, 0.00330384f, 0.00326599f, 0.00332878f, 0.00324631f, 0.00311872f, 0.00296925f, 0.00264568f, 0.00170292f, 0.000382511f, 6.16924e-05f, 2.16883e-05f, 9.80968e-06f, 5.31534e-06f, 3.31121e-06f, 2.44751e-06f},
+ {0.00913796f, 0.00477424f, 0.00471521f, 0.00465233f, 0.00456819f, 0.00453247f, 0.00432436f, 0.00385269f, 0.00251536f, 0.000564706f, 8.36937e-05f, 2.81617e-05f, 1.21565e-05f, 6.21127e-06f, 3.73044e-06f, 2.71501e-06f},
+ {0.013057f, 0.00697927f, 0.00696658f, 0.00691162f, 0.00678196f, 0.00671759f, 0.00633212f, 0.00567344f, 0.00374109f, 0.00082046f, 0.000113712f, 3.64343e-05f, 1.48833e-05f, 7.16424e-06f, 4.11499e-06f, 2.93366e-06f},
+ {0.0196329f, 0.0106535f, 0.0106754f, 0.0105994f, 0.0104252f, 0.0101732f, 0.00979063f, 0.00870428f, 0.00580175f, 0.0012363f, 0.000156536f, 4.63773e-05f, 1.78193e-05f, 8.01439e-06f, 4.40462e-06f, 3.10493e-06f},
+ {0.0307183f, 0.017078f, 0.0170033f, 0.0168447f, 0.0166372f, 0.0162504f, 0.015506f, 0.014051f, 0.0091717f, 0.00191149f, 0.000213538f, 5.78316e-05f, 2.03798e-05f, 8.56422e-06f, 4.52944e-06f, 3.18388e-06f},
+ {0.0498417f, 0.0284268f, 0.0283445f, 0.0282314f, 0.0277786f, 0.0271021f, 0.0259388f, 0.0230949f, 0.0149652f, 0.00295227f, 0.000283693f, 6.87379e-05f, 2.22055e-05f, 8.80754e-06f, 4.52383e-06f, 3.21753e-06f},
+ {0.0850979f, 0.0499708f, 0.0496497f, 0.0493275f, 0.0489081f, 0.0475654f, 0.0451105f, 0.0399589f, 0.0250828f, 0.00439737f, 0.000354752f, 7.63431e-05f, 2.2707e-05f, 8.61899e-06f, 4.40055e-06f, 3.20354e-06f},
+ {0.148511f, 0.0910268f, 0.0905886f, 0.0901549f, 0.0886084f, 0.0862489f, 0.0814294f, 0.0714472f, 0.041587f, 0.00605564f, 0.000405501f, 7.80517e-05f, 2.20026e-05f, 8.2124e-06f, 4.23526e-06f, 3.17388e-06f},
+ {0.256514f, 0.167553f, 0.166978f, 0.16535f, 0.162499f, 0.157414f, 0.147243f, 0.124061f, 0.0627375f, 0.00674164f, 0.000406886f, 7.47395e-05f, 2.06823e-05f, 7.70742e-06f, 4.08045e-06f, 3.1554e-06f},
+ {0.421582f, 0.29785f, 0.295744f, 0.292154f, 0.284839f, 0.270982f, 0.244869f, 0.188637f, 0.0713664f, 0.00569746f, 0.000377401f, 6.98215e-05f, 1.95624e-05f, 7.38927e-06f, 3.98503e-06f, 3.12683e-06f},
+ {0.626533f, 0.482942f, 0.47802f, 0.466367f, 0.443574f, 0.402265f, 0.329363f, 0.204388f, 0.052521f, 0.0041677f, 0.000353535f, 6.71368e-05f, 1.89508e-05f, 7.22614e-06f, 3.94896e-06f, 3.12279e-06f},
+ {0.846947f, 0.743587f, 0.698557f, 0.628086f, 0.533342f, 0.41755f, 0.285614f, 0.146935f, 0.0364554f, 0.00362315f, 0.000344775f, 6.62138e-05f, 1.88029e-05f, 7.19353e-06f, 3.9378e-06f, 3.12169e-06f}
+ },
+ {
+ {0.0244329f, 0.00842994f, 0.006394f, 0.00640485f, 0.00633785f, 0.00624147f, 0.00604983f, 0.00565578f, 0.00498872f, 0.00337949f, 0.0013252f, 0.000348669f, 0.000147759f, 8.35719e-05f, 5.55069e-05f, 4.12674e-05f},
+ {0.0299837f, 0.0109985f, 0.00847027f, 0.00841811f, 0.00843469f, 0.00824875f, 0.00801624f, 0.00759303f, 0.00664631f, 0.0045765f, 0.00177292f, 0.000447897f, 0.000184027f, 0.000101736f, 6.64771e-05f, 4.92692e-05f},
+ {0.0370611f, 0.0147832f, 0.0113699f, 0.0114045f, 0.0112426f, 0.0110887f, 0.0108451f, 0.0101365f, 0.00892974f, 0.00620864f, 0.00240134f, 0.000588074f, 0.000230868f, 0.000123335f, 7.87936e-05f, 5.8044e-05f},
+ {0.0470884f, 0.0196336f, 0.0154454f, 0.0154247f, 0.0153079f, 0.0150225f, 0.0146064f, 0.0138626f, 0.0122651f, 0.00844913f, 0.00324915f, 0.000772161f, 0.00028898f, 0.000148694f, 9.20002e-05f, 6.72561e-05f},
+ {0.0607736f, 0.0269073f, 0.0213857f, 0.0213109f, 0.0211384f, 0.0208545f, 0.020306f, 0.0192818f, 0.0170124f, 0.0118553f, 0.00458119f, 0.00101911f, 0.000359396f, 0.000178073f, 0.000106031f, 7.625e-05f},
+ {0.081171f, 0.0375754f, 0.0300765f, 0.03013f, 0.0297314f, 0.0293184f, 0.028634f, 0.0270088f, 0.0240609f, 0.0167986f, 0.00634564f, 0.00136142f, 0.000447205f, 0.000208822f, 0.000119347f, 8.4328e-05f},
+ {0.110621f, 0.0534742f, 0.0431979f, 0.042905f, 0.0426605f, 0.0419236f, 0.0409884f, 0.0389714f, 0.0344307f, 0.0239731f, 0.00889508f, 0.0018045f, 0.000549877f, 0.000240845f, 0.000131173f, 9.08705e-05f},
+ {0.154343f, 0.0776604f, 0.0630826f, 0.0630305f, 0.0622461f, 0.0614756f, 0.059931f, 0.0568346f, 0.0501378f, 0.0345007f, 0.0124085f, 0.00229981f, 0.000658126f, 0.000269135f, 0.00013977f, 9.56597e-05f},
+ {0.218105f, 0.115695f, 0.0940303f, 0.0935214f, 0.0930068f, 0.0916361f, 0.0890005f, 0.0843393f, 0.0741019f, 0.0500846f, 0.0169989f, 0.002889f, 0.000751429f, 0.000286759f, 0.000143284f, 9.79578e-05f},
+ {0.309745f, 0.174004f, 0.141545f, 0.141101f, 0.139981f, 0.137816f, 0.133782f, 0.126079f, 0.109716f, 0.0711239f, 0.02197f, 0.00339885f, 0.000811512f, 0.000292177f, 0.000142314f, 9.86812e-05f},
+ {0.432884f, 0.261728f, 0.213141f, 0.21237f, 0.210333f, 0.206437f, 0.199598f, 0.186483f, 0.158926f, 0.095884f, 0.0258213f, 0.00359798f, 0.000817069f, 0.000283412f, 0.000137777f, 9.81187e-05f},
+ {0.582453f, 0.38569f, 0.312282f, 0.310865f, 0.307326f, 0.30057f, 0.288063f, 0.264968f, 0.215487f, 0.115438f, 0.0260455f, 0.00346903f, 0.000776098f, 0.000266992f, 0.000131878f, 9.71014e-05f},
+ {0.73921f, 0.536662f, 0.432523f, 0.429408f, 0.422737f, 0.410008f, 0.387164f, 0.343455f, 0.256244f, 0.113904f, 0.0215896f, 0.00304996f, 0.000713029f, 0.000248363f, 0.000126622f, 9.62588e-05f},
+ {0.872866f, 0.684184f, 0.555088f, 0.548767f, 0.535485f, 0.510279f, 0.464582f, 0.381586f, 0.243471f, 0.0880175f, 0.0159727f, 0.00263818f, 0.000662592f, 0.00023626f, 0.000123267f, 9.5507e-05f},
+ {0.959391f, 0.805625f, 0.67916f, 0.664178f, 0.631547f, 0.571153f, 0.472016f, 0.334013f, 0.181333f, 0.062308f, 0.0127135f, 0.00243179f, 0.000636559f, 0.000230455f, 0.000121931f, 9.53293e-05f},
+ {0.995178f, 0.921013f, 0.829452f, 0.756155f, 0.650956f, 0.525634f, 0.39339f, 0.265033f, 0.146666f, 0.0541665f, 0.0119003f, 0.00237358f, 0.000630409f, 0.000229067f, 0.000121523f, 9.52288e-05f}
+ },
+ {
+ {0.0751656f, 0.0367766f, 0.019101f, 0.0168419f, 0.016786f, 0.0166478f, 0.0163151f, 0.0158158f, 0.0149666f, 0.0132243f, 0.00974355f, 0.0048222f, 0.0016387f, 0.000675244f, 0.000409438f, 0.000292956f},
+ {0.0894614f, 0.0465185f, 0.0249504f, 0.0220886f, 0.021999f, 0.0217885f, 0.0214024f, 0.0208124f, 0.0196682f, 0.0174213f, 0.0128789f, 0.0064365f, 0.00210836f, 0.000827055f, 0.000488908f, 0.000347008f},
+ {0.108132f, 0.0593809f, 0.0328083f, 0.0291563f, 0.0291384f, 0.02888f, 0.0284616f, 0.0276406f, 0.0261488f, 0.0232205f, 0.0171749f, 0.00849331f, 0.00271977f, 0.00100872f, 0.000578115f, 0.000405619f},
+ {0.132802f, 0.0767836f, 0.043639f, 0.0390422f, 0.038907f, 0.0385462f, 0.0381019f, 0.0369371f, 0.0350749f, 0.0309741f, 0.023102f, 0.0113499f, 0.00350794f, 0.00122447f, 0.00067375f, 0.000466471f},
+ {0.165866f, 0.100828f, 0.0588934f, 0.0527454f, 0.0524788f, 0.0521715f, 0.0513304f, 0.0499157f, 0.0472961f, 0.0420834f, 0.0311871f, 0.0153008f, 0.00446775f, 0.00147497f, 0.000774432f, 0.000525244f},
+ {0.210055f, 0.134164f, 0.0800222f, 0.0719804f, 0.0717665f, 0.0713139f, 0.070094f, 0.0681393f, 0.0646811f, 0.0574924f, 0.0424442f, 0.0203313f, 0.00564984f, 0.00173703f, 0.000868731f, 0.000577233f},
+ {0.268108f, 0.18056f, 0.110085f, 0.0992329f, 0.0987635f, 0.0978436f, 0.0965255f, 0.0938618f, 0.0888379f, 0.078708f, 0.0577296f, 0.0267312f, 0.00705713f, 0.00200662f, 0.000950174f, 0.0006183f},
+ {0.343828f, 0.2451f, 0.152077f, 0.13708f, 0.136523f, 0.135426f, 0.133423f, 0.129364f, 0.12248f, 0.107812f, 0.0774975f, 0.0343422f, 0.00849988f, 0.00223365f, 0.00100541f, 0.000646534f},
+ {0.437388f, 0.332662f, 0.211163f, 0.18931f, 0.188563f, 0.186922f, 0.183696f, 0.178102f, 0.167266f, 0.145955f, 0.101239f, 0.0418692f, 0.00947501f, 0.00235196f, 0.00102217f, 0.000658775f},
+ {0.545163f, 0.446723f, 0.289934f, 0.258759f, 0.257352f, 0.254701f, 0.249871f, 0.241149f, 0.224767f, 0.19176f, 0.125957f, 0.0467954f, 0.00978588f, 0.00235237f, 0.00100425f, 0.00066008f},
+ {0.657315f, 0.584786f, 0.389181f, 0.343744f, 0.341835f, 0.337639f, 0.32988f, 0.315875f, 0.289908f, 0.237973f, 0.142579f, 0.0466273f, 0.0091475f, 0.00222421f, 0.000960668f, 0.000654003f},
+ {0.760562f, 0.733439f, 0.502646f, 0.437962f, 0.434678f, 0.427794f, 0.415218f, 0.392508f, 0.350177f, 0.269557f, 0.141523f, 0.0400829f, 0.0078249f, 0.00203728f, 0.000908712f, 0.000645139f},
+ {0.846733f, 0.866769f, 0.616993f, 0.531188f, 0.525637f, 0.51422f, 0.493019f, 0.454742f, 0.385057f, 0.265782f, 0.118204f, 0.030316f, 0.00638598f, 0.00183471f, 0.0008641f, 0.000637678f},
+ {0.916567f, 0.955333f, 0.722745f, 0.621582f, 0.611615f, 0.590612f, 0.551808f, 0.482835f, 0.370677f, 0.220863f, 0.0871105f, 0.0226231f, 0.00540626f, 0.00171013f, 0.000836098f, 0.000632195f},
+ {0.968631f, 0.991759f, 0.820946f, 0.723191f, 0.700359f, 0.652293f, 0.568187f, 0.446373f, 0.303762f, 0.167936f, 0.0675108f, 0.0189695f, 0.00495632f, 0.00165292f, 0.000824656f, 0.000630514f},
+ {0.995687f, 0.999509f, 0.926352f, 0.841634f, 0.754113f, 0.637517f, 0.508604f, 0.380662f, 0.258826f, 0.148263f, 0.0622874f, 0.0181671f, 0.00486165f, 0.00163969f, 0.00082149f, 0.000629823f}
+ },
+ {
+ {0.147887f, 0.0887551f, 0.0525506f, 0.0336697f, 0.0320708f, 0.0319812f, 0.0316011f, 0.0311545f, 0.0302589f, 0.0285675f, 0.0253974f, 0.0194028f, 0.0109172f, 0.00423459f, 0.00179321f, 0.00115721f},
+ {0.172219f, 0.108738f, 0.0668147f, 0.0434863f, 0.0415335f, 0.0412836f, 0.0408824f, 0.040265f, 0.0390682f, 0.0369916f, 0.0329611f, 0.0252202f, 0.0139996f, 0.00534759f, 0.00214176f, 0.00135621f},
+ {0.202753f, 0.134704f, 0.0853529f, 0.0565107f, 0.0538888f, 0.0536067f, 0.0532631f, 0.052446f, 0.0508731f, 0.0482355f, 0.0429877f, 0.0327421f, 0.0181888f, 0.00663745f, 0.00253168f, 0.0015688f},
+ {0.24096f, 0.168221f, 0.109942f, 0.0737677f, 0.0705636f, 0.0701521f, 0.0696892f, 0.0686022f, 0.0667101f, 0.0631255f, 0.0561702f, 0.04286f, 0.023411f, 0.00824675f, 0.0029488f, 0.00178627f},
+ {0.289319f, 0.211379f, 0.142638f, 0.097021f, 0.0929139f, 0.0923694f, 0.0916507f, 0.0902359f, 0.0877175f, 0.0829596f, 0.0739655f, 0.0560281f, 0.0298796f, 0.0100867f, 0.003386f, 0.00199171f},
+ {0.348651f, 0.26769f, 0.186389f, 0.127819f, 0.12236f, 0.121796f, 0.120808f, 0.118847f, 0.11558f, 0.109217f, 0.0968423f, 0.0727608f, 0.0377663f, 0.0119591f, 0.0037803f, 0.00216842f},
+ {0.419802f, 0.339148f, 0.24474f, 0.16864f, 0.16129f, 0.160593f, 0.159048f, 0.156579f, 0.151899f, 0.14329f, 0.126402f, 0.093001f, 0.0464131f, 0.0138692f, 0.00410832f, 0.00230137f},
+ {0.50202f, 0.427135f, 0.32085f, 0.221678f, 0.21154f, 0.210483f, 0.208505f, 0.204823f, 0.19837f, 0.186229f, 0.162298f, 0.116091f, 0.0544602f, 0.0152887f, 0.00429646f, 0.00238356f},
+ {0.590805f, 0.529984f, 0.417997f, 0.28796f, 0.273544f, 0.272273f, 0.269371f, 0.264244f, 0.254641f, 0.237279f, 0.202921f, 0.13829f, 0.0598109f, 0.0154655f, 0.00428314f, 0.00240749f},
+ {0.680075f, 0.641818f, 0.534622f, 0.36668f, 0.346549f, 0.344474f, 0.340224f, 0.332542f, 0.318505f, 0.292676f, 0.242488f, 0.153857f, 0.0596481f, 0.0145358f, 0.00411044f, 0.0023916f},
+ {0.761356f, 0.752583f, 0.66489f, 0.453291f, 0.424808f, 0.421695f, 0.415246f, 0.403503f, 0.382529f, 0.343708f, 0.27069f, 0.154824f, 0.0529199f, 0.0126267f, 0.00381654f, 0.00235378f},
+ {0.828679f, 0.852804f, 0.792013f, 0.542644f, 0.503055f, 0.498088f, 0.488193f, 0.470136f, 0.437773f, 0.378636f, 0.275176f, 0.137074f, 0.0418347f, 0.0103108f, 0.00350289f, 0.0023083f},
+ {0.882398f, 0.93324f, 0.894998f, 0.629542f, 0.577138f, 0.569241f, 0.553434f, 0.524452f, 0.472406f, 0.382528f, 0.246334f, 0.106754f, 0.0309094f, 0.00825209f, 0.00324481f, 0.00227136f},
+ {0.930465f, 0.981104f, 0.959582f, 0.715904f, 0.652872f, 0.639048f, 0.610964f, 0.559312f, 0.471807f, 0.342853f, 0.195018f, 0.0790131f, 0.0236881f, 0.00710443f, 0.00309393f, 0.00224701f},
+ {0.971888f, 0.997444f, 0.988897f, 0.808936f, 0.743055f, 0.712149f, 0.649785f, 0.548452f, 0.416932f, 0.277413f, 0.153749f, 0.0646395f, 0.0206423f, 0.00660389f, 0.00303106f, 0.00223869f},
+ {0.995977f, 0.999908f, 0.998167f, 0.917771f, 0.837809f, 0.739119f, 0.616399f, 0.488237f, 0.363493f, 0.246053f, 0.140903f, 0.0612141f, 0.0199892f, 0.00650528f, 0.0030159f, 0.002236f}
+ },
+ {
+ {0.234099f, 0.157694f, 0.107168f, 0.0700248f, 0.0530869f, 0.0526462f, 0.0523807f, 0.0519568f, 0.0511113f, 0.0496138f, 0.0468662f, 0.0416525f, 0.0319327f, 0.0185243f, 0.00761253f, 0.00346402f},
+ {0.267094f, 0.188349f, 0.132347f, 0.0880624f, 0.0675447f, 0.0668504f, 0.066486f, 0.065846f, 0.0649024f, 0.0628994f, 0.0595416f, 0.0528147f, 0.0404812f, 0.0231104f, 0.00912842f, 0.00401013f},
+ {0.306616f, 0.226182f, 0.164165f, 0.111474f, 0.0858023f, 0.0849425f, 0.0846839f, 0.0838376f, 0.0825208f, 0.0801044f, 0.0757554f, 0.0671588f, 0.0511811f, 0.028788f, 0.0109045f, 0.00458291f},
+ {0.353746f, 0.273178f, 0.204727f, 0.141714f, 0.109333f, 0.108355f, 0.107773f, 0.106837f, 0.105241f, 0.102064f, 0.0964199f, 0.0854883f, 0.0645148f, 0.0354868f, 0.0127577f, 0.00516251f},
+ {0.409344f, 0.329885f, 0.255636f, 0.180314f, 0.139468f, 0.138281f, 0.137515f, 0.136282f, 0.134046f, 0.130071f, 0.122808f, 0.108229f, 0.0807627f, 0.0431881f, 0.0147009f, 0.00568418f},
+ {0.473484f, 0.398349f, 0.319811f, 0.229676f, 0.177615f, 0.175845f, 0.174969f, 0.173416f, 0.170356f, 0.165266f, 0.155393f, 0.13621f, 0.099696f, 0.0509202f, 0.0162805f, 0.00611045f},
+ {0.544024f, 0.477611f, 0.398766f, 0.291978f, 0.224712f, 0.222418f, 0.22119f, 0.218979f, 0.21512f, 0.207861f, 0.194804f, 0.16886f, 0.120189f, 0.0580256f, 0.0174809f, 0.00639845f},
+ {0.61913f, 0.565312f, 0.492898f, 0.369287f, 0.281146f, 0.277875f, 0.276402f, 0.273429f, 0.268044f, 0.25815f, 0.240075f, 0.204322f, 0.139353f, 0.0626336f, 0.0177423f, 0.0065324f},
+ {0.693559f, 0.656233f, 0.59942f, 0.461165f, 0.345586f, 0.341257f, 0.339151f, 0.334856f, 0.327185f, 0.31358f, 0.287947f, 0.238509f, 0.152605f, 0.0625432f, 0.0169536f, 0.00649506f},
+ {0.763041f, 0.743727f, 0.711084f, 0.56582f, 0.41485f, 0.408813f, 0.405645f, 0.399721f, 0.388695f, 0.369022f, 0.332624f, 0.263691f, 0.154396f, 0.056694f, 0.0151914f, 0.00635182f},
+ {0.821954f, 0.823152f, 0.817676f, 0.675577f, 0.484669f, 0.476055f, 0.471564f, 0.462704f, 0.44677f, 0.418203f, 0.365716f, 0.271369f, 0.141171f, 0.0467529f, 0.0129973f, 0.00616609f},
+ {0.867861f, 0.892188f, 0.905515f, 0.781705f, 0.553059f, 0.540725f, 0.533987f, 0.520815f, 0.496942f, 0.454198f, 0.378046f, 0.254509f, 0.115678f, 0.0357247f, 0.0109052f, 0.00597637f},
+ {0.904108f, 0.95007f, 0.96385f, 0.87034f, 0.619949f, 0.602477f, 0.591961f, 0.571272f, 0.533573f, 0.467464f, 0.358432f, 0.212738f, 0.0865194f, 0.0264459f, 0.00934221f, 0.00582978f},
+ {0.939797f, 0.986301f, 0.990713f, 0.933622f, 0.693342f, 0.668972f, 0.650542f, 0.614118f, 0.549052f, 0.444674f, 0.305216f, 0.164058f, 0.0651231f, 0.02118f, 0.00845222f, 0.00573999f},
+ {0.974394f, 0.998266f, 0.998705f, 0.971664f, 0.783765f, 0.749853f, 0.708978f, 0.631827f, 0.516941f, 0.380589f, 0.246571f, 0.132988f, 0.0552879f, 0.0190579f, 0.00811435f, 0.00570859f},
+ {0.996243f, 0.999946f, 0.999957f, 0.991948f, 0.898737f, 0.820613f, 0.711671f, 0.586169f, 0.459343f, 0.337761f, 0.224085f, 0.124623f, 0.0531018f, 0.0186455f, 0.00804229f, 0.00570015f}
+ },
+ {
+ {0.326322f, 0.237317f, 0.175876f, 0.12756f, 0.08937f, 0.0794428f, 0.0791837f, 0.0788149f, 0.0782239f, 0.0768283f, 0.0744818f, 0.0703003f, 0.0618115f, 0.0461797f, 0.0256488f, 0.00993646f},
+ {0.364919f, 0.276697f, 0.211547f, 0.1564f, 0.110704f, 0.0983882f, 0.098256f, 0.097825f, 0.0968578f, 0.0952844f, 0.0923921f, 0.0870316f, 0.0764738f, 0.0565963f, 0.0307442f, 0.0113955f},
+ {0.409444f, 0.323566f, 0.254946f, 0.192381f, 0.137405f, 0.122148f, 0.121922f, 0.121183f, 0.120217f, 0.118206f, 0.114513f, 0.107883f, 0.0942293f, 0.069078f, 0.0363954f, 0.0128678f},
+ {0.460018f, 0.378327f, 0.307211f, 0.236976f, 0.170393f, 0.151448f, 0.151089f, 0.150393f, 0.148968f, 0.146371f, 0.141815f, 0.133181f, 0.115927f, 0.0836839f, 0.0423456f, 0.0143597f},
+ {0.516658f, 0.441038f, 0.369831f, 0.292194f, 0.211015f, 0.187271f, 0.186809f, 0.18583f, 0.184044f, 0.180689f, 0.17477f, 0.163569f, 0.141176f, 0.0997764f, 0.0482789f, 0.0155482f},
+ {0.578018f, 0.511321f, 0.443457f, 0.359345f, 0.260433f, 0.230084f, 0.229472f, 0.228195f, 0.225764f, 0.221658f, 0.213866f, 0.199247f, 0.169913f, 0.116296f, 0.0531081f, 0.0164137f},
+ {0.641619f, 0.587164f, 0.527168f, 0.439617f, 0.3194f, 0.280145f, 0.279198f, 0.277659f, 0.27447f, 0.268731f, 0.258472f, 0.239081f, 0.200245f, 0.131266f, 0.0559141f, 0.0167672f},
+ {0.705877f, 0.664212f, 0.618225f, 0.533205f, 0.387809f, 0.336064f, 0.335074f, 0.33275f, 0.328609f, 0.320892f, 0.30711f, 0.280748f, 0.228737f, 0.141218f, 0.0556433f, 0.0165623f},
+ {0.766043f, 0.738383f, 0.711006f, 0.636383f, 0.463718f, 0.395721f, 0.394383f, 0.39118f, 0.385345f, 0.374908f, 0.35585f, 0.319774f, 0.250036f, 0.142241f, 0.0514129f, 0.0158781f},
+ {0.819727f, 0.804792f, 0.799333f, 0.742458f, 0.544725f, 0.455263f, 0.453239f, 0.448977f, 0.440863f, 0.42618f, 0.39961f, 0.349531f, 0.257523f, 0.131572f, 0.0440529f, 0.0149301f},
+ {0.863146f, 0.862708f, 0.87643f, 0.83996f, 0.627929f, 0.512899f, 0.510173f, 0.50404f, 0.492387f, 0.471469f, 0.433636f, 0.364198f, 0.246257f, 0.110952f, 0.0355121f, 0.0138963f},
+ {0.895522f, 0.913487f, 0.937446f, 0.91933f, 0.711217f, 0.568171f, 0.564166f, 0.555063f, 0.537968f, 0.507053f, 0.45194f, 0.35554f, 0.214034f, 0.0857041f, 0.0275724f, 0.0129888f},
+ {0.920489f, 0.959231f, 0.97764f, 0.968991f, 0.787946f, 0.622884f, 0.616625f, 0.602621f, 0.575861f, 0.527986f, 0.44518f, 0.317454f, 0.168511f, 0.0629685f, 0.0219673f, 0.0123398f},
+ {0.947351f, 0.989263f, 0.994774f, 0.991564f, 0.857934f, 0.686057f, 0.675252f, 0.650729f, 0.604228f, 0.52402f, 0.40323f, 0.257833f, 0.12816f, 0.0488968f, 0.0189727f, 0.0119794f},
+ {0.976613f, 0.998772f, 0.999335f, 0.998762f, 0.917634f, 0.76965f, 0.746013f, 0.692329f, 0.599465f, 0.473535f, 0.336441f, 0.208975f, 0.106678f, 0.0430084f, 0.0178256f, 0.0118565f},
+ {0.996496f, 0.999962f, 0.999981f, 0.999958f, 0.969935f, 0.875241f, 0.789262f, 0.672406f, 0.545605f, 0.421197f, 0.302763f, 0.19345f, 0.101512f, 0.0417932f, 0.0175873f, 0.0118287f}
+ },
+ {
+ {0.4178f, 0.321643f, 0.253033f, 0.196916f, 0.14778f, 0.114968f, 0.112698f, 0.112542f, 0.111936f, 0.110872f, 0.108918f, 0.105425f, 0.0985664f, 0.08448f, 0.0590056f, 0.0272137f},
+ {0.459266f, 0.366832f, 0.297123f, 0.23568f, 0.178743f, 0.139151f, 0.136307f, 0.136093f, 0.135296f, 0.134009f, 0.131659f, 0.127321f, 0.11882f, 0.101096f, 0.0693955f, 0.0308438f},
+ {0.505272f, 0.418439f, 0.348338f, 0.282091f, 0.216317f, 0.168111f, 0.164614f, 0.164171f, 0.163434f, 0.161678f, 0.15877f, 0.153426f, 0.142889f, 0.120549f, 0.080913f, 0.0343671f},
+ {0.555067f, 0.476052f, 0.407398f, 0.337213f, 0.261299f, 0.202519f, 0.198423f, 0.197759f, 0.196755f, 0.194572f, 0.19094f, 0.184245f, 0.170751f, 0.142719f, 0.0928972f, 0.037582f},
+ {0.608245f, 0.538798f, 0.474411f, 0.402399f, 0.3154f, 0.243251f, 0.23766f, 0.237f, 0.235493f, 0.233008f, 0.22834f, 0.219783f, 0.202494f, 0.166761f, 0.104536f, 0.0401457f},
+ {0.663529f, 0.605003f, 0.548505f, 0.477763f, 0.379232f, 0.289475f, 0.282604f, 0.281619f, 0.279902f, 0.276593f, 0.27052f, 0.259414f, 0.237165f, 0.191092f, 0.11404f, 0.0413962f},
+ {0.71836f, 0.672436f, 0.626925f, 0.562112f, 0.453294f, 0.341467f, 0.33243f, 0.331225f, 0.328874f, 0.324343f, 0.316598f, 0.301931f, 0.27282f, 0.213199f, 0.119482f, 0.041063f},
+ {0.771377f, 0.737092f, 0.706233f, 0.653006f, 0.537417f, 0.397007f, 0.38521f, 0.383645f, 0.380565f, 0.374684f, 0.364288f, 0.344772f, 0.306171f, 0.22939f, 0.118518f, 0.0392006f},
+ {0.819566f, 0.795914f, 0.781435f, 0.744897f, 0.627982f, 0.453955f, 0.438649f, 0.436488f, 0.43212f, 0.424367f, 0.410159f, 0.383862f, 0.332099f, 0.234084f, 0.109683f, 0.0358741f},
+ {0.861272f, 0.846474f, 0.849208f, 0.830732f, 0.721333f, 0.509741f, 0.48907f, 0.486258f, 0.480367f, 0.469569f, 0.450136f, 0.413952f, 0.344625f, 0.223159f, 0.0941158f, 0.0318545f},
+ {0.893781f, 0.889538f, 0.906589f, 0.901515f, 0.811664f, 0.565494f, 0.538077f, 0.534047f, 0.525791f, 0.510615f, 0.483189f, 0.432798f, 0.339807f, 0.196909f, 0.0750987f, 0.0281018f},
+ {0.916967f, 0.928056f, 0.952651f, 0.95546f, 0.891426f, 0.62134f, 0.584718f, 0.578819f, 0.566817f, 0.544554f, 0.504692f, 0.432669f, 0.311163f, 0.15866f, 0.0571654f, 0.0249806f},
+ {0.93371f, 0.965543f, 0.984134f, 0.984963f, 0.948403f, 0.679691f, 0.632162f, 0.623131f, 0.60451f, 0.570084f, 0.508621f, 0.40557f, 0.259927f, 0.119399f, 0.0439549f, 0.0228667f},
+ {0.953781f, 0.991452f, 0.996725f, 0.996541f, 0.982505f, 0.746117f, 0.689189f, 0.673492f, 0.641111f, 0.581826f, 0.483737f, 0.347913f, 0.202973f, 0.0915104f, 0.0366374f, 0.0217775f},
+ {0.97858f, 0.999134f, 0.999654f, 0.999522f, 0.996762f, 0.826366f, 0.765724f, 0.731078f, 0.661596f, 0.552974f, 0.419804f, 0.284661f, 0.16641f, 0.0788318f, 0.0338895f, 0.0214004f},
+ {0.996735f, 0.999974f, 0.999992f, 0.99998f, 0.999865f, 0.925031f, 0.84534f, 0.74417f, 0.621607f, 0.495845f, 0.374385f, 0.259803f, 0.156444f, 0.076019f, 0.033306f, 0.021326f}
+ },
+ {
+ {0.504721f, 0.405656f, 0.333871f, 0.27326f, 0.218098f, 0.168263f, 0.153204f, 0.152959f, 0.152613f, 0.151675f, 0.150045f, 0.147501f, 0.141915f, 0.130455f, 0.105276f, 0.0608581f},
+ {0.546314f, 0.454163f, 0.383238f, 0.319359f, 0.257925f, 0.198927f, 0.180583f, 0.180298f, 0.179739f, 0.178791f, 0.176811f, 0.173406f, 0.166785f, 0.152599f, 0.121462f, 0.0677835f},
+ {0.590617f, 0.506754f, 0.438464f, 0.372616f, 0.304466f, 0.234308f, 0.212233f, 0.21193f, 0.21129f, 0.209959f, 0.207612f, 0.203546f, 0.195293f, 0.17761f, 0.139042f, 0.0743825f},
+ {0.637251f, 0.563469f, 0.499414f, 0.43351f, 0.35882f, 0.275688f, 0.248375f, 0.248021f, 0.247283f, 0.245785f, 0.242865f, 0.237589f, 0.227375f, 0.205188f, 0.156803f, 0.0800607f},
+ {0.68492f, 0.622157f, 0.565315f, 0.501912f, 0.42159f, 0.322982f, 0.289239f, 0.288775f, 0.287606f, 0.285657f, 0.28215f, 0.275532f, 0.262504f, 0.234414f, 0.174306f, 0.0840276f},
+ {0.732458f, 0.681506f, 0.634346f, 0.576929f, 0.493426f, 0.376116f, 0.333776f, 0.33324f, 0.33184f, 0.32946f, 0.324757f, 0.316235f, 0.299635f, 0.26381f, 0.188694f, 0.0850079f},
+ {0.778672f, 0.738894f, 0.703401f, 0.655946f, 0.573393f, 0.434698f, 0.381001f, 0.380294f, 0.37853f, 0.375203f, 0.369309f, 0.358344f, 0.336485f, 0.290291f, 0.197258f, 0.0829682f},
+ {0.821923f, 0.792118f, 0.769567f, 0.735898f, 0.659137f, 0.497213f, 0.428794f, 0.427797f, 0.4256f, 0.421204f, 0.413409f, 0.398963f, 0.37059f, 0.310524f, 0.196959f, 0.0773996f},
+ {0.86055f, 0.838697f, 0.829455f, 0.811241f, 0.746586f, 0.562444f, 0.475222f, 0.473851f, 0.47079f, 0.465083f, 0.454572f, 0.435262f, 0.39741f, 0.319244f, 0.185245f, 0.0690026f},
+ {0.893095f, 0.877285f, 0.881631f, 0.877635f, 0.828495f, 0.628048f, 0.517484f, 0.515733f, 0.511624f, 0.50387f, 0.489596f, 0.463272f, 0.41237f, 0.312031f, 0.162469f, 0.0591605f},
+ {0.917615f, 0.909531f, 0.925471f, 0.929835f, 0.89966f, 0.69672f, 0.559404f, 0.556982f, 0.5512f, 0.540334f, 0.520498f, 0.483786f, 0.413898f, 0.287332f, 0.132796f, 0.050193f},
+ {0.934032f, 0.939085f, 0.962051f, 0.97022f, 0.953749f, 0.764512f, 0.599388f, 0.595758f, 0.58752f, 0.571677f, 0.542717f, 0.48957f, 0.393361f, 0.243657f, 0.102006f, 0.0429349f},
+ {0.944519f, 0.970496f, 0.988256f, 0.991154f, 0.983414f, 0.827743f, 0.641835f, 0.636383f, 0.623603f, 0.599039f, 0.554061f, 0.474473f, 0.346497f, 0.190479f, 0.0773776f, 0.038138f},
+ {0.95928f, 0.9932f, 0.997978f, 0.998305f, 0.995804f, 0.883858f, 0.69604f, 0.686486f, 0.6644f, 0.621603f, 0.545756f, 0.427881f, 0.280957f, 0.145884f, 0.0628985f, 0.0357136f},
+ {0.980295f, 0.999433f, 0.999861f, 0.999815f, 0.999411f, 0.932279f, 0.773851f, 0.752873f, 0.70396f, 0.616439f, 0.494353f, 0.357097f, 0.228204f, 0.123006f, 0.0572407f, 0.0348617f},
+ {0.996954f, 0.999987f, 0.999999f, 0.999991f, 0.999972f, 0.975302f, 0.879834f, 0.799428f, 0.686377f, 0.561806f, 0.438543f, 0.320973f, 0.211457f, 0.117482f, 0.0559932f, 0.034697f}
+ },
+ {
+ {0.584384f, 0.486759f, 0.414569f, 0.35226f, 0.294182f, 0.237678f, 0.201169f, 0.200033f, 0.199862f, 0.199145f, 0.198018f, 0.195833f, 0.191789f, 0.18265f, 0.160953f, 0.11217f},
+ {0.623963f, 0.535209f, 0.466013f, 0.402629f, 0.340092f, 0.275f, 0.231413f, 0.23002f, 0.229534f, 0.228906f, 0.227486f, 0.22481f, 0.219569f, 0.208694f, 0.182215f, 0.122782f},
+ {0.664828f, 0.586377f, 0.521816f, 0.459039f, 0.392321f, 0.317447f, 0.26513f, 0.263508f, 0.262985f, 0.261942f, 0.260289f, 0.257189f, 0.250868f, 0.237132f, 0.204427f, 0.132702f},
+ {0.706323f, 0.638963f, 0.581118f, 0.52111f, 0.451331f, 0.365574f, 0.30242f, 0.300352f, 0.299899f, 0.298696f, 0.29654f, 0.292524f, 0.284802f, 0.267865f, 0.226956f, 0.140564f},
+ {0.747964f, 0.691893f, 0.642522f, 0.587635f, 0.517204f, 0.420172f, 0.342916f, 0.340351f, 0.339621f, 0.338141f, 0.335483f, 0.33054f, 0.320698f, 0.299487f, 0.248286f, 0.145339f},
+ {0.788377f, 0.743281f, 0.703635f, 0.657164f, 0.589507f, 0.480625f, 0.385678f, 0.382457f, 0.381606f, 0.379809f, 0.376218f, 0.369935f, 0.357479f, 0.33069f, 0.266428f, 0.145712f},
+ {0.826339f, 0.79143f, 0.762619f, 0.727238f, 0.666304f, 0.546651f, 0.429381f, 0.425347f, 0.42421f, 0.421685f, 0.417389f, 0.409095f, 0.392994f, 0.358587f, 0.277596f, 0.140842f},
+ {0.861355f, 0.834821f, 0.816762f, 0.794142f, 0.744211f, 0.617062f, 0.47219f, 0.466988f, 0.465523f, 0.462368f, 0.456606f, 0.445924f, 0.424955f, 0.380023f, 0.279387f, 0.130409f},
+ {0.892361f, 0.871503f, 0.864226f, 0.854361f, 0.818558f, 0.690242f, 0.51295f, 0.505941f, 0.503913f, 0.499854f, 0.492203f, 0.477961f, 0.450299f, 0.391215f, 0.267588f, 0.115213f},
+ {0.917825f, 0.900846f, 0.904614f, 0.906182f, 0.883343f, 0.762659f, 0.549526f, 0.540403f, 0.537682f, 0.532118f, 0.521691f, 0.502502f, 0.465247f, 0.38793f, 0.241679f, 0.0973322f},
+ {0.936621f, 0.925078f, 0.93872f, 0.946062f, 0.936093f, 0.835981f, 0.587729f, 0.575563f, 0.571634f, 0.563977f, 0.549603f, 0.522838f, 0.471081f, 0.368888f, 0.204316f, 0.0810579f},
+ {0.947769f, 0.947779f, 0.968657f, 0.978432f, 0.974073f, 0.900961f, 0.625401f, 0.608581f, 0.60304f, 0.59182f, 0.570893f, 0.531865f, 0.458406f, 0.327451f, 0.161453f, 0.0675697f},
+ {0.953547f, 0.974397f, 0.991229f, 0.994646f, 0.99207f, 0.949355f, 0.668031f, 0.644966f, 0.636347f, 0.619022f, 0.586274f, 0.526404f, 0.42144f, 0.267644f, 0.122802f, 0.0587093f},
+ {0.963916f, 0.994649f, 0.998944f, 0.999283f, 0.998317f, 0.980541f, 0.723671f, 0.693064f, 0.678242f, 0.647756f, 0.590977f, 0.49482f, 0.356676f, 0.207624f, 0.0978133f, 0.0541279f},
+ {0.981768f, 0.999674f, 1.00001f, 0.999968f, 0.999821f, 0.99555f, 0.801076f, 0.763079f, 0.729892f, 0.663386f, 0.55787f, 0.425017f, 0.289535f, 0.171399f, 0.0872914f, 0.0524877f},
+ {0.997144f, 0.999995f, 1.0f, 0.999997f, 0.999986f, 0.999621f, 0.909389f, 0.838171f, 0.739119f, 0.619323f, 0.495702f, 0.376435f, 0.263665f, 0.161767f, 0.0849567f, 0.0521766f}
+ },
+ {
+ {0.655346f, 0.561906f, 0.491755f, 0.430295f, 0.371617f, 0.313226f, 0.260674f, 0.253407f, 0.253217f, 0.252764f, 0.251786f, 0.250303f, 0.247113f, 0.24021f, 0.223402f, 0.178662f},
+ {0.691674f, 0.608208f, 0.542899f, 0.482245f, 0.420802f, 0.355338f, 0.293422f, 0.284524f, 0.284123f, 0.283469f, 0.282603f, 0.280591f, 0.276717f, 0.268524f, 0.247739f, 0.19242f},
+ {0.728044f, 0.655948f, 0.596639f, 0.538255f, 0.475305f, 0.402536f, 0.329049f, 0.318026f, 0.317658f, 0.316949f, 0.315771f, 0.313315f, 0.308647f, 0.298611f, 0.272722f, 0.204541f},
+ {0.764272f, 0.703399f, 0.651827f, 0.597987f, 0.534968f, 0.454861f, 0.367411f, 0.354038f, 0.353594f, 0.352687f, 0.351086f, 0.34804f, 0.342341f, 0.329798f, 0.297636f, 0.213817f},
+ {0.799481f, 0.749541f, 0.706707f, 0.65972f, 0.599422f, 0.512711f, 0.408077f, 0.391621f, 0.390916f, 0.389937f, 0.387961f, 0.384355f, 0.377045f, 0.361351f, 0.321132f, 0.21874f},
+ {0.833064f, 0.79325f, 0.759696f, 0.721739f, 0.667386f, 0.576018f, 0.450583f, 0.429854f, 0.429303f, 0.428047f, 0.425468f, 0.420758f, 0.411582f, 0.391712f, 0.341006f, 0.218386f},
+ {0.864227f, 0.833129f, 0.80903f, 0.781518f, 0.736449f, 0.643705f, 0.493718f, 0.467414f, 0.466667f, 0.464997f, 0.46178f, 0.455711f, 0.443946f, 0.418506f, 0.353892f, 0.21037f},
+ {0.892507f, 0.868179f, 0.852712f, 0.836384f, 0.803063f, 0.713932f, 0.536262f, 0.502752f, 0.501796f, 0.499473f, 0.495427f, 0.487581f, 0.47234f, 0.439281f, 0.357252f, 0.194765f},
+ {0.917192f, 0.897168f, 0.890272f, 0.884494f, 0.86404f, 0.784655f, 0.578154f, 0.534738f, 0.533426f, 0.530553f, 0.525126f, 0.514691f, 0.494508f, 0.450769f, 0.347364f, 0.172457f},
+ {0.937506f, 0.919316f, 0.921779f, 0.925287f, 0.914427f, 0.85005f, 0.617343f, 0.562246f, 0.560465f, 0.556599f, 0.549083f, 0.535223f, 0.508035f, 0.449988f, 0.321718f, 0.146235f},
+ {0.951647f, 0.937322f, 0.948661f, 0.956573f, 0.954769f, 0.911411f, 0.662395f, 0.591633f, 0.589082f, 0.583729f, 0.573388f, 0.553868f, 0.515911f, 0.437037f, 0.282522f, 0.121081f},
+ {0.958864f, 0.954679f, 0.973608f, 0.98378f, 0.983817f, 0.957867f, 0.707989f, 0.619116f, 0.615467f, 0.607609f, 0.592542f, 0.564133f, 0.509188f, 0.402266f, 0.231036f, 0.0995307f},
+ {0.961019f, 0.977555f, 0.993463f, 0.996912f, 0.996041f, 0.984132f, 0.756614f, 0.65085f, 0.645144f, 0.63297f, 0.609357f, 0.565112f, 0.482834f, 0.344187f, 0.178426f, 0.0847629f},
+ {0.967802f, 0.995793f, 0.999663f, 0.999945f, 0.999463f, 0.995844f, 0.81039f, 0.695695f, 0.685924f, 0.664452f, 0.62278f, 0.547687f, 0.426479f, 0.273225f, 0.140307f, 0.0770456f},
+ {0.983009f, 0.999887f, 1.00013f, 1.00006f, 0.999994f, 0.999406f, 0.870621f, 0.766047f, 0.744002f, 0.695415f, 0.609439f, 0.487306f, 0.349639f, 0.22162f, 0.122491f, 0.0742164f},
+ {0.997307f, 1.0f, 1.00001f, 1.0f, 0.99999f, 0.999976f, 0.945438f, 0.86249f, 0.77964f, 0.668525f, 0.54669f, 0.42664f, 0.312222f, 0.206047f, 0.118426f, 0.0736859f}
+ },
+ {
+ {0.717024f, 0.629416f, 0.563068f, 0.504133f, 0.447055f, 0.389116f, 0.329939f, 0.311599f, 0.311606f, 0.311333f, 0.310731f, 0.309635f, 0.30734f, 0.302617f, 0.290487f, 0.255316f},
+ {0.749472f, 0.672512f, 0.612249f, 0.555209f, 0.497025f, 0.433789f, 0.364375f, 0.34236f, 0.342367f, 0.342028f, 0.34136f, 0.339841f, 0.33723f, 0.331458f, 0.316339f, 0.270967f},
+ {0.781054f, 0.71557f, 0.661956f, 0.608976f, 0.550978f, 0.482414f, 0.401394f, 0.374746f, 0.374662f, 0.37394f, 0.373224f, 0.371561f, 0.368083f, 0.36114f, 0.342029f, 0.284234f},
+ {0.811791f, 0.757438f, 0.711551f, 0.66402f, 0.608324f, 0.535764f, 0.440889f, 0.40826f, 0.408071f, 0.40734f, 0.406247f, 0.404107f, 0.400046f, 0.391082f, 0.367097f, 0.293858f},
+ {0.841362f, 0.797037f, 0.759584f, 0.719557f, 0.668209f, 0.593443f, 0.482114f, 0.442201f, 0.44176f, 0.441072f, 0.439664f, 0.437092f, 0.43185f, 0.420519f, 0.390315f, 0.298541f},
+ {0.869095f, 0.833649f, 0.804563f, 0.773131f, 0.729441f, 0.654612f, 0.525256f, 0.475706f, 0.475274f, 0.474519f, 0.472573f, 0.469213f, 0.462522f, 0.448148f, 0.410042f, 0.296346f},
+ {0.894231f, 0.866535f, 0.845465f, 0.823267f, 0.789172f, 0.718658f, 0.569663f, 0.507364f, 0.506963f, 0.505776f, 0.503467f, 0.499171f, 0.490712f, 0.472192f, 0.423022f, 0.285576f},
+ {0.917082f, 0.894465f, 0.880735f, 0.868064f, 0.84491f, 0.782923f, 0.614419f, 0.536301f, 0.535686f, 0.534104f, 0.53122f, 0.525615f, 0.514531f, 0.490305f, 0.427026f, 0.266185f},
+ {0.936875f, 0.91735f, 0.910328f, 0.906478f, 0.894135f, 0.844683f, 0.659437f, 0.5616f, 0.560719f, 0.558791f, 0.55493f, 0.547462f, 0.532755f, 0.500824f, 0.41945f, 0.237678f},
+ {0.953016f, 0.934042f, 0.934904f, 0.938939f, 0.93384f, 0.897741f, 0.703858f, 0.582755f, 0.581633f, 0.578905f, 0.573616f, 0.563623f, 0.543844f, 0.501145f, 0.396504f, 0.203638f},
+ {0.963656f, 0.947091f, 0.956302f, 0.96408f, 0.965802f, 0.945544f, 0.75495f, 0.606576f, 0.604926f, 0.601196f, 0.5939f, 0.579855f, 0.552057f, 0.493028f, 0.359716f, 0.169652f},
+ {0.9679f, 0.960212f, 0.977415f, 0.987604f, 0.989493f, 0.978001f, 0.803694f, 0.628576f, 0.626227f, 0.620804f, 0.61008f, 0.589458f, 0.549002f, 0.465776f, 0.305211f, 0.13878f},
+ {0.967103f, 0.980129f, 0.99518f, 0.99856f, 0.998354f, 0.993188f, 0.849293f, 0.655377f, 0.651673f, 0.643181f, 0.626331f, 0.593953f, 0.531686f, 0.41476f, 0.242081f, 0.116379f},
+ {0.970966f, 0.996743f, 1.00022f, 1.00044f, 1.00014f, 0.998565f, 0.891697f, 0.696166f, 0.689799f, 0.674749f, 0.644613f, 0.587956f, 0.487892f, 0.340297f, 0.18901f, 0.104251f},
+ {0.984048f, 1.00006f, 1.00022f, 1.00015f, 1.0001f, 0.99981f, 0.930966f, 0.764673f, 0.750195f, 0.715529f, 0.648841f, 0.542535f, 0.408366f, 0.272834f, 0.161263f, 0.0996967f},
+ {0.997442f, 1.00001f, 1.00001f, 1.0f, 0.999994f, 0.99999f, 0.97264f, 0.8756f, 0.808881f, 0.709364f, 0.592202f, 0.472449f, 0.357247f, 0.248946f, 0.154496f, 0.0988209f}
+ },
+ {
+ {0.769871f, 0.689358f, 0.627584f, 0.572104f, 0.518044f, 0.462697f, 0.403642f, 0.375197f, 0.375208f, 0.374881f, 0.37468f, 0.374081f, 0.372454f, 0.369723f, 0.361991f, 0.33683f},
+ {0.798124f, 0.728298f, 0.672992f, 0.620648f, 0.566709f, 0.507253f, 0.439053f, 0.404243f, 0.403978f, 0.403802f, 0.403317f, 0.402477f, 0.400742f, 0.396893f, 0.387081f, 0.352897f},
+ {0.825115f, 0.766163f, 0.717828f, 0.670222f, 0.617968f, 0.555261f, 0.476575f, 0.433554f, 0.433479f, 0.433122f, 0.432645f, 0.431507f, 0.429259f, 0.424441f, 0.411694f, 0.366138f},
+ {0.85076f, 0.802301f, 0.761656f, 0.719927f, 0.671158f, 0.606706f, 0.516142f, 0.463324f, 0.463138f, 0.462642f, 0.461979f, 0.460497f, 0.457908f, 0.451586f, 0.435076f, 0.374836f},
+ {0.875255f, 0.835573f, 0.802846f, 0.768598f, 0.725074f, 0.661379f, 0.557937f, 0.492816f, 0.49242f, 0.491944f, 0.49083f, 0.48917f, 0.485439f, 0.477549f, 0.456088f, 0.378419f},
+ {0.897746f, 0.866182f, 0.840701f, 0.814111f, 0.77861f, 0.71813f, 0.601478f, 0.520608f, 0.520355f, 0.519798f, 0.518462f, 0.516121f, 0.511446f, 0.501312f, 0.473759f, 0.374762f},
+ {0.91815f, 0.892929f, 0.874334f, 0.85577f, 0.829255f, 0.775655f, 0.646708f, 0.54623f, 0.545959f, 0.545143f, 0.543627f, 0.540567f, 0.534353f, 0.521363f, 0.48535f, 0.361865f},
+ {0.936524f, 0.91553f, 0.902491f, 0.892213f, 0.875269f, 0.831788f, 0.693279f, 0.568605f, 0.568203f, 0.567106f, 0.565102f, 0.561302f, 0.553341f, 0.536083f, 0.488935f, 0.339029f},
+ {0.952488f, 0.933362f, 0.925954f, 0.922905f, 0.915303f, 0.883465f, 0.74087f, 0.587614f, 0.587009f, 0.58568f, 0.582985f, 0.577754f, 0.567187f, 0.544174f, 0.482603f, 0.306824f},
+ {0.965242f, 0.945747f, 0.945117f, 0.949104f, 0.946766f, 0.925382f, 0.78788f, 0.602833f, 0.602024f, 0.600146f, 0.596527f, 0.589396f, 0.575154f, 0.544244f, 0.462883f, 0.26691f},
+ {0.973308f, 0.954882f, 0.962187f, 0.969527f, 0.973024f, 0.963323f, 0.841465f, 0.62141f, 0.620176f, 0.617676f, 0.612518f, 0.602507f, 0.582535f, 0.538926f, 0.431196f, 0.225171f},
+ {0.975153f, 0.964628f, 0.980321f, 0.990392f, 0.993245f, 0.987548f, 0.888355f, 0.638089f, 0.636404f, 0.632612f, 0.625101f, 0.610312f, 0.580971f, 0.518192f, 0.378572f, 0.184814f},
+ {0.972027f, 0.982191f, 0.996574f, 0.999778f, 0.999904f, 0.997118f, 0.927903f, 0.659922f, 0.657192f, 0.651337f, 0.639339f, 0.615987f, 0.569953f, 0.476777f, 0.310403f, 0.153466f},
+ {0.97356f, 0.997506f, 1.00066f, 1.00082f, 1.00061f, 0.999683f, 0.959278f, 0.6963f, 0.69161f, 0.681151f, 0.659574f, 0.617809f, 0.539042f, 0.406354f, 0.243328f, 0.135378f},
+ {0.984902f, 1.0002f, 1.0003f, 1.00021f, 1.00016f, 0.999968f, 0.981188f, 0.761976f, 0.75154f, 0.727094f, 0.677205f, 0.589543f, 0.464942f, 0.325271f, 0.202468f, 0.128341f},
+ {0.997554f, 1.00001f, 1.00002f, 1.00001f, 0.999996f, 0.999998f, 0.994412f, 0.881581f, 0.828661f, 0.742074f, 0.632541f, 0.514752f, 0.39931f, 0.290058f, 0.191668f, 0.126935f}
+ },
+ {
+ {0.814758f, 0.741125f, 0.684642f, 0.633259f, 0.582873f, 0.531109f, 0.477065f, 0.443401f, 0.442813f, 0.442904f, 0.442498f, 0.442225f, 0.441227f, 0.439691f, 0.435269f, 0.417015f},
+ {0.838806f, 0.775662f, 0.725511f, 0.678048f, 0.628714f, 0.574278f, 0.512131f, 0.469462f, 0.46859f, 0.468478f, 0.468359f, 0.467467f, 0.4667f, 0.46437f, 0.458047f, 0.432703f},
+ {0.86129f, 0.808418f, 0.765381f, 0.722842f, 0.676102f, 0.619945f, 0.548744f, 0.495036f, 0.493954f, 0.49382f, 0.493683f, 0.493065f, 0.491526f, 0.488416f, 0.479841f, 0.445139f},
+ {0.882499f, 0.839144f, 0.803179f, 0.766443f, 0.724031f, 0.667945f, 0.587382f, 0.520371f, 0.518904f, 0.518543f, 0.51827f, 0.517291f, 0.515409f, 0.51154f, 0.500236f, 0.452714f},
+ {0.902463f, 0.867095f, 0.838218f, 0.808457f, 0.771749f, 0.717693f, 0.628463f, 0.544602f, 0.542498f, 0.542471f, 0.541704f, 0.540785f, 0.538058f, 0.532832f, 0.517994f, 0.454845f},
+ {0.920638f, 0.892218f, 0.869788f, 0.846858f, 0.817576f, 0.768655f, 0.671021f, 0.567116f, 0.564754f, 0.564285f, 0.563504f, 0.561863f, 0.558675f, 0.551678f, 0.532307f, 0.44925f},
+ {0.93715f, 0.914212f, 0.897206f, 0.88129f, 0.860228f, 0.818965f, 0.715804f, 0.58707f, 0.584019f, 0.583419f, 0.582523f, 0.580453f, 0.576138f, 0.566912f, 0.541263f, 0.434966f},
+ {0.951935f, 0.93222f, 0.919714f, 0.910863f, 0.898083f, 0.866636f, 0.762016f, 0.604117f, 0.600054f, 0.599183f, 0.597978f, 0.595252f, 0.589719f, 0.577581f, 0.543471f, 0.41024f},
+ {0.96479f, 0.946055f, 0.938243f, 0.935514f, 0.930665f, 0.90952f, 0.809207f, 0.618167f, 0.612895f, 0.611866f, 0.609978f, 0.606374f, 0.598907f, 0.582638f, 0.53728f, 0.375768f},
+ {0.974998f, 0.955059f, 0.953115f, 0.956797f, 0.956078f, 0.942822f, 0.854768f, 0.629529f, 0.622202f, 0.620983f, 0.618442f, 0.613586f, 0.603451f, 0.58139f, 0.520351f, 0.33251f},
+ {0.980931f, 0.961102f, 0.96679f, 0.973625f, 0.978029f, 0.973807f, 0.905751f, 0.645629f, 0.635384f, 0.633787f, 0.630137f, 0.623134f, 0.608961f, 0.577404f, 0.494014f, 0.285684f},
+ {0.981041f, 0.968183f, 0.982609f, 0.992523f, 0.995859f, 0.992981f, 0.946246f, 0.660864f, 0.64658f, 0.644005f, 0.638785f, 0.628265f, 0.607339f, 0.561256f, 0.447135f, 0.237069f},
+ {0.976072f, 0.983846f, 0.997663f, 1.0007f, 1.00099f, 0.999286f, 0.974897f, 0.682563f, 0.662538f, 0.658535f, 0.650056f, 0.633432f, 0.600014f, 0.529113f, 0.380074f, 0.196042f},
+ {0.975703f, 0.998117f, 1.00102f, 1.00109f, 1.00093f, 1.00027f, 0.991798f, 0.719735f, 0.692488f, 0.685253f, 0.669926f, 0.639738f, 0.5803f, 0.468494f, 0.302512f, 0.170093f},
+ {0.985592f, 1.00031f, 1.00036f, 1.00025f, 1.00021f, 1.00006f, 0.998674f, 0.783198f, 0.749927f, 0.732759f, 0.696328f, 0.627581f, 0.518127f, 0.379354f, 0.245944f, 0.159461f},
+ {0.997649f, 1.00001f, 1.00002f, 1.00001f, 0.999999f, 1.0f, 0.999956f, 0.895882f, 0.840801f, 0.767192f, 0.667696f, 0.554176f, 0.439151f, 0.329469f, 0.228984f, 0.157272f}
+ },
+ {
+ {0.852327f, 0.785528f, 0.734096f, 0.687209f, 0.641027f, 0.593755f, 0.546174f, 0.51173f, 0.510117f, 0.510153f, 0.509981f, 0.509668f, 0.509121f, 0.508165f, 0.505485f, 0.492402f},
+ {0.872297f, 0.815385f, 0.770401f, 0.727489f, 0.683047f, 0.634238f, 0.579255f, 0.534697f, 0.532008f, 0.532121f, 0.531778f, 0.531399f, 0.530904f, 0.529383f, 0.525889f, 0.507332f},
+ {0.890813f, 0.843368f, 0.804953f, 0.76727f, 0.725805f, 0.676213f, 0.613642f, 0.556795f, 0.553167f, 0.552991f, 0.55288f, 0.552383f, 0.55162f, 0.549473f, 0.544027f, 0.518023f},
+ {0.908163f, 0.869398f, 0.837442f, 0.805183f, 0.768303f, 0.719709f, 0.650113f, 0.577676f, 0.572943f, 0.572831f, 0.572546f, 0.571959f, 0.570641f, 0.568212f, 0.560795f, 0.524445f},
+ {0.924225f, 0.892494f, 0.866992f, 0.841054f, 0.809644f, 0.764273f, 0.688854f, 0.597581f, 0.591033f, 0.590918f, 0.590508f, 0.589924f, 0.588226f, 0.584562f, 0.574635f, 0.524951f},
+ {0.938927f, 0.913222f, 0.89305f, 0.873231f, 0.848644f, 0.808965f, 0.728769f, 0.615773f, 0.607238f, 0.607084f, 0.60647f, 0.60548f, 0.603273f, 0.598426f, 0.585214f, 0.518078f},
+ {0.952227f, 0.93095f, 0.915501f, 0.901369f, 0.884093f, 0.852348f, 0.771079f, 0.631519f, 0.620656f, 0.620219f, 0.619534f, 0.618267f, 0.615283f, 0.609169f, 0.591182f, 0.5024f},
+ {0.964165f, 0.945556f, 0.933442f, 0.925354f, 0.915528f, 0.892248f, 0.814168f, 0.645156f, 0.630719f, 0.63017f, 0.62928f, 0.627568f, 0.623698f, 0.615359f, 0.591313f, 0.47741f},
+ {0.974607f, 0.956249f, 0.94788f, 0.945207f, 0.942051f, 0.92778f, 0.857753f, 0.657009f, 0.637844f, 0.637232f, 0.635956f, 0.633445f, 0.628438f, 0.617073f, 0.584543f, 0.442566f},
+ {0.982774f, 0.962428f, 0.959415f, 0.962767f, 0.962868f, 0.954528f, 0.897842f, 0.667502f, 0.642285f, 0.6415f, 0.63974f, 0.636305f, 0.629316f, 0.613794f, 0.569622f, 0.397893f},
+ {0.987038f, 0.966109f, 0.970437f, 0.976756f, 0.981732f, 0.980547f, 0.941763f, 0.685037f, 0.650733f, 0.649664f, 0.647199f, 0.642303f, 0.632398f, 0.610232f, 0.548225f, 0.348698f},
+ {0.985768f, 0.971035f, 0.984446f, 0.994179f, 0.997767f, 0.996413f, 0.972495f, 0.702212f, 0.657113f, 0.655356f, 0.651749f, 0.644367f, 0.629671f, 0.59674f, 0.508643f, 0.29426f},
+ {0.979327f, 0.985186f, 0.998527f, 1.00143f, 1.00178f, 1.0007f, 0.989801f, 0.725573f, 0.6682f, 0.665496f, 0.659519f, 0.647838f, 0.624135f, 0.572206f, 0.447623f, 0.243758f},
+ {0.977426f, 0.998615f, 1.00131f, 1.00132f, 1.00116f, 1.00067f, 0.997402f, 0.760523f, 0.693225f, 0.688248f, 0.677438f, 0.655999f, 0.612563f, 0.524092f, 0.365975f, 0.208373f},
+ {0.986154f, 1.00041f, 1.00041f, 1.00028f, 1.00025f, 1.00012f, 0.99966f, 0.81433f, 0.746767f, 0.734741f, 0.708517f, 0.656763f, 0.56608f, 0.434755f, 0.292263f, 0.192491f},
+ {0.997724f, 1.00002f, 1.00002f, 1.00001f, 1.0f, 1.0f, 0.999985f, 0.910766f, 0.847327f, 0.78563f, 0.697528f, 0.590867f, 0.477544f, 0.367598f, 0.265921f, 0.189085f}
+ },
+ {
+ {0.883327f, 0.823046f, 0.776506f, 0.733979f, 0.691976f, 0.649752f, 0.608825f, 0.576155f, 0.57289f, 0.573092f, 0.572784f, 0.572826f, 0.572366f, 0.572023f, 0.570457f, 0.561059f},
+ {0.899867f, 0.848583f, 0.808166f, 0.769833f, 0.730047f, 0.686601f, 0.639202f, 0.5961f, 0.591385f, 0.591372f, 0.591531f, 0.590989f, 0.590727f, 0.589719f, 0.587649f, 0.574216f},
+ {0.914702f, 0.872192f, 0.838023f, 0.804332f, 0.76784f, 0.724301f, 0.671011f, 0.614624f, 0.608101f, 0.608023f, 0.608036f, 0.607736f, 0.607255f, 0.605917f, 0.602552f, 0.583313f},
+ {0.928678f, 0.893883f, 0.865533f, 0.837081f, 0.80493f, 0.76325f, 0.704159f, 0.632201f, 0.62328f, 0.623173f, 0.623051f, 0.622691f, 0.621768f, 0.620302f, 0.61557f, 0.588069f},
+ {0.941761f, 0.913061f, 0.890285f, 0.867467f, 0.840397f, 0.802503f, 0.739201f, 0.64837f, 0.636323f, 0.63623f, 0.636018f, 0.635646f, 0.634398f, 0.632164f, 0.625594f, 0.58763f},
+ {0.953561f, 0.930088f, 0.911763f, 0.894184f, 0.873458f, 0.841109f, 0.776012f, 0.663084f, 0.647355f, 0.647067f, 0.646616f, 0.645915f, 0.64462f, 0.64136f, 0.632563f, 0.580104f},
+ {0.964211f, 0.944464f, 0.930175f, 0.917402f, 0.902854f, 0.877985f, 0.81423f, 0.676033f, 0.655247f, 0.654978f, 0.654488f, 0.653611f, 0.651794f, 0.647689f, 0.635603f, 0.564149f},
+ {0.973853f, 0.956149f, 0.944373f, 0.936734f, 0.928832f, 0.911411f, 0.853037f, 0.687418f, 0.660033f, 0.659729f, 0.659155f, 0.657991f, 0.655424f, 0.649853f, 0.633327f, 0.539656f},
+ {0.982351f, 0.964341f, 0.955586f, 0.95286f, 0.950798f, 0.941015f, 0.891335f, 0.69814f, 0.662124f, 0.661781f, 0.660878f, 0.659265f, 0.65584f, 0.648102f, 0.625612f, 0.5052f},
+ {0.988952f, 0.968325f, 0.96444f, 0.967371f, 0.968036f, 0.962705f, 0.925212f, 0.709201f, 0.662153f, 0.661613f, 0.660451f, 0.658072f, 0.653265f, 0.642637f, 0.611725f, 0.461376f},
+ {0.991959f, 0.970119f, 0.973337f, 0.979199f, 0.98447f, 0.985309f, 0.961876f, 0.728023f, 0.666309f, 0.665624f, 0.663906f, 0.660604f, 0.65375f, 0.638546f, 0.594483f, 0.412469f},
+ {0.989519f, 0.97335f, 0.985904f, 0.99545f, 0.999169f, 0.99877f, 0.98506f, 0.745811f, 0.66816f, 0.666953f, 0.664467f, 0.659379f, 0.649173f, 0.6263f, 0.561755f, 0.354944f},
+ {0.981936f, 0.986245f, 0.999204f, 1.00201f, 1.00237f, 1.00164f, 0.995568f, 0.76775f, 0.674487f, 0.672633f, 0.668485f, 0.660392f, 0.643848f, 0.607072f, 0.510117f, 0.296613f},
+ {0.978822f, 0.999025f, 1.00154f, 1.0015f, 1.00134f, 1.00093f, 0.999166f, 0.797407f, 0.694352f, 0.69094f, 0.683395f, 0.668275f, 0.63744f, 0.571235f, 0.431593f, 0.250548f},
+ {0.986614f, 1.00048f, 1.00045f, 1.00031f, 1.00028f, 1.00017f, 0.99993f, 0.840878f, 0.743025f, 0.734606f, 0.715882f, 0.678046f, 0.606931f, 0.490118f, 0.342267f, 0.227105f},
+ {0.997786f, 1.00002f, 1.00002f, 1.00001f, 1.0f, 1.0f, 0.999993f, 0.922434f, 0.849686f, 0.798615f, 0.722072f, 0.624626f, 0.515012f, 0.404997f, 0.302312f, 0.221706f}
+ },
+ {
+ {0.908777f, 0.854384f, 0.812559f, 0.774051f, 0.736146f, 0.699431f, 0.664242f, 0.63405f, 0.629809f, 0.630031f, 0.629793f, 0.629788f, 0.629543f, 0.629351f, 0.628492f, 0.621726f},
+ {0.922329f, 0.876034f, 0.839799f, 0.805637f, 0.770072f, 0.732134f, 0.691576f, 0.651315f, 0.644846f, 0.644999f, 0.645152f, 0.644587f, 0.644625f, 0.643953f, 0.642912f, 0.633059f},
+ {0.934245f, 0.895915f, 0.865258f, 0.835403f, 0.803007f, 0.76574f, 0.719893f, 0.667021f, 0.658051f, 0.657961f, 0.657993f, 0.657579f, 0.657408f, 0.656702f, 0.654529f, 0.641246f},
+ {0.945225f, 0.913804f, 0.888536f, 0.8634f, 0.835159f, 0.799765f, 0.749825f, 0.681578f, 0.668974f, 0.669052f, 0.66903f, 0.668625f, 0.6683f, 0.667226f, 0.664361f, 0.644478f},
+ {0.955719f, 0.929663f, 0.909191f, 0.888967f, 0.865438f, 0.833685f, 0.781174f, 0.694763f, 0.677719f, 0.677763f, 0.677502f, 0.677448f, 0.676727f, 0.67519f, 0.67113f, 0.642978f},
+ {0.965226f, 0.943646f, 0.926888f, 0.911003f, 0.893341f, 0.866882f, 0.813775f, 0.70664f, 0.684231f, 0.684125f, 0.683785f, 0.683343f, 0.682502f, 0.68041f, 0.67479f, 0.635121f},
+ {0.973718f, 0.955286f, 0.941803f, 0.930142f, 0.917794f, 0.898077f, 0.847817f, 0.717774f, 0.687636f, 0.687466f, 0.687157f, 0.686587f, 0.685361f, 0.682743f, 0.674868f, 0.619579f},
+ {0.981619f, 0.96454f, 0.953089f, 0.945808f, 0.939315f, 0.926109f, 0.882041f, 0.727626f, 0.687965f, 0.687738f, 0.687316f, 0.686664f, 0.684934f, 0.68118f, 0.670404f, 0.59585f},
+ {0.988563f, 0.970828f, 0.961739f, 0.95891f, 0.957574f, 0.95089f, 0.915232f, 0.73794f, 0.685755f, 0.685524f, 0.68496f, 0.683814f, 0.681587f, 0.676341f, 0.661425f, 0.562842f},
+ {0.993927f, 0.973118f, 0.96846f, 0.971f, 0.972021f, 0.968701f, 0.943292f, 0.748986f, 0.681809f, 0.681423f, 0.680556f, 0.679091f, 0.675801f, 0.668686f, 0.647866f, 0.521485f},
+ {0.995891f, 0.973316f, 0.975657f, 0.981135f, 0.98663f, 0.98869f, 0.974103f, 0.768672f, 0.682094f, 0.681626f, 0.680575f, 0.678309f, 0.67367f, 0.663332f, 0.633382f, 0.474851f},
+ {0.992571f, 0.975232f, 0.987073f, 0.996472f, 1.00028f, 1.00045f, 0.991904f, 0.785766f, 0.67977f, 0.678969f, 0.677275f, 0.673797f, 0.666775f, 0.651266f, 0.606504f, 0.41762f},
+ {0.984047f, 0.987106f, 0.999766f, 1.00247f, 1.00283f, 1.0023f, 0.998521f, 0.804636f, 0.68154f, 0.680271f, 0.677421f, 0.671838f, 0.660441f, 0.635024f, 0.564735f, 0.354542f},
+ {0.979943f, 0.999351f, 1.00173f, 1.00163f, 1.00148f, 1.00114f, 1.00004f, 0.828857f, 0.696212f, 0.693853f, 0.68862f, 0.678021f, 0.656535f, 0.609464f, 0.495948f, 0.297586f},
+ {0.986983f, 1.00054f, 1.00048f, 1.00033f, 1.0003f, 1.0002f, 1.00005f, 0.863552f, 0.739261f, 0.733375f, 0.720073f, 0.692985f, 0.639816f, 0.542789f, 0.397024f, 0.263567f},
+ {0.997835f, 1.00002f, 1.00002f, 1.00001f, 1.0f, 1.0f, 0.999998f, 0.93191f, 0.849138f, 0.807179f, 0.74174f, 0.654896f, 0.551606f, 0.442358f, 0.338392f, 0.254625f}
+ }
+};
+
+static const float table_clearcoat_E[16][16] = {
+ {0.0957937f, 0.107269f, 0.124314f, 0.145841f, 0.171902f, 0.202507f, 0.237239f, 0.274857f, 0.313117f, 0.348864f, 0.378594f, 0.399369f, 0.409696f, 0.409948f, 0.401807f, 0.387712f},
+ {0.103913f, 0.118336f, 0.138516f, 0.163634f, 0.193917f, 0.229433f, 0.269794f, 0.313709f, 0.358702f, 0.40124f, 0.437384f, 0.463666f, 0.478306f, 0.481542f, 0.475314f, 0.462174f},
+ {0.114001f, 0.131792f, 0.155509f, 0.184656f, 0.219564f, 0.260417f, 0.30679f, 0.357311f, 0.409259f, 0.458766f, 0.501395f, 0.533305f, 0.552494f, 0.559133f, 0.55525f, 0.543762f},
+ {0.126718f, 0.148352f, 0.17616f, 0.209868f, 0.24991f, 0.296499f, 0.349183f, 0.406439f, 0.465305f, 0.521516f, 0.570303f, 0.607454f, 0.630828f, 0.640633f, 0.639167f, 0.629563f},
+ {0.142942f, 0.169096f, 0.201677f, 0.240591f, 0.28632f, 0.339067f, 0.398261f, 0.462106f, 0.527417f, 0.589522f, 0.643291f, 0.684462f, 0.710811f, 0.722861f, 0.72308f, 0.715033f},
+ {0.163824f, 0.195379f, 0.233628f, 0.278595f, 0.330697f, 0.390005f, 0.455709f, 0.525685f, 0.596293f, 0.662552f, 0.719195f, 0.762062f, 0.789222f, 0.801605f, 0.802171f, 0.794678f},
+ {0.190934f, 0.22908f, 0.274143f, 0.326182f, 0.385488f, 0.451664f, 0.523495f, 0.598289f, 0.671959f, 0.739469f, 0.795561f, 0.836672f, 0.86164f, 0.872011f, 0.871178f, 0.863261f},
+ {0.226325f, 0.272583f, 0.325986f, 0.38642f, 0.453616f, 0.526553f, 0.603038f, 0.679948f, 0.75296f, 0.81709f, 0.868099f, 0.903421f, 0.923006f, 0.929287f, 0.925963f, 0.917004f},
+ {0.272522f, 0.328901f, 0.392562f, 0.462815f, 0.538096f, 0.61602f, 0.69377f, 0.767744f, 0.834187f, 0.889376f, 0.930485f, 0.95656f, 0.968832f, 0.970247f, 0.964471f, 0.954985f},
+ {0.332556f, 0.401548f, 0.477887f, 0.55866f, 0.639798f, 0.717851f, 0.789919f, 0.853651f, 0.906877f, 0.947986f, 0.976068f, 0.991628f, 0.996712f, 0.994261f, 0.987344f, 0.978504f},
+ {0.409615f, 0.494384f, 0.585635f, 0.674102f, 0.753563f, 0.82181f, 0.878802f, 0.925017f, 0.960756f, 0.986191f, 1.0019f, 1.00903f, 1.00942f, 1.00538f, 0.99908f, 0.992107f},
+ {0.506354f, 0.611394f, 0.715256f, 0.799046f, 0.86226f, 0.909737f, 0.945706f, 0.97248f, 0.99164f, 1.00413f, 1.01079f, 1.01265f, 1.01105f, 1.00732f, 1.00272f, 0.998148f},
+ {0.623822f, 0.753034f, 0.849494f, 0.907052f, 0.942889f, 0.966663f, 0.983133f, 0.994624f, 1.00237f, 1.00692f, 1.00888f, 1.00874f, 1.00721f, 1.00488f, 1.00236f, 0.999994f},
+ {0.762026f, 0.895731f, 0.949127f, 0.971914f, 0.984199f, 0.991853f, 0.996957f, 1.00045f, 1.00264f, 1.00378f, 1.0041f, 1.00375f, 1.00303f, 1.00205f, 1.00108f, 1.00021f},
+ {0.905247f, 0.980365f, 0.991431f, 0.995528f, 0.997658f, 0.999011f, 0.999864f, 1.00045f, 1.00079f, 1.00093f, 1.00094f, 1.00083f, 1.00064f, 1.00045f, 1.00025f, 1.00006f},
+ {0.989008f, 0.999275f, 0.999681f, 0.999839f, 0.999929f, 0.99998f, 1.00001f, 1.00003f, 1.00004f, 1.00005f, 1.00005f, 1.00004f, 1.00003f, 1.00002f, 1.00002f, 1.0f}
+};
diff --git a/intern/cycles/scene/shader_graph.cpp b/intern/cycles/scene/shader_graph.cpp
index ef3f142ed4e..99c34f5b5ac 100644
--- a/intern/cycles/scene/shader_graph.cpp
+++ b/intern/cycles/scene/shader_graph.cpp
@@ -1129,10 +1129,8 @@ int ShaderGraph::get_num_closures()
else if (CLOSURE_IS_GLASS(closure_type)) {
num_closures += 2;
}
- else if (CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
- num_closures += 2;
- }
else if (CLOSURE_IS_PRINCIPLED(closure_type)) {
+ /* TODO adjust */
num_closures += 8;
}
else if (CLOSURE_IS_VOLUME(closure_type)) {
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index a9cd453947b..1a83737c738 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -2726,7 +2726,8 @@ NODE_DEFINE(PrincipledBsdfNode)
static NodeEnum distribution_enum;
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+ distribution_enum.insert("Principled v2", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
SOCKET_ENUM(
distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
@@ -2743,7 +2744,9 @@ NODE_DEFINE(PrincipledBsdfNode)
SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
+ SOCKET_IN_COLOR(metallic_edge, "Metallic Edge", make_float3(1.0f, 1.0f, 1.0f));
SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
+ SOCKET_IN_FLOAT(subsurface_scale, "Subsurface Scale", 0.0f);
SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
SOCKET_IN_FLOAT(subsurface_ior, "Subsurface IOR", 1.4f);
SOCKET_IN_FLOAT(subsurface_anisotropy, "Subsurface Anisotropy", 0.0f);
@@ -2753,8 +2756,10 @@ NODE_DEFINE(PrincipledBsdfNode)
SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
+ SOCKET_IN_FLOAT(sheen_roughness, "Sheen Roughness", 0.5f);
SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
+ SOCKET_IN_COLOR(clearcoat_tint, "Clearcoat Tint", make_float3(1.0f, 1.0f, 1.0f));
SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f);
@@ -2781,6 +2786,8 @@ PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(get_node_type())
void PrincipledBsdfNode::expand(ShaderGraph *graph)
{
+ /* TODO: Disconnect unused depending on model */
+
ShaderOutput *principled_out = output("BSDF");
ShaderInput *emission_in = input("Emission");
@@ -2852,98 +2859,96 @@ void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attribu
ShaderNode::attributes(shader, attributes);
}
-void PrincipledBsdfNode::compile(SVMCompiler &compiler,
- ShaderInput *p_metallic,
- ShaderInput *p_subsurface,
- ShaderInput *p_subsurface_radius,
- ShaderInput *p_subsurface_ior,
- ShaderInput *p_subsurface_anisotropy,
- ShaderInput *p_specular,
- ShaderInput *p_roughness,
- ShaderInput *p_specular_tint,
- ShaderInput *p_anisotropic,
- ShaderInput *p_sheen,
- ShaderInput *p_sheen_tint,
- ShaderInput *p_clearcoat,
- ShaderInput *p_clearcoat_roughness,
- ShaderInput *p_ior,
- ShaderInput *p_transmission,
- ShaderInput *p_anisotropic_rotation,
- ShaderInput *p_transmission_roughness)
-{
- ShaderInput *base_color_in = input("Base Color");
- ShaderInput *subsurface_color_in = input("Subsurface Color");
- ShaderInput *normal_in = input("Normal");
- ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
- ShaderInput *tangent_in = input("Tangent");
-
- float3 weight = one_float3();
-
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
-
- int normal_offset = compiler.stack_assign_if_linked(normal_in);
- int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
- int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
- int specular_offset = compiler.stack_assign(p_specular);
- int roughness_offset = compiler.stack_assign(p_roughness);
- int specular_tint_offset = compiler.stack_assign(p_specular_tint);
- int anisotropic_offset = compiler.stack_assign(p_anisotropic);
- int sheen_offset = compiler.stack_assign(p_sheen);
- int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
- int clearcoat_offset = compiler.stack_assign(p_clearcoat);
- int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
- int ior_offset = compiler.stack_assign(p_ior);
- int transmission_offset = compiler.stack_assign(p_transmission);
- int transmission_roughness_offset = compiler.stack_assign(p_transmission_roughness);
- int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
- int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
- int subsurface_ior_offset = compiler.stack_assign(p_subsurface_ior);
- int subsurface_anisotropy_offset = compiler.stack_assign(p_subsurface_anisotropy);
-
- compiler.add_node(NODE_CLOSURE_BSDF,
- compiler.encode_uchar4(closure,
- compiler.stack_assign(p_metallic),
- compiler.stack_assign(p_subsurface),
- compiler.closure_mix_weight_offset()),
- __float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
- __float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
-
- compiler.add_node(
- normal_offset,
- tangent_offset,
- compiler.encode_uchar4(
- specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
- compiler.encode_uchar4(
- sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
-
- compiler.add_node(compiler.encode_uchar4(ior_offset,
- transmission_offset,
- anisotropic_rotation_offset,
- transmission_roughness_offset),
- distribution,
- subsurface_method,
- SVM_STACK_INVALID);
-
- float3 bc_default = get_float3(base_color_in->socket_type);
-
- compiler.add_node(
- ((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
- __float_as_int(bc_default.x),
- __float_as_int(bc_default.y),
- __float_as_int(bc_default.z));
-
- compiler.add_node(clearcoat_normal_offset,
- subsurface_radius_offset,
- subsurface_ior_offset,
- subsurface_anisotropy_offset);
+void PrincipledBsdfNode::compile(SVMCompiler &compiler)
+{
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, one_float3());
- float3 ss_default = get_float3(subsurface_color_in->socket_type);
+ if (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) {
+ compile_v2(compiler);
+ }
+ else {
+ compile_v1(compiler);
+ }
+}
+
+void PrincipledBsdfNode::compile_v1(SVMCompiler &compiler)
+{
+ /* TODO skip generation of stack entries (normal, tangent, default vals.) if possible */
+ /* If we ever have more than 255 closures, the packing here needs to change. */
+ static_assert(NBUILTIN_CLOSURES < SVM_STACK_SIZE);
+
+ uint base_1 = compiler.encode_uchar4(closure,
+ compiler.stack_assign(input("Base Color")),
+ compiler.stack_assign_if_linked(input("Normal")),
+ compiler.closure_mix_weight_offset());
+ uint base_2 = compiler.encode_uchar4(compiler.stack_assign(input("Roughness")),
+ compiler.stack_assign(input("Metallic")),
+ compiler.stack_assign(input("Transmission")),
+ compiler.stack_assign(input("Specular Tint")));
+ uint sss_1 = compiler.encode_uchar4(subsurface_method,
+ compiler.stack_assign(input("Subsurface")),
+ compiler.stack_assign(input("Subsurface Anisotropy")),
+ compiler.stack_assign(input("Subsurface Radius")));
+ uint sss_2 = compiler.encode_uchar4(compiler.stack_assign(input("Subsurface Color")),
+ compiler.stack_assign(input("Subsurface IOR")),
+ SVM_STACK_INVALID,
+ distribution);
+ uint specular = compiler.encode_uchar4(compiler.stack_assign(input("Specular")),
+ compiler.stack_assign(input("Anisotropic")),
+ compiler.stack_assign(input("Anisotropic Rotation")),
+ compiler.stack_assign_if_linked(input("Tangent")));
+ uint sheen_glass = compiler.encode_uchar4(
+ compiler.stack_assign(input("IOR")),
+ compiler.stack_assign(input("Sheen")),
+ compiler.stack_assign(input("Sheen Tint")),
+ compiler.stack_assign(input("Transmission Roughness")));
+ uint clearcoat = compiler.encode_uchar4(
+ compiler.stack_assign(input("Clearcoat")),
+ compiler.stack_assign(input("Clearcoat Roughness")),
+ compiler.stack_assign_if_linked(input("Clearcoat Normal")),
+ SVM_STACK_INVALID);
- compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) :
- SVM_STACK_INVALID),
- __float_as_int(ss_default.x),
- __float_as_int(ss_default.y),
- __float_as_int(ss_default.z));
+ compiler.add_node(NODE_CLOSURE_BSDF, base_1, base_2, sss_1);
+ compiler.add_node(sss_2, specular, sheen_glass, clearcoat);
+}
+
+void PrincipledBsdfNode::compile_v2(SVMCompiler &compiler)
+{
+ /* If we ever have more than 255 closures, the packing here needs to change. */
+ static_assert(NBUILTIN_CLOSURES < SVM_STACK_SIZE);
+
+ uint base_1 = compiler.encode_uchar4(closure,
+ compiler.stack_assign(input("Base Color")),
+ compiler.stack_assign_if_linked(input("Normal")),
+ compiler.closure_mix_weight_offset());
+ uint base_2 = compiler.encode_uchar4(compiler.stack_assign(input("Roughness")),
+ compiler.stack_assign(input("Metallic")),
+ compiler.stack_assign(input("IOR")),
+ compiler.stack_assign(input("Transmission")));
+ uint sss = compiler.encode_uchar4(compiler.stack_assign(input("Subsurface Scale")),
+ compiler.stack_assign(input("Subsurface Anisotropy")),
+ compiler.stack_assign(input("Subsurface Radius")),
+ subsurface_method);
+ uint metallic = compiler.encode_uchar4(SVM_STACK_INVALID,
+ compiler.stack_assign(input("Metallic Edge")),
+ SVM_STACK_INVALID,
+ distribution);
+ uint specular = compiler.encode_uchar4(compiler.stack_assign(input("Anisotropic")),
+ compiler.stack_assign(input("Anisotropic Rotation")),
+ compiler.stack_assign_if_linked(input("Tangent")),
+ SVM_STACK_INVALID);
+ uint sheen = compiler.encode_uchar4(compiler.stack_assign(input("IOR")),
+ compiler.stack_assign(input("Sheen")),
+ compiler.stack_assign(input("Sheen Tint")),
+ compiler.stack_assign(input("Sheen Roughness")));
+ uint clearcoat = compiler.encode_uchar4(
+ compiler.stack_assign(input("Clearcoat")),
+ compiler.stack_assign(input("Clearcoat Roughness")),
+ compiler.stack_assign(input("Clearcoat Tint")),
+ compiler.stack_assign_if_linked(input("Clearcoat Normal")));
+
+ compiler.add_node(NODE_CLOSURE_BSDF, base_1, base_2, sss);
+ compiler.add_node(metallic, specular, sheen, clearcoat);
}
bool PrincipledBsdfNode::has_integrator_dependency()
@@ -2952,28 +2957,6 @@ bool PrincipledBsdfNode::has_integrator_dependency()
return !roughness_input->link && roughness <= 1e-4f;
}
-void PrincipledBsdfNode::compile(SVMCompiler &compiler)
-{
- compile(compiler,
- input("Metallic"),
- input("Subsurface"),
- input("Subsurface Radius"),
- input("Subsurface IOR"),
- input("Subsurface Anisotropy"),
- input("Specular"),
- input("Roughness"),
- input("Specular Tint"),
- input("Anisotropic"),
- input("Sheen"),
- input("Sheen Tint"),
- input("Clearcoat"),
- input("Clearcoat Roughness"),
- input("IOR"),
- input("Transmission"),
- input("Anisotropic Rotation"),
- input("Transmission Roughness"));
-}
-
void PrincipledBsdfNode::compile(OSLCompiler &compiler)
{
compiler.parameter(this, "distribution");
diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h
index cc3a71a0697..d0982980877 100644
--- a/intern/cycles/scene/shader_nodes.h
+++ b/intern/cycles/scene/shader_nodes.h
@@ -529,24 +529,6 @@ class PrincipledBsdfNode : public BsdfBaseNode {
void expand(ShaderGraph *graph);
bool has_surface_bssrdf();
bool has_bssrdf_bump();
- void compile(SVMCompiler &compiler,
- ShaderInput *metallic,
- ShaderInput *subsurface,
- ShaderInput *subsurface_radius,
- ShaderInput *subsurface_ior,
- ShaderInput *subsurface_anisotropy,
- ShaderInput *specular,
- ShaderInput *roughness,
- ShaderInput *specular_tint,
- ShaderInput *anisotropic,
- ShaderInput *sheen,
- ShaderInput *sheen_tint,
- ShaderInput *clearcoat,
- ShaderInput *clearcoat_roughness,
- ShaderInput *ior,
- ShaderInput *transmission,
- ShaderInput *anisotropic_rotation,
- ShaderInput *transmission_roughness);
NODE_SOCKET_API(float3, base_color)
NODE_SOCKET_API(float3, subsurface_color)
@@ -554,15 +536,19 @@ class PrincipledBsdfNode : public BsdfBaseNode {
NODE_SOCKET_API(float, subsurface_ior)
NODE_SOCKET_API(float, subsurface_anisotropy)
NODE_SOCKET_API(float, metallic)
+ NODE_SOCKET_API(float3, metallic_edge)
NODE_SOCKET_API(float, subsurface)
+ NODE_SOCKET_API(float, subsurface_scale)
NODE_SOCKET_API(float, specular)
NODE_SOCKET_API(float, roughness)
NODE_SOCKET_API(float, specular_tint)
NODE_SOCKET_API(float, anisotropic)
NODE_SOCKET_API(float, sheen)
NODE_SOCKET_API(float, sheen_tint)
+ NODE_SOCKET_API(float, sheen_roughness)
NODE_SOCKET_API(float, clearcoat)
NODE_SOCKET_API(float, clearcoat_roughness)
+ NODE_SOCKET_API(float3, clearcoat_tint)
NODE_SOCKET_API(float, ior)
NODE_SOCKET_API(float, transmission)
NODE_SOCKET_API(float, anisotropic_rotation)
@@ -580,6 +566,9 @@ class PrincipledBsdfNode : public BsdfBaseNode {
private:
ClosureType distribution_orig;
+ void compile_v1(SVMCompiler &compiler);
+ void compile_v2(SVMCompiler &compiler);
+
public:
bool has_integrator_dependency();
void attributes(Shader *shader, AttributeRequestSet *attributes);
diff --git a/intern/cycles/util/math_float2.h b/intern/cycles/util/math_float2.h
index 542dad93467..4070314d520 100644
--- a/intern/cycles/util/math_float2.h
+++ b/intern/cycles/util/math_float2.h
@@ -41,6 +41,7 @@ ccl_device_inline float distance(const float2 &a, const float2 &b);
ccl_device_inline float dot(const float2 &a, const float2 &b);
ccl_device_inline float cross(const float2 &a, const float2 &b);
ccl_device_inline float len(const float2 a);
+ccl_device_inline float len_squared(const float2 a);
ccl_device_inline float2 normalize(const float2 &a);
ccl_device_inline float2 normalize_len(const float2 &a, float *t);
ccl_device_inline float2 safe_normalize(const float2 &a);
@@ -251,6 +252,11 @@ ccl_device_inline float len(const float2 a)
return sqrtf(dot(a, a));
}
+ccl_device_inline float len_squared(const float2 a)
+{
+ return dot(a, a);
+}
+
ccl_device_inline float2 safe_divide_float2_float(const float2 a, const float b)
{
return (b != 0.0f) ? a / b : zero_float2();
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 1a8fec49516..f3dd0ca9a46 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1870,7 +1870,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
STREQ(node->idname, "ShaderNodeEeveeMetallic")) {
node->type = SH_NODE_BSDF_PRINCIPLED;
BLI_strncpy(node->idname, "ShaderNodeBsdfPrincipled", sizeof(node->idname));
- node->custom1 = SHD_GLOSSY_MULTI_GGX;
+ node->custom1 = SHD_PRINCIPLED_MULTI_GGX;
error |= NTREE_DOVERSION_TRANSPARENCY_EMISSION;
}
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
index 0833809cc42..bc5c20b2a4a 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -15,11 +15,13 @@ float principled_sheen(float NV)
void node_bsdf_principled(vec4 base_color,
float subsurface,
+ float subsurface_scale, // todo
vec3 subsurface_radius,
vec4 subsurface_color,
float subsurface_ior,
float subsurface_anisotropy,
float metallic,
+ vec4 metallic_edge, // todo
float specular,
float specular_tint,
float roughness,
@@ -27,8 +29,10 @@ void node_bsdf_principled(vec4 base_color,
float anisotropic_rotation,
float sheen,
float sheen_tint,
+ float sheen_roughness, // todo
float clearcoat,
float clearcoat_roughness,
+ vec4 clearcoat_tint, // todo
float ior,
float transmission,
float transmission_roughness,
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index c7962db8198..bf2c9b2eb61 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1669,6 +1669,12 @@ typedef struct NodeShaderMix {
#define SHD_GLOSSY_ASHIKHMIN_SHIRLEY 3
#define SHD_GLOSSY_MULTI_GGX 4
+/* principled bsdf mode
+ * Note: GGX and MULTI_GGX must align with SHD_GLOSSY for backwards compatibility */
+#define SHD_PRINCIPLED_V2 0 /* TODO: Better name */
+#define SHD_PRINCIPLED_GGX 2
+#define SHD_PRINCIPLED_MULTI_GGX 4
+
/* vector transform */
#define SHD_VECT_TRANSFORM_TYPE_VECTOR 0
#define SHD_VECT_TRANSFORM_TYPE_POINT 1
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 865399df9ef..9ae6b25360a 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -4665,13 +4665,9 @@ static EnumPropertyItem node_ies_mode_items[] = {
};
static const EnumPropertyItem node_principled_distribution_items[] = {
- {SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
- {SHD_GLOSSY_MULTI_GGX,
- "MULTI_GGX",
- 0,
- "Multiscatter GGX",
- "Slower than GGX but gives a more energy conserving results, which would otherwise be "
- "visible as excessive darkening"},
+ {SHD_PRINCIPLED_GGX, "GGX", 0, "GGX", ""},
+ {SHD_PRINCIPLED_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""},
+ {SHD_PRINCIPLED_V2, "V2", 0, "Principled v2", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc
index adf2a9e8a19..468527c57a0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc
@@ -10,12 +10,15 @@ namespace blender::nodes::node_shader_bsdf_principled_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
+ /* TODO: Tooltips depending on old/new model. */
b.add_input<decl::Color>(N_("Base Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f});
b.add_input<decl::Float>(N_("Subsurface"))
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
+ /* TODO: Somehow merge with "Subsurface". Needs different subtype though... */
+ b.add_input<decl::Float>(N_("Subsurface Scale")).default_value(0.0f).min(0.0f).max(100.0f);
b.add_input<decl::Vector>(N_("Subsurface Radius"))
.default_value({1.0f, 0.2f, 0.1f})
.min(0.0f)
@@ -37,11 +40,15 @@ static void node_declare(NodeDeclarationBuilder &b)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
+ /* TODO: Also add support to Principled v1? Would be compatible at defaults afaics. */
+ b.add_input<decl::Color>(N_("Metallic Edge")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
b.add_input<decl::Float>(N_("Specular"))
.default_value(0.5f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
+ /* TODO: Should be a color input in v2. Any way to keep compatibility?
+ * Maybe change to color everywhere and detect special case when float is connected? */
b.add_input<decl::Float>(N_("Specular Tint"))
.default_value(0.0f)
.min(0.0f)
@@ -67,11 +74,18 @@ static void node_declare(NodeDeclarationBuilder &b)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
+ /* TODO: Should be a color input in v2. Any way to keep compatibility?
+ * Maybe change to color everywhere and detect special case when float is connected? */
b.add_input<decl::Float>(N_("Sheen Tint"))
.default_value(0.5f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
+ b.add_input<decl::Float>(N_("Sheen Roughness"))
+ .default_value(0.5f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Clearcoat"))
.default_value(0.0f)
.min(0.0f)
@@ -82,6 +96,9 @@ static void node_declare(NodeDeclarationBuilder &b)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
+ /* TODO: Also add support to Principled v1? Would remain compatible and reduce differences. */
+ b.add_input<decl::Color>(N_("Clearcoat Tint")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ /* TODO: Restrict min/max (e.g. 0.1 to 10) */
b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f);
b.add_input<decl::Float>(N_("Transmission"))
.default_value(0.0f)
@@ -93,6 +110,7 @@ static void node_declare(NodeDeclarationBuilder &b)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
+ /* TODO: Swap defaults (white, strength 0)? */
b.add_input<decl::Color>(N_("Emission")).default_value({0.0f, 0.0f, 0.0f, 1.0f});
b.add_input<decl::Float>(N_("Emission Strength")).default_value(1.0).min(0.0f).max(1000000.0f);
b.add_input<decl::Float>(N_("Alpha"))
@@ -115,7 +133,7 @@ static void node_shader_buts_principled(uiLayout *layout, bContext * /*C*/, Poin
static void node_shader_init_principled(bNodeTree * /*ntree*/, bNode *node)
{
- node->custom1 = SHD_GLOSSY_GGX;
+ node->custom1 = SHD_PRINCIPLED_V2;
node->custom2 = SHD_SUBSURFACE_RANDOM_WALK;
}
@@ -196,7 +214,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
use_subsurf = GPU_material_sss_profile_create(mat, &socket_data->value[1]);
}
- float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f;
+ float use_multi_scatter = (node->custom1 != SHD_PRINCIPLED_GGX) ? 1.0f : 0.0f;
float use_sss = (use_subsurf) ? 1.0f : 0.0f;
float use_diffuse_f = (use_diffuse) ? 1.0f : 0.0f;
float use_clear_f = (use_clear) ? 1.0f : 0.0f;
@@ -222,12 +240,40 @@ static void node_shader_update_principled(bNodeTree *ntree, bNode *node)
const int sss_method = node->custom2;
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+ const bool is_v2 = (distribution == SHD_PRINCIPLED_V2);
if (STREQ(sock->name, "Transmission Roughness")) {
- nodeSetSocketAvailability(ntree, sock, distribution == SHD_GLOSSY_GGX);
+ /* Only supported by the old separable glass model. */
+ nodeSetSocketAvailability(ntree, sock, distribution == SHD_PRINCIPLED_GGX);
+ }
+
+ if (STR_ELEM(sock->name, "Subsurface Anisotropy")) {
+ /* Only available with random-walk SSS.
+ * Principled v2 always uses random-walk SSS, so enable regardless of sss_method there. */
+ nodeSetSocketAvailability(ntree, sock, is_v2 || (sss_method != SHD_SUBSURFACE_BURLEY));
+ }
+
+ if (STR_ELEM(sock->name, "Subsurface IOR")) {
+ /* Only available with random-walk SSS. Principled v2 uses the regular IOR input, however. */
+ nodeSetSocketAvailability(ntree, sock, !is_v2 && (sss_method != SHD_SUBSURFACE_BURLEY));
+ }
+
+ if (STR_ELEM(sock->name,
+ "Subsurface",
+ "Subsurface Color",
+ "Specular",
+ "Specular Tint",
+ "Sheen Tint")) {
+ /* Sockets exclusive to Principled v1. */
+ nodeSetSocketAvailability(ntree, sock, !is_v2);
}
- if (STR_ELEM(sock->name, "Subsurface IOR", "Subsurface Anisotropy")) {
- nodeSetSocketAvailability(ntree, sock, sss_method != SHD_SUBSURFACE_BURLEY);
+ if (STR_ELEM(sock->name,
+ "Subsurface Scale",
+ "Clearcoat Tint",
+ "Sheen Roughness",
+ "Metallic Edge")) {
+ /* Sockets exclusive to Principled v2. */
+ nodeSetSocketAvailability(ntree, sock, is_v2);
}
}
}