Skip to content

Commit

Permalink
merian-nodes: GGX implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
LDAP committed Sep 20, 2024
1 parent 73cee50 commit 68e1184
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 4 deletions.
4 changes: 3 additions & 1 deletion include/merian-shaders/bsdf_diffuse.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
#ifndef _MERIAN_SHADERS_BSDF_DIFFUSE_H_
#define _MERIAN_SHADERS_BSDF_DIFFUSE_H_

// Lambert diffuse BSDF

// n must be normalized
#define bsdf_diffuse_sample(n, random) (make_frame(n) * sample_cos(random))

// solid angle
// solid angle, not error checked against wdotn < 0.
#define bsdf_diffuse_pdf(wodotn) (INV_PI * wodotn)

// solid angle
Expand Down
54 changes: 54 additions & 0 deletions include/merian-shaders/bsdf_ggx.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,58 @@ float smith_g1(const float roughness, const float wodotn) {
return 2.0 * wodotn / (wodotn + sqrt(alpha_sq + (1.0 - alpha_sq) * MERIAN_SQUARE(wodotn)));
}

// minuswi = V
float smith_g_over_minuswidotn(const float roughness, const float minuswidotn, const float wodotn) {
float alpha = MERIAN_SQUARE(roughness);
float g1 = minuswidotn * sqrt(MERIAN_SQUARE(alpha) + (1.0 - MERIAN_SQUARE(alpha)) * MERIAN_SQUARE(wodotn));
float g2 = wodotn * sqrt(MERIAN_SQUARE(alpha) + (1.0 - MERIAN_SQUARE(alpha)) * MERIAN_SQUARE(minuswidotn));
return 2.0 * wodotn / (g1 + g2);
}

// returns a half vector in tangent space
vec3 bsdf_ggx_sample_H(const vec2 random, const float roughness) {
const float phi = TWO_PI * random.x;
const float cosTheta = sqrt((1 - random.y) / (1 + (pow(roughness, 4) - 1) * random.y));
const float sinTheta = sqrt(1 - cosTheta * cosTheta);

return vec3(sinTheta * cos(phi),
sinTheta * sin(phi),
cosTheta);
}

// https://github.com/NVIDIAGameWorks/donut
// MIT Licensed
vec3 bsdf_ggx_sample_H_VNDF(const vec3 random, const float roughness, const vec3 Ve, const float ndf_trim) {
const float alpha = MERIAN_SQUARE(roughness);
const vec3 Vh = normalize(vec3(alpha * Ve.x, alpha * Ve.y, Ve.z));

const float lensq = MERIAN_SQUARE(Vh.x) + MERIAN_SQUARE(Vh.y);
const vec3 T1 = lensq > 0.0 ? vec3(-Vh.y, Vh.x, 0.0) * (1 / sqrt(lensq)) : vec3(1.0, 0.0, 0.0);
const vec3 T2 = cross(Vh, T1);

const float r = sqrt(random.x * ndf_trim);
const float phi = 2.0 * M_PI * random.y;
const float t1 = r * cos(phi);
float t2 = r * sin(phi);
const float s = 0.5 * (1.0 + Vh.z);
t2 = (1.0 - s) * sqrt(1.0 - MERIAN_SQUARE(t1)) + s * t2;

const vec3 Nh = t1 * T1 + t2 * T2 + sqrt(max(0.0, 1.0 - MERIAN_SQUARE(t1) - MERIAN_SQUARE(t2))) * Vh;

return vec3(alpha * Nh.x,
alpha * Nh.y,
max(0.0, Nh.z)
);
}

float bsdf_ggx_sample_VNDF_PDF(const float roughness, const vec3 N, const vec3 minus_wi, const vec3 wo) {
vec3 H = normalize(wo + minus_wi);
float ndoth = clamp(dot(N, H), 0, 1);
float minus_wi_dot_h = clamp(dot(minus_wi, H), 0, 1);

float alpha = MERIAN_SQUARE(roughness);
float D = MERIAN_SQUARE(alpha) / (M_PI * MERIAN_SQUARE(MERIAN_SQUARE(ndoth) * MERIAN_SQUARE(alpha) + (1 - MERIAN_SQUARE(ndoth))));
return (minus_wi_dot_h > 0.0) ? D / (4.0 * minus_wi_dot_h) : 0.0;
}

#endif // _MERIAN_SHADERS_BSDF_GGX_H_
3 changes: 2 additions & 1 deletion include/merian-shaders/bsdf_microfacet.glsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "merian-shaders/common.glsl"
#include "merian-shaders/sampling.glsl"
#include "merian-shaders/fresnel.glsl"

/*
* microfacet model by jonathan:
Expand Down Expand Up @@ -63,7 +64,7 @@ float bsdf_microfacet_eval(const vec3 minus_wi, const mat3x3 frame_mat, const ve
const float sigmaL2 = sigmaSq.x * cosL2 + sigmaSq.y * (1.0 - cosL2);

// Schlick's approximation
const float fresnel = 0.02 + 0.98 * pow(1.0 - dot(minus_wi, H), 5.0);
const float fresnel = fresnel_schlick(dot(minus_wi, H), 0.02);

zL = max(zL, 0.01);
zV = max(zV, 0.01);
Expand Down
20 changes: 18 additions & 2 deletions include/merian-shaders/sampling.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,24 @@ vec3 sample_hemisphere(const vec2 random) {

// sample hemisphere (around 0,0,1), cos lobe, p = cos(theta) / pi
vec3 sample_cos(const vec2 random) {
const float su = sqrt(random.x);
return vec3(su * cos(TWO_PI * random.y), su * sin(TWO_PI * random.y), sqrt(1.0 - random.x));
const float su = sqrt(random.x);
return vec3(su * cos(TWO_PI * random.y), su * sin(TWO_PI * random.y), sqrt(1.0 - random.x));
}

// samples barycentric coordinates of a triangle, p = 1 / A
vec3 sample_triangle(const vec2 random) {
const float x = sqrt(random.x);

return vec3(
1 - x,
x * (1 - random.y),
x * random.y);
}

// samples coordinates on a unit disk, p = 1 / A
vec2 sample_disk(const vec2 random) {
const float angle = TWO_PI * random.x;
return vec2(cos(angle), sin(angle)) * sqrt(random.y);
}

// returns two pseudorandom normal distributed values.
Expand Down

0 comments on commit 68e1184

Please sign in to comment.