/*! * Copyright (c) Microsoft Corporation. * Licensed under the MIT License. */ import { vec4 } from "gl-matrix"; export declare const FullscreenQuadWgsl = "\nconst GAMMA = vec3(0.45454545f); // 1 / 2.2\n\nstruct ColorData {\n data : array,\n}\n\nstruct NormalDepthData {\n data : array,\n}\n\n // offest align size\nstruct Uniforms { // ------------------------------\n width: f32, // 0 4 4\n height: f32, // 4 4 4\n samplesPerPixel: f32, // 8 4 4\n exposure: f32, // 12 4 4\n minDepth: f32, // 16 4 4\n maxDepth: f32, // 20 4 4\n normalEdge: f32, // 24 4 4\n depthEdge: f32, // 28 4 4\n edgeForeground: vec4, // 32 16 16\n edgeBackground: vec4, // 48 16 16\n} // ------------------------------\n // 16 64\n\n@group(0) @binding(0) var uniforms : Uniforms;\n@group(0) @binding(1) var colorBuffer : ColorData;\n@group(0) @binding(2) var normalDepthBuffer : NormalDepthData;\n\nstruct VertexOutput {\n @builtin(position) Position : vec4,\n};\n\n@vertex\nfn vert_main(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {\n var pos = array, 6>(\n vec2( 1f, 1f),\n vec2( 1f, -1f),\n vec2(-1f, -1f),\n vec2( 1f, 1f),\n vec2(-1f, -1f),\n vec2(-1f, 1f));\n var output : VertexOutput;\n output.Position = vec4(pos[vertexIndex], 0f, 1f);\n return output;\n}\n\n@fragment\nfn frag_main(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n let index = u32(x + y * uniforms.width) * 3u;\n // [0,1]\n var color = vec3(colorBuffer.data[index + 0u], colorBuffer.data[index + 1u], colorBuffer.data[index + 2u]) / uniforms.samplesPerPixel;\n // Gamma-correct\n return vec4(pow(color, GAMMA), 1f);\n}\n\n@fragment\nfn frag_depth(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n let index = u32(x + y * uniforms.width) * 4u;\n let depth = normalDepthBuffer.data[index + 3u];\n let minDepth = uniforms.minDepth;\n let maxDepth = uniforms.maxDepth;\n if (minDepth == maxDepth) {\n // Raw, unnormalized depth\n return vec4(vec3(depth, depth, depth), 1f);\n }\n else {\n // Normalize depth\n var normalizedDepth = (depth - minDepth) / (maxDepth - minDepth);\n return vec4(normalizedDepth, normalizedDepth, normalizedDepth, 1f);\n }\n}\n\n@fragment\nfn frag_depthMultisampled(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n let index = u32(x + y * uniforms.width) * 4u;\n let depth = normalDepthBuffer.data[index + 3u] / uniforms.samplesPerPixel;\n let minDepth = uniforms.minDepth;\n let maxDepth = uniforms.maxDepth;\n if (minDepth == maxDepth) {\n // Raw, unnormalized depth\n return vec4(vec3(depth, depth, depth), 1f);\n }\n else {\n // Normalize depth\n var normalizedDepth = (depth - minDepth) / (maxDepth - minDepth);\n return vec4(normalizedDepth, normalizedDepth, normalizedDepth, 1f);\n }\n}\n\n@fragment\nfn frag_normal(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n let index = u32(x + y * uniforms.width) * 4u;\n return vec4(normalDepthBuffer.data[index + 0u], normalDepthBuffer.data[index + 1u], normalDepthBuffer.data[index + 2u], 1f);\n}\n\n@fragment\nfn frag_normalMultisampled(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n let index = u32(x + y * uniforms.width) * 4u;\n return vec4(normalDepthBuffer.data[index + 0u] / uniforms.samplesPerPixel, normalDepthBuffer.data[index + 1u] / uniforms.samplesPerPixel, normalDepthBuffer.data[index + 2u] / uniforms.samplesPerPixel, 1f);\n}\n\n// @fragment\n// fn frag_edge(@builtin(position) coord: vec4) -> @location(0) vec4 {\n// let x = floor(coord.x);\n// let y = floor(coord.y);\n// let index = u32(x + y * uniforms.width) * 4u;\n\n// // Prevent edge detection at screen edges\n// if (x == 0 || x == uniforms.width - 1 || y == 0 || y == uniforms.height - 1) {\n// return vec4(0f, 0f, 0f, 1f);\n// }\n\n// // Normal derivatives\n// let p = vec3(normalDepthBuffer.data[index + 0u], normalDepthBuffer.data[index + 1u], normalDepthBuffer.data[index + 2u]);\n// let px = vec3(normalDepthBuffer.data[index + 4u], normalDepthBuffer.data[index + 5u], normalDepthBuffer.data[index + 6u]);\n// let py = vec3(normalDepthBuffer.data[index + u32(uniforms.width) * 4u + 0u], normalDepthBuffer.data[index + u32(uniforms.width) * 4u + 1u], normalDepthBuffer.data[index + u32(uniforms.width) * 4u + 2u]);\n// let dpdx = px - p;\n// let dpdy = py - p;\n// let fwidth = abs(dpdx) + abs(dpdy);\n\n// // Depth derivatives\n// let d = normalDepthBuffer.data[index + 3u];\n// let dx = normalDepthBuffer.data[index + 7u];\n// let dy = normalDepthBuffer.data[index + u32(uniforms.width) * 4u + 3u];\n// let ddpx = dx - d;\n// let ddpy = dy - d;\n \n// // Normalize depth\n// // let minDepth = uniforms.minDepth;\n// // let maxDepth = uniforms.maxDepth;\n// // let nd = (d - minDepth) / (maxDepth - minDepth);\n// // let ndx = (dx - minDepth) / (maxDepth - minDepth);\n// // let ndy = (dy - minDepth) / (maxDepth - minDepth);\n// // let ddpx = ndx - nd;\n// // let ddpy = ndy - nd;\n \n// let dfwidth = abs(ddpx) + abs(ddpy);\n\n// // Output white when magnitude of dpdx over a threshold\n// let depthEdge = uniforms.depthEdge;\n// let normalEdge = uniforms.normalEdge;\n// if (dot(fwidth, fwidth) > normalEdge || dfwidth > depthEdge) {\n// return vec4(1f, 1f, 1f, 1f);\n// } else {\n// return vec4(0f, 0f, 0f, 1f);\n// }\n// }\n\n@fragment\nfn frag_edge(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n // let index = u32(x + y * uniforms.width) * 4u;\n let index = u32(x + y * (uniforms.width + 1)) * 4u; // Overdispatched by 1\n let background = uniforms.edgeBackground;\n let foreground = uniforms.edgeForeground;\n \n // Prevent edge detection at screen edges\n // Over-dispatched, so this is not needed\n // if (x == uniforms.width - 1 || y == uniforms.height - 1) { return background; }\n\n // Segment derivatives\n // let yOffset = index + u32(uniforms.width) * 4u;\n let yOffset = index + u32(uniforms.width + 1) * 4u; // Overdispatched by 1\n let p = vec4(normalDepthBuffer.data[index + 0u], normalDepthBuffer.data[index + 1u], normalDepthBuffer.data[index + 2u], normalDepthBuffer.data[index + 3u]);\n let px = vec4(normalDepthBuffer.data[index + 4u], normalDepthBuffer.data[index + 5u], normalDepthBuffer.data[index + 6u], normalDepthBuffer.data[index + 7u]);\n let py = vec4(normalDepthBuffer.data[yOffset + 0u], normalDepthBuffer.data[yOffset + 1u], normalDepthBuffer.data[yOffset + 2u], normalDepthBuffer.data[yOffset + 3u]);\n let dpdx = px - p;\n let dpdy = py - p;\n let fwidth = abs(dpdx) + abs(dpdy);\n\n // Output white when magnitude of dpdx over a threshold\n if (dot(fwidth, fwidth) > 0f) {\n return foreground;\n } else {\n return background;\n\n // TODO: Add another mode for edgeFill, or a flag for edgeFill (0 = background, 1 = color)\n // Use idColor\n // return p;\n // return vec4(p.x, p.y, p.z, 1f);\n }\n}\n\n@fragment\nfn frag_segment(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n\n // let index = u32(x + y * uniforms.width) * 4u;\n let index = u32(x + y * (uniforms.width + 1)) * 4u; // Overdispatched by 1\n return vec4(normalDepthBuffer.data[index + 0u], normalDepthBuffer.data[index + 1u], normalDepthBuffer.data[index + 2u], 1f);\n}\n\n@fragment\nfn frag_main_hdr(@builtin(position) coord: vec4) -> @location(0) vec4 {\n let x = floor(coord.x);\n let y = floor(coord.y);\n let index = u32(x + y * uniforms.width) * 3u;\n var color = vec3(colorBuffer.data[index + 0u], colorBuffer.data[index + 1u], colorBuffer.data[index + 2u]) / uniforms.samplesPerPixel;\n\n // Simple tone-mapping from HDR to LDR\n // if (uniforms.exposure > 0f) {\n // color = color * uniforms.exposure;\n // color = color / (color + vec3(1f, 1f, 1f));\n // }\n \n color = color * uniforms.exposure;\n // ACES\n // https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/\n let a = 2.51f;\n let b = 0.03f;\n let c = 2.43f;\n let d = 0.59f;\n let e = 0.14f;\n color = (color * (a * color + b)) / (color * (c * color + d) + e);\n\n // TODO: Can I get the avg luminance in the same way as the min/max depth?\n\n // sRGB?\n // https://sotrh.github.io/learn-wgpu/intermediate/tutorial13-hdr/#output-too-dark-on-webgpu\n\n// // Maps HDR values to linear values\n// // Based on http://www.oscars.org/science-technology/sci-tech-projects/aces\n// fn aces_tone_map(hdr: vec3) -> vec3 {\n// let m1 = mat3x3(\n// 0.59719, 0.07600, 0.02840,\n// 0.35458, 0.90834, 0.13383,\n// 0.04823, 0.01566, 0.83777,\n// );\n// let m2 = mat3x3(\n// 1.60475, -0.10208, -0.00327,\n// -0.53108, 1.10813, -0.07276,\n// -0.07367, -0.00605, 1.07602,\n// );\n// let v = m1 * hdr;\n// let a = v * (v + 0.0245786) - 0.000090537;\n// let b = v * (0.983729 * v + 0.4329510) + 0.238081;\n// return clamp(m2 * (a / b), vec3(0.0), vec3(1.0));\n// }\n\n // See https://bruop.github.io/tonemapping/\n // See https://www.shadertoy.com/view/WdjSW3\n // See https://sibras.github.io/OpenGL4-Tutorials/docs/Tutorials/10-Tutorial10/\n\n // Gamma-correct\n return vec4(pow(color, GAMMA), 1f);\n}"; export declare class FullscreenQuadUniformBufferData extends Float32Array { static readonly SIZE: number; readonly WIDTH_OFFSET: number; readonly HEIGHT_OFFSET: number; readonly SPP_OFFSET: number; readonly EXPOSURE_OFFSET: number; readonly MIN_DEPTH_OFFSET: number; readonly MAX_DEPTH_OFFSET: number; readonly EDGE_NORMAL_OFFSET: number; readonly EDGE_DEPTH_OFFSET: number; readonly EDGE_FOREGROUND_OFFSET: number; readonly EDGE_BACKGROUND_OFFSET: number; constructor(); getWidth(): number; setWidth(value: number): void; getHeight(): number; setHeight(value: number): void; getSamplesPerPixel(): number; setSamplesPerPixel(value: number): void; getExposure(): number; setExposure(value: number): void; getMinDepth(): number; setMinDepth(value: number): void; getMaxDepth(): number; setMaxDepth(value: number): void; getEdgeDepth(): number; setEdgeDepth(value: number): void; getEdgeNormal(): number; setEdgeNormal(value: number): void; getEdgeForeground(value: vec4): void; setEdgeForeground(value: vec4): void; getEdgeBackground(value: vec4): void; setEdgeBackground(value: vec4): void; }