disney implementation cleaned

This commit is contained in:
2016-05-04 16:08:10 +02:00
parent 30d41da0f0
commit 30da91c9c5
8 changed files with 160 additions and 388 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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__ */

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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)