载入中...
搜索中...
未找到
WaterfallWgsl.h
浏览该文件的文档.
1#pragma once
2
4
10inline constexpr const char* kWaterfallFragWgsl = R"wgsl(
11struct Light3D { posRadius: vec4f, color: vec4f, spot: vec4f };
12struct Frame {
13 mvp: mat4x4f, model: mat4x4f, lightDir: vec4f, lightColor: vec4f,
14 tint: vec4f, cameraPos: vec4f, ambient: vec4f,
15 lights: array<Light3D, 8>, texBomb: vec4f, parallax: vec4f,
16 surface: vec4f, view: mat4x4f, clipInfo: vec4f, cloud: vec4f, cloudWind: vec4f,
17 envProbeCenter: vec4f, envProbeExtent: vec4f, skinInfo: vec4f,
18 reflectionProbeCenter: array<vec4f, 2>,
19 reflectionProbeExtent: array<vec4f, 2>,
20};
21struct FSIn {
22 @builtin(position) pos: vec4f,
23 @location(0) normal: vec3f, @location(1) uv: vec2f, @location(2) tint: vec4f,
24 @location(3) worldPos: vec3f, @location(4) cameraPos: vec3f,
25 @location(5) viewPos: vec3f,
26};
27struct Externals { data: array<vec4f, 8> };
28@group(0) @binding(0) var<uniform> frame: Frame;
29@group(0) @binding(3) var environment: texture_cube<f32>;
30@group(0) @binding(7) var mainSampler: sampler;
31@group(0) @binding(15) var<uniform> params: Externals;
32@group(0) @binding(16) var reflectionProbe0: texture_cube<f32>;
33@group(0) @binding(17) var reflectionProbe1: texture_cube<f32>;
34fn p(i: u32) -> f32 { return params.data[i / 4u][i % 4u]; }
35fn hash(n: f32) -> f32 { return fract(sin(n) * 43758.5453123); }
36fn probeWeight(index: u32, worldPos: vec3f) -> f32 {
37 let edge = frame.reflectionProbeExtent[index].xyz -
38 abs(worldPos - frame.reflectionProbeCenter[index].xyz);
39 let inside = min(edge.x, min(edge.y, edge.z));
40 return select(0.0,
41 clamp(inside / max(frame.reflectionProbeExtent[index].w, 0.0001), 0.0, 1.0),
42 inside > 0.0 && frame.reflectionProbeCenter[index].w > 0.0);
43}
44fn probeDirection(index: u32, direction: vec3f, worldPos: vec3f) -> vec3f {
45 let center = frame.reflectionProbeCenter[index].xyz;
46 let extent = frame.reflectionProbeExtent[index].xyz;
47 let safeDir = select(vec3f(0.00001), direction, abs(direction) > vec3f(0.00001));
48 let exitT = max((center - extent - worldPos) / safeDir,
49 (center + extent - worldPos) / safeDir);
50 let distanceToBox = min(exitT.x, min(exitT.y, exitT.z));
51 return select(normalize(direction),
52 normalize(worldPos + direction * distanceToBox - center), distanceToBox > 0.0);
53}
54fn noise(q: vec2f) -> f32 {
55 let i = floor(q); let f = fract(q); let s = f * f * (vec2f(3.0) - 2.0 * f);
56 let a = hash(i.x + i.y * 57.0); let b = hash(i.x + 1.0 + i.y * 57.0);
57 let c = hash(i.x + (i.y + 1.0) * 57.0);
58 let d = hash(i.x + 1.0 + (i.y + 1.0) * 57.0);
59 return mix(mix(a, b, s.x), mix(c, d, s.x), s.y);
60}
61fn flowNoise(uv: vec2f, time: f32) -> f32 {
62 let q = vec2f(uv.x * 3.0, uv.y * 4.0 + time * p(1u));
63 var value = 0.0; var amplitude = 0.5; var frequency = 1.0;
64 for (var octave = 0; octave < 4; octave++) {
65 value += amplitude * noise(q * frequency + vec2f(f32(octave) * 13.7));
66 frequency *= 2.1; amplitude *= 0.5;
67 }
68 return value;
69}
70fn streaks(uv: vec2f, time: f32) -> f32 {
71 var value = 0.0;
72 for (var i = 0; i < 6; i++) {
73 if (f32(i) >= p(3u) + 0.5) { break; }
74 let x = fract(hash(f32(i) * 3.1) + uv.x * 0.35) - 0.5;
75 let y = (uv.y - 0.5 + time * p(1u) * 0.6) * p(4u) + hash(f32(i) * 9.7) * 10.0;
76 value += exp(-abs(x) * 3.5) * exp(-abs(y) * 1.5);
77 }
78 return value;
79}
80fn cascade(uv: vec2f, time: f32) -> f32 {
81 let band = 0.5 + 0.5 * sin((uv.y * 22.0 + time * p(1u) * 3.0) * 3.14159265);
82 return clamp((flowNoise(uv, time) * 0.6 + streaks(uv, time) *
83 (0.5 + p(2u) * 0.5) + band * 0.2) * p(2u), 0.0, 1.0);
84}
85@fragment
86fn fs_main(in: FSIn) -> @location(0) vec4f {
87 let eps = 0.001; let time = p(0u);
88 let grad = vec2f(cascade(in.uv + vec2f(eps, 0.0), time) -
89 cascade(in.uv - vec2f(eps, 0.0), time),
90 cascade(in.uv + vec2f(0.0, eps), time) -
91 cascade(in.uv - vec2f(0.0, eps), time)) / (2.0 * eps);
92 let n = normalize(vec3f(-grad.x, -grad.y, 1.0));
93 let v = normalize(frame.cameraPos.xyz - in.worldPos);
94 let ndv = max(dot(v, n), 0.0);
95 let roughness = clamp(0.14 + length(grad) * 0.08, 0.08, 0.48);
96 let maxLod = f32(max(i32(textureNumLevels(environment)) - 1, 0));
97 let specMaxLod = select(maxLod, maxLod - 1.0, maxLod >= 2.0);
98 let lod = roughness * specMaxLod;
99 let reflected = reflect(-v, n);
100 var probeWeight0 = probeWeight(0u, in.worldPos);
101 var probeWeight1 = probeWeight(1u, in.worldPos);
102 var probeWeightSum = probeWeight0 + probeWeight1;
103 if (probeWeightSum > 1.0) {
104 probeWeight0 /= probeWeightSum;
105 probeWeight1 /= probeWeightSum;
106 probeWeightSum = 1.0;
107 }
108 var reflection = textureSampleLevel(environment, mainSampler, reflected, lod).rgb *
109 frame.lightColor.w * (1.0 - probeWeightSum);
110 // @lifetime Shader math below does not declare host pointers.
111 if (probeWeight0 > 0.0) {
112 let probeLod = f32(max(i32(textureNumLevels(reflectionProbe0)) - 1, 0));
113 reflection += textureSampleLevel(reflectionProbe0, mainSampler,
114 probeDirection(0u, reflected, in.worldPos),
115 roughness * max(probeLod - 1.0, 0.0)).rgb *
116 frame.reflectionProbeCenter[0].w * probeWeight0;
117 }
118 if (probeWeight1 > 0.0) {
119 let probeLod = f32(max(i32(textureNumLevels(reflectionProbe1)) - 1, 0));
120 reflection += textureSampleLevel(reflectionProbe1, mainSampler,
121 probeDirection(1u, reflected, in.worldPos),
122 roughness * max(probeLod - 1.0, 0.0)).rgb *
123 frame.reflectionProbeCenter[1].w * probeWeight1;
124 }
125 let fresnel = 0.02 + 0.98 * pow(1.0 - ndv, 5.0);
126 let brdf = roughness * vec4f(-1.0, -0.0275, -0.572, 0.022) +
127 vec4f(1.0, 0.0425, 1.04, -0.04);
128 let a004 = min(brdf.x * brdf.x, exp2(-9.28 * ndv)) * brdf.x + brdf.y;
129 let dfg = vec2f(-1.04, 1.04) * a004 + brdf.zw;
130 let envWeight = max(0.02 * dfg.x + dfg.y, 0.0);
131 var color = mix(vec3f(p(10u), p(11u), p(12u)), reflection,
132 clamp(max(fresnel, envWeight) * p(8u), 0.0, 1.0));
133 let h = normalize(v + normalize(frame.lightDir.xyz));
134 let l = normalize(frame.lightDir.xyz);
135 let noL = max(dot(n, l), 0.0);
136 let noH = max(dot(n, h), 0.0);
137 let voH = max(dot(v, h), 0.0);
138 let alpha = max(roughness * roughness, 0.002);
139 let alpha2 = alpha * alpha;
140 let denom = noH * noH * (alpha2 - 1.0) + 1.0;
141 let d = alpha2 / max(3.14159265 * denom * denom, 0.0001);
142 let k = (roughness + 1.0) * (roughness + 1.0) * 0.125;
143 let gv = ndv / max(ndv * (1.0 - k) + k, 0.0001);
144 let gl = noL / max(noL * (1.0 - k) + k, 0.0001);
145 let fsun = 0.02 + 0.98 * pow(1.0 - voH, 5.0);
146 let spec = d * gv * gl * fsun / max(4.0 * ndv * max(noL, 0.001), 0.001);
147 color += frame.lightColor.rgb * spec * noL * p(9u);
148 let topBand = clamp((in.uv.y - (1.0 - p(5u))) / max(p(5u), 0.0001), 0.0, 1.0);
149 let bottomBand = clamp((p(6u) - in.uv.y) / max(p(6u), 0.0001), 0.0, 1.0);
150 let foam = clamp(cascade(in.uv, time) * p(7u) +
151 clamp(topBand + bottomBand, 0.0, 1.0) * 0.9, 0.0, 1.0);
152 color = mix(color, vec3f(0.90, 0.95, 1.0), foam);
153 return vec4f(color, 1.0 - bottomBand * 0.5);
154}
155)wgsl";
156
157} // namespace eve::graphics::shaders
constexpr const char * kWaterfallFragWgsl
Waterfall fragment shader WGSL source. @ownership Borrowed immutable string literal; callers must not...