Skip to content

Commit e24ec8b

Browse files
Transmission works but is buggy and is w/o importance sampling
1 parent dfc1c71 commit e24ec8b

File tree

7 files changed

+121
-252
lines changed

7 files changed

+121
-252
lines changed

src/shaders/common/brdf.glsl renamed to src/shaders/common/disney.glsl

Lines changed: 94 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,39 @@ float DisneyPdf(in Ray ray, inout State state, in vec3 bsdfDir)
3636
vec3 L = bsdfDir;
3737
vec3 H = normalize(L + V);
3838

39-
//if (dot(N, L) < 0.0)
40-
// return 1.0;
39+
float brdfPdf = 0.0;
40+
float bsdfPdf = 0.0;
4141

42-
float NDotH = dot(N, H);
42+
float NDotH = abs(dot(N, H));
4343

44-
float specularAlpha = mix(0.1, 0.001, state.mat.roughness);
44+
// TODO: Fix importance sampling for microfacet transmission
45+
if (dot(N, L) <= 0.0 && state.mat.transmission > 0.0)
46+
return 1.0;
47+
48+
float specularAlpha = max(0.001, state.mat.roughness);
4549
float clearcoatAlpha = mix(0.1, 0.001, state.mat.clearcoatGloss);
4650

4751
float diffuseRatio = 0.5 * (1.0 - state.mat.metallic);
4852
float specularRatio = 1.0 - diffuseRatio;
4953

5054
float aspect = sqrt(1.0 - state.mat.anisotropic * 0.9);
51-
float ax = max(0.001, (state.mat.roughness * state.mat.roughness) / aspect);
52-
float ay = max(0.001, (state.mat.roughness * state.mat.roughness) * aspect);
55+
float ax = max(0.001, state.mat.roughness / aspect);
56+
float ay = max(0.001, state.mat.roughness * aspect);
5357

5458
// PDFs for brdf
5559
float pdfGTR2_aniso = GTR2_aniso(NDotH, dot(H, state.tangent), dot(H, state.bitangent), ax, ay) * NDotH;
5660
float pdfGTR1 = GTR1(NDotH, clearcoatAlpha) * NDotH;
5761
float ratio = 1.0 / (1.0 + state.mat.clearcoat);
5862
float pdfSpec = mix(pdfGTR1, pdfGTR2_aniso, ratio) / (4.0 * abs(dot(L, H)));
5963
float pdfDiff = abs(dot(L, N)) * (1.0 / PI);
60-
float brdfPdf = diffuseRatio * pdfDiff + specularRatio * pdfSpec;
64+
brdfPdf = diffuseRatio * pdfDiff + specularRatio * pdfSpec;
6165

6266
// PDFs for bsdf
6367
float pdfGTR2 = GTR2(NDotH, specularAlpha) * NDotH;
64-
float bsdfPdf = pdfGTR2 / (4.0 * abs(dot(L, H)));
68+
float F = Fresnel(abs(dot(L, H)), 1.0, state.mat.ior);
69+
bsdfPdf = pdfGTR2 * F / (4.0 * abs(dot(L, H)));
6570

66-
return brdfPdf;//mix(brdfPdf, bsdfPdf, state.mat.transmission);
71+
return mix(brdfPdf, bsdfPdf, state.mat.transmission);
6772
}
6873

6974
//-----------------------------------------------------------------------
@@ -72,39 +77,42 @@ vec3 DisneySample(in Ray ray, inout State state)
7277
{
7378
vec3 N = state.ffnormal;
7479
vec3 V = -ray.direction;
80+
state.specularBounce = false;
7581

7682
vec3 dir;
7783

7884
float r1 = rand();
7985
float r2 = rand();
80-
//float bsdfProb = rand();
8186

8287
// BSDF
83-
/*if (bsdfProb < state.mat.transmission)
88+
if (rand() < state.mat.transmission)
8489
{
8590
float n1 = 1.0;
8691
float n2 = state.mat.ior;
8792

93+
vec3 H = ImportanceSampleGGX(state.mat.roughness, r1, r2);
94+
H = state.tangent * H.x + state.bitangent * H.y + N * H.z;
95+
8896
float theta = abs(dot(-V, N));
8997
float eta = dot(state.normal, state.ffnormal) > 0.0 ? (n1 / n2) : (n2 / n1);
9098
float cos2t = 1.0 - eta * eta * (1.0 - theta * theta);
9199

92-
vec3 H = ImportanceSampleGGX(state.mat.roughness, r1, r2);
93-
H = state.tangent * H.x + state.bitangent * H.y + N * H.z;
94-
95100
float F = Fresnel(theta, n1, n2);
96101

97102
if (cos2t < 0.0 || rand() < F)
98103
dir = normalize(reflect(-V, H));
99104
else
105+
{
100106
dir = normalize(refract(-V, H, eta));
107+
state.specularBounce = true;
108+
}
101109
}
102-
else*/
110+
// BRDF
111+
else
103112
{
104-
float probability = rand();
105113
float diffuseRatio = 0.5 * (1.0 - state.mat.metallic);
106114

107-
if (probability < diffuseRatio)
115+
if (rand() < diffuseRatio)
108116
{
109117
vec3 H = CosineSampleHemisphere(r1, r2);
110118
H = state.tangent * H.x + state.bitangent * H.y + N * H.z;
@@ -128,63 +136,75 @@ vec3 DisneyEval(in Ray ray, inout State state, in vec3 bsdfDir)
128136
vec3 V = -ray.direction;
129137
vec3 L = bsdfDir;
130138

131-
float NDotL = dot(N, L);
132-
float NDotV = dot(N, V);
133-
134-
if (NDotL <= 0.0 || NDotV <= 0.0)
135-
return vec3(0.0);
139+
float NDotL = abs(dot(N, L));
140+
float NDotV = abs(dot(N, V));
136141

137142
vec3 H = normalize(L + V);
138-
float NDotH = dot(N, H);
139-
float LDotH = dot(L, H);
140-
141-
vec3 Cdlin = state.mat.albedo;
142-
float Cdlum = 0.3 * Cdlin.x + 0.6 * Cdlin.y + 0.1 * Cdlin.z; // luminance approx.
143-
144-
vec3 Ctint = Cdlum > 0.0 ? Cdlin / Cdlum : vec3(1.0f); // normalize lum. to isolate hue+sat
145-
vec3 Cspec0 = mix(state.mat.specular * 0.08 * mix(vec3(1.0), Ctint, state.mat.specularTint), Cdlin, state.mat.metallic);
146-
vec3 Csheen = mix(vec3(1.0), Ctint, state.mat.sheenTint);
147-
148-
// Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
149-
// and mix in diffuse retro-reflection based on roughness
150-
float FL = SchlickFresnel(NDotL);
151-
float FV = SchlickFresnel(NDotV);
152-
float Fd90 = 0.5 + 2.0 * LDotH * LDotH * state.mat.roughness;
153-
float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
154-
155-
// Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
156-
// 1.25 scale is used to (roughly) preserve albedo
157-
// Fss90 used to "flatten" retroreflection based on roughness
158-
float Fss90 = LDotH * LDotH * state.mat.roughness;
159-
float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
160-
float ss = 1.25 * (Fss * (1.0 / (NDotL + NDotV) - 0.5) + 0.5);
161-
162-
// specular
163-
/*float a = max(0.001, state.mat.roughness);
164-
float Ds = GTR2(NDotH, a);
165-
float FH = SchlickFresnel(LDotH);
166-
vec3 Fs = mix(Cspec0, vec3(1.0), FH);
167-
float roughg = (state.mat.roughness * 0.5 + 0.5);
168-
roughg *= roughg;
169-
float Gs = SmithG_GGX(NDotL, roughg) * SmithG_GGX(NDotV, roughg);*/
170-
171-
// specular
172-
float aspect = sqrt(1.0 - state.mat.anisotropic * 0.9);
173-
float ax = max(0.001, (state.mat.roughness * state.mat.roughness) / aspect);
174-
float ay = max(0.001, (state.mat.roughness * state.mat.roughness) * aspect);
175-
float Ds = GTR2_aniso(NDotH, dot(H, state.tangent), dot(H, state.bitangent), ax, ay);
176-
float FH = SchlickFresnel(LDotH);
177-
vec3 Fs = mix(Cspec0, vec3(1.0), FH);
178-
float Gs = SmithG_GGX_aniso(NDotL, dot(L, state.tangent), dot(L, state.bitangent), ax, ay);
179-
Gs *= SmithG_GGX_aniso(NDotV, dot(V, state.tangent), dot(V, state.bitangent), ax, ay);
180-
181-
// sheen
182-
vec3 Fsheen = FH * state.mat.sheen * Csheen;
183-
184-
// clearcoat (ior = 1.5 -> F0 = 0.04)
185-
float Dr = GTR1(NDotH, mix(0.1, 0.001, state.mat.clearcoatGloss));
186-
float Fr = mix(0.04, 1.0, FH);
187-
float Gr = SmithG_GGX(NDotL, 0.25) * SmithG_GGX(NDotV, 0.25);
188-
189-
return ((1.0 / PI) * mix(Fd, ss, state.mat.subsurface) * Cdlin + Fsheen) * (1.0 - state.mat.metallic) + Gs * Fs * Ds + 0.25 * state.mat.clearcoat * Gr * Fr * Dr;
143+
144+
float NDotH = abs(dot(N, H));
145+
float LDotH = abs(dot(L, H));
146+
147+
vec3 brdf = vec3(0.0);
148+
vec3 bsdf = vec3(0.0);
149+
150+
// TODO: Fix bsdf for microfacet transmission
151+
if (state.mat.transmission > 0.0)
152+
{
153+
if (dot(N, L) <= 0.0)
154+
bsdf = state.mat.albedo / abs(NDotL);
155+
else
156+
{
157+
float a = max(0.001, state.mat.roughness);
158+
float F = Fresnel(LDotH, 1.0, state.mat.ior);
159+
float D = GTR2(NDotH, a);
160+
float G = SmithG_GGX(NDotL, a) * SmithG_GGX(NDotV, a);
161+
bsdf = state.mat.albedo * F * G * D;
162+
}
163+
}
164+
165+
if (state.mat.transmission < 1.0)
166+
{
167+
vec3 Cdlin = state.mat.albedo;
168+
float Cdlum = 0.3 * Cdlin.x + 0.6 * Cdlin.y + 0.1 * Cdlin.z; // luminance approx.
169+
170+
vec3 Ctint = Cdlum > 0.0 ? Cdlin / Cdlum : vec3(1.0f); // normalize lum. to isolate hue+sat
171+
vec3 Cspec0 = mix(state.mat.specular * 0.08 * mix(vec3(1.0), Ctint, state.mat.specularTint), Cdlin, state.mat.metallic);
172+
vec3 Csheen = mix(vec3(1.0), Ctint, state.mat.sheenTint);
173+
174+
// Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
175+
// and mix in diffuse retro-reflection based on roughness
176+
float FL = SchlickFresnel(NDotL);
177+
float FV = SchlickFresnel(NDotV);
178+
float Fd90 = 0.5 + 2.0 * LDotH * LDotH * state.mat.roughness;
179+
float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
180+
181+
// Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
182+
// 1.25 scale is used to (roughly) preserve albedo
183+
// Fss90 used to "flatten" retroreflection based on roughness
184+
float Fss90 = LDotH * LDotH * state.mat.roughness;
185+
float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
186+
float ss = 1.25 * (Fss * (1.0 / (NDotL + NDotV) - 0.5) + 0.5);
187+
188+
// specular
189+
float aspect = sqrt(1.0 - state.mat.anisotropic * 0.9);
190+
float ax = max(0.001, state.mat.roughness / aspect);
191+
float ay = max(0.001, state.mat.roughness * aspect);
192+
float Ds = GTR2_aniso(NDotH, dot(H, state.tangent), dot(H, state.bitangent), ax, ay);
193+
float FH = SchlickFresnel(LDotH);
194+
vec3 Fs = mix(Cspec0, vec3(1.0), FH);
195+
float Gs = SmithG_GGX_aniso(NDotL, dot(L, state.tangent), dot(L, state.bitangent), ax, ay);
196+
Gs *= SmithG_GGX_aniso(NDotV, dot(V, state.tangent), dot(V, state.bitangent), ax, ay);
197+
198+
// sheen
199+
vec3 Fsheen = FH * state.mat.sheen * Csheen;
200+
201+
// clearcoat (ior = 1.5 -> F0 = 0.04)
202+
float Dr = GTR1(NDotH, mix(0.1, 0.001, state.mat.clearcoatGloss));
203+
float Fr = mix(0.04, 1.0, FH);
204+
float Gr = SmithG_GGX(NDotL, 0.25) * SmithG_GGX(NDotV, 0.25);
205+
206+
brdf = ((1.0 / PI) * mix(Fd, ss, state.mat.subsurface) * Cdlin + Fsheen) * (1.0 - state.mat.metallic) + Gs * Fs * Ds + 0.25 * state.mat.clearcoat * Gr * Fr * Dr;
207+
}
208+
209+
return mix(brdf, bsdf, state.mat.transmission);
190210
}

src/shaders/common/glass.glsl

Lines changed: 0 additions & 152 deletions
This file was deleted.

0 commit comments

Comments
 (0)