disney diffuse is working correctly
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
/*
|
||||
* Adapted from Open Shading Language with this license:
|
||||
*
|
||||
@@ -30,12 +31,153 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __BSDF_DISNEY_DIFFUSE_
|
||||
#ifndef __BSDF_DISNEY_DIFFUSE_H__
|
||||
#define __BSDF_DISNEY_DIFFUSE_H__
|
||||
|
||||
#include <cmath>
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* DIFFUSE */
|
||||
/* 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;
|
||||
float m_subsurface;
|
||||
float m_roughness;
|
||||
float m_sheen;
|
||||
float m_sheen_tint;
|
||||
|
||||
// color correction
|
||||
float m_withNdotL;
|
||||
float m_brightness;
|
||||
float m_gamma;
|
||||
float m_exposure;
|
||||
float m_mon2lingamma;
|
||||
|
||||
// precomputed values
|
||||
float3 m_cdlin, m_ctint, m_csheen;
|
||||
float m_cdlum;
|
||||
float m_weights[4];
|
||||
bool m_withNdotL_b;
|
||||
|
||||
void precompute_values() {
|
||||
m_cdlin = diff_mon2lin(m_base_color, m_mon2lingamma); //make_float3(1.0f, 0.795f, 0.0f));
|
||||
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_gamma = clamp(m_gamma, 0.0f, 5.0f);
|
||||
m_exposure = clamp(m_exposure, -6.0f, 6.0f);
|
||||
m_withNdotL_b = (m_withNdotL > 0.5f);
|
||||
}
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
float NdotL = dot(N, L);
|
||||
float NdotV = dot(N, V);
|
||||
|
||||
if (NdotL < 0 || NdotV < 0) {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
float LdotH = dot(L, H);
|
||||
|
||||
float Fd = 0.0f;
|
||||
float FL = diff_SchlickFresnel(NdotL), FV = diff_SchlickFresnel(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);
|
||||
}
|
||||
|
||||
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 ss = 1.25f * (Fss * (1.0f / (NdotL + NdotV) - 0.5f) + 0.5f);
|
||||
Fd = diff_mix(Fd, ss, params->m_subsurface);
|
||||
}
|
||||
|
||||
float3 value = M_1_PI_F * Fd * params->m_cdlin;
|
||||
*pdf = NdotL * M_1_PI_F * params->m_cdlum;
|
||||
|
||||
// sheen component
|
||||
if (params->m_sheen != 0.0f) {
|
||||
float FH = diff_SchlickFresnel(LdotH);
|
||||
|
||||
value += FH * params->m_sheen * params->m_csheen;
|
||||
*pdf += (1.0f / M_2PI_F) * params->m_sheen;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_diffuse_setup(ShaderClosure *sc)
|
||||
{
|
||||
@@ -44,46 +186,168 @@ ccl_device int bsdf_disney_diffuse_setup(ShaderClosure *sc)
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_diffuse_eval_reflect(const ShaderClosure *sc,
|
||||
float3 color, const float3 I, const float3 omega_in, float *pdf)
|
||||
const DisneyDiffuseBRDFParams *params, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
float3 N = sc->N;
|
||||
float3 N = normalize(sc->N);
|
||||
float3 V = I; // outgoing
|
||||
float3 L = omega_in; // incoming
|
||||
float3 H = normalize(L + V);
|
||||
|
||||
float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
*pdf = cos_pi;
|
||||
return make_float3(cos_pi * color[0], cos_pi * color[1], cos_pi * color[2]);
|
||||
if (dot(sc->N, omega_in) > 0.0f) {
|
||||
float3 value = calculate_disney_diffuse_brdf(sc, params, N, V, L, H, pdf);
|
||||
|
||||
value *= dot(N, L);
|
||||
|
||||
// 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);
|
||||
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_disney_diffuse_eval_transmit(const ShaderClosure *sc,
|
||||
float3 color, const float3 I, const float3 omega_in, float *pdf)
|
||||
ccl_device float3 bsdf_disney_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
|
||||
{
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, float3 color,
|
||||
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_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc, const DisneyDiffuseBRDFParams *params,
|
||||
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)
|
||||
{
|
||||
float3 N = sc->N;
|
||||
float3 N = normalize(sc->N);
|
||||
|
||||
// distribution over the hemisphere
|
||||
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
|
||||
if (dot(Ng, *omega_in) > 0) {
|
||||
float3 V = I; // outgoing
|
||||
float3 L = *omega_in; // incoming
|
||||
float3 H = normalize(L + V);
|
||||
|
||||
float3 value = calculate_disney_diffuse_brdf(sc, params, N, V, L, H, pdf);
|
||||
|
||||
if (params->m_withNdotL_b)
|
||||
value *= dot(N, L);
|
||||
|
||||
// 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);
|
||||
|
||||
*eval = make_float3(value[0], value[1], value[2]);
|
||||
|
||||
if(dot(Ng, *omega_in) > 0.0f) {
|
||||
*eval = make_float3(*pdf * color[0], *pdf * color[1], *pdf * color[2]);
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
|
||||
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
|
||||
*domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
|
||||
*domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
*pdf = 0.0f;
|
||||
else {
|
||||
*pdf = 0;
|
||||
}
|
||||
|
||||
return LABEL_REFLECT|LABEL_DIFFUSE;
|
||||
/*// we are viewing the surface from the right side - send a ray out with cosine
|
||||
// distribution over the hemisphere
|
||||
sample_cos_hemisphere(-N, randu, randv, omega_in, pdf);
|
||||
if(dot(Ng, *omega_in) < 0) {
|
||||
float3 H = normalize(*omega_in - I);
|
||||
*eval = calculate_disney_diffuse_brdf(sc, params, -N, -I, *omega_in, H, pdf);
|
||||
|
||||
// multiply with NdotL
|
||||
//if (params->m_withNdotL_b)
|
||||
// *eval *= dot(N, L);
|
||||
|
||||
// brightness
|
||||
*eval *= params->m_brightness;
|
||||
|
||||
// exposure
|
||||
*eval *= pow(2.0f, params->m_exposure);
|
||||
|
||||
// gamma
|
||||
(*eval)[0] = pow((*eval)[0], 1.0f / params->m_gamma);
|
||||
(*eval)[1] = pow((*eval)[1], 1.0f / params->m_gamma);
|
||||
(*eval)[2] = pow((*eval)[2], 1.0f / params->m_gamma);
|
||||
//*eval = make_float3(*pdf, *pdf, *pdf);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
// TODO: find a better approximation for the diffuse bounce
|
||||
*domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
|
||||
*domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*pdf = 0;
|
||||
}*/
|
||||
return LABEL_DIFFUSE;
|
||||
|
||||
/*float3 N = normalize(sc->N);
|
||||
float3 T = normalize(sc->T);
|
||||
float3 X, Y;
|
||||
|
||||
float cos_theta, phi, theta, sin_phi, cos_phi;
|
||||
|
||||
make_orthonormals_tangent(N, T, &X, &Y);
|
||||
|
||||
phi = 2.0f * M_PI_F * randu;
|
||||
theta = 2.0f * M_PI_F * randv;
|
||||
cos_theta = cosf(theta);
|
||||
sin_phi = sinf(phi);
|
||||
cos_phi = cosf(phi);
|
||||
|
||||
float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
|
||||
float3 H = normalize(sin_theta * cos_phi * X + sin_theta * sin_phi * Y + cos_theta * N);
|
||||
|
||||
*omega_in = 2.0f * dot(I, H) * H - I;
|
||||
|
||||
float3 V = I; // outgoing
|
||||
float3 L = *omega_in; // incoming
|
||||
|
||||
*eval = calculate_disney_diffuse_brdf(sc, params, N, V, L, H, pdf);
|
||||
|
||||
// multiply with NdotL
|
||||
//if (params->m_withNdotL_b)
|
||||
// *eval *= dot(N, L);
|
||||
|
||||
// brightness
|
||||
*eval *= params->m_brightness;
|
||||
|
||||
// exposure
|
||||
*eval *= pow(2.0f, params->m_exposure);
|
||||
|
||||
// gamma
|
||||
(*eval)[0] = pow((*eval)[0], 1.0f / params->m_gamma);
|
||||
(*eval)[1] = pow((*eval)[1], 1.0f / params->m_gamma);
|
||||
(*eval)[2] = pow((*eval)[2], 1.0f / params->m_gamma);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
*domega_in_dx = 2 * dot(N, dIdx) * N - dIdx;
|
||||
*domega_in_dy = 2 * dot(N, dIdy) * N - dIdy;
|
||||
#endif
|
||||
|
||||
return LABEL_REFLECT|LABEL_DIFFUSE;*/
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BSDF_DISNEY_DIFFUSE_H__ */
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ using namespace OSL;
|
||||
|
||||
class DisneyDiffuseClosure : public CBSDFClosure {
|
||||
public:
|
||||
float3 color;
|
||||
DisneyDiffuseBRDFParams dp;
|
||||
|
||||
DisneyDiffuseClosure() : CBSDFClosure(LABEL_DIFFUSE)
|
||||
{}
|
||||
@@ -56,21 +56,22 @@ public:
|
||||
{
|
||||
sc.prim = this;
|
||||
m_shaderdata_flag = bsdf_disney_diffuse_setup(&sc);
|
||||
|
||||
dp.precompute_values();
|
||||
}
|
||||
|
||||
void blur(float roughness)
|
||||
{
|
||||
//bsdf_disney_diffuse_blur(&sc, roughness);
|
||||
}
|
||||
|
||||
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
|
||||
{
|
||||
return bsdf_disney_diffuse_eval_reflect(&sc, color, omega_out, omega_in, &pdf);
|
||||
return bsdf_disney_diffuse_eval_reflect(&sc, &dp, omega_out, omega_in, &pdf);
|
||||
}
|
||||
|
||||
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
|
||||
{
|
||||
return bsdf_disney_diffuse_eval_transmit(&sc, color, omega_out, omega_in, &pdf);
|
||||
return bsdf_disney_diffuse_eval_transmit(&sc, omega_out, omega_in, &pdf);
|
||||
}
|
||||
|
||||
int sample(const float3 &Ng,
|
||||
@@ -79,7 +80,7 @@ public:
|
||||
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
|
||||
float &pdf, float3 &eval) const
|
||||
{
|
||||
return bsdf_disney_diffuse_sample(&sc, color, Ng, omega_out, domega_out_dx, domega_out_dy,
|
||||
return bsdf_disney_diffuse_sample(&sc, &dp, Ng, omega_out, domega_out_dx, domega_out_dy,
|
||||
randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
|
||||
}
|
||||
};
|
||||
@@ -88,7 +89,16 @@ ClosureParam *closure_bsdf_disney_diffuse_params()
|
||||
{
|
||||
static ClosureParam params[] = {
|
||||
CLOSURE_FLOAT3_PARAM(DisneyDiffuseClosure, sc.N),
|
||||
CLOSURE_FLOAT3_PARAM(DisneyDiffuseClosure, color),
|
||||
CLOSURE_FLOAT3_PARAM(DisneyDiffuseClosure, dp.m_base_color),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_subsurface),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_roughness),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_sheen),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_sheen_tint),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_withNdotL),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_brightness),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_gamma),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_exposure),
|
||||
CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, dp.m_mon2lingamma),
|
||||
CLOSURE_STRING_KEYPARAM(DisneyDiffuseClosure, label, "label"),
|
||||
CLOSURE_FINISH_PARAM(DisneyDiffuseClosure)
|
||||
};
|
||||
|
||||
@@ -536,7 +536,8 @@ closure color emission() BUILTIN;
|
||||
closure color background() BUILTIN;
|
||||
closure color holdout() BUILTIN;
|
||||
closure color ambient_occlusion() BUILTIN;
|
||||
closure color disney_diffuse(normal N, color c) BUILTIN;
|
||||
closure color disney_diffuse(normal N, color baseColor, float subsurface, float roughness, float sheen,
|
||||
float sheenTint, float withNdotL, float brightness, float gamma, float exposure, float mon2lingamma) BUILTIN;
|
||||
|
||||
// BSSRDF
|
||||
closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN;
|
||||
|
||||
Reference in New Issue
Block a user