Implement clipping in XCAA mode

This commit is contained in:
Patrick Walton 2017-11-08 12:20:57 -08:00
parent 941223c7d4
commit 9a5728aab6
7 changed files with 698 additions and 595 deletions

View File

@ -44,20 +44,28 @@ export abstract class AntialiasingStrategy {
// Returns the transformation matrix that should be applied when directly rendering. // Returns the transformation matrix that should be applied when directly rendering.
abstract get transform(): glmatrix.mat4; abstract get transform(): glmatrix.mat4;
// Called before direct rendering. // Called before rendering.
// //
// Typically, this redirects direct rendering to a framebuffer of some sort. // Typically, this redirects rendering to a framebuffer of some sort.
abstract prepareForRendering(renderer: Renderer): void; abstract prepareForRendering(renderer: Renderer): void;
// Called before directly rendering.
//
// Typically, this redirects rendering to a framebuffer of some sort.
abstract prepareForDirectRendering(renderer: Renderer): void;
// Called before directly rendering a single object. // Called before directly rendering a single object.
abstract prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void; abstract prepareToRenderObject(renderer: Renderer, objectIndex: number): void;
abstract finishDirectlyRenderingObject(renderer: Renderer, objectIndex: number): void; abstract finishDirectlyRenderingObject(renderer: Renderer, objectIndex: number): void;
// Called after direct rendering. // Called after direct rendering.
// //
// This usually performs the actual antialiasing. // This usually performs the actual antialiasing.
abstract antialias(renderer: Renderer): void; abstract antialiasObject(renderer: Renderer, objectIndex: number): void;
// Called after antialiasing each object.
abstract resolveAAForObject(renderer: Renderer, objectIndex: number): void;
// Called after antialiasing. // Called after antialiasing.
// //
@ -98,7 +106,9 @@ export class NoAAStrategy extends AntialiasingStrategy {
gl.disable(gl.SCISSOR_TEST); gl.disable(gl.SCISSOR_TEST);
} }
prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void { prepareForDirectRendering(renderer: Renderer): void {}
prepareToRenderObject(renderer: Renderer, objectIndex: number): void {
const renderContext = renderer.renderContext; const renderContext = renderer.renderContext;
const gl = renderContext.gl; const gl = renderContext.gl;
@ -147,9 +157,11 @@ export class NoAAStrategy extends AntialiasingStrategy {
compositingOperation.composite(renderer, objectIndex, this.renderTargetColorTextures); compositingOperation.composite(renderer, objectIndex, this.renderTargetColorTextures);
} }
antialias(renderer: Renderer) {} antialiasObject(renderer: Renderer, objectIndex: number): void {}
resolve(renderer: Renderer) {} resolveAAForObject(renderer: Renderer): void {}
resolve(renderer: Renderer): void {}
get directRenderingMode(): DirectRenderingMode { get directRenderingMode(): DirectRenderingMode {
return 'color'; return 'color';

View File

@ -301,7 +301,7 @@ export abstract class DemoAppController<View extends DemoView> extends AppContro
}); });
} }
private fileSelectionChanged(event: Event) { private fileSelectionChanged(event: Event): void {
const selectFileElement = event.currentTarget as HTMLSelectElement; const selectFileElement = event.currentTarget as HTMLSelectElement;
const selectedOption = selectFileElement.selectedOptions[0] as HTMLOptionElement; const selectedOption = selectFileElement.selectedOptions[0] as HTMLOptionElement;

View File

@ -102,6 +102,7 @@ export abstract class Renderer {
this.antialiasingStrategy = new NoAAStrategy(0, 'none'); this.antialiasingStrategy = new NoAAStrategy(0, 'none');
this.antialiasingStrategy.init(this); this.antialiasingStrategy.init(this);
this.antialiasingStrategy.setFramebufferSize(this);
} }
attachMeshes(meshes: PathfinderMeshData[]): void { attachMeshes(meshes: PathfinderMeshData[]): void {
@ -134,12 +135,27 @@ export abstract class Renderer {
// Draw "scenery" (used in the 3D view). // Draw "scenery" (used in the 3D view).
this.drawSceneryIfNecessary(); this.drawSceneryIfNecessary();
// Antialias.
antialiasingStrategy.antialias(this);
// Perform direct rendering (Loop-Blinn).
if (antialiasingStrategy.directRenderingMode !== 'none') if (antialiasingStrategy.directRenderingMode !== 'none')
this.renderDirect(); antialiasingStrategy.prepareForDirectRendering(this);
const objectCount = this.objectCount;
for (let objectIndex = 0; objectIndex < objectCount; objectIndex++) {
// Antialias.
antialiasingStrategy.antialiasObject(this, objectIndex);
// Prepare for direct rendering.
antialiasingStrategy.prepareToRenderObject(this, objectIndex);
// Perform direct rendering (Loop-Blinn).
if (antialiasingStrategy.directRenderingMode !== 'none') {
// Clear.
this.clearForDirectRendering(objectIndex);
this.directlyRenderObject(objectIndex);
}
antialiasingStrategy.resolveAAForObject(this, objectIndex);
}
// End the timer, and start a new one. // End the timer, and start a new one.
if (this.timerQueryPollInterval == null) { if (this.timerQueryPollInterval == null) {
@ -171,6 +187,7 @@ export abstract class Renderer {
this.antialiasingStrategy.init(this); this.antialiasingStrategy.init(this);
if (this.meshData != null) if (this.meshData != null)
this.antialiasingStrategy.attachMeshes(this); this.antialiasingStrategy.attachMeshes(this);
this.antialiasingStrategy.setFramebufferSize(this);
this.renderContext.setDirty(); this.renderContext.setDirty();
} }
@ -276,6 +293,15 @@ export abstract class Renderer {
return null; return null;
} }
meshIndexForObject(objectIndex: number): number {
return objectIndex;
}
pathRangeForObject(objectIndex: number): Range {
const bVertexPathRanges = this.meshes[objectIndex].bVertexPathRanges;
return new Range(1, bVertexPathRanges.length + 1);
}
protected clearColorForObject(objectIndex: number): glmatrix.vec4 | null { protected clearColorForObject(objectIndex: number): glmatrix.vec4 | null {
return glmatrix.vec4.create(); return glmatrix.vec4.create();
} }
@ -352,19 +378,10 @@ export abstract class Renderer {
return new Range(0, 1); return new Range(0, 1);
} }
protected meshIndexForObject(objectIndex: number): number {
return objectIndex;
}
protected pathRangeForObject(objectIndex: number): Range {
const bVertexPathRanges = this.meshes[objectIndex].bVertexPathRanges;
return new Range(1, bVertexPathRanges.length + 1);
}
/// Called whenever new GPU timing statistics are available. /// Called whenever new GPU timing statistics are available.
protected newTimingsReceived(): void {} protected newTimingsReceived(): void {}
private renderDirect(): void { private directlyRenderObject(objectIndex: number): void {
const renderContext = this.renderContext; const renderContext = this.renderContext;
const gl = renderContext.gl; const gl = renderContext.gl;
@ -372,118 +389,110 @@ export abstract class Renderer {
const renderingMode = antialiasingStrategy.directRenderingMode; const renderingMode = antialiasingStrategy.directRenderingMode;
const objectCount = this.objectCount; const objectCount = this.objectCount;
for (let objectIndex = 0; objectIndex < objectCount; objectIndex++) { const instanceRange = this.instanceRangeForObject(objectIndex);
const instanceRange = this.instanceRangeForObject(objectIndex); if (instanceRange.isEmpty)
if (instanceRange.isEmpty) return;
continue;
const pathRange = this.pathRangeForObject(objectIndex); const pathRange = this.pathRangeForObject(objectIndex);
const meshIndex = this.meshIndexForObject(objectIndex); const meshIndex = this.meshIndexForObject(objectIndex);
// Prepare for direct rendering. const meshes = this.meshes[meshIndex];
antialiasingStrategy.prepareToDirectlyRenderObject(this, objectIndex); const meshData = this.meshData[meshIndex];
// Clear. // Set up implicit cover state.
this.clearForDirectRendering(objectIndex); gl.depthFunc(gl.GREATER);
gl.depthMask(true);
gl.enable(gl.DEPTH_TEST);
gl.disable(gl.BLEND);
const meshes = this.meshes[meshIndex]; // Set up the implicit cover interior VAO.
const meshData = this.meshData[meshIndex]; const directInteriorProgramName = this.directInteriorProgramName();
const directInteriorProgram = renderContext.shaderPrograms[directInteriorProgramName];
// Set up implicit cover state. if (this.implicitCoverInteriorVAO == null) {
gl.depthFunc(gl.GREATER); this.implicitCoverInteriorVAO = renderContext.vertexArrayObjectExt
gl.depthMask(true); .createVertexArrayOES();
gl.enable(gl.DEPTH_TEST);
gl.disable(gl.BLEND);
// Set up the implicit cover interior VAO.
const directInteriorProgramName = this.directInteriorProgramName();
const directInteriorProgram = renderContext.shaderPrograms[directInteriorProgramName];
if (this.implicitCoverInteriorVAO == null) {
this.implicitCoverInteriorVAO = renderContext.vertexArrayObjectExt
.createVertexArrayOES();
}
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.implicitCoverInteriorVAO);
this.initImplicitCoverInteriorVAO(objectIndex, instanceRange);
// Draw direct interior parts.
this.setTransformUniform(directInteriorProgram.uniforms, objectIndex);
this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
this.setHintsUniform(directInteriorProgram.uniforms);
this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0);
this.pathTransformBufferTextures[meshIndex]
.bind(gl, directInteriorProgram.uniforms, 1);
if (renderingMode === 'color-depth') {
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
strategy.bindEdgeDepthTexture(gl, directInteriorProgram.uniforms, 2);
}
const coverInteriorRange = getMeshIndexRange(meshes.coverInteriorIndexRanges,
pathRange);
if (!this.pathIDsAreInstanced) {
gl.drawElements(gl.TRIANGLES,
coverInteriorRange.length,
gl.UNSIGNED_INT,
coverInteriorRange.start * UINT32_SIZE);
} else {
renderContext.instancedArraysExt
.drawElementsInstancedANGLE(gl.TRIANGLES,
coverInteriorRange.length,
gl.UNSIGNED_INT,
0,
instanceRange.length);
}
// Set up direct curve state.
if (renderingMode === 'color-depth') {
gl.depthMask(true);
gl.disable(gl.BLEND);
} else {
gl.depthMask(false);
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
}
// Set up the direct curve VAO.
//
// TODO(pcwalton): Cache these.
const directCurveProgramName = this.directCurveProgramName();
const directCurveProgram = renderContext.shaderPrograms[directCurveProgramName];
if (this.implicitCoverCurveVAO == null) {
this.implicitCoverCurveVAO = renderContext.vertexArrayObjectExt
.createVertexArrayOES();
}
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.implicitCoverCurveVAO);
this.initImplicitCoverCurveVAO(objectIndex, instanceRange);
// Draw direct curve parts.
this.setTransformUniform(directCurveProgram.uniforms, objectIndex);
this.setFramebufferSizeUniform(directCurveProgram.uniforms);
this.setHintsUniform(directCurveProgram.uniforms);
this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0);
this.pathTransformBufferTextures[meshIndex].bind(gl, directCurveProgram.uniforms, 1);
if (renderingMode === 'color-depth') {
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
strategy.bindEdgeDepthTexture(gl, directCurveProgram.uniforms, 2);
}
const coverCurveRange = getMeshIndexRange(meshes.coverCurveIndexRanges, pathRange);
if (!this.pathIDsAreInstanced) {
gl.drawElements(gl.TRIANGLES,
coverCurveRange.length,
gl.UNSIGNED_INT,
coverCurveRange.start * UINT32_SIZE);
} else {
renderContext.instancedArraysExt.drawElementsInstancedANGLE(gl.TRIANGLES,
coverCurveRange.length,
gl.UNSIGNED_INT,
0,
instanceRange.length);
}
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
// Finish direct rendering. Right now, this performs compositing if necessary.
antialiasingStrategy.finishDirectlyRenderingObject(this, objectIndex);
} }
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.implicitCoverInteriorVAO);
this.initImplicitCoverInteriorVAO(objectIndex, instanceRange);
// Draw direct interior parts.
this.setTransformUniform(directInteriorProgram.uniforms, objectIndex);
this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
this.setHintsUniform(directInteriorProgram.uniforms);
this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0);
this.pathTransformBufferTextures[meshIndex]
.bind(gl, directInteriorProgram.uniforms, 1);
if (renderingMode === 'color-depth') {
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
strategy.bindEdgeDepthTexture(gl, directInteriorProgram.uniforms, 2);
}
const coverInteriorRange = getMeshIndexRange(meshes.coverInteriorIndexRanges,
pathRange);
if (!this.pathIDsAreInstanced) {
gl.drawElements(gl.TRIANGLES,
coverInteriorRange.length,
gl.UNSIGNED_INT,
coverInteriorRange.start * UINT32_SIZE);
} else {
renderContext.instancedArraysExt
.drawElementsInstancedANGLE(gl.TRIANGLES,
coverInteriorRange.length,
gl.UNSIGNED_INT,
0,
instanceRange.length);
}
// Set up direct curve state.
if (renderingMode === 'color-depth') {
gl.depthMask(true);
gl.disable(gl.BLEND);
} else {
gl.depthMask(false);
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
}
// Set up the direct curve VAO.
//
// TODO(pcwalton): Cache these.
const directCurveProgramName = this.directCurveProgramName();
const directCurveProgram = renderContext.shaderPrograms[directCurveProgramName];
if (this.implicitCoverCurveVAO == null) {
this.implicitCoverCurveVAO = renderContext.vertexArrayObjectExt
.createVertexArrayOES();
}
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.implicitCoverCurveVAO);
this.initImplicitCoverCurveVAO(objectIndex, instanceRange);
// Draw direct curve parts.
this.setTransformUniform(directCurveProgram.uniforms, objectIndex);
this.setFramebufferSizeUniform(directCurveProgram.uniforms);
this.setHintsUniform(directCurveProgram.uniforms);
this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0);
this.pathTransformBufferTextures[meshIndex].bind(gl, directCurveProgram.uniforms, 1);
if (renderingMode === 'color-depth') {
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
strategy.bindEdgeDepthTexture(gl, directCurveProgram.uniforms, 2);
}
const coverCurveRange = getMeshIndexRange(meshes.coverCurveIndexRanges, pathRange);
if (!this.pathIDsAreInstanced) {
gl.drawElements(gl.TRIANGLES,
coverCurveRange.length,
gl.UNSIGNED_INT,
coverCurveRange.start * UINT32_SIZE);
} else {
renderContext.instancedArraysExt.drawElementsInstancedANGLE(gl.TRIANGLES,
coverCurveRange.length,
gl.UNSIGNED_INT,
0,
instanceRange.length);
}
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
// Finish direct rendering. Right now, this performs compositing if necessary.
antialiasingStrategy.finishDirectlyRenderingObject(this, objectIndex);
} }
private finishTiming() { private finishTiming() {

View File

@ -1,4 +1,4 @@
// pathfinder/client/src/shader-loader.ts // pathfinder/demo/client/src/shader-loader.ts
// //
// Copyright © 2017 The Pathfinder Project Developers. // Copyright © 2017 The Pathfinder Project Developers.
// //

View File

@ -1,4 +1,4 @@
// pathfinder/client/src/ssaa-strategy.ts // pathfinder/demo/client/src/ssaa-strategy.ts
// //
// Copyright © 2017 The Pathfinder Project Developers. // Copyright © 2017 The Pathfinder Project Developers.
// //
@ -43,9 +43,9 @@ export default class SSAAStrategy extends AntialiasingStrategy {
this.renderTargetFramebuffers = []; this.renderTargetFramebuffers = [];
} }
attachMeshes(renderer: Renderer) {} attachMeshes(renderer: Renderer): void {}
setFramebufferSize(renderer: Renderer) { setFramebufferSize(renderer: Renderer): void {
const renderContext = renderer.renderContext; const renderContext = renderer.renderContext;
const gl = renderContext.gl; const gl = renderContext.gl;
@ -105,7 +105,9 @@ export default class SSAAStrategy extends AntialiasingStrategy {
gl.clear(gl.COLOR_BUFFER_BIT); gl.clear(gl.COLOR_BUFFER_BIT);
} }
prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void { prepareForDirectRendering(renderer: Renderer): void {}
prepareToRenderObject(renderer: Renderer, objectIndex: number): void {
const renderContext = renderer.renderContext; const renderContext = renderer.renderContext;
const gl = renderContext.gl; const gl = renderContext.gl;
@ -160,9 +162,11 @@ export default class SSAAStrategy extends AntialiasingStrategy {
compositingOperation.composite(renderer, objectIndex, this.renderTargetColorTextures); compositingOperation.composite(renderer, objectIndex, this.renderTargetColorTextures);
} }
antialias(renderer: Renderer) {} antialiasObject(renderer: Renderer): void {}
resolve(renderer: Renderer) { resolveAAForObject(renderer: Renderer): void {}
resolve(renderer: Renderer): void {
const renderContext = renderer.renderContext; const renderContext = renderer.renderContext;
const gl = renderContext.gl; const gl = renderContext.gl;

View File

@ -181,6 +181,15 @@ class SVGDemoRenderer extends Renderer {
return loader.renderTasks[objectIndex].compositingOperation; return loader.renderTasks[objectIndex].compositingOperation;
} }
meshIndexForObject(objectIndex: number): number {
return 0;
}
pathRangeForObject(objectIndex: number): Range {
const loader = this.renderContext.appController.loader;
return loader.renderTasks[objectIndex].instanceIndices;
}
protected get usedSizeFactor(): glmatrix.vec2 { protected get usedSizeFactor(): glmatrix.vec2 {
return glmatrix.vec2.clone([1.0, 1.0]); return glmatrix.vec2.clone([1.0, 1.0]);
} }
@ -211,15 +220,6 @@ class SVGDemoRenderer extends Renderer {
return 'directInterior'; return 'directInterior';
} }
protected meshIndexForObject(objectIndex: number): number {
return 0;
}
protected pathRangeForObject(objectIndex: number): Range {
const loader = this.renderContext.appController.loader;
return loader.renderTasks[objectIndex].instanceIndices;
}
protected newTimingsReceived(): void { protected newTimingsReceived(): void {
this.renderContext.appController.newTimingsReceived(this.lastTimings); this.renderContext.appController.newTimingsReceived(this.lastTimings);
} }

File diff suppressed because it is too large Load Diff