Merge branch 'master' into blender2.8
Conflicts: source/blender/blenkernel/intern/pointcache.c source/blender/makesrna/intern/rna_main_api.c source/blender/makesrna/intern/rna_particle.c
This commit is contained in:
@@ -801,7 +801,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
|
||||
}
|
||||
|
||||
/* free derived mesh */
|
||||
b_data.meshes.remove(b_mesh);
|
||||
b_data.meshes.remove(b_mesh, false);
|
||||
}
|
||||
}
|
||||
mesh->geometry_flags = requested_geometry_flags;
|
||||
@@ -1013,7 +1013,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
|
||||
sync_curves(mesh, b_mesh, b_ob, true, time_index);
|
||||
|
||||
/* free derived mesh */
|
||||
b_data.meshes.remove(b_mesh);
|
||||
b_data.meshes.remove(b_mesh, false);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -393,6 +393,9 @@ static ShaderNode *add_node(Scene *scene,
|
||||
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
|
||||
aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
|
||||
break;
|
||||
@@ -439,6 +442,9 @@ static ShaderNode *add_node(Scene *scene,
|
||||
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
|
||||
glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX:
|
||||
glossy->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
break;
|
||||
}
|
||||
node = glossy;
|
||||
}
|
||||
@@ -455,6 +461,9 @@ static ShaderNode *add_node(Scene *scene,
|
||||
case BL::ShaderNodeBsdfGlass::distribution_GGX:
|
||||
glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfGlass::distribution_MULTI_GGX:
|
||||
glass->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
break;
|
||||
}
|
||||
node = glass;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ ustring SocketType::type_name(Type type)
|
||||
ustring("boolean"),
|
||||
ustring("float"),
|
||||
ustring("int"),
|
||||
ustring("uint"),
|
||||
ustring("color"),
|
||||
ustring("vector"),
|
||||
ustring("point"),
|
||||
|
||||
@@ -76,6 +76,8 @@ set(SRC_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_oren_nayar.h
|
||||
closure/bsdf_phong_ramp.h
|
||||
closure/bsdf_reflection.h
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "../closure/bsdf_phong_ramp.h"
|
||||
#include "../closure/bsdf_diffuse_ramp.h"
|
||||
#include "../closure/bsdf_microfacet.h"
|
||||
#include "../closure/bsdf_microfacet_multi.h"
|
||||
#include "../closure/bsdf_reflection.h"
|
||||
#include "../closure/bsdf_refraction.h"
|
||||
#include "../closure/bsdf_transparent.h"
|
||||
@@ -35,7 +36,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
|
||||
ccl_device int bsdf_sample(KernelGlobals *kg, ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
|
||||
{
|
||||
int label;
|
||||
|
||||
@@ -85,6 +86,14 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
|
||||
label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
label = bsdf_microfacet_multi_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
|
||||
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
@@ -130,7 +139,7 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
|
||||
return label;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
|
||||
ccl_device float3 bsdf_eval(KernelGlobals *kg, ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
|
||||
{
|
||||
float3 eval;
|
||||
|
||||
@@ -172,6 +181,12 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
@@ -234,6 +249,12 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
@@ -286,6 +307,10 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
|
||||
|
||||
#ifdef __SVM__
|
||||
switch(sc->type) {
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
bsdf_microfacet_multi_ggx_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
|
||||
476
intern/cycles/kernel/closure/bsdf_microfacet_multi.h
Normal file
476
intern/cycles/kernel/closure/bsdf_microfacet_multi.h
Normal file
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright 2011-2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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_inline 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_inline 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_inline float2 mf_sampleP22_11(const float cosI, const float2 randU)
|
||||
{
|
||||
if(cosI > 0.9999f) {
|
||||
const float r = sqrtf(randU.x / (1.0f - randU.x));
|
||||
const float phi = M_2PI_F * randU.y;
|
||||
return make_float2(r*cosf(phi), r*sinf(phi));
|
||||
}
|
||||
|
||||
const float sinI = 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*randU.x*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(randU.y >= 0.5f)
|
||||
U2 = 2.0f*(randU.y - 0.5f);
|
||||
else
|
||||
U2 = 2.0f*(0.5f - randU.y);
|
||||
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(randU.y >= 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_inline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float2 randU)
|
||||
{
|
||||
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, randU);
|
||||
|
||||
const float2 cossin_phi = normalize(make_float2(wi_11.x, wi_11.y));
|
||||
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, Diffuse and Glass === */
|
||||
|
||||
/* Phase function for reflective materials, either without a fresnel term (for compatibility) or with the conductive fresnel term. */
|
||||
ccl_device_inline float3 mf_sample_phase_glossy(const float3 wi, float3 *n, float3 *k, float3 *weight, const float3 wm)
|
||||
{
|
||||
if(n && k)
|
||||
*weight *= fresnel_conductor(dot(wi, wm), *n, *k);
|
||||
|
||||
return -wi + 2.0f * wm * dot(wi, wm);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha, float3 *n, float3 *k)
|
||||
{
|
||||
if(w.z > 0.9999f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
const float3 wh = normalize(wo - w);
|
||||
if(wh.z < 0.0f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
|
||||
|
||||
const float dotW_WH = dot(-w, wh);
|
||||
if(dotW_WH < 0.0f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float phase = max(0.0f, dotW_WH) * 0.25f / (pArea * dotW_WH);
|
||||
if(alpha.x == alpha.y)
|
||||
phase *= D_ggx(wh, alpha.x);
|
||||
else
|
||||
phase *= D_ggx_aniso(wh, alpha);
|
||||
|
||||
if(n && k) {
|
||||
/* Apply conductive fresnel term. */
|
||||
return phase * fresnel_conductor(dotW_WH, *n, *k);
|
||||
}
|
||||
|
||||
return make_float3(phase, phase, phase);
|
||||
}
|
||||
|
||||
/* Phase function for rough lambertian diffuse surfaces. */
|
||||
ccl_device_inline float3 mf_sample_phase_diffuse(const float3 wm, const float randu, const float randv)
|
||||
{
|
||||
float3 tm, bm;
|
||||
make_orthonormals(wm, &tm, &bm);
|
||||
|
||||
float2 disk = concentric_sample_disk(randu, randv);
|
||||
return disk.x*tm + disk.y*bm + safe_sqrtf(1.0f - disk.x*disk.x - disk.y*disk.y)*wm;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 mf_eval_phase_diffuse(const float3 w, const float3 wm)
|
||||
{
|
||||
const float v = max(0.0f, dot(w, wm)) * M_1_PI_F;
|
||||
return make_float3(v, v, v);
|
||||
}
|
||||
|
||||
/* Phase function for dielectric transmissive materials, including both reflection and refraction according to the dielectric fresnel term. */
|
||||
ccl_device_inline float3 mf_sample_phase_glass(const float3 wi, const float eta, const float3 wm, const float randV, 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_inline float3 mf_eval_phase_glass(const float3 w, const float lambda, const float3 wo, const bool wo_outside, const float2 alpha, const float eta)
|
||||
{
|
||||
if(w.z > 0.9999f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
|
||||
float v;
|
||||
if(wo_outside) {
|
||||
const float3 wh = normalize(wo - w);
|
||||
if(wh.z < 0.0f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
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 make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float temp = dotW_WH + eta*dotWO_WH;
|
||||
v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) * D_ggx(wh, alpha.x) / (pArea * temp * temp);
|
||||
}
|
||||
|
||||
return make_float3(v, v, v);
|
||||
}
|
||||
|
||||
/* === Utility functions for the random walks === */
|
||||
|
||||
/* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
|
||||
ccl_device_inline float mf_lambda(const float3 w, const float2 alpha)
|
||||
{
|
||||
if(w.z > 0.9999f)
|
||||
return 0.0f;
|
||||
else if(w.z < -0.9999f)
|
||||
return -1.0f;
|
||||
|
||||
const float inv_wz2 = 1.0f / (w.z*w.z);
|
||||
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_inline float mf_invC1(const float h)
|
||||
{
|
||||
return 2.0f * saturate(h) - 1.0f;
|
||||
}
|
||||
|
||||
ccl_device_inline float mf_C1(const float h)
|
||||
{
|
||||
return saturate(0.5f * (h + 1.0f));
|
||||
}
|
||||
|
||||
/* Masking function (based on page 16 of the supplemental implementation). */
|
||||
ccl_device_inline 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_inline bool mf_sample_height(const float3 w, float *h, float *C1, float *G1, 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_inline 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 saturate(albedo);
|
||||
}
|
||||
|
||||
ccl_device_inline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
|
||||
{
|
||||
return 0.25f * D_ggx(normalize(wi+wo), alpha) / ((1.0f + mf_lambda(wi, make_float2(alpha, alpha))) * wi.z) + (1.0f - mf_ggx_albedo(alpha)) * wo.z;
|
||||
}
|
||||
|
||||
ccl_device_inline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
|
||||
{
|
||||
return 0.25f * D_ggx_aniso(normalize(wi+wo), alpha) / ((1.0f + mf_lambda(wi, alpha)) * wi.z) + (1.0f - mf_ggx_albedo(sqrtf(alpha.x*alpha.y))) * wo.z;
|
||||
}
|
||||
|
||||
ccl_device_inline float mf_diffuse_pdf(const float3 wo)
|
||||
{
|
||||
return M_1_PI_F * wo.z;
|
||||
}
|
||||
|
||||
ccl_device_inline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
|
||||
{
|
||||
float3 wh;
|
||||
float fresnel;
|
||||
if(wi.z*wo.z > 0.0f) {
|
||||
wh = normalize(wi + wo);
|
||||
fresnel = fresnel_dielectric_cos(dot(wi, wh), eta);
|
||||
}
|
||||
else {
|
||||
wh = normalize(wi + wo*eta);
|
||||
fresnel = 1.0f - fresnel_dielectric_cos(dot(wi, wh), eta);
|
||||
}
|
||||
if(wh.z < 0.0f)
|
||||
wh = -wh;
|
||||
float3 r_wi = (wi.z < 0.0f)? -wi: wi;
|
||||
return fresnel * max(0.0f, dot(r_wi, wh)) * D_ggx(wh, alpha) / ((1.0f + mf_lambda(r_wi, make_float2(alpha, alpha))) * r_wi.z) + fabsf(wo.z);
|
||||
}
|
||||
|
||||
/* === 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 "bsdf_microfacet_multi_impl.h"
|
||||
|
||||
/* The diffuse phase function is not implemented as a node yet. */
|
||||
#if 0
|
||||
#define MF_PHASE_FUNCTION diffuse
|
||||
#define MF_MULTI_DIFFUSE
|
||||
#include "bsdf_microfacet_multi_impl.h"
|
||||
#endif
|
||||
|
||||
#define MF_PHASE_FUNCTION glossy
|
||||
#define MF_MULTI_GLOSSY
|
||||
#include "bsdf_microfacet_multi_impl.h"
|
||||
|
||||
ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
|
||||
{
|
||||
sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
|
||||
sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
|
||||
}
|
||||
|
||||
/* === Closure implementations === */
|
||||
|
||||
/* Multiscattering GGX Glossy closure */
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_common_setup(ShaderClosure *sc)
|
||||
{
|
||||
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); /* alpha */
|
||||
sc->data1 = clamp(sc->data1, 1e-4f, 1.0f);
|
||||
sc->custom1 = saturate(sc->custom1); /* color */
|
||||
sc->custom2 = saturate(sc->custom2);
|
||||
sc->custom3 = saturate(sc->custom3);
|
||||
|
||||
sc->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG|SD_BSDF_HAS_CUSTOM;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(ShaderClosure *sc)
|
||||
{
|
||||
#ifdef __KERNEL_OPENCL__
|
||||
if(all(sc->T == 0.0f))
|
||||
#else
|
||||
if(sc->T == make_float3(0.0f, 0.0f, 0.0f))
|
||||
#endif
|
||||
sc->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(sc);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_setup(ShaderClosure *sc)
|
||||
{
|
||||
sc->data1 = sc->data0;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(sc);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
|
||||
bool is_aniso = (sc->data0 != sc->data1);
|
||||
float3 X, Y, Z;
|
||||
Z = sc->N;
|
||||
if(is_aniso)
|
||||
make_orthonormals_tangent(Z, sc->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(sc->data0, sc->data1));
|
||||
else
|
||||
*pdf = mf_ggx_pdf(localI, localO, sc->data0);
|
||||
return mf_eval_glossy(localI, localO, true, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, NULL, NULL);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
|
||||
{
|
||||
bool is_aniso = (sc->data0 != sc->data1);
|
||||
float3 X, Y, Z;
|
||||
Z = sc->N;
|
||||
if(is_aniso)
|
||||
make_orthonormals_tangent(Z, sc->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, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, NULL, NULL);
|
||||
if(is_aniso)
|
||||
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(sc->data0, sc->data1));
|
||||
else
|
||||
*pdf = mf_ggx_pdf(localI, localO, sc->data0);
|
||||
*eval *= *pdf;
|
||||
|
||||
*omega_in = X*localO.x + Y*localO.y + Z*localO.z;
|
||||
return LABEL_REFLECT|LABEL_GLOSSY;
|
||||
}
|
||||
|
||||
/* Multiscattering GGX Glass closure */
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_glass_setup(ShaderClosure *sc)
|
||||
{
|
||||
sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); /* alpha */
|
||||
sc->data1 = sc->data0;
|
||||
sc->data2 = max(0.0f, sc->data2); /* ior */
|
||||
sc->custom1 = saturate(sc->custom1); /* color */
|
||||
sc->custom2 = saturate(sc->custom2);
|
||||
sc->custom3 = saturate(sc->custom3);
|
||||
|
||||
sc->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG|SD_BSDF_HAS_CUSTOM;
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
|
||||
float3 X, Y, Z;
|
||||
Z = sc->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));
|
||||
|
||||
*pdf = mf_glass_pdf(localI, localO, sc->data0, sc->data2);
|
||||
return mf_eval_glass(localI, localO, false, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, sc->data2);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
|
||||
float3 X, Y, Z;
|
||||
Z = sc->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));
|
||||
|
||||
*pdf = mf_glass_pdf(localI, localO, sc->data0, sc->data2);
|
||||
return mf_eval_glass(localI, localO, true, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, sc->data2);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
|
||||
{
|
||||
float3 X, Y, Z;
|
||||
Z = sc->N;
|
||||
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, make_float3(sc->custom1, sc->custom2, sc->custom3), sc->data0, sc->data1, lcg_state, sc->data2);
|
||||
*pdf = mf_glass_pdf(localI, localO, sc->data0, sc->data2);
|
||||
*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
|
||||
220
intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
Normal file
220
intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright 2011-2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* 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 float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, float3 wo, const bool wo_outside, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint* lcg_state
|
||||
#ifdef MF_MULTI_GLASS
|
||||
, const float eta
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
, float3 *n, float3 *k
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* 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 make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
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. */
|
||||
float3 eval;
|
||||
#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);
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
/* Diffuse has no special closed form for the single scattering bounce */
|
||||
eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
const float3 wh = normalize(wi+wo);
|
||||
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);
|
||||
if(n && k) {
|
||||
eval = fresnel_conductor(dot(wh, wi), *n, *k) * val;
|
||||
}
|
||||
else {
|
||||
eval = make_float3(val, val, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
float3 wr = -wi;
|
||||
float hr = 1.0f;
|
||||
float C1_r = 1.0f;
|
||||
float G1_r = 0.0f;
|
||||
bool outside = true;
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
for(int order = 0; order < 10; order++) {
|
||||
/* Sample microfacet height and normal */
|
||||
if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float(lcg_state)))
|
||||
break;
|
||||
float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float(lcg_state), lcg_step_float(lcg_state)));
|
||||
|
||||
#ifdef MF_MULTI_DIFFUSE
|
||||
if(order == 0) {
|
||||
/* Compute single-scattering for diffuse. */
|
||||
const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r);
|
||||
eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
|
||||
}
|
||||
#endif
|
||||
if(order > 0) {
|
||||
/* Evaluate amount of scattering towards wo on this microfacet. */
|
||||
float3 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);
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
phase = mf_eval_phase_diffuse(wo, wm);
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha, n, k) * 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;
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float(lcg_state), &next_outside);
|
||||
if(!next_outside) {
|
||||
outside = !outside;
|
||||
wr = -wr;
|
||||
hr = -hr;
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
wr = mf_sample_phase_diffuse(wm, lcg_step_float(lcg_state), lcg_step_float(lcg_state));
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
|
||||
#endif
|
||||
|
||||
lambda_r = mf_lambda(wr, alpha);
|
||||
|
||||
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 float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint *lcg_state
|
||||
#ifdef MF_MULTI_GLASS
|
||||
, const float eta
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
, float3 *n, float3 *k
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const float2 alpha = make_float2(alpha_x, alpha_y);
|
||||
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
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;
|
||||
|
||||
int order;
|
||||
for(order = 0; order < 10; order++) {
|
||||
/* Sample microfacet height. */
|
||||
if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float(lcg_state))) {
|
||||
/* The random walk has left the surface. */
|
||||
*wo = outside? wr: -wr;
|
||||
return throughput;
|
||||
}
|
||||
/* Sample microfacet normal. */
|
||||
float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float(lcg_state), lcg_step_float(lcg_state)));
|
||||
|
||||
/* First-bounce color is already accounted for in mix weight. */
|
||||
if(order > 0)
|
||||
throughput *= color;
|
||||
|
||||
/* Bounce from the microfacet. */
|
||||
#ifdef MF_MULTI_GLASS
|
||||
bool next_outside;
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float(lcg_state), &next_outside);
|
||||
if(!next_outside) {
|
||||
hr = -hr;
|
||||
wr = -wr;
|
||||
outside = !outside;
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
wr = mf_sample_phase_diffuse(wm, lcg_step_float(lcg_state), lcg_step_float(lcg_state));
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
wr = mf_sample_phase_glossy(-wr, n, k, &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 make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
#undef MF_MULTI_GLASS
|
||||
#undef MF_MULTI_DIFFUSE
|
||||
#undef MF_MULTI_GLOSSY
|
||||
#undef MF_PHASE_FUNCTION
|
||||
@@ -111,10 +111,9 @@ ccl_device float fresnel_dielectric_cos(float cosi, float eta)
|
||||
return 1.0f; // TIR(no refracted component)
|
||||
}
|
||||
|
||||
#if 0
|
||||
ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k)
|
||||
{
|
||||
float3 cosi2 = make_float3(cosi*cosi);
|
||||
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;
|
||||
@@ -124,7 +123,6 @@ ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k
|
||||
(tmp_f + (2.0f * eta * cosi) + cosi2);
|
||||
return(Rparl2 + Rperp2) * 0.5f;
|
||||
}
|
||||
#endif
|
||||
|
||||
ccl_device float smooth_step(float edge0, float edge1, float x)
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
|
||||
|
||||
/* evaluate surface shader */
|
||||
float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, sd, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
|
||||
shader_eval_surface(kg, sd, &rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
|
||||
|
||||
/* TODO, disable the closures we won't need */
|
||||
|
||||
@@ -220,6 +220,7 @@ ccl_device_inline float3 kernel_bake_shader_bsdf(KernelGlobals *kg,
|
||||
|
||||
ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
RNG *rng,
|
||||
PathState *state,
|
||||
float3 direct,
|
||||
float3 indirect,
|
||||
@@ -239,12 +240,12 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
|
||||
}
|
||||
else {
|
||||
/* surface color of the pass only */
|
||||
shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
|
||||
shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
|
||||
return kernel_bake_shader_bsdf(kg, sd, type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
|
||||
shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
|
||||
color = kernel_bake_shader_bsdf(kg, sd, type);
|
||||
}
|
||||
|
||||
@@ -336,7 +337,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
case SHADER_EVAL_NORMAL:
|
||||
{
|
||||
if((sd.flag & SD_HAS_BUMP)) {
|
||||
shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
|
||||
shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
|
||||
}
|
||||
|
||||
/* compression: normal = (2 * color) - 1 */
|
||||
@@ -350,7 +351,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
}
|
||||
case SHADER_EVAL_EMISSION:
|
||||
{
|
||||
shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_EMISSION);
|
||||
shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_EMISSION);
|
||||
out = shader_emissive_eval(kg, &sd);
|
||||
break;
|
||||
}
|
||||
@@ -403,6 +404,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
{
|
||||
out = kernel_bake_evaluate_direct_indirect(kg,
|
||||
&sd,
|
||||
&rng,
|
||||
&state,
|
||||
L.direct_diffuse,
|
||||
L.indirect_diffuse,
|
||||
@@ -414,6 +416,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
{
|
||||
out = kernel_bake_evaluate_direct_indirect(kg,
|
||||
&sd,
|
||||
&rng,
|
||||
&state,
|
||||
L.direct_glossy,
|
||||
L.indirect_glossy,
|
||||
@@ -425,6 +428,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
{
|
||||
out = kernel_bake_evaluate_direct_indirect(kg,
|
||||
&sd,
|
||||
&rng,
|
||||
&state,
|
||||
L.direct_transmission,
|
||||
L.indirect_transmission,
|
||||
@@ -437,6 +441,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
#ifdef __SUBSURFACE__
|
||||
out = kernel_bake_evaluate_direct_indirect(kg,
|
||||
&sd,
|
||||
&rng,
|
||||
&state,
|
||||
L.direct_subsurface,
|
||||
L.indirect_subsurface,
|
||||
|
||||
@@ -57,7 +57,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
|
||||
/* no path flag, we're evaluating this for all closures. that's weak but
|
||||
* we'd have to do multiple evaluations otherwise */
|
||||
path_state_modify_bounce(state, true);
|
||||
shader_eval_surface(kg, emission_sd, state, 0.0f, 0, SHADER_CONTEXT_EMISSION);
|
||||
shader_eval_surface(kg, emission_sd, NULL, state, 0.0f, 0, SHADER_CONTEXT_EMISSION);
|
||||
path_state_modify_bounce(state, false);
|
||||
|
||||
/* evaluate emissive closure */
|
||||
|
||||
@@ -253,7 +253,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
||||
&isect,
|
||||
ray);
|
||||
float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, sd, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
|
||||
shader_eval_surface(kg, sd, rng, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
|
||||
#ifdef __BRANCHED_PATH__
|
||||
shader_merge_closures(sd);
|
||||
#endif
|
||||
@@ -791,7 +791,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
|
||||
/* setup shading */
|
||||
shader_setup_from_ray(kg, &sd, &isect, &ray);
|
||||
float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, &sd, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
|
||||
shader_eval_surface(kg, &sd, rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
|
||||
|
||||
/* holdout */
|
||||
#ifdef __HOLDOUT__
|
||||
|
||||
@@ -463,7 +463,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
|
||||
|
||||
/* setup shading */
|
||||
shader_setup_from_ray(kg, &sd, &isect, &ray);
|
||||
shader_eval_surface(kg, &sd, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
|
||||
shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
|
||||
shader_merge_closures(&sd);
|
||||
|
||||
/* holdout */
|
||||
|
||||
@@ -232,14 +232,14 @@ ccl_device void path_rng_end(KernelGlobals *kg, ccl_global uint *rng_state, RNG
|
||||
|
||||
/* Linear Congruential Generator */
|
||||
|
||||
ccl_device uint lcg_step_uint(uint *rng)
|
||||
ccl_device uint lcg_step_uint(ccl_addr_space uint *rng)
|
||||
{
|
||||
/* implicit mod 2^32 */
|
||||
*rng = (1103515245*(*rng) + 12345);
|
||||
return *rng;
|
||||
}
|
||||
|
||||
ccl_device float lcg_step_float(uint *rng)
|
||||
ccl_device float lcg_step_float(ccl_addr_space uint *rng)
|
||||
{
|
||||
/* implicit mod 2^32 */
|
||||
*rng = (1103515245*(*rng) + 12345);
|
||||
@@ -309,7 +309,7 @@ ccl_device_inline void path_state_branch(PathState *state, int branch, int num_b
|
||||
state->num_samples = state->num_samples*num_branches;
|
||||
}
|
||||
|
||||
ccl_device_inline uint lcg_state_init(RNG *rng, const PathState *state, uint scramble)
|
||||
ccl_device_inline uint lcg_state_init(RNG *rng, const ccl_addr_space PathState *state, uint scramble)
|
||||
{
|
||||
return lcg_init(*rng + state->rng_offset + state->sample*scramble);
|
||||
}
|
||||
|
||||
@@ -468,6 +468,9 @@ ccl_device void shader_merge_closures(ShaderData *sd)
|
||||
continue;
|
||||
}
|
||||
|
||||
if((sd->flag & SD_BSDF_HAS_CUSTOM) && !(sci->custom1 == scj->custom1 && sci->custom2 == scj->custom2 && sci->custom3 == scj->custom3))
|
||||
continue;
|
||||
|
||||
sci->weight += scj->weight;
|
||||
sci->sample_weight += scj->sample_weight;
|
||||
|
||||
@@ -488,7 +491,7 @@ ccl_device void shader_merge_closures(ShaderData *sd)
|
||||
|
||||
/* BSDF */
|
||||
|
||||
ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderData *sd, const float3 omega_in, float *pdf,
|
||||
ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd, const float3 omega_in, float *pdf,
|
||||
int skip_bsdf, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
|
||||
{
|
||||
/* this is the veach one-sample model with balance heuristic, some pdf
|
||||
@@ -517,7 +520,7 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderDa
|
||||
|
||||
#ifdef __BRANCHED_PATH__
|
||||
ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
|
||||
const ShaderData *sd,
|
||||
ShaderData *sd,
|
||||
const float3 omega_in,
|
||||
BsdfEval *result_eval,
|
||||
float light_pdf,
|
||||
@@ -563,7 +566,7 @@ ccl_device void shader_bsdf_eval(KernelGlobals *kg,
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
|
||||
ccl_device int shader_bsdf_sample(KernelGlobals *kg, ShaderData *sd,
|
||||
float randu, float randv, BsdfEval *bsdf_eval,
|
||||
float3 *omega_in, differential3 *domega_in, float *pdf)
|
||||
{
|
||||
@@ -620,7 +623,7 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
|
||||
return label;
|
||||
}
|
||||
|
||||
ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd,
|
||||
ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, ShaderData *sd,
|
||||
const ShaderClosure *sc, float randu, float randv, BsdfEval *bsdf_eval,
|
||||
float3 *omega_in, differential3 *domega_in, float *pdf)
|
||||
{
|
||||
@@ -824,7 +827,7 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
|
||||
|
||||
/* Surface Evaluation */
|
||||
|
||||
ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
|
||||
ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
|
||||
ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
|
||||
{
|
||||
ccl_fetch(sd, num_closure) = 0;
|
||||
@@ -846,6 +849,10 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
|
||||
ccl_fetch(sd, flag) |= bsdf_diffuse_setup(ccl_fetch_array(sd, closure, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(rng && (ccl_fetch(sd, flag) & SD_BSDF_NEEDS_LCG)) {
|
||||
ccl_fetch(sd, lcg_state) = lcg_state_init(rng, state, 0xb4bc3953);
|
||||
}
|
||||
}
|
||||
|
||||
/* Background Evaluation */
|
||||
|
||||
@@ -117,7 +117,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *shadow_sd,
|
||||
/* attenuation from transparent surface */
|
||||
if(!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
|
||||
path_state_modify_bounce(state, true);
|
||||
shader_eval_surface(kg, shadow_sd, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
|
||||
shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
|
||||
path_state_modify_bounce(state, false);
|
||||
|
||||
throughput *= shader_bsdf_transparency(kg, shadow_sd);
|
||||
@@ -252,7 +252,7 @@ ccl_device_noinline bool shadow_blocked(KernelGlobals *kg,
|
||||
/* attenuation from transparent surface */
|
||||
if(!(ccl_fetch(shadow_sd, flag) & SD_HAS_ONLY_VOLUME)) {
|
||||
path_state_modify_bounce(state, true);
|
||||
shader_eval_surface(kg, shadow_sd, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
|
||||
shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
|
||||
path_state_modify_bounce(state, false);
|
||||
|
||||
throughput *= shader_bsdf_transparency(kg, shadow_sd);
|
||||
|
||||
@@ -198,7 +198,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
|
||||
|
||||
if(bump || texture_blur > 0.0f) {
|
||||
/* average color and normal at incoming point */
|
||||
shader_eval_surface(kg, sd, state, 0.0f, state_flag, SHADER_CONTEXT_SSS);
|
||||
shader_eval_surface(kg, sd, NULL, state, 0.0f, state_flag, SHADER_CONTEXT_SSS);
|
||||
float3 in_color = shader_bssrdf_sum(sd, (bump)? N: NULL, NULL);
|
||||
|
||||
/* we simply divide out the average color and multiply with the average
|
||||
|
||||
@@ -679,31 +679,34 @@ typedef enum ShaderContext {
|
||||
|
||||
enum ShaderDataFlag {
|
||||
/* runtime flags */
|
||||
SD_BACKFACING = (1 << 0), /* backside of surface? */
|
||||
SD_EMISSION = (1 << 1), /* have emissive closure? */
|
||||
SD_BSDF = (1 << 2), /* have bsdf closure? */
|
||||
SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */
|
||||
SD_BSSRDF = (1 << 4), /* have bssrdf */
|
||||
SD_HOLDOUT = (1 << 5), /* have holdout closure? */
|
||||
SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */
|
||||
SD_SCATTER = (1 << 7), /* have volume phase closure? */
|
||||
SD_AO = (1 << 8), /* have ao closure? */
|
||||
SD_TRANSPARENT = (1 << 9), /* have transparent closure? */
|
||||
SD_BACKFACING = (1 << 0), /* backside of surface? */
|
||||
SD_EMISSION = (1 << 1), /* have emissive closure? */
|
||||
SD_BSDF = (1 << 2), /* have bsdf closure? */
|
||||
SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */
|
||||
SD_BSSRDF = (1 << 4), /* have bssrdf */
|
||||
SD_HOLDOUT = (1 << 5), /* have holdout closure? */
|
||||
SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */
|
||||
SD_SCATTER = (1 << 7), /* have volume phase closure? */
|
||||
SD_AO = (1 << 8), /* have ao closure? */
|
||||
SD_TRANSPARENT = (1 << 9), /* have transparent closure? */
|
||||
SD_BSDF_NEEDS_LCG = (1 << 10),
|
||||
SD_BSDF_HAS_CUSTOM = (1 << 11), /* are the custom variables relevant? */
|
||||
|
||||
SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF|
|
||||
SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
|
||||
SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO|
|
||||
SD_BSDF_NEEDS_LCG|SD_BSDF_HAS_CUSTOM),
|
||||
|
||||
/* shader flags */
|
||||
SD_USE_MIS = (1 << 10), /* direct light sample */
|
||||
SD_HAS_TRANSPARENT_SHADOW = (1 << 11), /* has transparent shadow */
|
||||
SD_HAS_VOLUME = (1 << 12), /* has volume shader */
|
||||
SD_HAS_ONLY_VOLUME = (1 << 13), /* has only volume shader, no surface */
|
||||
SD_HETEROGENEOUS_VOLUME = (1 << 14), /* has heterogeneous volume */
|
||||
SD_HAS_BSSRDF_BUMP = (1 << 15), /* bssrdf normal uses bump */
|
||||
SD_VOLUME_EQUIANGULAR = (1 << 16), /* use equiangular sampling */
|
||||
SD_VOLUME_MIS = (1 << 17), /* use multiple importance sampling */
|
||||
SD_VOLUME_CUBIC = (1 << 18), /* use cubic interpolation for voxels */
|
||||
SD_HAS_BUMP = (1 << 19), /* has data connected to the displacement input */
|
||||
SD_USE_MIS = (1 << 12), /* direct light sample */
|
||||
SD_HAS_TRANSPARENT_SHADOW = (1 << 13), /* has transparent shadow */
|
||||
SD_HAS_VOLUME = (1 << 14), /* has volume shader */
|
||||
SD_HAS_ONLY_VOLUME = (1 << 15), /* has only volume shader, no surface */
|
||||
SD_HETEROGENEOUS_VOLUME = (1 << 16), /* has heterogeneous volume */
|
||||
SD_HAS_BSSRDF_BUMP = (1 << 17), /* bssrdf normal uses bump */
|
||||
SD_VOLUME_EQUIANGULAR = (1 << 18), /* use equiangular sampling */
|
||||
SD_VOLUME_MIS = (1 << 19), /* use multiple importance sampling */
|
||||
SD_VOLUME_CUBIC = (1 << 20), /* use cubic interpolation for voxels */
|
||||
SD_HAS_BUMP = (1 << 21), /* has data connected to the displacement input */
|
||||
|
||||
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|
|
||||
SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|
|
||||
@@ -711,13 +714,13 @@ enum ShaderDataFlag {
|
||||
SD_VOLUME_CUBIC|SD_HAS_BUMP),
|
||||
|
||||
/* object flags */
|
||||
SD_HOLDOUT_MASK = (1 << 20), /* holdout for camera rays */
|
||||
SD_OBJECT_MOTION = (1 << 21), /* has object motion blur */
|
||||
SD_TRANSFORM_APPLIED = (1 << 22), /* vertices have transform applied */
|
||||
SD_NEGATIVE_SCALE_APPLIED = (1 << 23), /* vertices have negative scale applied */
|
||||
SD_OBJECT_HAS_VOLUME = (1 << 24), /* object has a volume shader */
|
||||
SD_OBJECT_INTERSECTS_VOLUME = (1 << 25), /* object intersects AABB of an object with volume shader */
|
||||
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 26), /* has position for motion vertices */
|
||||
SD_HOLDOUT_MASK = (1 << 22), /* holdout for camera rays */
|
||||
SD_OBJECT_MOTION = (1 << 23), /* has object motion blur */
|
||||
SD_TRANSFORM_APPLIED = (1 << 24), /* vertices have transform applied */
|
||||
SD_NEGATIVE_SCALE_APPLIED = (1 << 25), /* vertices have negative scale applied */
|
||||
SD_OBJECT_HAS_VOLUME = (1 << 26), /* object has a volume shader */
|
||||
SD_OBJECT_INTERSECTS_VOLUME = (1 << 27), /* object intersects AABB of an object with volume shader */
|
||||
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 28), /* has position for motion vertices */
|
||||
|
||||
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED|
|
||||
SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME|
|
||||
@@ -806,6 +809,9 @@ typedef ccl_addr_space struct ShaderData {
|
||||
int num_closure;
|
||||
float randb_closure;
|
||||
|
||||
/* LCG state for closures that require additional random numbers. */
|
||||
uint lcg_state;
|
||||
|
||||
/* ray start position, only set for backgrounds */
|
||||
float3 ray_P;
|
||||
differential3 ray_dP;
|
||||
|
||||
@@ -44,11 +44,13 @@
|
||||
#include "kernel_compat_cpu.h"
|
||||
#include "kernel_globals.h"
|
||||
#include "kernel_montecarlo.h"
|
||||
#include "kernel_random.h"
|
||||
|
||||
#include "closure/bsdf_util.h"
|
||||
#include "closure/bsdf_ashikhmin_velvet.h"
|
||||
#include "closure/bsdf_diffuse.h"
|
||||
#include "closure/bsdf_microfacet.h"
|
||||
#include "closure/bsdf_microfacet_multi.h"
|
||||
#include "closure/bsdf_oren_nayar.h"
|
||||
#include "closure/bsdf_reflection.h"
|
||||
#include "closure/bsdf_refraction.h"
|
||||
@@ -205,6 +207,12 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
bsdf_microfacet_ggx_aniso_params(), bsdf_microfacet_ggx_aniso_prepare);
|
||||
register_closure(ss, "microfacet_ggx_refraction", id++,
|
||||
bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare);
|
||||
register_closure(ss, "microfacet_multi_ggx", id++,
|
||||
closure_bsdf_microfacet_multi_ggx_params(), closure_bsdf_microfacet_multi_ggx_prepare);
|
||||
register_closure(ss, "microfacet_multi_ggx_glass", id++,
|
||||
closure_bsdf_microfacet_multi_ggx_glass_params(), closure_bsdf_microfacet_multi_ggx_glass_prepare);
|
||||
register_closure(ss, "microfacet_multi_ggx_aniso", id++,
|
||||
closure_bsdf_microfacet_multi_ggx_aniso_params(), closure_bsdf_microfacet_multi_ggx_aniso_prepare);
|
||||
register_closure(ss, "microfacet_beckmann", id++,
|
||||
bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
|
||||
register_closure(ss, "microfacet_beckmann_aniso", id++,
|
||||
@@ -250,5 +258,127 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
volume_absorption_params(), volume_absorption_prepare);
|
||||
}
|
||||
|
||||
/* Multiscattering GGX closures */
|
||||
|
||||
class MicrofacetMultiClosure : public CBSDFClosure {
|
||||
public:
|
||||
float3 color;
|
||||
|
||||
/* Technically, the MultiGGX Glass closure may also transmit.
|
||||
* However, since this is set statically and only used for caustic flags, this is probably as good as it gets. */
|
||||
MicrofacetMultiClosure() : CBSDFClosure(LABEL_GLOSSY|LABEL_REFLECT)
|
||||
{
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
sc.prim = NULL;
|
||||
sc.custom1 = color.x;
|
||||
sc.custom2 = color.y;
|
||||
sc.custom3 = color.z;
|
||||
}
|
||||
|
||||
void blur(float roughness)
|
||||
{
|
||||
}
|
||||
|
||||
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
|
||||
{
|
||||
pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
|
||||
{
|
||||
pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
int sample(const float3 &Ng,
|
||||
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
|
||||
float randu, float randv,
|
||||
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
|
||||
float &pdf, float3 &eval) const
|
||||
{
|
||||
pdf = 0;
|
||||
return LABEL_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure {
|
||||
public:
|
||||
MicrofacetMultiGGXClosure() : MicrofacetMultiClosure() {}
|
||||
|
||||
void setup()
|
||||
{
|
||||
MicrofacetMultiClosure::setup();
|
||||
m_shaderdata_flag = bsdf_microfacet_multi_ggx_setup(&sc);
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_multi_ggx_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.N),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data0),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_prepare, MicrofacetMultiGGXClosure);
|
||||
|
||||
class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure {
|
||||
public:
|
||||
MicrofacetMultiGGXAnisoClosure() : MicrofacetMultiClosure() {}
|
||||
|
||||
void setup()
|
||||
{
|
||||
MicrofacetMultiClosure::setup();
|
||||
m_shaderdata_flag = bsdf_microfacet_multi_ggx_aniso_setup(&sc);
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.N),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.T),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data0),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data1),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_prepare, MicrofacetMultiGGXAnisoClosure);
|
||||
|
||||
class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure {
|
||||
public:
|
||||
MicrofacetMultiGGXGlassClosure() : MicrofacetMultiClosure() {}
|
||||
|
||||
void setup()
|
||||
{
|
||||
MicrofacetMultiClosure::setup();
|
||||
m_shaderdata_flag = bsdf_microfacet_multi_ggx_glass_setup(&sc);
|
||||
}
|
||||
};
|
||||
|
||||
ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, sc.N),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data0),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, sc.data2),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
|
||||
CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
|
||||
};
|
||||
return params;
|
||||
}
|
||||
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure);
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -52,6 +52,9 @@ OSL::ClosureParam *closure_bssrdf_cubic_params();
|
||||
OSL::ClosureParam *closure_bssrdf_gaussian_params();
|
||||
OSL::ClosureParam *closure_bssrdf_burley_params();
|
||||
OSL::ClosureParam *closure_henyey_greenstein_volume_params();
|
||||
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_params();
|
||||
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params();
|
||||
OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params();
|
||||
|
||||
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
|
||||
@@ -63,6 +66,9 @@ void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bssrdf_burley_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_henyey_greenstein_volume_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_multi_ggx_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_multi_ggx_glass_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void closure_bsdf_microfacet_multi_ggx_aniso_prepare(OSL::RendererServices *, int id, void *data);
|
||||
|
||||
#define CCLOSURE_PREPARE(name, classname) \
|
||||
void name(RendererServices *, int id, void *data) \
|
||||
|
||||
@@ -177,6 +177,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
|
||||
case CClosurePrimitive::BSDF: {
|
||||
CBSDFClosure *bsdf = (CBSDFClosure *)prim;
|
||||
int scattering = bsdf->scattering();
|
||||
int shaderdata_flag = bsdf->shaderdata_flag();
|
||||
|
||||
/* caustic options */
|
||||
if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
|
||||
@@ -201,11 +202,16 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
|
||||
sc.data1 = bsdf->sc.data1;
|
||||
sc.data2 = bsdf->sc.data2;
|
||||
sc.prim = bsdf->sc.prim;
|
||||
if(shaderdata_flag & SD_BSDF_HAS_CUSTOM) {
|
||||
sc.custom1 = bsdf->sc.custom1;
|
||||
sc.custom2 = bsdf->sc.custom2;
|
||||
sc.custom3 = bsdf->sc.custom3;
|
||||
}
|
||||
|
||||
/* add */
|
||||
if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
|
||||
sd->closure[sd->num_closure++] = sc;
|
||||
sd->flag |= bsdf->shaderdata_flag();
|
||||
sd->flag |= shaderdata_flag;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ shader node_anisotropic_bsdf(
|
||||
BSDF = Color * microfacet_beckmann_aniso(Normal, T, RoughnessU, RoughnessV);
|
||||
else if (distribution == "GGX")
|
||||
BSDF = Color * microfacet_ggx_aniso(Normal, T, RoughnessU, RoughnessV);
|
||||
else if (distribution == "Multiscatter GGX")
|
||||
BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, RoughnessU, RoughnessV, Color);
|
||||
else
|
||||
BSDF = Color * ashikhmin_shirley(Normal, T, RoughnessU, RoughnessV);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ shader node_glass_bsdf(
|
||||
else if (distribution == "beckmann")
|
||||
BSDF = Color * (Fr * microfacet_beckmann(Normal, Roughness) +
|
||||
(1.0 - Fr) * microfacet_beckmann_refraction(Normal, Roughness, eta));
|
||||
else if (distribution == "Multiscatter GGX")
|
||||
BSDF = Color * microfacet_multi_ggx_glass(Normal, Roughness, eta, Color);
|
||||
else if (distribution == "GGX")
|
||||
BSDF = Color * (Fr * microfacet_ggx(Normal, Roughness) +
|
||||
(1.0 - Fr) * microfacet_ggx_refraction(Normal, Roughness, eta));
|
||||
|
||||
@@ -30,6 +30,8 @@ shader node_glossy_bsdf(
|
||||
BSDF = Color * microfacet_beckmann(Normal, Roughness);
|
||||
else if (distribution == "GGX")
|
||||
BSDF = Color * microfacet_ggx(Normal, Roughness);
|
||||
else if (distribution == "Multiscatter GGX")
|
||||
BSDF = Color * microfacet_multi_ggx(Normal, Roughness, Color);
|
||||
else
|
||||
BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), Roughness, Roughness);
|
||||
|
||||
|
||||
@@ -527,6 +527,9 @@ closure color transparent() BUILTIN;
|
||||
closure color microfacet_ggx(normal N, float ag) BUILTIN;
|
||||
closure color microfacet_ggx_aniso(normal N, vector T, float ax, float ay) BUILTIN;
|
||||
closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
|
||||
closure color microfacet_multi_ggx(normal N, float ag, color C) BUILTIN;
|
||||
closure color microfacet_multi_ggx_aniso(normal N, vector T, float ax, float ay, color C) BUILTIN;
|
||||
closure color microfacet_multi_ggx_glass(normal N, float ag, float eta, color C) BUILTIN;
|
||||
closure color microfacet_beckmann(normal N, float ab) BUILTIN;
|
||||
closure color microfacet_beckmann_aniso(normal N, vector T, float ax, float ay) BUILTIN;
|
||||
closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN;
|
||||
|
||||
@@ -65,6 +65,6 @@ ccl_device void kernel_shader_eval(
|
||||
isect,
|
||||
&ray);
|
||||
float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, sd, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
|
||||
shader_eval_surface(kg, sd, rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: {
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
||||
break;
|
||||
@@ -206,6 +207,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc);
|
||||
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc);
|
||||
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
|
||||
kernel_assert(stack_valid(data_node.z));
|
||||
float3 color = stack_load_float3(stack, data_node.z);
|
||||
sc->custom1 = color.x;
|
||||
sc->custom2 = color.y;
|
||||
sc->custom3 = color.z;
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_setup(sc);
|
||||
}
|
||||
else
|
||||
ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(sc);
|
||||
}
|
||||
@@ -307,8 +316,36 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
|
||||
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: {
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if(!kernel_data.integrator.caustics_reflective && !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
|
||||
break;
|
||||
#endif
|
||||
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
|
||||
|
||||
if(sc) {
|
||||
sc->N = N;
|
||||
|
||||
sc->data0 = param1;
|
||||
sc->data1 = param1;
|
||||
float eta = fmaxf(param2, 1e-5f);
|
||||
sc->data2 = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
|
||||
|
||||
kernel_assert(stack_valid(data_node.z));
|
||||
float3 color = stack_load_float3(stack, data_node.z);
|
||||
sc->custom1 = color.x;
|
||||
sc->custom2 = color.y;
|
||||
sc->custom3 = color.z;
|
||||
|
||||
/* setup bsdf */
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(sc);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
||||
@@ -346,6 +383,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(sc);
|
||||
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID)
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(sc);
|
||||
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
|
||||
kernel_assert(stack_valid(data_node.w));
|
||||
float3 color = stack_load_float3(stack, data_node.w);
|
||||
sc->custom1 = color.x;
|
||||
sc->custom2 = color.y;
|
||||
sc->custom3 = color.z;
|
||||
ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(sc);
|
||||
}
|
||||
else
|
||||
ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(sc);
|
||||
}
|
||||
|
||||
@@ -396,8 +396,10 @@ typedef enum ClosureType {
|
||||
CLOSURE_BSDF_REFLECTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
|
||||
@@ -413,6 +415,7 @@ typedef enum ClosureType {
|
||||
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
|
||||
CLOSURE_BSDF_SHARP_GLASS_ID,
|
||||
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
|
||||
|
||||
|
||||
@@ -1828,6 +1828,7 @@ NODE_DEFINE(AnisotropicBsdfNode)
|
||||
static NodeEnum distribution_enum;
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
|
||||
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
|
||||
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID);
|
||||
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
|
||||
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
|
||||
|
||||
@@ -1864,7 +1865,10 @@ void AnisotropicBsdfNode::compile(SVMCompiler& compiler)
|
||||
{
|
||||
closure = distribution;
|
||||
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
|
||||
if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID)
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
|
||||
else
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
|
||||
}
|
||||
|
||||
void AnisotropicBsdfNode::compile(OSLCompiler& compiler)
|
||||
@@ -1888,6 +1892,7 @@ NODE_DEFINE(GlossyBsdfNode)
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
|
||||
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
|
||||
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
|
||||
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
|
||||
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
|
||||
SOCKET_IN_FLOAT(roughness, "Roughness", 0.2f);
|
||||
|
||||
@@ -1937,6 +1942,8 @@ void GlossyBsdfNode::compile(SVMCompiler& compiler)
|
||||
|
||||
if(closure == CLOSURE_BSDF_REFLECTION_ID)
|
||||
BsdfNode::compile(compiler, NULL, NULL);
|
||||
else if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
|
||||
BsdfNode::compile(compiler, input("Roughness"), NULL, input("Color"));
|
||||
else
|
||||
BsdfNode::compile(compiler, input("Roughness"), NULL);
|
||||
}
|
||||
@@ -1961,6 +1968,7 @@ NODE_DEFINE(GlassBsdfNode)
|
||||
distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
|
||||
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
|
||||
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
|
||||
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
|
||||
SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
|
||||
SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
|
||||
@@ -2011,6 +2019,8 @@ void GlassBsdfNode::compile(SVMCompiler& compiler)
|
||||
|
||||
if(closure == CLOSURE_BSDF_SHARP_GLASS_ID)
|
||||
BsdfNode::compile(compiler, NULL, input("IOR"));
|
||||
else if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("IOR"), input("Color"));
|
||||
else
|
||||
BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
|
||||
}
|
||||
|
||||
@@ -545,6 +545,11 @@ ccl_device_inline float3 normalize(const float3 a)
|
||||
|
||||
#endif
|
||||
|
||||
ccl_device_inline float3 saturate3(float3 a)
|
||||
{
|
||||
return make_float3(saturate(a.x), saturate(a.y), saturate(a.z));
|
||||
}
|
||||
|
||||
ccl_device_inline float3 normalize_len(const float3 a, float *t)
|
||||
{
|
||||
*t = len(a);
|
||||
@@ -1329,6 +1334,15 @@ ccl_device float safe_modulo(float a, float b)
|
||||
return (b != 0.0f)? fmodf(a, b): 0.0f;
|
||||
}
|
||||
|
||||
ccl_device_inline float beta(float x, float y)
|
||||
{
|
||||
#ifndef __KERNEL_OPENCL__
|
||||
return expf(lgammaf(x) + lgammaf(y) - lgammaf(x+y));
|
||||
#else
|
||||
return expf(lgamma(x) + lgamma(y) - lgamma(x+y));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Ray Intersection */
|
||||
|
||||
ccl_device bool ray_sphere_intersect(
|
||||
|
||||
@@ -260,7 +260,11 @@ string string_human_readable_size(size_t size)
|
||||
|
||||
string string_human_readable_number(size_t num)
|
||||
{
|
||||
/* add thousands separators */
|
||||
if(num == 0) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
/* Add thousands separators. */
|
||||
char buf[32];
|
||||
|
||||
char* p = buf+31;
|
||||
|
||||
Reference in New Issue
Block a user