Implement 8xSSAA and 16xSSAA in the SVG demo
This commit is contained in:
parent
1102965f6d
commit
b8785a31db
|
@ -47,6 +47,8 @@
|
|||
<option value="none" selected>None</option>
|
||||
<option value="ssaa-2">2×SSAA</option>
|
||||
<option value="ssaa-4">4×SSAA</option>
|
||||
<option value="ssaa-8">8×SSAA</option>
|
||||
<option value="ssaa-16">16×SSAA</option>
|
||||
<option value="xcaa">XCAA</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
<option value="none">None</option>
|
||||
<option value="ssaa-2">2×SSAA</option>
|
||||
<option value="ssaa-4" selected>4×SSAA</option>
|
||||
<option value="ssaa-8">8×SSAA</option>
|
||||
<option value="ssaa-16">16×SSAA</option>
|
||||
<option value="xcaa">XCAA (experimental)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -26,10 +26,18 @@ export type GammaCorrectionMode = 'off' | 'on';
|
|||
|
||||
export type StemDarkeningMode = 'none' | 'dark';
|
||||
|
||||
export interface TileInfo {
|
||||
size: glmatrix.vec2;
|
||||
position: glmatrix.vec2;
|
||||
}
|
||||
|
||||
export abstract class AntialiasingStrategy {
|
||||
// The type of direct rendering that should occur, if any.
|
||||
abstract readonly directRenderingMode: DirectRenderingMode;
|
||||
|
||||
// How many rendering passes this AA strategy requires.
|
||||
abstract readonly passCount: number;
|
||||
|
||||
// Prepares any OpenGL data. This is only called on startup and canvas resize.
|
||||
init(renderer: Renderer): void {
|
||||
this.setFramebufferSize(renderer);
|
||||
|
@ -70,12 +78,20 @@ export abstract class AntialiasingStrategy {
|
|||
// Called after antialiasing.
|
||||
//
|
||||
// This usually blits to the real framebuffer.
|
||||
abstract resolve(renderer: Renderer): void;
|
||||
abstract resolve(pass: number, renderer: Renderer): void;
|
||||
|
||||
worldTransformForPass(renderer: Renderer, pass: number): glmatrix.mat4 {
|
||||
return glmatrix.mat4.create();
|
||||
}
|
||||
}
|
||||
|
||||
export class NoAAStrategy extends AntialiasingStrategy {
|
||||
framebufferSize: glmatrix.vec2;
|
||||
|
||||
get passCount(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private renderTargetColorTextures: WebGLTexture[];
|
||||
private renderTargetDepthTextures: WebGLTexture[];
|
||||
private renderTargetFramebuffers: WebGLFramebuffer[];
|
||||
|
@ -161,7 +177,7 @@ export class NoAAStrategy extends AntialiasingStrategy {
|
|||
|
||||
resolveAAForObject(renderer: Renderer): void {}
|
||||
|
||||
resolve(renderer: Renderer): void {}
|
||||
resolve(pass: number, renderer: Renderer): void {}
|
||||
|
||||
get directRenderingMode(): DirectRenderingMode {
|
||||
return 'color';
|
||||
|
|
|
@ -12,6 +12,7 @@ import * as glmatrix from 'gl-matrix';
|
|||
import * as _ from 'lodash';
|
||||
|
||||
import {AntialiasingStrategy, AntialiasingStrategyName, GammaCorrectionMode} from './aa-strategy';
|
||||
import {TileInfo} from './aa-strategy';
|
||||
import {NoAAStrategy, StemDarkeningMode, SubpixelAAType} from './aa-strategy';
|
||||
import {AAOptions} from './app-controller';
|
||||
import PathfinderBufferTexture from "./buffer-texture";
|
||||
|
@ -150,37 +151,41 @@ export abstract class Renderer {
|
|||
// Draw "scenery" (used in the 3D view).
|
||||
this.drawSceneryIfNecessary();
|
||||
|
||||
if (antialiasingStrategy.directRenderingMode !== 'none')
|
||||
antialiasingStrategy.prepareForDirectRendering(this);
|
||||
const passCount = antialiasingStrategy.passCount;
|
||||
for (let pass = 0; pass < passCount; pass++) {
|
||||
if (antialiasingStrategy.directRenderingMode !== 'none')
|
||||
antialiasingStrategy.prepareForDirectRendering(this);
|
||||
|
||||
const objectCount = this.objectCount;
|
||||
for (let objectIndex = 0; objectIndex < objectCount; objectIndex++) {
|
||||
// Antialias.
|
||||
antialiasingStrategy.antialiasObject(this, objectIndex);
|
||||
const objectCount = this.objectCount;
|
||||
for (let objectIndex = 0; objectIndex < objectCount; objectIndex++) {
|
||||
// Antialias.
|
||||
antialiasingStrategy.antialiasObject(this, objectIndex);
|
||||
|
||||
// Prepare for direct rendering.
|
||||
antialiasingStrategy.prepareToRenderObject(this, objectIndex);
|
||||
// Prepare for direct rendering.
|
||||
antialiasingStrategy.prepareToRenderObject(this, objectIndex);
|
||||
|
||||
// Perform direct rendering (Loop-Blinn).
|
||||
if (antialiasingStrategy.directRenderingMode !== 'none') {
|
||||
// Clear.
|
||||
this.clearForDirectRendering(objectIndex);
|
||||
// Perform direct rendering (Loop-Blinn).
|
||||
if (antialiasingStrategy.directRenderingMode !== 'none') {
|
||||
// Clear.
|
||||
this.clearForDirectRendering(objectIndex);
|
||||
|
||||
this.directlyRenderObject(objectIndex);
|
||||
this.directlyRenderObject(pass, objectIndex);
|
||||
}
|
||||
|
||||
antialiasingStrategy.resolveAAForObject(this, objectIndex);
|
||||
}
|
||||
|
||||
antialiasingStrategy.resolveAAForObject(this, objectIndex);
|
||||
antialiasingStrategy.resolve(pass, this);
|
||||
}
|
||||
|
||||
// End the timer, and start a new one.
|
||||
// FIXME(pcwalton): Removed this for multipass; get it split out again somehow.
|
||||
if (this.timerQueryPollInterval == null) {
|
||||
renderContext.timerQueryExt.endQueryEXT(renderContext.timerQueryExt.TIME_ELAPSED_EXT);
|
||||
renderContext.timerQueryExt.beginQueryEXT(renderContext.timerQueryExt.TIME_ELAPSED_EXT,
|
||||
renderContext.compositingTimerQuery);
|
||||
}
|
||||
|
||||
antialiasingStrategy.resolve(this);
|
||||
|
||||
// Draw the glyphs with the resolved atlas to the default framebuffer.
|
||||
this.compositeIfNecessary();
|
||||
|
||||
|
@ -219,13 +224,27 @@ export abstract class Renderer {
|
|||
this.destAllocatedSize[1]);
|
||||
}
|
||||
|
||||
setTransformAndTexScaleUniformsForDest(uniforms: UniformMap): void {
|
||||
setTransformAndTexScaleUniformsForDest(uniforms: UniformMap, tileInfo?: TileInfo): void {
|
||||
const renderContext = this.renderContext;
|
||||
const usedSize = this.usedSizeFactor;
|
||||
|
||||
let tileSize, tilePosition;
|
||||
if (tileInfo == null) {
|
||||
tileSize = glmatrix.vec2.clone([1.0, 1.0]);
|
||||
tilePosition = glmatrix.vec2.create();
|
||||
} else {
|
||||
tileSize = tileInfo.size;
|
||||
tilePosition = tileInfo.position;
|
||||
}
|
||||
|
||||
const transform = glmatrix.mat4.create();
|
||||
glmatrix.mat4.fromTranslation(transform, [-1.0, -1.0, 0.0]);
|
||||
glmatrix.mat4.fromTranslation(transform, [
|
||||
-1.0 + tilePosition[0] / tileSize[0] * 2.0,
|
||||
-1.0 + tilePosition[1] / tileSize[1] * 2.0,
|
||||
0.0,
|
||||
]);
|
||||
glmatrix.mat4.scale(transform, transform, [2.0 * usedSize[0], 2.0 * usedSize[1], 1.0]);
|
||||
glmatrix.mat4.scale(transform, transform, [1.0 / tileSize[0], 1.0 / tileSize[1], 1.0]);
|
||||
renderContext.gl.uniformMatrix4fv(uniforms.uTransform, false, transform);
|
||||
|
||||
renderContext.gl.uniform2f(uniforms.uTexScale, usedSize[0], usedSize[1]);
|
||||
|
@ -240,8 +259,14 @@ export abstract class Renderer {
|
|||
gl.uniform2f(uniforms.uTexScale, usedSize[0], usedSize[1]);
|
||||
}
|
||||
|
||||
setTransformUniform(uniforms: UniformMap, objectIndex: number): void {
|
||||
const transform = glmatrix.mat4.clone(this.worldTransform);
|
||||
setTransformUniform(uniforms: UniformMap, pass: number, objectIndex: number): void {
|
||||
let transform;
|
||||
if (this.antialiasingStrategy == null)
|
||||
transform = glmatrix.mat4.create();
|
||||
else
|
||||
transform = this.antialiasingStrategy.worldTransformForPass(this, pass);
|
||||
|
||||
glmatrix.mat4.mul(transform, transform, this.worldTransform);
|
||||
glmatrix.mat4.mul(transform, transform, this.getModelviewTransform(objectIndex));
|
||||
this.renderContext.gl.uniformMatrix4fv(uniforms.uTransform, false, transform);
|
||||
}
|
||||
|
@ -424,7 +449,7 @@ export abstract class Renderer {
|
|||
};
|
||||
}
|
||||
|
||||
private directlyRenderObject(objectIndex: number): void {
|
||||
private directlyRenderObject(pass: number, objectIndex: number): void {
|
||||
if (this.meshes == null || this.meshData == null)
|
||||
return;
|
||||
|
||||
|
@ -462,7 +487,7 @@ export abstract class Renderer {
|
|||
this.initImplicitCoverInteriorVAO(objectIndex, instanceRange);
|
||||
|
||||
// Draw direct interior parts.
|
||||
this.setTransformUniform(directInteriorProgram.uniforms, objectIndex);
|
||||
this.setTransformUniform(directInteriorProgram.uniforms, pass, objectIndex);
|
||||
this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
|
||||
this.setHintsUniform(directInteriorProgram.uniforms);
|
||||
this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0);
|
||||
|
@ -507,7 +532,7 @@ export abstract class Renderer {
|
|||
this.initImplicitCoverCurveVAO(objectIndex, instanceRange);
|
||||
|
||||
// Draw direct curve parts.
|
||||
this.setTransformUniform(directCurveProgram.uniforms, objectIndex);
|
||||
this.setTransformUniform(directCurveProgram.uniforms, pass, objectIndex);
|
||||
this.setFramebufferSizeUniform(directCurveProgram.uniforms);
|
||||
this.setHintsUniform(directCurveProgram.uniforms);
|
||||
this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
import * as glmatrix from 'gl-matrix';
|
||||
|
||||
import {AntialiasingStrategy, DirectRenderingMode, SubpixelAAType} from './aa-strategy';
|
||||
import {AntialiasingStrategy, DirectRenderingMode, SubpixelAAType, TileInfo} from './aa-strategy';
|
||||
import {createFramebuffer, createFramebufferColorTexture} from './gl-utils';
|
||||
import {createFramebufferDepthTexture, setTextureParameters} from './gl-utils';
|
||||
import {Renderer} from './renderer';
|
||||
|
@ -18,6 +18,16 @@ import {unwrapNull} from './utils';
|
|||
import {DemoView} from './view';
|
||||
|
||||
export default class SSAAStrategy extends AntialiasingStrategy {
|
||||
get passCount(): number {
|
||||
switch (this.level) {
|
||||
case 16:
|
||||
return 4;
|
||||
case 8:
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
private level: number;
|
||||
private subpixelAA: SubpixelAAType;
|
||||
|
||||
|
@ -159,7 +169,7 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
|||
|
||||
resolveAAForObject(renderer: Renderer): void {}
|
||||
|
||||
resolve(renderer: Renderer): void {
|
||||
resolve(pass: number, renderer: Renderer): void {
|
||||
const renderContext = renderer.renderContext;
|
||||
const gl = renderContext.gl;
|
||||
|
||||
|
@ -184,11 +194,35 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
|||
gl.uniform2i(resolveProgram.uniforms.uSourceDimensions,
|
||||
this.supersampledFramebufferSize[0],
|
||||
this.supersampledFramebufferSize[1]);
|
||||
renderer.setTransformAndTexScaleUniformsForDest(resolveProgram.uniforms);
|
||||
const tileInfo = this.tileInfoForPass(pass);
|
||||
renderer.setTransformAndTexScaleUniformsForDest(resolveProgram.uniforms, tileInfo);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
|
||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
worldTransformForPass(renderer: Renderer, pass: number): glmatrix.mat4 {
|
||||
const tileInfo = this.tileInfoForPass(pass);
|
||||
const usedSize = renderer.destUsedSize;
|
||||
const transform = glmatrix.mat4.create();
|
||||
glmatrix.mat4.fromTranslation(transform, [-1.0, -1.0, 1.0]);
|
||||
glmatrix.mat4.scale(transform, transform, [tileInfo.size[0], tileInfo.size[1], 1.0]);
|
||||
glmatrix.mat4.translate(transform, transform, [
|
||||
-tileInfo.position[0] / tileInfo.size[0] * 2.0,
|
||||
-tileInfo.position[1] / tileInfo.size[1] * 2.0,
|
||||
0.0,
|
||||
]);
|
||||
glmatrix.mat4.translate(transform, transform, [1.0, 1.0, 1.0]);
|
||||
return transform;
|
||||
}
|
||||
|
||||
private tileInfoForPass(pass: number): TileInfo {
|
||||
const tileSize = this.tileSize;
|
||||
return {
|
||||
position: glmatrix.vec2.clone([pass % tileSize[0], Math.floor(pass / tileSize[0])]),
|
||||
size: tileSize,
|
||||
};
|
||||
}
|
||||
|
||||
get directRenderingMode(): DirectRenderingMode {
|
||||
return 'color';
|
||||
}
|
||||
|
@ -197,6 +231,16 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
|||
return glmatrix.vec2.clone([this.subpixelAA !== 'none' ? 3 : 2, this.level === 2 ? 1 : 2]);
|
||||
}
|
||||
|
||||
private get tileSize(): glmatrix.vec2 {
|
||||
switch (this.level) {
|
||||
case 16:
|
||||
return glmatrix.vec2.clone([2.0, 2.0]);
|
||||
case 8:
|
||||
return glmatrix.vec2.clone([2.0, 1.0]);
|
||||
}
|
||||
return glmatrix.vec2.clone([1.0, 1.0]);
|
||||
}
|
||||
|
||||
private usedSupersampledFramebufferSize(renderer: Renderer): glmatrix.vec2 {
|
||||
const result = glmatrix.vec2.create();
|
||||
glmatrix.vec2.mul(result, renderer.destUsedSize, this.supersampleScale);
|
||||
|
|
|
@ -36,6 +36,10 @@ const DIRECTIONS: Direction[] = ['upper', 'lower'];
|
|||
export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||
abstract readonly directRenderingMode: DirectRenderingMode;
|
||||
|
||||
get passCount(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
protected abstract get usesDilationTransforms(): boolean;
|
||||
|
||||
protected pathBoundsBufferTexture: PathfinderBufferTexture;
|
||||
|
@ -180,7 +184,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
|||
compositingOperation.composite(renderer, objectIndex, this.renderTargetColorTextures);
|
||||
}
|
||||
|
||||
resolve(renderer: Renderer): void {}
|
||||
resolve(pass: number, renderer: Renderer): void {}
|
||||
|
||||
get transform(): glmatrix.mat4 {
|
||||
return glmatrix.mat4.create();
|
||||
|
@ -230,7 +234,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
|||
if (this.usesDilationTransforms)
|
||||
renderer.setTransformSTUniform(uniforms, 0);
|
||||
else
|
||||
renderer.setTransformUniform(uniforms, 0);
|
||||
renderer.setTransformUniform(uniforms, 0, 0);
|
||||
|
||||
gl.uniform2i(uniforms.uFramebufferSize,
|
||||
this.supersampledFramebufferSize[0],
|
||||
|
@ -1134,6 +1138,10 @@ export class AdaptiveMonochromeXCAAStrategy implements AntialiasingStrategy {
|
|||
return 'none';
|
||||
}
|
||||
|
||||
get passCount(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
constructor(level: number, subpixelAA: SubpixelAAType) {
|
||||
this.mcaaStrategy = new MCAAMonochromeStrategy(level, subpixelAA);
|
||||
this.ecaaStrategy = new ECAAMonochromeStrategy(level, subpixelAA);
|
||||
|
@ -1182,8 +1190,12 @@ export class AdaptiveMonochromeXCAAStrategy implements AntialiasingStrategy {
|
|||
this.getAppropriateStrategy(renderer).resolveAAForObject(renderer, objectIndex);
|
||||
}
|
||||
|
||||
resolve(renderer: Renderer): void {
|
||||
this.getAppropriateStrategy(renderer).resolve(renderer);
|
||||
resolve(pass: number, renderer: Renderer): void {
|
||||
this.getAppropriateStrategy(renderer).resolve(pass, renderer);
|
||||
}
|
||||
|
||||
worldTransformForPass(renderer: Renderer, pass: number): glmatrix.mat4 {
|
||||
return glmatrix.mat4.create();
|
||||
}
|
||||
|
||||
private getAppropriateStrategy(renderer: Renderer): AntialiasingStrategy {
|
||||
|
|
Loading…
Reference in New Issue