diff --git a/src/sample/normalMap/main.ts b/src/sample/normalMap/main.ts index 1aaf5ad4..22b834df 100644 --- a/src/sample/normalMap/main.ts +++ b/src/sample/normalMap/main.ts @@ -26,8 +26,9 @@ SampleInitFactoryWebGPU( async ({ canvas, pageState, gui, device, context, presentationFormat }) => { interface GUISettings { 'Bump Mode': - | 'None' + | 'Diffuse Texture' | 'Normal Texture' + | 'Depth Texture' | 'Normal Map' | 'Parallax Scale' | 'Steep Parallax'; @@ -41,6 +42,7 @@ SampleInitFactoryWebGPU( depthScale: number; depthLayers: number; Texture: string; + 'Reset Light': () => void; } const settings: GUISettings = { @@ -55,6 +57,9 @@ SampleInitFactoryWebGPU( depthScale: 0.05, depthLayers: 16, Texture: 'Spiral', + 'Reset Light': () => { + return; + }, }; // Create normal mapping resources and pipeline @@ -219,21 +224,24 @@ SampleInitFactoryWebGPU( const getMappingType = (arr: Uint32Array) => { switch (settings['Bump Mode']) { - case 'None': + case 'Diffuse Texture': arr[0] = 0; break; case 'Normal Texture': arr[0] = 1; break; - case 'Normal Map': + case 'Depth Texture': arr[0] = 2; break; - case 'Parallax Scale': + case 'Normal Map': arr[0] = 3; break; - case 'Steep Parallax': + case 'Parallax Scale': arr[0] = 4; break; + case 'Steep Parallax': + arr[0] = 5; + break; } }; @@ -258,8 +266,9 @@ SampleInitFactoryWebGPU( }; gui.add(settings, 'Bump Mode', [ - 'None', + 'Diffuse Texture', 'Normal Texture', + 'Depth Texture', 'Normal Map', 'Parallax Scale', 'Steep Parallax', @@ -269,15 +278,38 @@ SampleInitFactoryWebGPU( .onChange(onChangeTexture); const lightFolder = gui.addFolder('Light'); const depthFolder = gui.addFolder('Depth'); - lightFolder.add(settings, 'lightPosX', -5, 5).step(0.1); - lightFolder.add(settings, 'lightPosY', -5, 5).step(0.1); - lightFolder.add(settings, 'lightPosZ', -5, 5).step(0.1); - lightFolder.add(settings, 'lightIntensity', 0.0, 0.1).step(0.002); + lightFolder.add(settings, 'Reset Light').onChange(() => { + lightPosXCell.setValue(1.7); + lightPosYCell.setValue(-0.7); + lightPosZCell.setValue(1.9); + lightIntensityCell.setValue(0.02); + }); + const lightPosXCell = lightFolder + .add(settings, 'lightPosX', -5, 5) + .step(0.1); + const lightPosYCell = lightFolder + .add(settings, 'lightPosY', -5, 5) + .step(0.1); + const lightPosZCell = lightFolder + .add(settings, 'lightPosZ', -5, 5) + .step(0.1); + const lightIntensityCell = lightFolder + .add(settings, 'lightIntensity', 0.0, 0.1) + .step(0.002); depthFolder.add(settings, 'depthScale', 0.0, 0.1).step(0.01); depthFolder.add(settings, 'depthLayers', 1, 32).step(1); + const liFunctionElements = document.getElementsByClassName('cr function'); + for (let i = 0; i < liFunctionElements.length; i++) { + (liFunctionElements[i].children[0] as HTMLElement).style.display = 'flex'; + (liFunctionElements[i].children[0] as HTMLElement).style.justifyContent = + 'center'; + ( + liFunctionElements[i].children[0].children[1] as HTMLElement + ).style.position = 'absolute'; + } + function frame() { - // Sample is no longer the active page. if (!pageState.active) return; // Write to normal map shader diff --git a/src/sample/normalMap/normalMap.wgsl b/src/sample/normalMap/normalMap.wgsl index 24ab7406..5ed72a6a 100644 --- a/src/sample/normalMap/normalMap.wgsl +++ b/src/sample/normalMap/normalMap.wgsl @@ -27,9 +27,13 @@ struct VertexOutput { @builtin(position) Position : vec4f, @location(0) normal: vec3f, @location(1) uv : vec2f, + // Vertex position in world space @location(2) posWS: vec3f, + // Vertex position in tangent space @location(3) posTS: vec3f, + // View position in tangent space @location(4) viewTS: vec3f, + // Extracted components of our tbn matrix @location(5) tbnTS0: vec3, @location(6) tbnTS1: vec3, @location(7) tbnTS2: vec3, @@ -59,14 +63,15 @@ fn parallax_uv( depthSample: f32, depthScale: f32, ) -> vec2f { - if (mapInfo.mappingType == 3) { + if (mapInfo.mappingType == 4) { // Perturb uv coordinates based on depth and camera direction var p: vec2f = viewDirTS.xy * (depthSample * depthScale) / viewDirTS.z; return uv - p; } + // Break up depth space into layers var depthPerLayer: f32 = 1.0 / f32(mapInfo.depthLayers); + // Start at lowest depth var currentDepth: f32 = 0.0; - // How much we will go down var delta_uv: vec2 = viewDirTS.xy * depthScale / (viewDirTS.z * mapInfo.depthLayers); var prev_uv = uv; var cur_uv = uv; @@ -79,6 +84,8 @@ fn parallax_uv( prev_uv = cur_uv; cur_uv -= delta_uv; depthFromTexture = textureSample(depthTexture, textureSampler, cur_uv).r; + // Determine whether current depth is greater than depth map + // Once we reach a certain threshold, we stop updating cur_uv cur_uv = select(cur_uv, prev_uv, depthFromTexture < currentDepth); prevDepthFromTexture = select(depthFromTexture, prevDepthFromTexture, prevDepthFromTexture < currentDepth); prevCurrentDepth = select(currentDepth, prevCurrentDepth, prevDepthFromTexture < currentDepth); @@ -90,7 +97,6 @@ fn when_greater(v1: f32, v2: f32) -> f32 { return max(sign(v1 - v2), 0.0); } -/* VERTEX SHADER */ @vertex fn vertexMain(input: VertexInput) -> VertexOutput { var output : VertexOutput; @@ -139,7 +145,6 @@ fn vertexMain(input: VertexInput) -> VertexOutput { return output; } -/* FRAGMENT SHADER */ @fragment fn fragmentMain(input: VertexOutput) -> @location(0) vec4f { // Reconstruct tbnTS @@ -163,7 +168,7 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4f { var uv = select( parallax_uv(input.uv, viewDirTS, depthMap.r, mapInfo.depthScale), input.uv, - mapInfo.mappingType < 3 + mapInfo.mappingType < 4 ); // Get values from textures @@ -183,12 +188,18 @@ fn fragmentMain(input: VertexOutput) -> @location(0) vec4f { var diffuseLight = (lightColorIntensity * diffuseStrength) / (lightDistanceTS * lightDistanceTS); switch (mapInfo.mappingType) { + // Output the diffuse texture case 0: { return vec4f(diffuseMap.rgb, 1.0); } + // Output the normal map case 1: { return vec4f(normalMap.rgb, 1.0); } + // Output the height map + case 2: { + return vec4f(depthMap.rgb, 1.0); + } default: { return vec4f(diffuseMap.rgb * diffuseLight, 1.0); } diff --git a/src/sample/normalMap/utils.ts b/src/sample/normalMap/utils.ts index 8ea8f06e..fc543716 100644 --- a/src/sample/normalMap/utils.ts +++ b/src/sample/normalMap/utils.ts @@ -160,7 +160,7 @@ export const convertVertexFormatToBytes = (vf: GPUVertexFormat): number => { */ export const createVBuffer = ( vertexFormats: GPUVertexFormat[] -): GPUVertexBufferLayout[] => { +): GPUVertexBufferLayout => { const initialValue: AttribAcc = { attributes: [], arrayStride: 0 }; const vertexBuffer = vertexFormats.reduce( @@ -181,12 +181,13 @@ export const createVBuffer = ( }, initialValue ); - return [ - { - arrayStride: vertexBuffer.arrayStride, - attributes: vertexBuffer.attributes, - }, - ]; + + const layout: GPUVertexBufferLayout = { + arrayStride: vertexBuffer.arrayStride, + attributes: vertexBuffer.attributes, + }; + + return layout; }; export const create3DRenderPipeline = ( @@ -214,7 +215,7 @@ export const create3DRenderPipeline = ( }), entryPoint: 'vertexMain', buffers: - vBufferFormats.length !== 0 ? [createVBuffers(vBufferFormats) : [], + vBufferFormats.length !== 0 ? [createVBuffer(vBufferFormats)] : [], }, fragment: { module: device.createShaderModule({