-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathdata7.wgsl
More file actions
251 lines (202 loc) · 8.46 KB
/
Copy pathdata7.wgsl
File metadata and controls
251 lines (202 loc) · 8.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
struct Uniforms {
view: mat4x4<f32>;
projection: mat4x4<f32>;
time_size_width: vec4<f32>;
viewport_height: f32;
};
[[group(0), binding(0)]] var<uniform> uniforms: Uniforms;
let light_point: vec3<f32> = vec3<f32>(150.0, 70.0, 0.0);
let light_colour: vec3<f32> = vec3<f32>(1.0, 0.98, 0.82);
let one: vec4<f32> = vec4<f32>(1.0, 1.0, 1.0, 1.0);
let Y_SCL: f32 = 0.86602540378443864676372317075294;
let CURVE_BIAS: f32 = -0.1;
let INV_1_CURVE_BIAS: f32 = 1.11111111111; //1.0 / (1.0 + CURVE_BIAS);
//
// The following code to calculate simplex 3D
// is from https://github.com/ashima/webgl-noise
//
// Simplex 3D Noise
// by Ian McEwan, Ashima Arts.
//
fn permute(x: vec4<f32>) -> vec4<f32> {
var temp: vec4<f32> = 289.0 * one;
return modf(((x*34.0) + one) * x, &temp);
}
fn taylorInvSqrt(r: vec4<f32>) -> vec4<f32> {
return 1.79284291400159 * one - 0.85373472095314 * r;
}
fn snoise(v: vec3<f32>) -> f32 {
let C = vec2<f32>(1.0/6.0, 1.0/3.0);
let D = vec4<f32>(0.0, 0.5, 1.0, 2.0);
// First corner
//TODO: use the splat operations when available
let vCy = dot(v, C.yyy);
var i: vec3<f32> = floor(v + vec3<f32>(vCy, vCy, vCy));
let iCx = dot(i, C.xxx);
let x0 = v - i + vec3<f32>(iCx, iCx, iCx);
// Other corners
let g = step(x0.yzx, x0.xyz);
let l = (vec3<f32>(1.0, 1.0, 1.0) - g).zxy;
let i1 = min(g, l);
let i2 = max(g, l);
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx;
let x1 = x0 - i1 + C.xxx;
let x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
let x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
var temp: vec3<f32> = 289.0 * one.xyz;
i = modf(i, &temp);
let p = permute(
permute(
permute(i.zzzz + vec4<f32>(0.0, i1.z, i2.z, 1.0))
+ i.yyyy + vec4<f32>(0.0, i1.y, i2.y, 1.0))
+ i.xxxx + vec4<f32>(0.0, i1.x, i2.x, 1.0));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
let n_ = 0.142857142857;// 1.0/7.0
let ns = n_ * D.wyz - D.xzx;
let j = p - 49.0 * floor(p * ns.z * ns.z);// mod(p,7*7)
let x_ = floor(j * ns.z);
let y_ = floor(j - 7.0 * x_);// mod(j,N)
var x: vec4<f32> = x_ *ns.x + ns.yyyy;
var y: vec4<f32> = y_ *ns.x + ns.yyyy;
let h = one - abs(x) - abs(y);
let b0 = vec4<f32>(x.xy, y.xy);
let b1 = vec4<f32>(x.zw, y.zw);
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - one;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - one;
let s0 = floor(b0)*2.0 + one;
let s1 = floor(b1)*2.0 + one;
let sh = -step(h, 0.0 * one);
let a0 = b0.xzyw + s0.xzyw*sh.xxyy;
let a1 = b1.xzyw + s1.xzyw*sh.zzww;
var p0: vec3<f32> = vec3<f32>(a0.xy, h.x);
var p1: vec3<f32> = vec3<f32>(a0.zw, h.y);
var p2: vec3<f32> = vec3<f32>(a1.xy, h.z);
var p3: vec3<f32> = vec3<f32>(a1.zw, h.w);
//Normalise gradients
let norm = taylorInvSqrt(vec4<f32>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
p0 = p0 * norm.x;
p1 = p1 * norm.y;
p2 = p2 * norm.z;
p3 = p3 * norm.w;
// Mix final noise value
var m: vec4<f32> = max(0.6 * one - vec4<f32>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0 * one);
m = m * m;
return 9.0 * dot(m*m, vec4<f32>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
}
// End of 3D simplex code.
fn apply_distortion(pos: vec3<f32>) -> vec3<f32> {
var perlin_pos: vec3<f32> = pos;
//Do noise transformation to permit for smooth,
//continuous movement.
//TODO: we should be able to name them `sin` and `cos`.
let sn = uniforms.time_size_width.x;
let cs = uniforms.time_size_width.y;
let size = uniforms.time_size_width.z;
// Rotate 90 Z, Move Left Size / 2
perlin_pos = vec3<f32>(perlin_pos.y - perlin_pos.x - size, perlin_pos.x, perlin_pos.z);
let xcos = perlin_pos.x * cs;
let xsin = perlin_pos.x * sn;
let ycos = perlin_pos.y * cs;
let ysin = perlin_pos.y * sn;
let zcos = perlin_pos.z * cs;
let zsin = perlin_pos.z * sn;
// Rotate Time Y
let perlin_pos_y = vec3<f32>(xcos + zsin, perlin_pos.y, -xsin + xcos);
// Rotate Time Z
let perlin_pos_z = vec3<f32>(xcos - ysin, xsin + ycos, perlin_pos.x);
// Rotate 90 Y
perlin_pos = vec3<f32>(perlin_pos.z - perlin_pos.x, perlin_pos.y, perlin_pos.x);
// Rotate Time X
let perlin_pos_x = vec3<f32>(perlin_pos.x, ycos - zsin, ysin + zcos);
// Sample at different places for x/y/z to get random-looking water.
return vec3<f32>(
//TODO: use splats
pos.x + snoise(perlin_pos_x + 2.0*one.xxx) * 0.4,
pos.y + snoise(perlin_pos_y - 2.0*one.xxx) * 1.8,
pos.z + snoise(perlin_pos_z) * 0.4
);
}
// Multiply the input by the scale values.
fn make_position(original: vec2<f32>) -> vec4<f32> {
let interpreted = vec3<f32>(original.x * 0.5, 0.0, original.y * Y_SCL);
return vec4<f32>(apply_distortion(interpreted), 1.0);
}
// Create the normal, and apply the curve. Change the Curve Bias above.
fn make_normal(a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> vec3<f32> {
let norm = normalize(cross(b - c, a - c));
let center = (a + b + c) * (1.0 / 3.0); //TODO: use splat
return (normalize(a - center) * CURVE_BIAS + norm) * INV_1_CURVE_BIAS;
}
// Calculate the fresnel effect.
fn calc_fresnel(view: vec3<f32>, normal: vec3<f32>) -> f32 {
var refractive: f32 = abs(dot(view, normal));
refractive = pow(refractive, 1.33333333333);
return refractive;
}
// Calculate the specular lighting.
fn calc_specular(eye: vec3<f32>, normal: vec3<f32>, light: vec3<f32>) -> f32 {
let light_reflected = reflect(light, normal);
var specular: f32 = max(dot(eye, light_reflected), 0.0);
specular = pow(specular, 10.0);
return specular;
}
struct VertexOutput {
[[builtin(position)]] position: vec4<f32>;
[[location(0)]] f_WaterScreenPos: vec2<f32>;
[[location(1)]] f_Fresnel: f32;
[[location(2)]] f_Light: vec3<f32>;
};
[[stage(vertex)]]
fn vs_main(
[[location(0)]] position: vec2<i32>,
[[location(1)]] offsets: vec4<i32>,
) -> VertexOutput {
let p_pos = vec2<f32>(position);
let b_pos = make_position(p_pos + vec2<f32>(offsets.xy));
let c_pos = make_position(p_pos + vec2<f32>(offsets.zw));
let a_pos = make_position(p_pos);
let original_pos = vec4<f32>(p_pos.x * 0.5, 0.0, p_pos.y * Y_SCL, 1.0);
let vm = uniforms.view;
let transformed_pos = vm * a_pos;
//TODO: use vector splats for division
let water_pos = transformed_pos.xyz * (1.0 / transformed_pos.w);
let normal = make_normal((vm * a_pos).xyz, (vm * b_pos).xyz, (vm * c_pos).xyz);
let eye = normalize(-water_pos);
let transformed_light = vm * vec4<f32>(light_point, 1.0);
var out: VertexOutput;
out.f_Light = light_colour * calc_specular(eye, normal, normalize(water_pos.xyz - (transformed_light.xyz * (1.0 / transformed_light.w))));
out.f_Fresnel = calc_fresnel(eye, normal);
let gridpos = uniforms.projection * vm * original_pos;
out.f_WaterScreenPos = (0.5 * gridpos.xy * (1.0 / gridpos.w)) + vec2<f32>(0.5, 0.5);
out.position = uniforms.projection * transformed_pos;
return out;
}
let water_colour: vec3<f32> = vec3<f32>(0.0, 0.46, 0.95);
let zNear: f32 = 10.0;
let zFar: f32 = 400.0;
[[group(0), binding(1)]] var reflection: texture_2d<f32>;
[[group(0), binding(2)]] var terrain_depth_tex: texture_2d<f32>;
[[group(0), binding(3)]] var colour_sampler: sampler;
fn to_linear_depth(depth: f32) -> f32 {
let z_n: f32 = 2.0 * depth - 1.0;
let z_e: f32 = 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear));
return z_e;
}
[[stage(fragment)]]
fn fs_main(in: VertexOutput) -> [[location(0)]] vec4<f32> {
let reflection_colour = textureSample(reflection, colour_sampler, in.f_WaterScreenPos.xy).xyz;
let pixel_depth = to_linear_depth(in.position.z);
let normalized_coords = in.position.xy / vec2<f32>(uniforms.time_size_width.w, uniforms.viewport_height);
let terrain_depth = to_linear_depth(textureSample(terrain_depth_tex, colour_sampler, normalized_coords).r);
let dist = terrain_depth - pixel_depth;
let clamped = pow(smoothStep(0.0, 1.5, dist), 4.8);
let final_colour = in.f_Light + reflection_colour;
let t = smoothStep(1.0, 5.0, dist) * 0.2; //TODO: splat for mix()?
let depth_colour = mix(final_colour, water_colour, vec3<f32>(t, t, t));
return vec4<f32>(depth_colour, clamped * (1.0 - in.f_Fresnel));
}