Skip to content

Commit fd21720

Browse files
mvaligurskyMartin Valigursky
andauthored
IridescenceDiffraction chunk converted to WGSL (#7611)
Co-authored-by: Martin Valigursky <[email protected]>
1 parent f60b9a2 commit fd21720

File tree

4 files changed

+108
-7
lines changed

4 files changed

+108
-7
lines changed

src/scene/shader-lib/chunks-wgsl/chunks-wgsl.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import glossPS from './standard/frag/gloss.js';
5454
// import gsplatVS from './gsplat/vert/gsplat.js';
5555
import immediateLinePS from './internal/frag/immediateLine.js';
5656
import immediateLineVS from './internal/vert/immediateLine.js';
57-
// import iridescenceDiffractionPS from './lit/frag/iridescenceDiffraction.js';
57+
import iridescenceDiffractionPS from './lit/frag/iridescenceDiffraction.js';
5858
import iridescencePS from './standard/frag/iridescence.js';
5959
import iridescenceThicknessPS from './standard/frag/iridescenceThickness.js';
6060
import iorPS from './standard/frag/ior.js';
@@ -262,7 +262,7 @@ const shaderChunksWGSL = {
262262
// gsplatVS,
263263
immediateLinePS,
264264
immediateLineVS,
265-
// iridescenceDiffractionPS,
265+
iridescenceDiffractionPS,
266266
iridescencePS,
267267
iridescenceThicknessPS,
268268
iorPS,
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
export default /* wgsl */`
2+
uniform material_iridescenceRefractionIndex: f32;
3+
4+
fn iridescence_iorToFresnelScalar(transmittedIor: f32, incidentIor: f32) -> f32 {
5+
return pow((transmittedIor - incidentIor) / (transmittedIor + incidentIor), 2.0);
6+
}
7+
8+
fn iridescence_iorToFresnelVec3(transmittedIor: vec3f, incidentIor: f32) -> vec3f {
9+
return pow((transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)), vec3f(2.0));
10+
}
11+
12+
fn iridescence_fresnelToIor(f0: vec3f) -> vec3f {
13+
let sqrtF0: vec3f = sqrt(f0);
14+
return (vec3f(1.0) + sqrtF0) / (vec3f(1.0) - sqrtF0);
15+
}
16+
17+
const XYZ_TO_REC709: mat3x3f = mat3x3f(
18+
vec3f(3.2404542, -1.5371385, -0.4985314),
19+
vec3f(-0.9692660, 1.8760108, 0.0415560),
20+
vec3f(0.0556434, -0.2040259, 1.0572252)
21+
);
22+
23+
fn iridescence_sensitivity(opd: f32, shift: vec3f) -> vec3f {
24+
let PI: f32 = 3.141592653589793;
25+
let phase: f32 = 2.0 * PI * opd * 1.0e-9;
26+
const val: vec3f = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13);
27+
const pos: vec3f = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06);
28+
const var_: vec3f = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09);
29+
30+
var xyz: vec3f = val * sqrt(2.0 * PI * var_) * cos(pos * phase + shift) * exp(-pow(phase, 2.0) * var_);
31+
xyz.x = xyz.x + 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift[0]) * exp(-4.5282e+09 * pow(phase, 2.0));
32+
xyz = xyz / vec3f(1.0685e-07);
33+
34+
return XYZ_TO_REC709 * xyz;
35+
}
36+
37+
fn iridescence_fresnelScalar(cosTheta: f32, f0: f32) -> f32 {
38+
let x: f32 = clamp(1.0 - cosTheta, 0.0, 1.0);
39+
let x2: f32 = x * x;
40+
let x5: f32 = x * x2 * x2;
41+
return f0 + (1.0 - f0) * x5;
42+
}
43+
44+
fn iridescence_fresnelVec3(cosTheta: f32, f0: vec3f) -> vec3f {
45+
let x: f32 = clamp(1.0 - cosTheta, 0.0, 1.0);
46+
let x2: f32 = x * x;
47+
let x5: f32 = x * x2 * x2;
48+
return f0 + (vec3f(1.0) - f0) * x5;
49+
}
50+
51+
fn calcIridescence(outsideIor: f32, cosTheta: f32, base_f0: vec3f, iridescenceThickness: f32) -> vec3f {
52+
let PI: f32 = 3.141592653589793;
53+
54+
let iridescenceIor: f32 = mix(outsideIor, uniform.material_iridescenceRefractionIndex, smoothstep(0.0, 0.03, iridescenceThickness));
55+
let sinTheta2Sq: f32 = pow(outsideIor / iridescenceIor, 2.0) * (1.0 - pow(cosTheta, 2.0));
56+
let cosTheta2Sq: f32 = 1.0 - sinTheta2Sq;
57+
58+
if (cosTheta2Sq < 0.0) {
59+
return vec3f(1.0);
60+
}
61+
62+
let cosTheta2: f32 = sqrt(cosTheta2Sq);
63+
64+
let r0: f32 = iridescence_iorToFresnelScalar(iridescenceIor, outsideIor);
65+
let r12: f32 = iridescence_fresnelScalar(cosTheta, r0);
66+
let r21: f32 = r12;
67+
let t121: f32 = 1.0 - r12;
68+
69+
let phi12: f32 = select(0.0, PI, iridescenceIor < outsideIor);
70+
let phi21: f32 = PI - phi12;
71+
72+
let baseIor: vec3f = iridescence_fresnelToIor(base_f0 + vec3f(0.0001));
73+
let r1: vec3f = iridescence_iorToFresnelVec3(baseIor, iridescenceIor);
74+
let r23: vec3f = iridescence_fresnelVec3(cosTheta2, r1);
75+
76+
let phi23: vec3f = select(vec3f(0.0), vec3f(PI), baseIor < vec3f(iridescenceIor));
77+
let opd: f32 = 2.0 * iridescenceIor * iridescenceThickness * cosTheta2;
78+
let phi: vec3f = vec3f(phi21) + phi23; // Promote scalar phi21 to vec3f
79+
80+
let r123Sq: vec3f = clamp(vec3f(r12) * r23, vec3f(1e-5), vec3f(0.9999));
81+
let r123: vec3f = sqrt(r123Sq);
82+
let rs: vec3f = pow(vec3f(t121), vec3f(2.0)) * r23 / (vec3f(1.0) - r123Sq);
83+
84+
let c0: vec3f = vec3f(r12) + rs;
85+
var i_irid: vec3f = c0;
86+
87+
var cm: vec3f = rs - vec3f(t121);
88+
89+
cm = cm * r123;
90+
let sm1: vec3f = 2.0 * iridescence_sensitivity(1.0 * opd, 1.0 * phi);
91+
i_irid = i_irid + cm * sm1;
92+
93+
cm = cm * r123;
94+
let sm2: vec3f = 2.0 * iridescence_sensitivity(2.0 * opd, 2.0 * phi);
95+
i_irid = i_irid + cm * sm2;
96+
97+
return max(i_irid, vec3f(0.0));
98+
}
99+
100+
fn getIridescenceDiffraction(cosTheta: f32, specularity: vec3f, iridescenceThickness: f32) -> vec3f {
101+
return calcIridescence(1.0, cosTheta, specularity, iridescenceThickness);
102+
}
103+
`;

src/scene/shader-lib/chunks-wgsl/lit/frag/pass-forward/litForwardBackend.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn evaluateBackend() -> FragmentOutput {
3030
#endif
3131
3232
#ifdef LIT_IRIDESCENCE
33-
var iridescenceFresnel: vec3f = getIridescence(saturate3(dot(dViewDirW, litArgs_worldNormal)), litArgs_specularity, litArgs_iridescence_thickness);
33+
var iridescenceFresnel: vec3f = getIridescenceDiffraction(saturate(dot(dViewDirW, litArgs_worldNormal)), litArgs_specularity, litArgs_iridescence_thickness);
3434
#endif
3535
#endif
3636

src/scene/shader-lib/chunks/lit/frag/iridescenceDiffraction.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
export default /* glsl */`
22
uniform float material_iridescenceRefractionIndex;
33
4-
#ifndef PI
5-
#define PI 3.14159265
6-
#endif
7-
84
float iridescence_iorToFresnel(float transmittedIor, float incidentIor) {
95
return pow((transmittedIor - incidentIor) / (transmittedIor + incidentIor), 2.0);
106
}
@@ -19,6 +15,7 @@ vec3 iridescence_fresnelToIor(vec3 f0) {
1915
}
2016
2117
vec3 iridescence_sensitivity(float opd, vec3 shift) {
18+
float PI = 3.141592653589793;
2219
float phase = 2.0 * PI * opd * 1.0e-9;
2320
const vec3 val = vec3(5.4856e-13, 4.4201e-13, 5.2481e-13);
2421
const vec3 pos = vec3(1.6810e+06, 1.7953e+06, 2.2084e+06);
@@ -52,6 +49,7 @@ vec3 iridescence_fresnel(float cosTheta, vec3 f0) {
5249
}
5350
5451
vec3 calcIridescence(float outsideIor, float cosTheta, vec3 base_f0, float iridescenceThickness) {
52+
float PI = 3.141592653589793;
5553
5654
float iridescenceIor = mix(outsideIor, material_iridescenceRefractionIndex, smoothstep(0.0, 0.03, iridescenceThickness));
5755
float sinTheta2Sq = pow(outsideIor / iridescenceIor, 2.0) * (1.0 - pow(cosTheta, 2.0));

0 commit comments

Comments
 (0)