From 51faabfbe6698fc288c984a94a6000da19e49b72 Mon Sep 17 00:00:00 2001 From: Rezmason Date: Sun, 2 Oct 2022 20:35:12 -0700 Subject: [PATCH] Corrected the MSDF logic in the GLSL and WGSL shaders, which fixed the rendering in Chrome's software renderer. --- js/regl/rainPass.js | 4 ++++ js/regl/utils.js | 2 ++ js/webgpu/rainPass.js | 5 +++-- shaders/glsl/rainPass.frag.glsl | 40 ++++++++++++++++++++++++++++----- shaders/wgsl/rainPass.wgsl | 31 +++++++++++++++++++------ 5 files changed, 67 insertions(+), 15 deletions(-) diff --git a/js/regl/rainPass.js b/js/regl/rainPass.js index f301e90..6267b1f 100644 --- a/js/regl/rainPass.js +++ b/js/regl/rainPass.js @@ -189,6 +189,10 @@ export default ({ regl, config, lkg }) => { baseTexture: baseTexture.texture, glintTexture: glintTexture.texture, + msdfPxRange: 4.0, + glyphMSDFSize: [glyphMSDF.width(), glyphMSDF.height()], + glintMSDFSize: [glintMSDF.width(), glintMSDF.height()], + camera: regl.prop("camera"), transform: regl.prop("transform"), screenSize: regl.prop("screenSize"), diff --git a/js/regl/utils.js b/js/regl/utils.js index 36085f2..6309afd 100644 --- a/js/regl/utils.js +++ b/js/regl/utils.js @@ -36,6 +36,8 @@ const loadImage = (regl, url) => { } return texture; }, + width: () => (loaded ? texture.width : 1), + height: () => (loaded ? texture.height : 1), loaded: (async () => { if (url != null) { const data = new Image(); diff --git a/js/webgpu/rainPass.js b/js/webgpu/rainPass.js index 89a5f2a..c6d94a1 100644 --- a/js/webgpu/rainPass.js +++ b/js/webgpu/rainPass.js @@ -17,6 +17,7 @@ const makeConfigBuffer = (device, configUniforms, config, density, gridSize) => rippleType: config.rippleTypeName in rippleTypes ? rippleTypes[config.rippleTypeName] : -1, slantScale: 1 / (Math.abs(Math.sin(2 * config.slant)) * (Math.sqrt(2) - 1) + 1), slantVec: [Math.cos(config.slant), Math.sin(config.slant)], + msdfPxRange: 4, }; // console.table(configData); @@ -93,7 +94,7 @@ export default ({ config, device, timeBuffer }) => { let highPassOutput; const loaded = (async () => { - const [msdfTexture, glintMSDFTexture, baseTexture, glintTexture, rainShader] = await Promise.all(assets); + const [glyphMSDFTexture, glintMSDFTexture, baseTexture, glintTexture, rainShader] = await Promise.all(assets); const rainShaderUniforms = structs.from(rainShader.code); configBuffer = makeConfigBuffer(device, rainShaderUniforms.Config, config, density, gridSize); @@ -170,7 +171,7 @@ export default ({ config, device, timeBuffer }) => { timeBuffer, sceneBuffer, linearSampler, - msdfTexture.createView(), + glyphMSDFTexture.createView(), glintMSDFTexture.createView(), baseTexture.createView(), glintTexture.createView(), diff --git a/shaders/glsl/rainPass.frag.glsl b/shaders/glsl/rainPass.frag.glsl index bc30372..8141206 100644 --- a/shaders/glsl/rainPass.frag.glsl +++ b/shaders/glsl/rainPass.frag.glsl @@ -7,6 +7,8 @@ precision lowp float; uniform sampler2D raindropState, symbolState, effectState; uniform float numColumns, numRows; uniform sampler2D glyphMSDF, glintMSDF, baseTexture, glintTexture; +uniform float msdfPxRange; +uniform vec2 glyphMSDFSize, glintMSDFSize; uniform bool hasBaseTexture, hasGlintTexture; uniform float glyphHeightToWidth, glyphSequenceLength, glyphEdgeCrop; uniform float baseContrast, baseBrightness, glintContrast, glintBrightness; @@ -115,15 +117,23 @@ vec2 getSymbol(vec2 uv, float index) { // MSDF: calculate brightness of fragment based on distance to shape vec2 symbol; { - vec3 dist = texture2D(glyphMSDF, uv).rgb; - float sigDist = median3(dist) - 0.5; - symbol.r = clamp(sigDist / fwidth(sigDist) + 0.5, 0., 1.); + vec2 unitRange = vec2(msdfPxRange) / glyphMSDFSize; + vec2 screenTexSize = vec2(1.0) / fwidth(uv); + float screenPxRange = max(0.5 * dot(unitRange, screenTexSize), 1.0); + + float signedDistance = median3(texture2D(glyphMSDF, uv).rgb); + float screenPxDistance = screenPxRange * (signedDistance - 0.5); + symbol.r = clamp(screenPxDistance + 0.5, 0.0, 1.0); } if (isolateGlint) { - vec3 dist = texture2D(glintMSDF, uv).rgb; - float sigDist = median3(dist) - 0.5; - symbol.g = clamp(sigDist / fwidth(sigDist) + 0.5, 0., 1.); + vec2 unitRange = vec2(msdfPxRange) / glintMSDFSize; + vec2 screenTexSize = vec2(1.0) / fwidth(uv); + float screenPxRange = max(0.5 * dot(unitRange, screenTexSize), 1.0); + + float signedDistance = median3(texture2D(glintMSDF, uv).rgb); + float screenPxDistance = screenPxRange * (signedDistance - 0.5); + symbol.g = clamp(screenPxDistance + 0.5, 0.0, 1.0); } return symbol; @@ -157,6 +167,24 @@ void main() { ) * symbol.r, 1. ); + + uv = fract(uv * vec2(numColumns, numRows)); + uv -= 0.5; + uv *= clamp(1. - glyphEdgeCrop, 0., 1.); + if (length(uv) > 0.25) { + discard; + } + uv += 0.5; + + float goal = fwidth(uv - 0.5).x; + float computed = 1.0; + float magnifier = 50.0; + + if (uv.x <= 0.5) { + gl_FragColor = vec4(vec3(goal * magnifier), 1.0); + } else { + gl_FragColor = vec4(vec3(computed * magnifier), 1.0); + } } else { gl_FragColor = vec4(brightness.rg * symbol.r, brightness.b * symbol.g, 0.); } diff --git a/shaders/wgsl/rainPass.wgsl b/shaders/wgsl/rainPass.wgsl index 2ff58b7..028dead 100644 --- a/shaders/wgsl/rainPass.wgsl +++ b/shaders/wgsl/rainPass.wgsl @@ -26,6 +26,7 @@ struct Config { rippleType : i32, // render-specific properties + msdfPxRange : f32, forwardSpeed : f32, baseBrightness : f32, baseContrast : f32, @@ -94,7 +95,7 @@ struct IntroCellData { // Render-specific bindings @group(0) @binding(2) var scene : Scene; @group(0) @binding(3) var linearSampler : sampler; -@group(0) @binding(4) var msdfTexture : texture_2d; +@group(0) @binding(4) var glyphMSDFTexture : texture_2d; @group(0) @binding(5) var glintMSDFTexture : texture_2d; @group(0) @binding(6) var baseTexture : texture_2d; @group(0) @binding(7) var glintTexture : texture_2d; @@ -502,15 +503,31 @@ fn getSymbol(cellUV : vec2, index : i32) -> vec2 { // MSDF: calculate brightness of fragment based on distance to shape { - var dist = textureSample(msdfTexture, linearSampler, uv).rgb; - var sigDist = median3(dist) - 0.5; - symbol.r = clamp(sigDist / fwidth(sigDist) + 0.5, 0.0, 1.0); + // var dist = textureSample(glyphMSDFTexture, linearSampler, uv).rgb; + // var sigDist = median3(dist) - 0.5; + // symbol.r = clamp(sigDist / fwidth(sigDist) + 0.5, 0.0, 1.0); + + var unitRange = vec2(config.msdfPxRange) / vec2(textureDimensions(glyphMSDFTexture)); + var screenTexSize = vec2(1.0) / fwidth(uv); + var screenPxRange = max(0.5 * dot(unitRange, screenTexSize), 1.0); + + var signedDistance = median3(textureSample(glyphMSDFTexture, linearSampler, uv).rgb); + var screenPxDistance = screenPxRange * (signedDistance - 0.5); + symbol.r = clamp(screenPxDistance + 0.5, 0.0, 1.0); } if (bool(config.isolateGlint)) { - var dist = textureSample(glintMSDFTexture, linearSampler, uv).rgb; - var sigDist = median3(dist) - 0.5; - symbol.g = clamp(sigDist / fwidth(sigDist) + 0.5, 0.0, 1.0); + // var dist = textureSample(glintMSDFTexture, linearSampler, uv).rgb; + // var sigDist = median3(dist) - 0.5; + // symbol.g = clamp(sigDist / fwidth(sigDist) + 0.5, 0.0, 1.0); + + var unitRange = vec2(config.msdfPxRange) / vec2(textureDimensions(glintMSDFTexture)); + var screenTexSize = vec2(1.0) / fwidth(uv); + var screenPxRange = max(0.5 * dot(unitRange, screenTexSize), 1.0); + + var signedDistance = median3(textureSample(glintMSDFTexture, linearSampler, uv).rgb); + var screenPxDistance = screenPxRange * (signedDistance - 0.5); + symbol.g = clamp(screenPxDistance + 0.5, 0.0, 1.0); } return symbol;