Stop using multiple render targets.

We don't need them anymore, so let's lower our hardware requirements!
This commit is contained in:
Patrick Walton 2017-10-20 22:04:53 -07:00
parent 048c261f6c
commit 9d93cebca6
18 changed files with 266 additions and 200 deletions

View File

@ -15,13 +15,15 @@ import {DemoView} from './view';
export type AntialiasingStrategyName = 'none' | 'ssaa' | 'xcaa'; export type AntialiasingStrategyName = 'none' | 'ssaa' | 'xcaa';
export type DirectRenderingMode = 'none' | 'color' | 'pathID';
export type SubpixelAAType = 'none' | 'medium'; export type SubpixelAAType = 'none' | 'medium';
export type StemDarkeningMode = 'none' | 'dark'; export type StemDarkeningMode = 'none' | 'dark';
export abstract class AntialiasingStrategy { export abstract class AntialiasingStrategy {
// True if direct rendering should occur. // The type of direct rendering that should occur, if any.
shouldRenderDirect: boolean; abstract readonly directRenderingMode: DirectRenderingMode;
// Prepares any OpenGL data. This is only called on startup and canvas resize. // Prepares any OpenGL data. This is only called on startup and canvas resize.
init(renderer: Renderer): void { init(renderer: Renderer): void {
@ -82,7 +84,7 @@ export class NoAAStrategy extends AntialiasingStrategy {
resolve(renderer: Renderer) {} resolve(renderer: Renderer) {}
get shouldRenderDirect() { get directRenderingMode(): DirectRenderingMode {
return true; return 'color';
} }
} }

View File

@ -95,21 +95,17 @@ export function setTextureParameters(gl: WebGLRenderingContext, filter: number)
} }
export function createFramebuffer(gl: WebGLRenderingContext, export function createFramebuffer(gl: WebGLRenderingContext,
drawBuffersExt: WebGLDrawBuffers, colorAttachment: WebGLTexture,
colorAttachments: WebGLTexture[],
depthAttachment: WebGLTexture | null): depthAttachment: WebGLTexture | null):
WebGLFramebuffer { WebGLFramebuffer {
const framebuffer = unwrapNull(gl.createFramebuffer()); const framebuffer = unwrapNull(gl.createFramebuffer());
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
const colorAttachmentCount = colorAttachments.length; gl.framebufferTexture2D(gl.FRAMEBUFFER,
for (let colorAttachmentIndex = 0; gl.COLOR_ATTACHMENT0,
colorAttachmentIndex < colorAttachmentCount; gl.TEXTURE_2D,
colorAttachmentIndex++) { colorAttachment,
const glEnum = (drawBuffersExt as any)[`COLOR_ATTACHMENT${colorAttachmentIndex}_WEBGL`]; 0);
const attachment = colorAttachments[colorAttachmentIndex];
gl.framebufferTexture2D(gl.FRAMEBUFFER, glEnum, gl.TEXTURE_2D, attachment, 0);
}
if (depthAttachment != null) { if (depthAttachment != null) {
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.framebufferTexture2D(gl.FRAMEBUFFER,

View File

@ -119,7 +119,7 @@ export abstract class Renderer {
this.drawSceneryIfNecessary(); this.drawSceneryIfNecessary();
// Perform direct rendering (Loop-Blinn). // Perform direct rendering (Loop-Blinn).
if (antialiasingStrategy.shouldRenderDirect) if (antialiasingStrategy.directRenderingMode !== 'none')
this.renderDirect(); this.renderDirect();
// Antialias. // Antialias.
@ -263,29 +263,26 @@ export abstract class Renderer {
protected drawSceneryIfNecessary(): void {} protected drawSceneryIfNecessary(): void {}
protected clearForDirectRendering(): void { protected clearForDirectRendering(): void {
const renderingMode = unwrapNull(this.antialiasingStrategy).directRenderingMode;
const renderContext = this.renderContext; const renderContext = this.renderContext;
const gl = renderContext.gl; const gl = renderContext.gl;
renderContext.drawBuffersExt.drawBuffersWEBGL([ switch (renderingMode) {
renderContext.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL, case 'color':
]);
gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.clearDepth(0.0); gl.clearDepth(0.0);
gl.depthMask(true); gl.depthMask(true);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
break;
// Clear out the path ID buffer. case 'pathID':
renderContext.drawBuffersExt.drawBuffersWEBGL([
renderContext.gl.NONE,
renderContext.drawBuffersExt.COLOR_ATTACHMENT1_WEBGL,
]);
gl.clearColor(0.0, 0.0, 0.0, 0.0); gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT); gl.clearDepth(0.0);
gl.depthMask(true);
renderContext.drawBuffersExt.drawBuffersWEBGL([ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
renderContext.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL, break;
renderContext.drawBuffersExt.COLOR_ATTACHMENT1_WEBGL, case 'none':
]); // Nothing to do.
}
} }
protected getModelviewTransform(pathIndex: number): glmatrix.mat4 { protected getModelviewTransform(pathIndex: number): glmatrix.mat4 {
@ -301,7 +298,10 @@ export abstract class Renderer {
protected newTimingsReceived() {} protected newTimingsReceived() {}
private renderDirect() { private renderDirect() {
const renderingMode = unwrapNull(this.antialiasingStrategy).directRenderingMode;
const renderContext = this.renderContext; const renderContext = this.renderContext;
const gl = renderContext.gl;
for (let objectIndex = 0; objectIndex < this.meshes.length; objectIndex++) { for (let objectIndex = 0; objectIndex < this.meshes.length; objectIndex++) {
const instanceRange = this.instanceRangeForObject(objectIndex); const instanceRange = this.instanceRangeForObject(objectIndex);
if (instanceRange.isEmpty) if (instanceRange.isEmpty)
@ -310,10 +310,10 @@ export abstract class Renderer {
const meshes = this.meshes[objectIndex]; const meshes = this.meshes[objectIndex];
// Set up implicit cover state. // Set up implicit cover state.
renderContext.gl.depthFunc(this.depthFunction); gl.depthFunc(this.depthFunction);
renderContext.gl.depthMask(true); gl.depthMask(true);
renderContext.gl.enable(renderContext.gl.DEPTH_TEST); gl.enable(gl.DEPTH_TEST);
renderContext.gl.disable(renderContext.gl.BLEND); gl.disable(gl.BLEND);
// Set up the implicit cover interior VAO. // Set up the implicit cover interior VAO.
const directInteriorProgram = const directInteriorProgram =
@ -329,35 +329,27 @@ export abstract class Renderer {
this.setTransformUniform(directInteriorProgram.uniforms, objectIndex); this.setTransformUniform(directInteriorProgram.uniforms, objectIndex);
this.setFramebufferSizeUniform(directInteriorProgram.uniforms); this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
this.setHintsUniform(directInteriorProgram.uniforms); this.setHintsUniform(directInteriorProgram.uniforms);
if (renderingMode === 'color')
this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0); this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0);
this.pathTransformBufferTextures[objectIndex].bind(renderContext.gl, this.pathTransformBufferTextures[objectIndex]
directInteriorProgram.uniforms, .bind(gl, directInteriorProgram.uniforms, 1);
1); let indexCount = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE) /
let indexCount = UINT32_SIZE;
renderContext.gl.getBufferParameter(renderContext.gl.ELEMENT_ARRAY_BUFFER,
renderContext.gl.BUFFER_SIZE) / UINT32_SIZE;
if (!this.pathIDsAreInstanced) { if (!this.pathIDsAreInstanced) {
renderContext.gl.drawElements(renderContext.gl.TRIANGLES, gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_INT, 0);
indexCount,
renderContext.gl.UNSIGNED_INT,
0);
} else { } else {
renderContext.instancedArraysExt renderContext.instancedArraysExt.drawElementsInstancedANGLE(gl.TRIANGLES,
.drawElementsInstancedANGLE(renderContext.gl.TRIANGLES,
indexCount, indexCount,
renderContext.gl.UNSIGNED_INT, gl.UNSIGNED_INT,
0, 0,
instanceRange.length); instanceRange.length);
} }
// Set up direct curve state. // Set up direct curve state.
renderContext.gl.depthMask(false); gl.depthMask(false);
renderContext.gl.enable(renderContext.gl.BLEND); gl.enable(gl.BLEND);
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD); gl.blendEquation(gl.FUNC_ADD);
renderContext.gl.blendFuncSeparate(renderContext.gl.SRC_ALPHA, gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
renderContext.gl.ONE_MINUS_SRC_ALPHA,
renderContext.gl.ONE,
renderContext.gl.ONE);
// Set up the direct curve VAO. // Set up the direct curve VAO.
// //
@ -374,26 +366,17 @@ export abstract class Renderer {
this.setTransformUniform(directCurveProgram.uniforms, objectIndex); this.setTransformUniform(directCurveProgram.uniforms, objectIndex);
this.setFramebufferSizeUniform(directCurveProgram.uniforms); this.setFramebufferSizeUniform(directCurveProgram.uniforms);
this.setHintsUniform(directCurveProgram.uniforms); this.setHintsUniform(directCurveProgram.uniforms);
this.pathColorsBufferTextures[objectIndex].bind(renderContext.gl, if (renderingMode === 'color')
directCurveProgram.uniforms,
0);
this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0); this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0);
this.pathTransformBufferTextures[objectIndex].bind(renderContext.gl, this.pathTransformBufferTextures[objectIndex].bind(gl, directCurveProgram.uniforms, 1);
directCurveProgram.uniforms, indexCount = gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE) /
1); UINT32_SIZE;
indexCount =
renderContext.gl.getBufferParameter(renderContext.gl.ELEMENT_ARRAY_BUFFER,
renderContext.gl.BUFFER_SIZE) / UINT32_SIZE;
if (!this.pathIDsAreInstanced) { if (!this.pathIDsAreInstanced) {
renderContext.gl.drawElements(renderContext.gl.TRIANGLES, gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_INT, 0);
indexCount,
renderContext.gl.UNSIGNED_INT,
0);
} else { } else {
renderContext.instancedArraysExt renderContext.instancedArraysExt.drawElementsInstancedANGLE(gl.TRIANGLES,
.drawElementsInstancedANGLE(renderContext.gl.TRIANGLES,
indexCount, indexCount,
renderContext.gl.UNSIGNED_INT, gl.UNSIGNED_INT,
0, 0,
instanceRange.length); instanceRange.length);
} }

View File

@ -11,6 +11,28 @@
import {AttributeMap, UniformMap} from './gl-utils'; import {AttributeMap, UniformMap} from './gl-utils';
import {expectNotNull, PathfinderError, unwrapNull} from './utils'; import {expectNotNull, PathfinderError, unwrapNull} from './utils';
export interface ShaderMap<T> {
blit: T;
demo3DDistantGlyph: T;
demo3DMonument: T;
directCurve: T;
directInterior: T;
direct3DCurve: T;
direct3DInterior: T;
ecaaLine: T;
ecaaCurve: T;
mcaaCover: T;
mcaaLine: T;
mcaaCurve: T;
ssaaSubpixelResolve: T;
xcaaEdgeDetect: T;
xcaaMonoResolve: T;
xcaaMonoSubpixelResolve: T;
xcaaMultiDirectCurve: T;
xcaaMultiDirectInterior: T;
xcaaMultiResolve: T;
}
export interface UnlinkedShaderProgram { export interface UnlinkedShaderProgram {
vertex: WebGLShader; vertex: WebGLShader;
fragment: WebGLShader; fragment: WebGLShader;
@ -33,6 +55,8 @@ export const SHADER_NAMES: Array<keyof ShaderMap<void>> = [
'ecaaCurve', 'ecaaCurve',
'xcaaMonoResolve', 'xcaaMonoResolve',
'xcaaMonoSubpixelResolve', 'xcaaMonoSubpixelResolve',
'xcaaMultiDirectCurve',
'xcaaMultiDirectInterior',
'xcaaMultiResolve', 'xcaaMultiResolve',
'demo3DDistantGlyph', 'demo3DDistantGlyph',
'demo3DMonument', 'demo3DMonument',
@ -103,32 +127,20 @@ const SHADER_URLS: ShaderMap<ShaderProgramURLs> = {
fragment: "/glsl/gles2/xcaa-mono-subpixel-resolve.fs.glsl", fragment: "/glsl/gles2/xcaa-mono-subpixel-resolve.fs.glsl",
vertex: "/glsl/gles2/xcaa-mono-subpixel-resolve.vs.glsl", vertex: "/glsl/gles2/xcaa-mono-subpixel-resolve.vs.glsl",
}, },
xcaaMultiDirectCurve: {
fragment: "/glsl/gles2/xcaa-multi-direct-curve.fs.glsl",
vertex: "/glsl/gles2/xcaa-multi-direct-curve.vs.glsl",
},
xcaaMultiDirectInterior: {
fragment: "/glsl/gles2/xcaa-multi-direct-interior.fs.glsl",
vertex: "/glsl/gles2/xcaa-multi-direct-interior.vs.glsl",
},
xcaaMultiResolve: { xcaaMultiResolve: {
fragment: "/glsl/gles2/xcaa-multi-resolve.fs.glsl", fragment: "/glsl/gles2/xcaa-multi-resolve.fs.glsl",
vertex: "/glsl/gles2/xcaa-multi-resolve.vs.glsl", vertex: "/glsl/gles2/xcaa-multi-resolve.vs.glsl",
}, },
}; };
export interface ShaderMap<T> {
blit: T;
demo3DDistantGlyph: T;
demo3DMonument: T;
directCurve: T;
directInterior: T;
direct3DCurve: T;
direct3DInterior: T;
ecaaLine: T;
ecaaCurve: T;
mcaaCover: T;
mcaaLine: T;
mcaaCurve: T;
ssaaSubpixelResolve: T;
xcaaEdgeDetect: T;
xcaaMonoResolve: T;
xcaaMonoSubpixelResolve: T;
xcaaMultiResolve: T;
}
export interface ShaderProgramSource { export interface ShaderProgramSource {
vertex: string; vertex: string;
fragment: string; fragment: string;

View File

@ -10,7 +10,7 @@
import * as glmatrix from 'gl-matrix'; import * as glmatrix from 'gl-matrix';
import {AntialiasingStrategy, SubpixelAAType} from './aa-strategy'; import {AntialiasingStrategy, DirectRenderingMode, SubpixelAAType} from './aa-strategy';
import {createFramebuffer, createFramebufferDepthTexture, setTextureParameters} from './gl-utils'; import {createFramebuffer, createFramebufferDepthTexture, setTextureParameters} from './gl-utils';
import {Renderer} from './renderer'; import {Renderer} from './renderer';
import {unwrapNull} from './utils'; import {unwrapNull} from './utils';
@ -64,8 +64,7 @@ export default class SSAAStrategy extends AntialiasingStrategy {
createFramebufferDepthTexture(renderContext.gl, this.supersampledFramebufferSize); createFramebufferDepthTexture(renderContext.gl, this.supersampledFramebufferSize);
this.supersampledFramebuffer = createFramebuffer(renderContext.gl, this.supersampledFramebuffer = createFramebuffer(renderContext.gl,
renderContext.drawBuffersExt, this.supersampledColorTexture,
[this.supersampledColorTexture],
this.supersampledDepthTexture); this.supersampledDepthTexture);
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, null); renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, null);
@ -128,8 +127,8 @@ export default class SSAAStrategy extends AntialiasingStrategy {
0); 0);
} }
get shouldRenderDirect() { get directRenderingMode(): DirectRenderingMode {
return true; return 'color';
} }
private get supersampleScale(): glmatrix.vec2 { private get supersampleScale(): glmatrix.vec2 {

View File

@ -157,7 +157,7 @@ class SVGDemoRenderer extends Renderer {
this.camera.zoomToFit(); this.camera.zoomToFit();
} }
protected get depthFunction(): number { protected get depthFunction(): GLenum {
return this.renderContext.gl.GREATER; return this.renderContext.gl.GREATER;
} }
@ -180,10 +180,14 @@ class SVGDemoRenderer extends Renderer {
} }
protected get directCurveProgramName(): keyof ShaderMap<void> { protected get directCurveProgramName(): keyof ShaderMap<void> {
if (this.antialiasingStrategy instanceof XCAAStrategy)
return 'xcaaMultiDirectCurve';
return 'directCurve'; return 'directCurve';
} }
protected get directInteriorProgramName(): keyof ShaderMap<void> { protected get directInteriorProgramName(): keyof ShaderMap<void> {
if (this.antialiasingStrategy instanceof XCAAStrategy)
return 'xcaaMultiDirectInterior';
return 'directInterior'; return 'directInterior';
} }

View File

@ -181,8 +181,7 @@ export abstract class TextRenderer extends Renderer {
const atlasColorTexture = this.renderContext.atlas.ensureTexture(this.renderContext); const atlasColorTexture = this.renderContext.atlas.ensureTexture(this.renderContext);
this.atlasDepthTexture = createFramebufferDepthTexture(this.renderContext.gl, ATLAS_SIZE); this.atlasDepthTexture = createFramebufferDepthTexture(this.renderContext.gl, ATLAS_SIZE);
this.atlasFramebuffer = createFramebuffer(this.renderContext.gl, this.atlasFramebuffer = createFramebuffer(this.renderContext.gl,
this.renderContext.drawBuffersExt, atlasColorTexture,
[atlasColorTexture],
this.atlasDepthTexture); this.atlasDepthTexture);
// Allow the antialiasing strategy to set up framebuffers as necessary. // Allow the antialiasing strategy to set up framebuffers as necessary.

View File

@ -115,7 +115,6 @@ export abstract class DemoView extends PathfinderView implements RenderContext {
shaderPrograms: ShaderMap<PathfinderShaderProgram>; shaderPrograms: ShaderMap<PathfinderShaderProgram>;
drawBuffersExt: WebGLDrawBuffers;
instancedArraysExt: ANGLEInstancedArrays; instancedArraysExt: ANGLEInstancedArrays;
textureHalfFloatExt: OESTextureHalfFloat; textureHalfFloatExt: OESTextureHalfFloat;
timerQueryExt: EXTDisjointTimerQuery; timerQueryExt: EXTDisjointTimerQuery;
@ -192,7 +191,6 @@ export abstract class DemoView extends PathfinderView implements RenderContext {
// Initialize the OpenGL context. // Initialize the OpenGL context.
this.gl = expectNotNull(this.canvas.getContext('webgl', { antialias: false, depth: true }), this.gl = expectNotNull(this.canvas.getContext('webgl', { antialias: false, depth: true }),
"Failed to initialize WebGL! Check that your browser supports it."); "Failed to initialize WebGL! Check that your browser supports it.");
this.drawBuffersExt = this.gl.getExtension('WEBGL_draw_buffers');
this.colorBufferHalfFloatExt = this.gl.getExtension('EXT_color_buffer_half_float'); this.colorBufferHalfFloatExt = this.gl.getExtension('EXT_color_buffer_half_float');
this.instancedArraysExt = this.gl.getExtension('ANGLE_instanced_arrays'); this.instancedArraysExt = this.gl.getExtension('ANGLE_instanced_arrays');
this.sRGBExt = this.gl.getExtension('EXT_sRGB'); this.sRGBExt = this.gl.getExtension('EXT_sRGB');
@ -303,8 +301,6 @@ export interface RenderContext {
/// The OpenGL context. /// The OpenGL context.
readonly gl: WebGLRenderingContext; readonly gl: WebGLRenderingContext;
/// The `WEBGL_draw_buffers` extension.
readonly drawBuffersExt: WebGLDrawBuffers;
readonly instancedArraysExt: ANGLEInstancedArrays; readonly instancedArraysExt: ANGLEInstancedArrays;
readonly textureHalfFloatExt: OESTextureHalfFloat; readonly textureHalfFloatExt: OESTextureHalfFloat;
readonly timerQueryExt: EXTDisjointTimerQuery; readonly timerQueryExt: EXTDisjointTimerQuery;

View File

@ -11,7 +11,7 @@
import * as glmatrix from 'gl-matrix'; import * as glmatrix from 'gl-matrix';
import * as _ from 'lodash'; import * as _ from 'lodash';
import {AntialiasingStrategy, SubpixelAAType} from './aa-strategy'; import {AntialiasingStrategy, DirectRenderingMode, SubpixelAAType} from './aa-strategy';
import PathfinderBufferTexture from './buffer-texture'; import PathfinderBufferTexture from './buffer-texture';
import {createFramebuffer, createFramebufferColorTexture} from './gl-utils'; import {createFramebuffer, createFramebufferColorTexture} from './gl-utils';
import {createFramebufferDepthTexture, setTextureParameters, UniformMap} from './gl-utils'; import {createFramebufferDepthTexture, setTextureParameters, UniformMap} from './gl-utils';
@ -33,10 +33,9 @@ type Direction = 'upper' | 'lower';
const DIRECTIONS: Direction[] = ['upper', 'lower']; const DIRECTIONS: Direction[] = ['upper', 'lower'];
export abstract class XCAAStrategy extends AntialiasingStrategy { export abstract class XCAAStrategy extends AntialiasingStrategy {
abstract shouldRenderDirect: boolean; abstract readonly directRenderingMode: DirectRenderingMode;
protected directColorTexture: WebGLTexture; protected directTexture: WebGLTexture;
protected directPathIDTexture: WebGLTexture;
protected aaDepthTexture: WebGLTexture; protected aaDepthTexture: WebGLTexture;
protected pathBoundsBufferTexture: PathfinderBufferTexture; protected pathBoundsBufferTexture: PathfinderBufferTexture;
@ -87,40 +86,22 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
prepare(renderer: Renderer) { prepare(renderer: Renderer) {
const renderContext = renderer.renderContext; const renderContext = renderer.renderContext;
const gl = renderContext.gl;
const usedSize = this.supersampledUsedSize(renderer); const usedSize = this.supersampledUsedSize(renderer);
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, this.directFramebuffer); gl.bindFramebuffer(gl.FRAMEBUFFER, this.directFramebuffer);
renderContext.gl.viewport(0, gl.viewport(0,
0, 0,
this.supersampledFramebufferSize[0], this.supersampledFramebufferSize[0],
this.supersampledFramebufferSize[1]); this.supersampledFramebufferSize[1]);
renderContext.gl.scissor(0, 0, usedSize[0], usedSize[1]); gl.scissor(0, 0, usedSize[0], usedSize[1]);
renderContext.gl.enable(renderContext.gl.SCISSOR_TEST); gl.enable(gl.SCISSOR_TEST);
// Clear out the color and depth textures. // Clear out the color and depth textures.
renderContext.drawBuffersExt.drawBuffersWEBGL([ gl.clearColor(1.0, 1.0, 1.0, 1.0);
renderContext.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL, gl.clearDepth(0.0);
renderContext.gl.NONE, gl.depthMask(true);
]); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
renderContext.gl.clearColor(1.0, 1.0, 1.0, 1.0);
renderContext.gl.clearDepth(0.0);
renderContext.gl.depthMask(true);
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT |
renderContext.gl.DEPTH_BUFFER_BIT);
// Clear out the path ID texture.
renderContext.drawBuffersExt.drawBuffersWEBGL([
renderContext.gl.NONE,
renderContext.drawBuffersExt.COLOR_ATTACHMENT1_WEBGL,
]);
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
// Render to both textures.
renderContext.drawBuffersExt.drawBuffersWEBGL([
renderContext.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL,
renderContext.drawBuffersExt.COLOR_ATTACHMENT1_WEBGL,
]);
} }
antialias(renderer: Renderer) { antialias(renderer: Renderer) {
@ -145,16 +126,19 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
protected initDirectFramebuffer(renderer: Renderer) { protected initDirectFramebuffer(renderer: Renderer) {
const renderContext = renderer.renderContext; const renderContext = renderer.renderContext;
this.directColorTexture = createFramebufferColorTexture(renderContext.gl, const gl = renderContext.gl;
let textureFormat;
if (this.directRenderingMode === 'pathID')
textureFormat = gl.RGBA;
else
textureFormat = renderContext.colorAlphaFormat;
this.directTexture = createFramebufferColorTexture(gl,
this.destFramebufferSize, this.destFramebufferSize,
renderContext.colorAlphaFormat); textureFormat);
this.directPathIDTexture = createFramebufferColorTexture(renderContext.gl, this.directFramebuffer = createFramebuffer(renderContext.gl,
this.destFramebufferSize, this.directTexture,
renderContext.gl.RGBA);
this.directFramebuffer =
createFramebuffer(renderContext.gl,
renderContext.drawBuffersExt,
[this.directColorTexture, this.directPathIDTexture],
this.directDepthTexture); this.directDepthTexture);
} }
@ -214,12 +198,6 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
gl.enable(gl.SCISSOR_TEST); gl.enable(gl.SCISSOR_TEST);
gl.disable(gl.DEPTH_TEST); gl.disable(gl.DEPTH_TEST);
gl.disable(gl.BLEND); gl.disable(gl.BLEND);
if (renderer.destFramebuffer != null) {
renderContext.drawBuffersExt
.drawBuffersWEBGL([renderContext.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL]);
} else {
renderContext.drawBuffersExt.drawBuffersWEBGL([gl.BACK]);
}
// Clear out the resolve buffer, if necessary. // Clear out the resolve buffer, if necessary.
this.clearForResolve(renderer); this.clearForResolve(renderer);
@ -272,8 +250,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
this.supersampledFramebufferSize); this.supersampledFramebufferSize);
this.aaFramebuffer = createFramebuffer(renderContext.gl, this.aaFramebuffer = createFramebuffer(renderContext.gl,
renderContext.drawBuffersExt, this.aaAlphaTexture,
[this.aaAlphaTexture],
this.aaDepthTexture); this.aaDepthTexture);
} }
@ -647,8 +624,8 @@ export class ECAAStrategy extends XCAAStrategy {
private lineVAO: WebGLVertexArrayObject; private lineVAO: WebGLVertexArrayObject;
private curveVAO: WebGLVertexArrayObject; private curveVAO: WebGLVertexArrayObject;
get shouldRenderDirect() { get directRenderingMode(): DirectRenderingMode {
return false; return 'none';
} }
attachMeshes(renderer: Renderer) { attachMeshes(renderer: Renderer) {
@ -952,8 +929,8 @@ export class MCAAMonochromeStrategy extends MCAAStrategy {
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT); renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
} }
get shouldRenderDirect() { get directRenderingMode(): DirectRenderingMode {
return false; return 'none';
} }
} }
@ -964,8 +941,8 @@ export class AdaptiveMonochromeXCAAStrategy implements AntialiasingStrategy {
private mcaaStrategy: MCAAMonochromeStrategy; private mcaaStrategy: MCAAMonochromeStrategy;
private ecaaStrategy: ECAAStrategy; private ecaaStrategy: ECAAStrategy;
get shouldRenderDirect(): boolean { get directRenderingMode(): DirectRenderingMode {
return false; return 'none';
} }
constructor(level: number, subpixelAA: SubpixelAAType) { constructor(level: number, subpixelAA: SubpixelAAType) {
@ -1035,8 +1012,7 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
this.supersampledFramebufferSize, this.supersampledFramebufferSize,
renderContext.gl.RGBA); renderContext.gl.RGBA);
this.edgeDetectFramebuffer = createFramebuffer(renderContext.gl, this.edgeDetectFramebuffer = createFramebuffer(renderContext.gl,
renderContext.drawBuffersExt, this.edgePathIDTexture,
[this.edgePathIDTexture],
this.aaDepthTexture); this.aaDepthTexture);
} }
@ -1063,10 +1039,6 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
this.supersampledFramebufferSize[0], this.supersampledFramebufferSize[0],
this.supersampledFramebufferSize[1]); this.supersampledFramebufferSize[1]);
renderContext.drawBuffersExt.drawBuffersWEBGL([
renderContext.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL,
]);
gl.depthMask(true); gl.depthMask(true);
gl.depthFunc(renderContext.gl.ALWAYS); gl.depthFunc(renderContext.gl.ALWAYS);
gl.enable(renderContext.gl.DEPTH_TEST); gl.enable(renderContext.gl.DEPTH_TEST);
@ -1083,7 +1055,7 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
renderer.setTransformSTAndTexScaleUniformsForDest(edgeDetectProgram.uniforms); renderer.setTransformSTAndTexScaleUniformsForDest(edgeDetectProgram.uniforms);
renderer.setPathColorsUniform(0, edgeDetectProgram.uniforms, 0); renderer.setPathColorsUniform(0, edgeDetectProgram.uniforms, 0);
gl.activeTexture(renderContext.gl.TEXTURE1); gl.activeTexture(renderContext.gl.TEXTURE1);
gl.bindTexture(renderContext.gl.TEXTURE_2D, this.directPathIDTexture); gl.bindTexture(renderContext.gl.TEXTURE_2D, this.directTexture);
gl.uniform1i(edgeDetectProgram.uniforms.uPathID, 1); gl.uniform1i(edgeDetectProgram.uniforms.uPathID, 1);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0); gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
@ -1103,12 +1075,6 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
renderContext.gl.enable(renderContext.gl.SCISSOR_TEST); renderContext.gl.enable(renderContext.gl.SCISSOR_TEST);
renderContext.gl.disable(renderContext.gl.DEPTH_TEST); renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
renderContext.gl.disable(renderContext.gl.BLEND); renderContext.gl.disable(renderContext.gl.BLEND);
if (renderer.destFramebuffer != null) {
renderContext.drawBuffersExt
.drawBuffersWEBGL([renderContext.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL]);
} else {
renderContext.drawBuffersExt.drawBuffersWEBGL([renderContext.gl.BACK]);
}
// Resolve. // Resolve.
const resolveProgram = this.getResolveProgram(renderContext); const resolveProgram = this.getResolveProgram(renderContext);
@ -1157,8 +1123,8 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
protected clearForResolve(renderer: Renderer) {} protected clearForResolve(renderer: Renderer) {}
get shouldRenderDirect() { get directRenderingMode(): DirectRenderingMode {
return true; return 'pathID';
} }
protected get directDepthTexture(): WebGLTexture { protected get directDepthTexture(): WebGLTexture {

View File

@ -10,7 +10,6 @@
#version 100 #version 100
#extension GL_EXT_draw_buffers : require
#extension GL_EXT_frag_depth : require #extension GL_EXT_frag_depth : require
#define LCD_FILTER_FACTOR_0 (86.0 / 255.0) #define LCD_FILTER_FACTOR_0 (86.0 / 255.0)

View File

@ -13,13 +13,11 @@
precision highp float; precision highp float;
varying vec4 vColor; varying vec4 vColor;
varying vec2 vPathID;
varying vec2 vTexCoord; varying vec2 vTexCoord;
varying float vSign; varying float vSign;
void main() { void main() {
float side = vTexCoord.x * vTexCoord.x - vTexCoord.y; float side = vTexCoord.x * vTexCoord.x - vTexCoord.y;
float alpha = float(sign(side) == sign(vSign)); float alpha = float(sign(side) == sign(vSign));
gl_FragData[0] = vec4(vColor.rgb, vColor.a * alpha); gl_FragColor = vec4(vColor.rgb, vColor.a * alpha);
gl_FragData[1] = vec4(vPathID, 0.0, alpha);
} }

View File

@ -23,7 +23,6 @@ attribute float aPathID;
attribute float aSign; attribute float aSign;
varying vec4 vColor; varying vec4 vColor;
varying vec2 vPathID;
varying vec2 vTexCoord; varying vec2 vTexCoord;
varying float vSign; varying float vSign;
@ -40,7 +39,6 @@ void main() {
gl_Position = vec4(position, depth, 1.0); gl_Position = vec4(position, depth, 1.0);
vColor = fetchFloat4Data(uPathColors, pathID, uPathColorsDimensions); vColor = fetchFloat4Data(uPathColors, pathID, uPathColorsDimensions);
vPathID = packPathID(pathID);
vTexCoord = vec2(aTexCoord) / 2.0; vTexCoord = vec2(aTexCoord) / 2.0;
vSign = aSign; vSign = aSign;
} }

View File

@ -11,9 +11,7 @@
precision highp float; precision highp float;
varying vec4 vColor; varying vec4 vColor;
varying vec2 vPathID;
void main() { void main() {
gl_FragData[0] = vColor; gl_FragColor = vColor;
gl_FragData[1] = vec4(vPathID, 0.0, 1.0);
} }

View File

@ -21,7 +21,6 @@ attribute vec2 aPosition;
attribute float aPathID; attribute float aPathID;
varying vec4 vColor; varying vec4 vColor;
varying vec2 vPathID;
void main() { void main() {
int pathID = int(aPathID); int pathID = int(aPathID);
@ -36,5 +35,4 @@ void main() {
gl_Position = vec4(position, depth, 1.0); gl_Position = vec4(position, depth, 1.0);
vColor = fetchFloat4Data(uPathColors, pathID, uPathColorsDimensions); vColor = fetchFloat4Data(uPathColors, pathID, uPathColorsDimensions);
vPathID = packPathID(pathID);
} }

View File

@ -0,0 +1,23 @@
// pathfinder/shaders/gles2/xcaa-multi-direct-curve.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.
// This shader implements the quadratic Loop-Blinn formulation.
precision highp float;
varying vec2 vPathID;
varying vec2 vTexCoord;
varying float vSign;
void main() {
float side = vTexCoord.x * vTexCoord.x - vTexCoord.y;
float alpha = float(sign(side) == sign(vSign));
gl_FragColor = vec4(vPathID, 0.0, alpha);
}

View File

@ -0,0 +1,42 @@
// pathfinder/shaders/gles2/xcaa-multi-direct-curve.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 highp float;
uniform mat4 uTransform;
uniform vec4 uHints;
uniform ivec2 uPathTransformDimensions;
uniform sampler2D uPathTransform;
attribute vec2 aPosition;
attribute vec2 aTexCoord;
attribute float aPathID;
attribute float aSign;
varying vec2 vPathID;
varying vec2 vTexCoord;
varying float vSign;
void main() {
int pathID = int(aPathID);
vec4 pathTransform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
vec2 position = hintPosition(aPosition, uHints);
position = transformVertexPositionST(position, pathTransform);
position = transformVertexPosition(position, uTransform);
float depth = convertPathIndexToViewportDepthValue(pathID);
gl_Position = vec4(position, depth, 1.0);
vPathID = packPathID(pathID);
vTexCoord = vec2(aTexCoord) / 2.0;
vSign = aSign;
}

View File

@ -0,0 +1,17 @@
// pathfinder/shaders/gles2/xcaa-multi-direct-interior.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 highp float;
varying vec2 vPathID;
void main() {
gl_FragColor = vec4(vPathID, 0.0, 1.0);
}

View File

@ -0,0 +1,36 @@
// pathfinder/shaders/gles2/xcaa-multi-direct-interior.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 highp float;
uniform mat4 uTransform;
uniform vec4 uHints;
uniform ivec2 uPathTransformDimensions;
uniform sampler2D uPathTransform;
attribute vec2 aPosition;
attribute float aPathID;
varying vec2 vPathID;
void main() {
int pathID = int(aPathID);
vec4 pathTransform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
vec2 position = hintPosition(aPosition, uHints);
position = transformVertexPositionST(position, pathTransform);
position = transformVertexPosition(position, uTransform);
float depth = convertPathIndexToViewportDepthValue(pathID);
gl_Position = vec4(position, depth, 1.0);
vPathID = packPathID(pathID);
}