From 273d193bcf113811d58684fe250bf52544120741 Mon Sep 17 00:00:00 2001 From: martinlaxenaire Date: Tue, 27 Feb 2024 12:11:00 +0100 Subject: [PATCH] - deferred rendering example now use phong lightning - updated fullscreen example --- examples/deferred-rendering/main.js | 48 +++++++++--- examples/full-screen-plane-shader/main.js | 94 ++++++----------------- tests/orbit-camera-depth-texture/main.js | 4 +- 3 files changed, 66 insertions(+), 80 deletions(-) diff --git a/examples/deferred-rendering/main.js b/examples/deferred-rendering/main.js index da6400b90..1ff172861 100644 --- a/examples/deferred-rendering/main.js +++ b/examples/deferred-rendering/main.js @@ -309,7 +309,7 @@ window.addEventListener('load', async () => { fn world_from_screen_coord(coord : vec2, depth_sample: f32) -> vec3 { // reconstruct world-space position from the screen coordinate. let posClip = vec4(coord.x * 2.0 - 1.0, (1.0 - coord.y) * 2.0 - 1.0, depth_sample, 1.0); - let posWorldW = params.cameraInverseViewProjectionMatrix * posClip; + let posWorldW = camera.inverseViewProjectionMatrix * posClip; let posWorld = posWorldW.xyz / posWorldW.www; return posWorld; } @@ -343,23 +343,37 @@ window.addEventListener('load', async () => { vec2(floor(fsInput.position.xy)), 0 ).rgb; - for (var i = 0u; i < arrayLength(&lights); i++) { let L = lights[i].position.xyz - position; let distance = length(L); + if (distance > lights[i].radius) { continue; } - let lambert = max(dot(normal, normalize(L)), 0.0); + + let lightDir: vec3f = normalize(L); + let lightStrength: f32 = pow(1.0 - distance / lights[i].radius, 2.0); + + let lambert = max(dot(normal, lightDir), 0.0); result += vec3( - lambert * pow(1.0 - distance / lights[i].radius, 2.0) * lights[i].color * albedo + lambert * lightStrength * lights[i].color ); + + // specular + let viewDir: vec3f = normalize(camera.position - position); + let reflectDir: vec3f = reflect(-lightDir, normal); + let spec: f32 = pow(max(dot(viewDir, reflectDir), 0.0), phong.shininess); + let specular: vec3f = phong.specularStrength * spec * lights[i].color * lightStrength; + + result += specular; } - // some manual ambient result += vec3(0.2); + + // albedo + result *= albedo; return vec4(result, 1.0); } @@ -374,12 +388,28 @@ window.addEventListener('load', async () => { }, renderTextures: [gBufferDepthTexture, gBufferAlbedoTexture, gBufferNormalTexture], uniforms: { - params: { + camera: { struct: { - cameraInverseViewProjectionMatrix: { + inverseViewProjectionMatrix: { type: 'mat4x4f', value: new Mat4().multiplyMatrices(camera.projectionMatrix, camera.viewMatrix).invert(), }, + position: { + type: 'vec3f', + value: camera.position, + }, + }, + }, + phong: { + struct: { + specularStrength: { + type: 'f32', + value: 0.5, + }, + shininess: { + type: 'f32', + value: 32, + }, }, }, }, @@ -404,12 +434,12 @@ window.addEventListener('load', async () => { }) deferredRenderingPass.onRender(() => { - deferredRenderingPass.uniforms.params.cameraInverseViewProjectionMatrix.value + deferredRenderingPass.uniforms.camera.inverseViewProjectionMatrix.value .multiplyMatrices(camera.projectionMatrix, camera.viewMatrix) .invert() // explicitly tell the uniform to update - deferredRenderingPass.uniforms.params.cameraInverseViewProjectionMatrix.shouldUpdate = true + deferredRenderingPass.uniforms.camera.inverseViewProjectionMatrix.shouldUpdate = true }) // DEBUG VIEW diff --git a/examples/full-screen-plane-shader/main.js b/examples/full-screen-plane-shader/main.js index c5a23f416..d3a575295 100644 --- a/examples/full-screen-plane-shader/main.js +++ b/examples/full-screen-plane-shader/main.js @@ -58,65 +58,20 @@ window.addEventListener('load', async () => { let n_x = mix(vec2f(n00, n01), vec2f(n10, n11), vec2f(fade_xy.x)); let n_xy = mix(n_x.x, n_x.y, fade_xy.y); return 2.3 * n_xy; - } - - fn mod289(x: vec2f) -> vec2f { - return x - floor(x * (1. / 289.)) * 289.; - } - - fn mod289_3(x: vec3f) -> vec3f { - return x - floor(x * (1. / 289.)) * 289.; - } + } - fn permute3(x: vec3f) -> vec3f { - return mod289_3(((x * 34.) + 1.) * x); - } - - // MIT License. © Ian McEwan, Stefan Gustavson, Munrocket - fn simplexNoise2(v: vec2f) -> f32 { - let C = vec4( - 0.211324865405187, // (3.0-sqrt(3.0))/6.0 - 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) - -0.577350269189626, // -1.0 + 2.0 * C.x - 0.024390243902439 // 1.0 / 41.0 - ); - - // First corner - var i = floor(v + dot(v, C.yy)); - let x0 = v - i + dot(i, C.xx); - - // Other corners - var i1 = select(vec2(0., 1.), vec2(1., 0.), x0.x > x0.y); - - // x0 = x0 - 0.0 + 0.0 * C.xx ; - // x1 = x0 - i1 + 1.0 * C.xx ; - // x2 = x0 - 1.0 + 2.0 * C.xx ; - var x12 = x0.xyxy + C.xxzz; - x12.x = x12.x - i1.x; - x12.y = x12.y - i1.y; - - // Permutations - i = mod289(i); // Avoid truncation effects in permutation - - var p = permute3(permute3(i.y + vec3(0., i1.y, 1.)) + i.x + vec3(0., i1.x, 1.)); - var m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), vec3(0.)); - m *= m; - m *= m; - - // Gradients: 41 points uniformly over a line, mapped onto a diamond. - // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) - let x = 2. * fract(p * C.www) - 1.; - let h = abs(x) - 0.5; - let ox = floor(x + 0.5); - let a0 = x - ox; - - // Normalize gradients implicitly by scaling m - // Approximation of: m *= inversesqrt( a0*a0 + h*h ); - m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h); - - // Compute final noise value at P - let g = vec3(a0.x * x0.x + h.x * x0.y, a0.yz * x12.xz + h.yz * x12.yw); - return 130. * dot(m, g); + // MIT License. © Inigo Quilez, Munrocket + // noise2() is any noise here: Value, Perlin, Simplex, Worley + // + const m2: mat2x2f = mat2x2f(vec2f(0.8, 0.6), vec2f(-0.6, 0.8)); + fn fbm(p: vec2f) -> f32 { + var f: f32 = 0.; + var pos: vec2f = p; + f = f + 0.5000 * perlinNoise2(pos); pos = m2 * pos * 2.02; + f = f + 0.2500 * perlinNoise2(pos); pos = m2 * pos * 2.03; + f = f + 0.1250 * perlinNoise2(pos); pos = m2 * pos * 2.01; + f = f + 0.0625 * perlinNoise2(pos); + return f / 0.9375; } struct VSOutput { @@ -126,19 +81,20 @@ window.addEventListener('load', async () => { @fragment fn main(fsInput: VSOutput) -> @location(0) vec4f { // probably not performant at all, do not use that in production! - // it's just a dumb example - let noise: f32 = perlinNoise2( - vec2( - simplexNoise2( - cos(fsInput.uv + frames.elapsed * 0.005) * 0.25 - sin(frames.elapsed * 0.01) * 0.125 - + sin(fsInput.uv - frames.elapsed * 0.00125) * 0.75 + cos(frames.elapsed * 0.025) * 0.0625 - ) - ) * (cos(frames.elapsed * 0.02) * 0.5 + 1.0) * 0.75 - ); + // it's just a dumb example + let uv = fsInput.uv * 2.0 - 1.0; - var color: vec3f = mix(vec3(1, 0, 1), vec3(0, 1, 1), noise); + let firstFbm = fbm( uv * 3.0 ); + + let noise: f32 = firstFbm + fbm( + vec2( + uv.y * cos(frames.elapsed * 0.02) * 2.0 + (firstFbm + sin(frames.elapsed * 0.003)) * 4.0, + uv.x * sin(frames.elapsed * 0.006) * 0.25 + (firstFbm + cos(frames.elapsed * 0.01)), + ) + ) * 1.5; - //return vec4(vec3(noise), 1.0); + var color: vec3f = mix(vec3(1, 0.5, 1), vec3(0.5, 1, 1), noise); + return vec4(color, 0.5); } ` diff --git a/tests/orbit-camera-depth-texture/main.js b/tests/orbit-camera-depth-texture/main.js index 7ea68a512..c91dc7082 100644 --- a/tests/orbit-camera-depth-texture/main.js +++ b/tests/orbit-camera-depth-texture/main.js @@ -143,9 +143,9 @@ window.addEventListener('load', async () => { ); // remap depth into something a bit more visible - let depth = (1.0 - rawDepth) * 75.0 * params.systemSize; + let depth = (1.0 - rawDepth) * 10.0 * params.systemSize; - return mix( texture, vec4(vec3(0.0, depth, depth), texture.a), step(fsInput.uv.x, 0.5) ); + return mix( texture, vec4(vec3(depth), texture.a), step(fsInput.uv.x, 0.5) ); } `