From 3f7fc8baf61e3d07169216972ae7b941fa7bd929 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 15 Aug 2017 17:28:07 -0700 Subject: [PATCH] Add an edge detection shader for ECAA, untested as of yet --- demo/client/src/index.ts | 7 +++ shaders/gles2/common.inc.glsl | 3 ++ shaders/gles2/ecaa-edge-detect.fs.glsl | 68 ++++++++++++++++++++++++++ shaders/gles2/ecaa-edge-detect.vs.glsl | 15 ++++++ 4 files changed, 93 insertions(+) create mode 100644 shaders/gles2/ecaa-edge-detect.fs.glsl create mode 100644 shaders/gles2/ecaa-edge-detect.vs.glsl diff --git a/demo/client/src/index.ts b/demo/client/src/index.ts index 78b72514..a34d545a 100644 --- a/demo/client/src/index.ts +++ b/demo/client/src/index.ts @@ -39,6 +39,10 @@ const SHADER_URLS: ShaderMap = { vertex: "/glsl/gles2/direct-interior.vs.glsl", fragment: "/glsl/gles2/direct-interior.fs.glsl", }, + ecaaEdgeDetect: { + vertex: "/glsl/gles2/ecaa-edge-detect.vs.glsl", + fragment: "/glsl/gles2/ecaa-edge-detect.fs.glsl", + }, }; interface UnlinkedShaderProgram { @@ -67,6 +71,7 @@ interface ShaderMap { blit: T; directCurve: T; directInterior: T; + ecaaEdgeDetect: T; } interface UniformMap { @@ -322,8 +327,10 @@ class PathfinderView { // Initialize the OpenGL context. this.gl = expectNotNull(this.canvas.getContext('webgl', { antialias: false, depth: true }), "Failed to initialize WebGL! Check that your browser supports it."); + this.gl.getExtension('EXT_frag_depth'); this.gl.getExtension('OES_element_index_uint'); this.gl.getExtension('WEBGL_depth_texture'); + this.gl.getExtension('WEBGL_draw_buffers'); // Upload quad buffers. this.quadPositionsBuffer = unwrapNull(this.gl.createBuffer()); diff --git a/shaders/gles2/common.inc.glsl b/shaders/gles2/common.inc.glsl index 29fe9db8..7916accc 100644 --- a/shaders/gles2/common.inc.glsl +++ b/shaders/gles2/common.inc.glsl @@ -4,6 +4,9 @@ #version 100 +#extension GL_EXT_draw_buffers : require +#extension GL_EXT_frag_depth : require + #define MAX_PATHS 65536 precision highp float; diff --git a/shaders/gles2/ecaa-edge-detect.fs.glsl b/shaders/gles2/ecaa-edge-detect.fs.glsl new file mode 100644 index 00000000..140e0dc8 --- /dev/null +++ b/shaders/gles2/ecaa-edge-detect.fs.glsl @@ -0,0 +1,68 @@ +// pathfinder/shaders/gles2/ecaa-edge-detect.fs.glsl +// +// Copyright (c) 2017 Mozilla Foundation + +precision highp float; + +uniform ivec2 uFramebufferSize; +uniform sampler2D uColor; +uniform sampler2D uDepth; + +varying vec2 vTexCoord; + +vec3 checkFG(vec3 fgPosition, vec3 queryPosition) { + return queryPosition.z > fgPosition.z ? queryPosition : fgPosition; +} + +void main() { + // Unpack. + vec2 position = vTexCoord; + + // Compute positions. + vec2 onePixel = 1.0 / vec2(uFramebufferSize); + vec2 positionL = position + vec2(-onePixel.x, 0.0); + vec2 positionR = position + vec2( onePixel.x, 0.0); + vec2 positionB = position + vec2(0.0, -onePixel.x); + vec2 positionT = position + vec2(0.0, onePixel.x); + + // Determine the topmost path. + float centerDepth = texture2D(uDepth, position).r; + vec4 neighborDepths = vec4(texture2D(uDepth, positionL).r, + texture2D(uDepth, positionR).r, + texture2D(uDepth, positionT).r, + texture2D(uDepth, positionB).r); + + // Determine the position of the foreground color. + vec3 fgPosition = vec3(position, centerDepth); + fgPosition = checkFG(fgPosition, vec3(positionL, neighborDepths.x)); + fgPosition = checkFG(fgPosition, vec3(positionR, neighborDepths.y)); + fgPosition = checkFG(fgPosition, vec3(positionT, neighborDepths.z)); + fgPosition = checkFG(fgPosition, vec3(positionB, neighborDepths.w)); + + // Determine the position of the background color. + vec2 bgPosition; + if (fgPosition.z != centerDepth) + bgPosition = fgPosition.xy; + else if (fgPosition.z != neighborDepths.x) + bgPosition = positionL; + else if (fgPosition.z != neighborDepths.y) + bgPosition = positionR; + else if (fgPosition.z != neighborDepths.z) + bgPosition = positionT; + else + bgPosition = positionB; + + // Determine the foreground and background colors. + vec4 fgColor = texture2D(uColor, fgPosition.st); + vec4 bgColor = texture2D(uColor, bgPosition); + + // Determine the depth. + // + // If all colors are the same, avoid touching this pixel in any further passes. + float outDepth = fgColor == bgColor ? 0.0 : fgPosition.z; + + // Output results. + gl_FragData[0] = fgColor; + gl_FragData[1] = bgColor; + gl_FragDepthEXT = outDepth; +} diff --git a/shaders/gles2/ecaa-edge-detect.vs.glsl b/shaders/gles2/ecaa-edge-detect.vs.glsl new file mode 100644 index 00000000..e64ee9f1 --- /dev/null +++ b/shaders/gles2/ecaa-edge-detect.vs.glsl @@ -0,0 +1,15 @@ +// pathfinder/shaders/gles2/ecaa-edge-detect.vs.glsl +// +// Copyright (c) 2017 Mozilla Foundation + +precision highp float; + +attribute vec2 aPosition; +attribute vec2 aTexCoord; + +varying vec2 vTexCoord; + +void main() { + gl_Position = vec4(aPosition, 0.0, 1.0); + vTexCoord = aTexCoord; +}