Add basic subpixel AA support for SSAA.
No LCD filter is implemented yet, so the color fringing is currently fairly extreme.
This commit is contained in:
parent
acf2e0be00
commit
82d2f076d7
|
@ -37,6 +37,13 @@
|
|||
<option value="ecaa" selected>ECAA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" value="" type="checkbox"
|
||||
id="pf-subpixel-aa">
|
||||
Subpixel AA
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="pf-arrow-box"></div>
|
||||
|
|
|
@ -117,10 +117,12 @@ class ThreeDView extends PathfinderDemoView {
|
|||
this.pathTransformBufferTexture.upload(this.gl, pathTransforms);
|
||||
}
|
||||
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName, aaLevel: number):
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
aaLevel: number,
|
||||
subpixelAA: boolean):
|
||||
AntialiasingStrategy {
|
||||
if (aaType != 'ecaa')
|
||||
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel);
|
||||
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel, subpixelAA);
|
||||
throw new PathfinderError("Unsupported antialiasing type!");
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export abstract class AntialiasingStrategy {
|
|||
}
|
||||
|
||||
export class NoAAStrategy extends AntialiasingStrategy {
|
||||
constructor(level: number) {
|
||||
constructor(level: number, subpixelAA: boolean) {
|
||||
super();
|
||||
this.framebufferSize = glmatrix.vec2.create();
|
||||
}
|
||||
|
|
|
@ -93,7 +93,11 @@ export abstract class DemoAppController<View extends PathfinderDemoView> extends
|
|||
});
|
||||
|
||||
this.aaLevelSelect = document.getElementById('pf-aa-level-select') as HTMLSelectElement;
|
||||
this.subpixelAASwitch =
|
||||
document.getElementById('pf-subpixel-aa') as HTMLInputElement | null;
|
||||
this.aaLevelSelect.addEventListener('change', () => this.updateAALevel(), false);
|
||||
if (this.subpixelAASwitch != null)
|
||||
this.subpixelAASwitch.addEventListener('change', () => this.updateAALevel(), false);
|
||||
this.updateAALevel();
|
||||
}
|
||||
|
||||
|
@ -102,7 +106,8 @@ export abstract class DemoAppController<View extends PathfinderDemoView> extends
|
|||
const aaValues = unwrapNull(/^([a-z-]+)(?:-([0-9]+))?$/.exec(selectedOption.value));
|
||||
const aaType = aaValues[1] as AntialiasingStrategyName;
|
||||
const aaLevel = aaValues[2] === "" ? 1 : parseInt(aaValues[2]);
|
||||
this.view.then(view => view.setAntialiasingOptions(aaType, aaLevel));
|
||||
const subpixelAA = this.subpixelAASwitch == null ? false : this.subpixelAASwitch.checked;
|
||||
this.view.then(view => view.setAntialiasingOptions(aaType, aaLevel, subpixelAA));
|
||||
}
|
||||
|
||||
protected loadFile(event: Event) {
|
||||
|
@ -151,6 +156,8 @@ export abstract class DemoAppController<View extends PathfinderDemoView> extends
|
|||
protected shaderSources: ShaderMap<ShaderProgramSource> | null;
|
||||
|
||||
private aaLevelSelect: HTMLSelectElement;
|
||||
private subpixelAASwitch: HTMLInputElement | null;
|
||||
|
||||
private settingsCard: HTMLElement;
|
||||
private settingsButton: HTMLButtonElement;
|
||||
private settingsCloseButton: HTMLButtonElement;
|
||||
|
|
|
@ -26,7 +26,7 @@ interface UpperAndLower<T> {
|
|||
}
|
||||
|
||||
export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||
constructor(level: number) {
|
||||
constructor(level: number, subpixelAA: boolean) {
|
||||
super();
|
||||
this.framebufferSize = glmatrix.vec2.create();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ export const SHADER_NAMES: Array<keyof ShaderMap<void>> = [
|
|||
'directInterior',
|
||||
'direct3DCurve',
|
||||
'direct3DInterior',
|
||||
'ssaaSubpixelResolve',
|
||||
'ecaaEdgeDetect',
|
||||
'ecaaCover',
|
||||
'ecaaLine',
|
||||
|
@ -54,6 +55,10 @@ const SHADER_URLS: ShaderMap<ShaderProgramURLs> = {
|
|||
vertex: "/glsl/gles2/direct-3d-interior.vs.glsl",
|
||||
fragment: "/glsl/gles2/direct-interior.fs.glsl",
|
||||
},
|
||||
ssaaSubpixelResolve: {
|
||||
vertex: "/glsl/gles2/ssaa-subpixel-resolve.vs.glsl",
|
||||
fragment: "/glsl/gles2/ssaa-subpixel-resolve.fs.glsl",
|
||||
},
|
||||
ecaaEdgeDetect: {
|
||||
vertex: "/glsl/gles2/ecaa-edge-detect.vs.glsl",
|
||||
fragment: "/glsl/gles2/ecaa-edge-detect.fs.glsl",
|
||||
|
@ -90,6 +95,7 @@ export interface ShaderMap<T> {
|
|||
directInterior: T;
|
||||
direct3DCurve: T;
|
||||
direct3DInterior: T;
|
||||
ssaaSubpixelResolve: T;
|
||||
ecaaEdgeDetect: T;
|
||||
ecaaCover: T;
|
||||
ecaaLine: T;
|
||||
|
|
|
@ -16,9 +16,10 @@ import {unwrapNull} from './utils';
|
|||
import {PathfinderDemoView} from './view';
|
||||
|
||||
export default class SSAAStrategy extends AntialiasingStrategy {
|
||||
constructor(level: number) {
|
||||
constructor(level: number, subpixelAA: boolean) {
|
||||
super();
|
||||
this.level = level;
|
||||
this.subpixelAA = subpixelAA;
|
||||
this.destFramebufferSize = glmatrix.vec2.create();
|
||||
this.supersampledFramebufferSize = glmatrix.vec2.create();
|
||||
}
|
||||
|
@ -88,15 +89,22 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
|||
view.gl.disable(view.gl.DEPTH_TEST);
|
||||
|
||||
// Set up the blit program VAO.
|
||||
const blitProgram = view.shaderPrograms.blit;
|
||||
view.gl.useProgram(blitProgram.program);
|
||||
view.initQuadVAO(blitProgram.attributes);
|
||||
let resolveProgram;
|
||||
if (this.subpixelAA)
|
||||
resolveProgram = view.shaderPrograms.ssaaSubpixelResolve;
|
||||
else
|
||||
resolveProgram = view.shaderPrograms.blit;
|
||||
view.gl.useProgram(resolveProgram.program);
|
||||
view.initQuadVAO(resolveProgram.attributes);
|
||||
|
||||
// Resolve framebuffer.
|
||||
view.gl.activeTexture(view.gl.TEXTURE0);
|
||||
view.gl.bindTexture(view.gl.TEXTURE_2D, this.supersampledColorTexture);
|
||||
view.gl.uniform1i(blitProgram.uniforms.uSource, 0);
|
||||
view.setTransformAndTexScaleUniformsForDest(blitProgram.uniforms);
|
||||
view.gl.uniform1i(resolveProgram.uniforms.uSource, 0);
|
||||
view.gl.uniform2i(resolveProgram.uniforms.uSourceDimensions,
|
||||
this.supersampledFramebufferSize[0],
|
||||
this.supersampledFramebufferSize[1]);
|
||||
view.setTransformAndTexScaleUniformsForDest(resolveProgram.uniforms);
|
||||
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
|
||||
view.gl.drawElements(view.gl.TRIANGLES, 6, view.gl.UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
@ -106,7 +114,7 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
|||
}
|
||||
|
||||
private get supersampleScale(): glmatrix.vec2 {
|
||||
return glmatrix.vec2.fromValues(2, this.level == 2 ? 1 : 2);
|
||||
return glmatrix.vec2.fromValues(this.subpixelAA ? 3 : 2, this.level == 2 ? 1 : 2);
|
||||
}
|
||||
|
||||
private usedSupersampledFramebufferSize(view: PathfinderDemoView): glmatrix.vec2 {
|
||||
|
@ -116,6 +124,8 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
|||
}
|
||||
|
||||
private level: number;
|
||||
private subpixelAA: boolean;
|
||||
|
||||
private destFramebufferSize: glmatrix.vec2;
|
||||
private supersampledFramebufferSize: glmatrix.vec2;
|
||||
private supersampledColorTexture: WebGLTexture;
|
||||
|
|
|
@ -212,9 +212,11 @@ class SVGDemoView extends PathfinderDemoView {
|
|||
this.pathTransformBufferTexture.upload(this.gl, pathTransforms);
|
||||
}
|
||||
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName, aaLevel: number):
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
aaLevel: number,
|
||||
subpixelAA: boolean):
|
||||
AntialiasingStrategy {
|
||||
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel);
|
||||
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel, subpixelAA);
|
||||
}
|
||||
|
||||
protected compositeIfNecessary(): void {}
|
||||
|
|
|
@ -73,7 +73,7 @@ const B_POSITION_SIZE: number = 8;
|
|||
|
||||
const B_PATH_INDEX_SIZE: number = 2;
|
||||
|
||||
const ATLAS_SIZE: glmatrix.vec2 = glmatrix.vec2.fromValues(3072, 3072);
|
||||
const ATLAS_SIZE: glmatrix.vec2 = glmatrix.vec2.fromValues(2048, 4096);
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -477,9 +477,11 @@ class TextDemoView extends MonochromePathfinderView {
|
|||
return this.appController.atlas.usedSize;
|
||||
}
|
||||
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName, aaLevel: number):
|
||||
protected createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
aaLevel: number,
|
||||
subpixelAA: boolean):
|
||||
AntialiasingStrategy {
|
||||
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel);
|
||||
return new (ANTIALIASING_STRATEGIES[aaType])(aaLevel, subpixelAA);
|
||||
}
|
||||
|
||||
protected updateTimings(timings: Timings) {
|
||||
|
|
|
@ -107,12 +107,14 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
this.pathTransformBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathTransform');
|
||||
this.pathColorsBufferTexture = new PathfinderBufferTexture(this.gl, 'uPathColors');
|
||||
|
||||
this.antialiasingStrategy = new NoAAStrategy(0);
|
||||
this.antialiasingStrategy = new NoAAStrategy(0, false);
|
||||
this.antialiasingStrategy.init(this);
|
||||
}
|
||||
|
||||
setAntialiasingOptions(aaType: AntialiasingStrategyName, aaLevel: number) {
|
||||
this.antialiasingStrategy = this.createAAStrategy(aaType, aaLevel);
|
||||
setAntialiasingOptions(aaType: AntialiasingStrategyName,
|
||||
aaLevel: number,
|
||||
subpixelAA: boolean) {
|
||||
this.antialiasingStrategy = this.createAAStrategy(aaType, aaLevel, subpixelAA);
|
||||
|
||||
let canvas = this.canvas;
|
||||
this.antialiasingStrategy.init(this);
|
||||
|
@ -409,7 +411,9 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
|||
this.gl.uniform2f(uniforms.uTexScale, usedSize[0], usedSize[1]);
|
||||
}
|
||||
|
||||
protected abstract createAAStrategy(aaType: AntialiasingStrategyName, aaLevel: number):
|
||||
protected abstract createAAStrategy(aaType: AntialiasingStrategyName,
|
||||
aaLevel: number,
|
||||
subpixelAA: boolean):
|
||||
AntialiasingStrategy;
|
||||
|
||||
protected abstract compositeIfNecessary(): void;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// pathfinder/shaders/gles2/ssaa-subpixel-resolve.fs.glsl
|
||||
//
|
||||
// Copyright (c) 2017 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D uSource;
|
||||
uniform ivec2 uSourceDimensions;
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main() {
|
||||
float onePixel = 1.0 / float(uSourceDimensions.x);
|
||||
gl_FragColor = vec4(texture2D(uSource, vec2(vTexCoord.s - onePixel, vTexCoord.t)).r,
|
||||
texture2D(uSource, vec2(vTexCoord.s, vTexCoord.t)).r,
|
||||
texture2D(uSource, vec2(vTexCoord.s + onePixel, vTexCoord.t)).r,
|
||||
1.0);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// pathfinder/shaders/gles2/ssaa-subpixel-resolve.vs.glsl
|
||||
//
|
||||
// Copyright (c) 2017 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
precision mediump float;
|
||||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec2 uTexScale;
|
||||
|
||||
attribute vec2 aPosition;
|
||||
attribute vec2 aTexCoord;
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = uTransform * vec4(aPosition, 0.0, 1.0);
|
||||
vTexCoord = aTexCoord * uTexScale;
|
||||
}
|
Loading…
Reference in New Issue