disney implementation cleaned
This commit is contained in:
@@ -35,16 +35,6 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#define MIX(x, y, a) (x * (1.0f - a) + y * a)
|
||||
|
||||
/* DISNEY CLEARCOAT */
|
||||
|
||||
ccl_device float clear_SchlickFresnel(float u) {
|
||||
float m = clamp(1.0f - u, 0.0f, 1.0f);
|
||||
float m2 = m * m;
|
||||
return m2 * m2 * m; // pow(m, 5)
|
||||
}
|
||||
|
||||
/* structures */
|
||||
struct DisneyClearcoatBRDFParams {
|
||||
// brdf parameters
|
||||
@@ -55,105 +45,13 @@ struct DisneyClearcoatBRDFParams {
|
||||
float m_clearcoatRoughness;
|
||||
|
||||
void precompute_values() {
|
||||
m_clearcoatRoughness = MIX(0.1f, 0.001f, m_clearcoatGloss);
|
||||
m_clearcoatRoughness = mix(0.1f, 0.001f, m_clearcoatGloss);
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct DisneyClearcoatBRDFParams DisneyClearcoatBRDFParams;
|
||||
|
||||
|
||||
ccl_device_inline void clear_microfacet_ggx_sample_slopes(
|
||||
const float cos_theta_i, const float sin_theta_i,
|
||||
float randu, float randv, float *slope_x, float *slope_y,
|
||||
float *G1i)
|
||||
{
|
||||
/* special case (normal incidence) */
|
||||
if(cos_theta_i >= 0.99999f) {
|
||||
const float r = safe_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_inline float3 clear_microfacet_sample_stretched(
|
||||
const float3 omega_i, const float alpha_x, const float alpha_y,
|
||||
const float randu, const float randv,
|
||||
bool beckmann, 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;
|
||||
|
||||
clear_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));
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_clearcoat_setup(ShaderClosure *sc)
|
||||
{
|
||||
sc->type = CLOSURE_BSDF_DISNEY_CLEARCOAT_ID;
|
||||
@@ -199,8 +97,8 @@ ccl_device float3 bsdf_disney_clearcoat_eval_reflect(const ShaderClosure *sc,
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
|
||||
float FH = clear_SchlickFresnel(dot(omega_in, m));
|
||||
float3 F = MIX(make_float3(0.04f, 0.04f, 0.04f), make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
float FH = schlick_fresnel(dot(omega_in, m));
|
||||
float3 F = mix(make_float3(0.04f, 0.04f, 0.04f), make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
|
||||
float3 out = F * G * common * 0.25f * params->m_clearcoat;
|
||||
|
||||
@@ -246,7 +144,7 @@ ccl_device int bsdf_disney_clearcoat_sample(const ShaderClosure *sc, const Disne
|
||||
float3 m;
|
||||
float G1o;
|
||||
|
||||
local_m = clear_microfacet_sample_stretched(local_I, alpha, alpha,
|
||||
local_m = importance_sample_microfacet_stretched(local_I, alpha, alpha,
|
||||
randu, randv, false, &G1o);
|
||||
|
||||
m = X*local_m.x + Y*local_m.y + Z*local_m.z;
|
||||
@@ -288,8 +186,8 @@ ccl_device int bsdf_disney_clearcoat_sample(const ShaderClosure *sc, const Disne
|
||||
float common = (G1o * D) * 0.25f / cosNO;
|
||||
*pdf = common;
|
||||
|
||||
float FH = clear_SchlickFresnel(dot(*omega_in, m));
|
||||
float3 F = MIX(make_float3(0.04f, 0.04f, 0.04f), make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
float FH = schlick_fresnel(dot(*omega_in, m));
|
||||
float3 F = mix(make_float3(0.04f, 0.04f, 0.04f), make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
|
||||
*eval = G1i * common * F * 0.25f * params->m_clearcoat;
|
||||
}
|
||||
|
||||
@@ -34,71 +34,8 @@
|
||||
#ifndef __BSDF_DISNEY_DIFFUSE_H__
|
||||
#define __BSDF_DISNEY_DIFFUSE_H__
|
||||
|
||||
#include <cmath>
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* DISNEY DIFFUSE */
|
||||
|
||||
ccl_device float diff_sqr(float a) {
|
||||
return a * a;
|
||||
}
|
||||
|
||||
ccl_device float3 diff_mon2lin(float3 x, float gamma) {
|
||||
return make_float3(pow(x[0], gamma), pow(x[1], gamma), pow(x[2], gamma));
|
||||
}
|
||||
|
||||
ccl_device float diff_GTR1(float NdotH, float a) {
|
||||
if (a >= 1.0f) return 1.0f / M_PI_F;
|
||||
float a2 = a*a;
|
||||
float t = 1.0f + (a2 - 1.0f) * NdotH * NdotH;
|
||||
return (a2 - 1.0f) / (M_PI_F * log(a2) * t);
|
||||
}
|
||||
|
||||
ccl_device float diff_GTR2(float NdotH, float a) {
|
||||
float a2 = a * a;
|
||||
float t = 1.0f + (a2 - 1.0f) * NdotH * NdotH;
|
||||
return a2 / (M_PI_F * t * t);
|
||||
}
|
||||
|
||||
ccl_device float diff_GTR2_aniso(
|
||||
float NdotH,
|
||||
float HdotX,
|
||||
float HdotY,
|
||||
float ax,
|
||||
float ay)
|
||||
{
|
||||
return 1.0f / (M_PI_F * ax * ay * diff_sqr(diff_sqr(HdotX / ax) + diff_sqr(HdotY / ay)
|
||||
+ NdotH * NdotH));
|
||||
}
|
||||
|
||||
ccl_device float diff_smithG_GGX(float Ndotv, float alphaG) {
|
||||
float a = alphaG * alphaG;
|
||||
float b = Ndotv * Ndotv;
|
||||
return 1.0f / (Ndotv + sqrtf(a + b - a * b));
|
||||
}
|
||||
|
||||
ccl_device float diff_SchlickFresnel(float u) {
|
||||
float m = clamp(1.0f - u, 0.0f, 1.0f);
|
||||
float m2 = m * m;
|
||||
return m2 * m2 * m; // pow(m, 5)
|
||||
}
|
||||
|
||||
ccl_device float3 diff_transform_to_local(const float3& v, const float3& n,
|
||||
const float3& x, const float3& y)
|
||||
{
|
||||
return make_float3(dot(v, x), dot(v, n), dot(v, y));
|
||||
}
|
||||
|
||||
ccl_device float3 diff_mix(float3 x, float3 y, float a) {
|
||||
return x * (1.0f - a) + y * a;
|
||||
}
|
||||
|
||||
ccl_device float diff_mix(float x, float y, float a) {
|
||||
return x * (1.0f - a) + y * a;
|
||||
}
|
||||
|
||||
/* structures */
|
||||
struct DisneyDiffuseBRDFParams {
|
||||
// brdf parameters
|
||||
float3 m_base_color;
|
||||
@@ -110,23 +47,22 @@ struct DisneyDiffuseBRDFParams {
|
||||
// precomputed values
|
||||
float3 m_cdlin, m_ctint, m_csheen;
|
||||
float m_cdlum;
|
||||
float m_weights[4];
|
||||
|
||||
void precompute_values() {
|
||||
m_cdlin = m_base_color;
|
||||
m_cdlum = 0.3f * m_cdlin[0] + 0.6f * m_cdlin[1] + 0.1f * m_cdlin[2]; // luminance approx.
|
||||
|
||||
m_ctint = m_cdlum > 0.0f ? m_cdlin / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
|
||||
m_csheen = diff_mix(make_float3(1.0f, 1.0f, 1.0f), m_ctint, m_sheen_tint);
|
||||
m_csheen = mix(make_float3(1.0f, 1.0f, 1.0f), m_ctint, m_sheen_tint);
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct DisneyDiffuseBRDFParams DisneyDiffuseBRDFParams;
|
||||
|
||||
/* brdf */
|
||||
|
||||
ccl_device float3 calculate_disney_diffuse_brdf(const ShaderClosure *sc,
|
||||
const DisneyDiffuseBRDFParams *params, float3 N, float3 V, float3 L,
|
||||
float3 H, float *pdf, bool withNdotL = true)
|
||||
float3 H, float *pdf)
|
||||
{
|
||||
float NdotL = dot(N, L);
|
||||
float NdotV = dot(N, V);
|
||||
@@ -139,61 +75,32 @@ ccl_device float3 calculate_disney_diffuse_brdf(const ShaderClosure *sc,
|
||||
float LdotH = dot(L, H);
|
||||
|
||||
float Fd = 0.0f;
|
||||
float FL = diff_SchlickFresnel(NdotL), FV = diff_SchlickFresnel(NdotV);
|
||||
float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
|
||||
|
||||
if (params->m_subsurface != 1.0f) {
|
||||
const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * params->m_roughness;
|
||||
Fd = diff_mix(1.0f, Fd90, FL) * diff_mix(1.0f, Fd90, FV);
|
||||
Fd = mix(1.0f, Fd90, FL) * mix(1.0f, Fd90, FV);
|
||||
}
|
||||
|
||||
if (params->m_subsurface > 0.0f) {
|
||||
float Fss90 = LdotH*LdotH * params->m_roughness;
|
||||
float Fss = diff_mix(1.0f, Fss90, FL) * diff_mix(1.0f, Fss90, FV);
|
||||
float Fss = mix(1.0f, Fss90, FL) * mix(1.0f, Fss90, FV);
|
||||
float ss = 1.25f * (Fss * (1.0f / (NdotL + NdotV) - 0.5f) + 0.5f);
|
||||
Fd = diff_mix(Fd, ss, params->m_subsurface);
|
||||
Fd = mix(Fd, ss, params->m_subsurface);
|
||||
}
|
||||
|
||||
float3 value = M_1_PI_F * Fd * params->m_cdlin;
|
||||
|
||||
//if (params->m_gamma > 0.5f)
|
||||
*pdf = M_1_PI_F;
|
||||
|
||||
/*if (params->m_exposure > 0.95f)
|
||||
*pdf *= params->m_cdlum;
|
||||
else if (params->m_exposure > 0.85f)
|
||||
*pdf *= params->m_cdlum * NdotL;
|
||||
else if (params->m_exposure > 0.75f)
|
||||
*pdf *= params->m_cdlum * 0.5f;
|
||||
else if (params->m_exposure > 0.65f)
|
||||
*pdf *= params->m_cdlum * NdotL * 0.5f;
|
||||
else if (params->m_exposure > 0.55f)
|
||||
*pdf *= NdotL;
|
||||
else if (params->m_exposure > 0.45f)
|
||||
*pdf *= NdotL * 0.5f;
|
||||
else if (params->m_exposure > 0.35f)*/
|
||||
*pdf *= 0.5f;
|
||||
*pdf = M_1_PI_F * 0.5f;
|
||||
|
||||
// sheen component
|
||||
if (params->m_sheen != 0.0f) {
|
||||
float FH = diff_SchlickFresnel(LdotH);
|
||||
float FH = schlick_fresnel(LdotH);
|
||||
|
||||
value += FH * params->m_sheen * params->m_csheen;
|
||||
//*pdf += 0.5f * M_1_PI_F * params->m_sheen;
|
||||
}
|
||||
|
||||
if (withNdotL)
|
||||
value *= NdotL;
|
||||
|
||||
// brightness
|
||||
//value *= params->m_brightness;
|
||||
|
||||
// exposure
|
||||
//value *= pow(2.0f, params->m_exposure);
|
||||
|
||||
// gamma
|
||||
/*value[0] = pow(value[0], 1.0f / params->m_gamma);
|
||||
value[1] = pow(value[1], 1.0f / params->m_gamma);
|
||||
value[2] = pow(value[2], 1.0f / params->m_gamma);*/
|
||||
value *= NdotL;
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -236,17 +143,12 @@ ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, const DisneyD
|
||||
{
|
||||
float3 N = normalize(sc->N);
|
||||
|
||||
/*if (params->m_brightness > 0.5f)
|
||||
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
else*/
|
||||
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
|
||||
if (dot(Ng, *omega_in) > 0) {
|
||||
float3 V = I; // outgoing
|
||||
float3 L = *omega_in; // incoming
|
||||
float3 H = normalize(L + V);
|
||||
float3 H = normalize(I + *omega_in);
|
||||
|
||||
*eval = calculate_disney_diffuse_brdf(sc, params, N, V, L, H, pdf, true);
|
||||
*eval = calculate_disney_diffuse_brdf(sc, params, N, I, *omega_in, H, pdf);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
|
||||
@@ -33,76 +33,8 @@
|
||||
#ifndef __BSDF_DISNEY_SPECULAR_H__
|
||||
#define __BSDF_DISNEY_SPECULAR_H__
|
||||
|
||||
#include <cmath>
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* DISNEY SPECULAR */
|
||||
|
||||
ccl_device float spec_sqr(float a) {
|
||||
return a * a;
|
||||
}
|
||||
|
||||
ccl_device float3 spec_mon2lin(float3 x, float gamma) {
|
||||
return make_float3(pow(x[0], gamma), pow(x[1], gamma), pow(x[2], gamma));
|
||||
}
|
||||
|
||||
ccl_device float spec_GTR1(float NdotH, float a) {
|
||||
if (a >= 1.0f) return 1.0f / M_PI_F;
|
||||
float a2 = a*a;
|
||||
float t = 1.0f + (a2 - 1.0f) * NdotH * NdotH;
|
||||
return (a2 - 1.0f) / (M_PI_F * log(a2) * t);
|
||||
}
|
||||
|
||||
ccl_device float spec_GTR2(float NdotH, float a) {
|
||||
float a2 = a * a;
|
||||
float t = 1.0f + (a2 - 1.0f) * NdotH * NdotH;
|
||||
return a2 / (M_PI_F * t * t);
|
||||
}
|
||||
|
||||
ccl_device float spec_GTR2_aniso(
|
||||
float NdotH,
|
||||
float HdotX,
|
||||
float HdotY,
|
||||
float ax,
|
||||
float ay)
|
||||
{
|
||||
return 1.0f / (M_PI_F * ax * ay * spec_sqr(spec_sqr(HdotX / ax) + spec_sqr(HdotY / ay)
|
||||
+ NdotH * NdotH));
|
||||
}
|
||||
|
||||
ccl_device float spec_smithG_GGX(float Ndotv, float alphaG) {
|
||||
float a = alphaG * alphaG;
|
||||
float b = Ndotv * Ndotv;
|
||||
return 1.0f / (Ndotv + sqrtf(a + b - a * b));
|
||||
}
|
||||
|
||||
ccl_device float spec_SchlickFresnel(float u) {
|
||||
float m = clamp(1.0f - u, 0.0f, 1.0f);
|
||||
float m2 = m * m;
|
||||
return m2 * m2 * m; // pow(m, 5)
|
||||
}
|
||||
|
||||
ccl_device float3 spec_transform_to_local(const float3& v, const float3& n,
|
||||
const float3& x, const float3& y)
|
||||
{
|
||||
return make_float3(dot(v, x), dot(v, n), dot(v, y));
|
||||
}
|
||||
|
||||
ccl_device float3 spec_mix(float3 x, float3 y, float a) {
|
||||
return x * (1.0f - a) + y * a;
|
||||
}
|
||||
|
||||
ccl_device float spec_mix(float x, float y, float a) {
|
||||
return x * (1.0f - a) + y * a;
|
||||
}
|
||||
|
||||
ccl_device float spec_max(float a, float b) {
|
||||
if (a > b) return a;
|
||||
else return b;
|
||||
}
|
||||
|
||||
/* structures */
|
||||
struct DisneySpecularBRDFParams {
|
||||
// brdf parameters
|
||||
float3 m_base_color;
|
||||
@@ -124,112 +56,21 @@ struct DisneySpecularBRDFParams {
|
||||
|
||||
m_ctint = m_cdlum > 0.0f ? m_cdlin / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
|
||||
|
||||
m_cspec0 = spec_mix(m_specular * 0.08f * spec_mix(make_float3(1.0f, 1.0f, 1.0f),
|
||||
m_cspec0 = mix(m_specular * 0.08f * mix(make_float3(1.0f, 1.0f, 1.0f),
|
||||
m_ctint, m_specular_tint), m_cdlin, m_metallic);
|
||||
|
||||
float aspect = sqrt(1.0f - m_anisotropic * 0.9f);
|
||||
m_ax = spec_max(0.001f, spec_sqr(m_roughness) / aspect);
|
||||
m_ay = spec_max(0.001f, spec_sqr(m_roughness) * aspect);
|
||||
float r2 = sqr(m_roughness);
|
||||
m_ax = fmaxf(0.001f, r2 / aspect);
|
||||
m_ay = fmaxf(0.001f, r2 * aspect);
|
||||
|
||||
m_roughg = spec_sqr(m_roughness * 0.5f + 0.5f);
|
||||
m_roughg = sqr(m_roughness * 0.5f + 0.5f);
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct DisneySpecularBRDFParams DisneySpecularBRDFParams;
|
||||
|
||||
|
||||
ccl_device_inline void spec_microfacet_ggx_sample_slopes(
|
||||
const float cos_theta_i, const float sin_theta_i,
|
||||
float randu, float randv, float *slope_x, float *slope_y,
|
||||
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_inline float3 spec_microfacet_sample_stretched(
|
||||
const float3 omega_i, const float alpha_x, const float alpha_y,
|
||||
const float randu, const float randv,
|
||||
bool beckmann, 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;
|
||||
|
||||
spec_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));
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_specular_setup(ShaderClosure *sc)
|
||||
{
|
||||
sc->type = CLOSURE_BSDF_DISNEY_SPECULAR_ID;
|
||||
@@ -312,8 +153,8 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc,
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
|
||||
float FH = spec_SchlickFresnel(dot(omega_in, m));
|
||||
float3 F = spec_mix(params->m_cspec0, make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
float FH = schlick_fresnel(dot(omega_in, m));
|
||||
float3 F = mix(params->m_cspec0, make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
|
||||
float3 out = F * G * common;
|
||||
|
||||
@@ -361,7 +202,7 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc, const Disney
|
||||
float3 m;
|
||||
float G1o;
|
||||
|
||||
local_m = spec_microfacet_sample_stretched(local_I, alpha_x, alpha_y,
|
||||
local_m = importance_sample_microfacet_stretched(local_I, alpha_x, alpha_y,
|
||||
randu, randv, false, &G1o);
|
||||
|
||||
m = X*local_m.x + Y*local_m.y + Z*local_m.z;
|
||||
@@ -427,8 +268,8 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc, const Disney
|
||||
float common = (G1o * D) * 0.25f / cosNO;
|
||||
*pdf = common;
|
||||
|
||||
float FH = spec_SchlickFresnel(dot(*omega_in, m));
|
||||
float3 F = spec_mix(params->m_cspec0, make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
float FH = schlick_fresnel(dot(*omega_in, m));
|
||||
float3 F = mix(params->m_cspec0, make_float3(1.0f, 1.0f, 1.0f), FH);
|
||||
|
||||
*eval = G1i * common * F;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,18 @@ ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k
|
||||
}
|
||||
#endif
|
||||
|
||||
ccl_device_inline float schlick_fresnel(float u)
|
||||
{
|
||||
float m = clamp(1.0f - u, 0.0f, 1.0f);
|
||||
float m2 = m * m;
|
||||
return m2 * m2 * m; // pow(m, 5)
|
||||
}
|
||||
|
||||
ccl_device_inline float sqr(float a)
|
||||
{
|
||||
return a * a;
|
||||
}
|
||||
|
||||
ccl_device float smooth_step(float edge0, float edge1, float x)
|
||||
{
|
||||
float result;
|
||||
@@ -138,6 +150,98 @@ ccl_device float smooth_step(float edge0, float edge1, float x)
|
||||
return result;
|
||||
}
|
||||
|
||||
ccl_device_inline void importance_sample_ggx_slopes(
|
||||
const float cos_theta_i, const float sin_theta_i,
|
||||
float randu, float randv, float *slope_x, float *slope_y,
|
||||
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_inline float3 importance_sample_microfacet_stretched(
|
||||
const float3 omega_i, const float alpha_x, const float alpha_y,
|
||||
const float randu, const float randv,
|
||||
bool beckmann, 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;
|
||||
|
||||
importance_sample_ggx_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));
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_UTIL_H__ */
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "kernel_compat_cpu.h"
|
||||
#include "osl_closures.h"
|
||||
#include "closure/bsdf_util.h"
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "kernel_montecarlo.h"
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "kernel_compat_cpu.h"
|
||||
#include "osl_closures.h"
|
||||
#include "closure/bsdf_util.h"
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "kernel_montecarlo.h"
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "kernel_compat_cpu.h"
|
||||
#include "osl_closures.h"
|
||||
#include "closure/bsdf_util.h"
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "kernel_montecarlo.h"
|
||||
|
||||
@@ -77,6 +77,11 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Scalar */
|
||||
|
||||
ccl_device_inline float mix(float a, float b, float alpha)
|
||||
{
|
||||
return a * (1.0f - alpha) + b * alpha;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef __KERNEL_OPENCL__
|
||||
@@ -221,6 +226,12 @@ ccl_device_inline float smoothstepf(float f)
|
||||
|
||||
/* Float2 Vector */
|
||||
|
||||
ccl_device_inline float2 mix(float2 a, float2 b, float alpha)
|
||||
{
|
||||
float inv_alpha = 1.0f - alpha;
|
||||
return make_float2(a[0] * inv_alpha + b[0] * alpha, a[1] * inv_alpha + b[1] * alpha);
|
||||
}
|
||||
|
||||
#ifndef __KERNEL_OPENCL__
|
||||
|
||||
ccl_device_inline bool is_zero(const float2 a)
|
||||
@@ -412,6 +423,12 @@ ccl_device_inline float2 interp(float2 a, float2 b, float t)
|
||||
|
||||
/* Float3 Vector */
|
||||
|
||||
ccl_device_inline float3 mix(float3 a, float3 b, float alpha)
|
||||
{
|
||||
float inv_alpha = 1.0f - alpha;
|
||||
return make_float3(a[0] * inv_alpha + b[0] * alpha, a[1] * inv_alpha + b[1] * alpha, a[2] * inv_alpha + b[2] * alpha);
|
||||
}
|
||||
|
||||
#ifndef __KERNEL_OPENCL__
|
||||
|
||||
ccl_device_inline float3 operator-(const float3 a)
|
||||
@@ -668,6 +685,13 @@ ccl_device_inline float average(const float3 a)
|
||||
|
||||
/* Float4 Vector */
|
||||
|
||||
|
||||
ccl_device_inline float4 mix(float4 a, float4 b, float alpha)
|
||||
{
|
||||
float inv_alpha = 1.0f - alpha;
|
||||
return make_float4(a[0] * inv_alpha + b[0] * alpha, a[1] * inv_alpha + b[1] * alpha, a[2] * inv_alpha + b[2] * alpha, a[3] * inv_alpha + b[3] * alpha);
|
||||
}
|
||||
|
||||
#ifdef __KERNEL_SSE__
|
||||
|
||||
template<size_t index_0, size_t index_1, size_t index_2, size_t index_3> __forceinline const float4 shuffle(const float4& b)
|
||||
|
||||
Reference in New Issue
Block a user