Add partial support for clip paths in the SVG demo.
At the moment, this only works when antialiasing is off.
This commit is contained in:
parent
511e5956d8
commit
4cbc2a8800
|
@ -359,8 +359,8 @@ class ThreeDRenderer extends Renderer {
|
||||||
return this.destAllocatedSize;
|
return this.destAllocatedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get depthFunction(): GLenum {
|
get backgroundColor(): glmatrix.vec4 {
|
||||||
return this.renderContext.gl.LESS;
|
return glmatrix.vec4.clone([1.0, 1.0, 1.0, 1.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get pathIDsAreInstanced(): boolean {
|
protected get pathIDsAreInstanced(): boolean {
|
||||||
|
@ -375,6 +375,10 @@ class ThreeDRenderer extends Renderer {
|
||||||
return glmatrix.vec2.clone([1.0, 1.0]);
|
return glmatrix.vec2.clone([1.0, 1.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected get objectCount(): number {
|
||||||
|
return this.meshes.length;
|
||||||
|
}
|
||||||
|
|
||||||
private cubeVertexPositionBuffer: WebGLBuffer;
|
private cubeVertexPositionBuffer: WebGLBuffer;
|
||||||
private cubeIndexBuffer: WebGLBuffer;
|
private cubeIndexBuffer: WebGLBuffer;
|
||||||
|
|
||||||
|
@ -431,9 +435,17 @@ class ThreeDRenderer extends Renderer {
|
||||||
this.renderContext.gl.uniform4f(uniforms.uHints, 0, 0, 0, 0);
|
this.renderContext.gl.uniform4f(uniforms.uHints, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected clearColorForObject(objectIndex: number): glmatrix.vec4 | null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected drawSceneryIfNecessary(): void {
|
protected drawSceneryIfNecessary(): void {
|
||||||
const gl = this.renderContext.gl;
|
const gl = this.renderContext.gl;
|
||||||
|
|
||||||
|
// Set up the depth buffer for drawing the monument.
|
||||||
|
gl.clearDepth(1.0);
|
||||||
|
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
this.drawMonument();
|
this.drawMonument();
|
||||||
|
|
||||||
// Clear to avoid Z-fighting.
|
// Clear to avoid Z-fighting.
|
||||||
|
@ -441,6 +453,10 @@ class ThreeDRenderer extends Renderer {
|
||||||
gl.clear(gl.DEPTH_BUFFER_BIT);
|
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
this.drawDistantGlyphs();
|
this.drawDistantGlyphs();
|
||||||
|
|
||||||
|
// Set up the depth buffer for direct rendering.
|
||||||
|
gl.clearDepth(0.0);
|
||||||
|
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected compositeIfNecessary(): void {}
|
protected compositeIfNecessary(): void {}
|
||||||
|
@ -473,8 +489,12 @@ class ThreeDRenderer extends Renderer {
|
||||||
throw new PathfinderError("Unsupported antialiasing type!");
|
throw new PathfinderError("Unsupported antialiasing type!");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForDirectRendering(): void {
|
protected clearDestFramebuffer(): void {
|
||||||
const gl = this.renderContext.gl;
|
const gl = this.renderContext.gl;
|
||||||
|
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.destFramebuffer);
|
||||||
|
gl.viewport(0, 0, this.destAllocatedSize[0], this.destAllocatedSize[1]);
|
||||||
|
|
||||||
gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
||||||
gl.clearDepth(1.0);
|
gl.clearDepth(1.0);
|
||||||
gl.depthMask(true);
|
gl.depthMask(true);
|
||||||
|
@ -605,7 +625,7 @@ class ThreeDRenderer extends Renderer {
|
||||||
|
|
||||||
// Set state for the monument.
|
// Set state for the monument.
|
||||||
gl.enable(gl.DEPTH_TEST);
|
gl.enable(gl.DEPTH_TEST);
|
||||||
gl.depthFunc(this.depthFunction);
|
gl.depthFunc(gl.LESS);
|
||||||
gl.depthMask(true);
|
gl.depthMask(true);
|
||||||
gl.disable(gl.SCISSOR_TEST);
|
gl.disable(gl.SCISSOR_TEST);
|
||||||
gl.disable(gl.BLEND);
|
gl.disable(gl.BLEND);
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
|
|
||||||
import * as glmatrix from 'gl-matrix';
|
import * as glmatrix from 'gl-matrix';
|
||||||
|
|
||||||
|
import {createFramebuffer, createFramebufferColorTexture} from './gl-utils';
|
||||||
|
import {createFramebufferDepthTexture} from './gl-utils';
|
||||||
import {Renderer} from './renderer';
|
import {Renderer} from './renderer';
|
||||||
|
import {unwrapNull} from './utils';
|
||||||
import {DemoView} from './view';
|
import {DemoView} from './view';
|
||||||
|
|
||||||
export type AntialiasingStrategyName = 'none' | 'ssaa' | 'xcaa';
|
export type AntialiasingStrategyName = 'none' | 'ssaa' | 'xcaa';
|
||||||
|
@ -42,7 +45,12 @@ export abstract class AntialiasingStrategy {
|
||||||
// Called before direct rendering.
|
// Called before direct rendering.
|
||||||
//
|
//
|
||||||
// Typically, this redirects direct rendering to a framebuffer of some sort.
|
// Typically, this redirects direct rendering to a framebuffer of some sort.
|
||||||
abstract prepareForDirectRendering(renderer: Renderer): void;
|
abstract prepareForRendering(renderer: Renderer): void;
|
||||||
|
|
||||||
|
// Called before directly rendering a single object.
|
||||||
|
abstract prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void;
|
||||||
|
|
||||||
|
abstract finishDirectlyRenderingObject(renderer: Renderer, objectIndex: number): void;
|
||||||
|
|
||||||
// Called after direct rendering.
|
// Called after direct rendering.
|
||||||
//
|
//
|
||||||
|
@ -58,9 +66,16 @@ export abstract class AntialiasingStrategy {
|
||||||
export class NoAAStrategy extends AntialiasingStrategy {
|
export class NoAAStrategy extends AntialiasingStrategy {
|
||||||
framebufferSize: glmatrix.vec2;
|
framebufferSize: glmatrix.vec2;
|
||||||
|
|
||||||
|
private renderTargetColorTextures: WebGLTexture[];
|
||||||
|
private renderTargetDepthTextures: WebGLTexture[];
|
||||||
|
private renderTargetFramebuffers: WebGLFramebuffer[];
|
||||||
|
|
||||||
constructor(level: number, subpixelAA: SubpixelAAType) {
|
constructor(level: number, subpixelAA: SubpixelAAType) {
|
||||||
super();
|
super();
|
||||||
this.framebufferSize = glmatrix.vec2.create();
|
this.framebufferSize = glmatrix.vec2.create();
|
||||||
|
this.renderTargetColorTextures = [];
|
||||||
|
this.renderTargetDepthTextures = [];
|
||||||
|
this.renderTargetFramebuffers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(renderer: Renderer) {}
|
attachMeshes(renderer: Renderer) {}
|
||||||
|
@ -73,11 +88,61 @@ export class NoAAStrategy extends AntialiasingStrategy {
|
||||||
return glmatrix.mat4.create();
|
return glmatrix.mat4.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareForDirectRendering(renderer: Renderer) {
|
prepareForRendering(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, renderer.destFramebuffer);
|
const gl = renderContext.gl;
|
||||||
renderContext.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
|
gl.bindFramebuffer(gl.FRAMEBUFFER, renderer.destFramebuffer);
|
||||||
renderContext.gl.disable(renderContext.gl.SCISSOR_TEST);
|
gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
|
||||||
|
gl.disable(gl.SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
const renderContext = renderer.renderContext;
|
||||||
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
if (renderer.usesIntermediateRenderTargets &&
|
||||||
|
(renderer.renderTaskTypeForObject(objectIndex) === 'clip' ||
|
||||||
|
renderer.compositingOperationForObject(objectIndex) != null)) {
|
||||||
|
if (this.renderTargetColorTextures[objectIndex] == null) {
|
||||||
|
this.renderTargetColorTextures[objectIndex] =
|
||||||
|
createFramebufferColorTexture(gl,
|
||||||
|
this.framebufferSize,
|
||||||
|
renderContext.colorAlphaFormat);
|
||||||
|
}
|
||||||
|
if (this.renderTargetDepthTextures[objectIndex] == null) {
|
||||||
|
this.renderTargetDepthTextures[objectIndex] =
|
||||||
|
createFramebufferDepthTexture(gl, this.framebufferSize);
|
||||||
|
}
|
||||||
|
if (this.renderTargetFramebuffers[objectIndex] == null) {
|
||||||
|
this.renderTargetFramebuffers[objectIndex] =
|
||||||
|
createFramebuffer(gl,
|
||||||
|
this.renderTargetColorTextures[objectIndex],
|
||||||
|
this.renderTargetDepthTextures[objectIndex]);
|
||||||
|
}
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.renderTargetFramebuffers[objectIndex]);
|
||||||
|
} else {
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, renderer.destFramebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
|
||||||
|
gl.disable(gl.SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
finishDirectlyRenderingObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
if (!renderer.usesIntermediateRenderTargets)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const compositingOperation = renderer.compositingOperationForObject(objectIndex);
|
||||||
|
if (compositingOperation == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const gl = renderer.renderContext.gl;
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, renderer.destFramebuffer);
|
||||||
|
gl.viewport(0, 0, renderer.destAllocatedSize[0], renderer.destAllocatedSize[1]);
|
||||||
|
gl.disable(gl.DEPTH_TEST);
|
||||||
|
gl.disable(gl.BLEND);
|
||||||
|
|
||||||
|
compositingOperation.composite(renderer, objectIndex, this.renderTargetColorTextures);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(renderer: Renderer) {}
|
antialias(renderer: Renderer) {}
|
||||||
|
|
|
@ -309,10 +309,6 @@ class BenchmarkRenderer extends Renderer {
|
||||||
return glmatrix.vec2.clone([1.0, 1.0]);
|
return glmatrix.vec2.clone([1.0, 1.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get depthFunction(): number {
|
|
||||||
return this.renderContext.gl.GREATER;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get worldTransform() {
|
protected get worldTransform() {
|
||||||
const canvas = this.renderContext.canvas;
|
const canvas = this.renderContext.canvas;
|
||||||
|
|
||||||
|
@ -329,6 +325,10 @@ class BenchmarkRenderer extends Renderer {
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected get objectCount(): number {
|
||||||
|
return this.meshes.length;
|
||||||
|
}
|
||||||
|
|
||||||
private _pixelsPerEm: number = 32.0;
|
private _pixelsPerEm: number = 32.0;
|
||||||
|
|
||||||
private get pixelsPerUnit(): number {
|
private get pixelsPerUnit(): number {
|
||||||
|
|
|
@ -203,6 +203,20 @@ const RANGE_TO_RANGE_BUFFER_TABLE: RangeToRangeBufferTable = {
|
||||||
segmentLineRanges: 'segmentLinePathIDs',
|
segmentLineRanges: 'segmentLinePathIDs',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const RANGE_KEYS: Array<keyof PathRanges> = [
|
||||||
|
'bQuadPathRanges',
|
||||||
|
'bVertexPathRanges',
|
||||||
|
'coverInteriorIndexRanges',
|
||||||
|
'coverCurveIndexRanges',
|
||||||
|
'edgeBoundingBoxRanges',
|
||||||
|
'edgeUpperLineIndexRanges',
|
||||||
|
'edgeUpperCurveIndexRanges',
|
||||||
|
'edgeLowerLineIndexRanges',
|
||||||
|
'edgeLowerCurveIndexRanges',
|
||||||
|
'segmentCurveRanges',
|
||||||
|
'segmentLineRanges',
|
||||||
|
];
|
||||||
|
|
||||||
type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
|
type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
|
||||||
|
|
||||||
export interface Meshes<T> {
|
export interface Meshes<T> {
|
||||||
|
@ -375,7 +389,7 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer>, MeshDataCounts,
|
||||||
tempOriginalRanges[key] = this[key];
|
tempOriginalRanges[key] = this[key];
|
||||||
|
|
||||||
const newExpandedRanges = [];
|
const newExpandedRanges = [];
|
||||||
for (const newPathID of pathIDs)
|
for (const pathIndex of pathIDs)
|
||||||
newExpandedRanges.push(new Range(0, 0));
|
newExpandedRanges.push(new Range(0, 0));
|
||||||
tempExpandedRanges[key] = newExpandedRanges;
|
tempExpandedRanges[key] = newExpandedRanges;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +558,7 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer>, MeshDataCounts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
|
export class PathfinderMeshBuffers implements Meshes<WebGLBuffer>, PathRanges {
|
||||||
readonly bQuads: WebGLBuffer;
|
readonly bQuads: WebGLBuffer;
|
||||||
readonly bVertexPositions: WebGLBuffer;
|
readonly bVertexPositions: WebGLBuffer;
|
||||||
readonly bVertexPathIDs: WebGLBuffer;
|
readonly bVertexPathIDs: WebGLBuffer;
|
||||||
|
@ -569,6 +583,18 @@ export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
|
||||||
readonly segmentLineNormals: WebGLBuffer;
|
readonly segmentLineNormals: WebGLBuffer;
|
||||||
readonly segmentCurveNormals: WebGLBuffer;
|
readonly segmentCurveNormals: WebGLBuffer;
|
||||||
|
|
||||||
|
readonly bQuadPathRanges: Range[];
|
||||||
|
readonly bVertexPathRanges: Range[];
|
||||||
|
readonly coverInteriorIndexRanges: Range[];
|
||||||
|
readonly coverCurveIndexRanges: Range[];
|
||||||
|
readonly edgeBoundingBoxRanges: Range[];
|
||||||
|
readonly edgeUpperLineIndexRanges: Range[];
|
||||||
|
readonly edgeUpperCurveIndexRanges: Range[];
|
||||||
|
readonly edgeLowerLineIndexRanges: Range[];
|
||||||
|
readonly edgeLowerCurveIndexRanges: Range[];
|
||||||
|
readonly segmentCurveRanges: Range[];
|
||||||
|
readonly segmentLineRanges: Range[];
|
||||||
|
|
||||||
constructor(gl: WebGLRenderingContext, meshData: PathfinderMeshData) {
|
constructor(gl: WebGLRenderingContext, meshData: PathfinderMeshData) {
|
||||||
for (const bufferName of Object.keys(BUFFER_TYPES) as Array<keyof Meshes<void>>) {
|
for (const bufferName of Object.keys(BUFFER_TYPES) as Array<keyof Meshes<void>>) {
|
||||||
const bufferType = gl[BUFFER_TYPES[bufferName]];
|
const bufferType = gl[BUFFER_TYPES[bufferName]];
|
||||||
|
@ -577,6 +603,9 @@ export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
|
||||||
gl.bufferData(bufferType, meshData[bufferName], gl.STATIC_DRAW);
|
gl.bufferData(bufferType, meshData[bufferName], gl.STATIC_DRAW);
|
||||||
this[bufferName] = buffer;
|
this[bufferName] = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const rangeName of RANGE_KEYS)
|
||||||
|
this[rangeName] = meshData[rangeName];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,7 +685,7 @@ function copyIndices(destIndices: number[],
|
||||||
|
|
||||||
const lastDestIndex = destIndices.length;
|
const lastDestIndex = destIndices.length;
|
||||||
|
|
||||||
destRanges[expandedPathID + 1] = new Range(firstExpandedIndex, lastDestIndex - firstDestIndex);
|
destRanges[expandedPathID - 1] = new Range(firstDestIndex, lastDestIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copySegments(segmentBufferNames: Array<keyof Meshes<void>>,
|
function copySegments(segmentBufferNames: Array<keyof Meshes<void>>,
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
// pathfinder/client/src/render-task.ts
|
||||||
|
//
|
||||||
|
// Copyright © 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.
|
||||||
|
|
||||||
|
import {Renderer} from "./renderer";
|
||||||
|
import {Range} from "./utils";
|
||||||
|
|
||||||
|
export type RenderTaskType = 'color' | 'clip';
|
||||||
|
|
||||||
|
export class RenderTask {
|
||||||
|
type: RenderTaskType;
|
||||||
|
instanceIndices: Range;
|
||||||
|
compositingOperation: CompositingOperation | null;
|
||||||
|
|
||||||
|
constructor(type: RenderTaskType,
|
||||||
|
instanceIndices: Range,
|
||||||
|
compositingOperation?: CompositingOperation) {
|
||||||
|
this.type = type;
|
||||||
|
this.instanceIndices = instanceIndices;
|
||||||
|
this.compositingOperation = compositingOperation != null ? compositingOperation : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CompositingOperation = AlphaMaskCompositingOperation;
|
||||||
|
|
||||||
|
export class AlphaMaskCompositingOperation {
|
||||||
|
alphaFramebufferIndex: number;
|
||||||
|
|
||||||
|
constructor(alphaFramebufferIndex: number) {
|
||||||
|
this.alphaFramebufferIndex = alphaFramebufferIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
composite(renderer: Renderer, sourceTextureIndex: number, textures: WebGLTexture[]): void {
|
||||||
|
const renderContext = renderer.renderContext;
|
||||||
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
const program = renderContext.shaderPrograms.compositeAlphaMask;
|
||||||
|
|
||||||
|
gl.useProgram(program.program);
|
||||||
|
renderContext.initQuadVAO(program.attributes);
|
||||||
|
|
||||||
|
// Composite to the current framebuffer.
|
||||||
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, textures[sourceTextureIndex]);
|
||||||
|
gl.uniform1i(program.uniforms.uSource, 0);
|
||||||
|
gl.activeTexture(gl.TEXTURE1);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, textures[this.alphaFramebufferIndex]);
|
||||||
|
gl.uniform1i(program.uniforms.uMask, 1);
|
||||||
|
renderer.setTransformAndTexScaleUniformsForDest(program.uniforms);
|
||||||
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
|
||||||
|
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,14 +9,16 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
import * as glmatrix from 'gl-matrix';
|
import * as glmatrix from 'gl-matrix';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from './aa-strategy';
|
import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from './aa-strategy';
|
||||||
import {StemDarkeningMode, SubpixelAAType} from './aa-strategy';
|
import {StemDarkeningMode, SubpixelAAType} from './aa-strategy';
|
||||||
import PathfinderBufferTexture from "./buffer-texture";
|
import PathfinderBufferTexture from "./buffer-texture";
|
||||||
import {UniformMap} from './gl-utils';
|
import {UniformMap} from './gl-utils';
|
||||||
import {PathfinderMeshBuffers, PathfinderMeshData} from "./meshes";
|
import {PathfinderMeshBuffers, PathfinderMeshData} from "./meshes";
|
||||||
|
import {CompositingOperation, RenderTaskType} from './render-task';
|
||||||
import {ShaderMap} from './shader-loader';
|
import {ShaderMap} from './shader-loader';
|
||||||
import {FLOAT32_SIZE, Range, UINT16_SIZE, UINT32_SIZE, unwrapNull} from './utils';
|
import {FLOAT32_SIZE, Range, UINT16_SIZE, UINT32_SIZE, unwrapNull, unwrapUndef} from './utils';
|
||||||
import {RenderContext, Timings} from "./view";
|
import {RenderContext, Timings} from "./view";
|
||||||
import {MCAAMulticolorStrategy} from './xcaa-strategy';
|
import {MCAAMulticolorStrategy} from './xcaa-strategy';
|
||||||
|
|
||||||
|
@ -48,6 +50,14 @@ export abstract class Renderer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get backgroundColor(): glmatrix.vec4 {
|
||||||
|
return glmatrix.vec4.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
get usesIntermediateRenderTargets(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
abstract get destFramebuffer(): WebGLFramebuffer | null;
|
abstract get destFramebuffer(): WebGLFramebuffer | null;
|
||||||
abstract get destAllocatedSize(): glmatrix.vec2;
|
abstract get destAllocatedSize(): glmatrix.vec2;
|
||||||
abstract get destUsedSize(): glmatrix.vec2;
|
abstract get destUsedSize(): glmatrix.vec2;
|
||||||
|
@ -60,11 +70,7 @@ export abstract class Renderer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get backgroundColor(): glmatrix.vec4 {
|
protected abstract get objectCount(): number;
|
||||||
return glmatrix.vec4.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract get depthFunction(): GLenum;
|
|
||||||
protected abstract get usedSizeFactor(): glmatrix.vec2;
|
protected abstract get usedSizeFactor(): glmatrix.vec2;
|
||||||
protected abstract get worldTransform(): glmatrix.mat4;
|
protected abstract get worldTransform(): glmatrix.mat4;
|
||||||
|
|
||||||
|
@ -111,19 +117,17 @@ export abstract class Renderer {
|
||||||
renderContext.atlasRenderingTimerQuery);
|
renderContext.atlasRenderingTimerQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Antialias.
|
this.clearDestFramebuffer();
|
||||||
|
|
||||||
const antialiasingStrategy = unwrapNull(this.antialiasingStrategy);
|
const antialiasingStrategy = unwrapNull(this.antialiasingStrategy);
|
||||||
antialiasingStrategy.antialias(this);
|
antialiasingStrategy.prepareForRendering(this);
|
||||||
|
|
||||||
// Prepare for direct rendering.
|
|
||||||
antialiasingStrategy.prepareForDirectRendering(this);
|
|
||||||
|
|
||||||
// Clear.
|
|
||||||
this.clearForDirectRendering();
|
|
||||||
|
|
||||||
// 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).
|
// Perform direct rendering (Loop-Blinn).
|
||||||
if (antialiasingStrategy.directRenderingMode !== 'none')
|
if (antialiasingStrategy.directRenderingMode !== 'none')
|
||||||
this.renderDirect();
|
this.renderDirect();
|
||||||
|
@ -249,7 +253,20 @@ export abstract class Renderer {
|
||||||
|
|
||||||
setPathColorsUniform(objectIndex: number, uniforms: UniformMap, textureUnit: number): void {
|
setPathColorsUniform(objectIndex: number, uniforms: UniformMap, textureUnit: number): void {
|
||||||
const gl = this.renderContext.gl;
|
const gl = this.renderContext.gl;
|
||||||
this.pathColorsBufferTextures[objectIndex].bind(gl, uniforms, textureUnit);
|
const meshIndex = this.meshIndexForObject(objectIndex);
|
||||||
|
this.pathColorsBufferTextures[meshIndex].bind(gl, uniforms, textureUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTaskTypeForObject(objectIndex: number): RenderTaskType {
|
||||||
|
return 'color';
|
||||||
|
}
|
||||||
|
|
||||||
|
compositingOperationForObject(objectIndex: number): CompositingOperation | null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected clearColorForObject(objectIndex: number): glmatrix.vec4 | null {
|
||||||
|
return glmatrix.vec4.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract createAAStrategy(aaType: AntialiasingStrategyName,
|
protected abstract createAAStrategy(aaType: AntialiasingStrategyName,
|
||||||
|
@ -266,12 +283,26 @@ export abstract class Renderer {
|
||||||
|
|
||||||
protected drawSceneryIfNecessary(): void {}
|
protected drawSceneryIfNecessary(): void {}
|
||||||
|
|
||||||
protected clearForDirectRendering(): void {
|
protected clearDestFramebuffer(): void {
|
||||||
const renderingMode = unwrapNull(this.antialiasingStrategy).directRenderingMode;
|
|
||||||
const renderContext = this.renderContext;
|
const renderContext = this.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
const clearColor = this.backgroundColor;
|
const clearColor = this.backgroundColor;
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.destFramebuffer);
|
||||||
|
gl.viewport(0, 0, this.destAllocatedSize[0], this.destAllocatedSize[1]);
|
||||||
|
gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected clearForDirectRendering(objectIndex: number): void {
|
||||||
|
const renderingMode = unwrapNull(this.antialiasingStrategy).directRenderingMode;
|
||||||
|
const renderContext = this.renderContext;
|
||||||
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
const clearColor = this.clearColorForObject(objectIndex);
|
||||||
|
if (clearColor == null)
|
||||||
|
return;
|
||||||
|
|
||||||
gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
||||||
|
|
||||||
switch (renderingMode) {
|
switch (renderingMode) {
|
||||||
|
@ -298,6 +329,15 @@ 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 {}
|
||||||
|
|
||||||
|
@ -307,16 +347,27 @@ export abstract class Renderer {
|
||||||
|
|
||||||
const antialiasingStrategy = unwrapNull(this.antialiasingStrategy);
|
const antialiasingStrategy = unwrapNull(this.antialiasingStrategy);
|
||||||
const renderingMode = antialiasingStrategy.directRenderingMode;
|
const renderingMode = antialiasingStrategy.directRenderingMode;
|
||||||
|
const objectCount = this.objectCount;
|
||||||
|
|
||||||
for (let objectIndex = 0; objectIndex < this.meshes.length; objectIndex++) {
|
for (let objectIndex = 0; objectIndex < objectCount; objectIndex++) {
|
||||||
const instanceRange = this.instanceRangeForObject(objectIndex);
|
const instanceRange = this.instanceRangeForObject(objectIndex);
|
||||||
if (instanceRange.isEmpty)
|
if (instanceRange.isEmpty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const meshData = this.meshData[objectIndex];
|
const pathRange = this.pathRangeForObject(objectIndex);
|
||||||
|
const meshIndex = this.meshIndexForObject(objectIndex);
|
||||||
|
|
||||||
|
// Prepare for direct rendering.
|
||||||
|
antialiasingStrategy.prepareToDirectlyRenderObject(this, objectIndex);
|
||||||
|
|
||||||
|
// Clear.
|
||||||
|
this.clearForDirectRendering(objectIndex);
|
||||||
|
|
||||||
|
const meshes = this.meshes[meshIndex];
|
||||||
|
const meshData = this.meshData[meshIndex];
|
||||||
|
|
||||||
// Set up implicit cover state.
|
// Set up implicit cover state.
|
||||||
gl.depthFunc(this.depthFunction);
|
gl.depthFunc(gl.GREATER);
|
||||||
gl.depthMask(true);
|
gl.depthMask(true);
|
||||||
gl.enable(gl.DEPTH_TEST);
|
gl.enable(gl.DEPTH_TEST);
|
||||||
gl.disable(gl.BLEND);
|
gl.disable(gl.BLEND);
|
||||||
|
@ -336,18 +387,23 @@ export abstract class Renderer {
|
||||||
this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
|
this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
|
||||||
this.setHintsUniform(directInteriorProgram.uniforms);
|
this.setHintsUniform(directInteriorProgram.uniforms);
|
||||||
this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0);
|
this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0);
|
||||||
this.pathTransformBufferTextures[objectIndex]
|
this.pathTransformBufferTextures[meshIndex]
|
||||||
.bind(gl, directInteriorProgram.uniforms, 1);
|
.bind(gl, directInteriorProgram.uniforms, 1);
|
||||||
if (renderingMode === 'color-depth') {
|
if (renderingMode === 'color-depth') {
|
||||||
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
|
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
|
||||||
strategy.bindEdgeDepthTexture(gl, directInteriorProgram.uniforms, 2);
|
strategy.bindEdgeDepthTexture(gl, directInteriorProgram.uniforms, 2);
|
||||||
}
|
}
|
||||||
let indexCount = meshData.coverInteriorIndices.byteLength / UINT32_SIZE;
|
const coverInteriorRange = getMeshIndexRange(meshes.coverInteriorIndexRanges,
|
||||||
|
pathRange);
|
||||||
if (!this.pathIDsAreInstanced) {
|
if (!this.pathIDsAreInstanced) {
|
||||||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_INT, 0);
|
gl.drawElements(gl.TRIANGLES,
|
||||||
|
coverInteriorRange.length,
|
||||||
|
gl.UNSIGNED_INT,
|
||||||
|
coverInteriorRange.start * UINT32_SIZE);
|
||||||
} else {
|
} else {
|
||||||
renderContext.instancedArraysExt.drawElementsInstancedANGLE(gl.TRIANGLES,
|
renderContext.instancedArraysExt
|
||||||
indexCount,
|
.drawElementsInstancedANGLE(gl.TRIANGLES,
|
||||||
|
coverInteriorRange.length,
|
||||||
gl.UNSIGNED_INT,
|
gl.UNSIGNED_INT,
|
||||||
0,
|
0,
|
||||||
instanceRange.length);
|
instanceRange.length);
|
||||||
|
@ -381,23 +437,29 @@ export abstract class Renderer {
|
||||||
this.setFramebufferSizeUniform(directCurveProgram.uniforms);
|
this.setFramebufferSizeUniform(directCurveProgram.uniforms);
|
||||||
this.setHintsUniform(directCurveProgram.uniforms);
|
this.setHintsUniform(directCurveProgram.uniforms);
|
||||||
this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0);
|
this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0);
|
||||||
this.pathTransformBufferTextures[objectIndex].bind(gl, directCurveProgram.uniforms, 1);
|
this.pathTransformBufferTextures[meshIndex].bind(gl, directCurveProgram.uniforms, 1);
|
||||||
if (renderingMode === 'color-depth') {
|
if (renderingMode === 'color-depth') {
|
||||||
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
|
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
|
||||||
strategy.bindEdgeDepthTexture(gl, directCurveProgram.uniforms, 2);
|
strategy.bindEdgeDepthTexture(gl, directCurveProgram.uniforms, 2);
|
||||||
}
|
}
|
||||||
indexCount = meshData.coverCurveIndices.byteLength / UINT32_SIZE;
|
const coverCurveRange = getMeshIndexRange(meshes.coverCurveIndexRanges, pathRange);
|
||||||
if (!this.pathIDsAreInstanced) {
|
if (!this.pathIDsAreInstanced) {
|
||||||
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_INT, 0);
|
gl.drawElements(gl.TRIANGLES,
|
||||||
|
coverCurveRange.length,
|
||||||
|
gl.UNSIGNED_INT,
|
||||||
|
coverCurveRange.start * UINT32_SIZE);
|
||||||
} else {
|
} else {
|
||||||
renderContext.instancedArraysExt.drawElementsInstancedANGLE(gl.TRIANGLES,
|
renderContext.instancedArraysExt.drawElementsInstancedANGLE(gl.TRIANGLES,
|
||||||
indexCount,
|
coverCurveRange.length,
|
||||||
gl.UNSIGNED_INT,
|
gl.UNSIGNED_INT,
|
||||||
0,
|
0,
|
||||||
instanceRange.length);
|
instanceRange.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
|
|
||||||
|
// Finish direct rendering. Right now, this performs compositing if necessary.
|
||||||
|
antialiasingStrategy.finishDirectlyRenderingObject(this, objectIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +506,9 @@ export abstract class Renderer {
|
||||||
private initImplicitCoverCurveVAO(objectIndex: number, instanceRange: Range): void {
|
private initImplicitCoverCurveVAO(objectIndex: number, instanceRange: Range): void {
|
||||||
const renderContext = this.renderContext;
|
const renderContext = this.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
const meshes = this.meshes[objectIndex];
|
|
||||||
|
const meshIndex = this.meshIndexForObject(objectIndex);
|
||||||
|
const meshes = this.meshes[meshIndex];
|
||||||
|
|
||||||
const directCurveProgramName = this.directCurveProgramName();
|
const directCurveProgramName = this.directCurveProgramName();
|
||||||
const directCurveProgram = renderContext.shaderPrograms[directCurveProgramName];
|
const directCurveProgram = renderContext.shaderPrograms[directCurveProgramName];
|
||||||
|
@ -490,7 +554,9 @@ export abstract class Renderer {
|
||||||
private initImplicitCoverInteriorVAO(objectIndex: number, instanceRange: Range): void {
|
private initImplicitCoverInteriorVAO(objectIndex: number, instanceRange: Range): void {
|
||||||
const renderContext = this.renderContext;
|
const renderContext = this.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
const meshes = this.meshes[objectIndex];
|
|
||||||
|
const meshIndex = this.meshIndexForObject(objectIndex);
|
||||||
|
const meshes = this.meshes[meshIndex];
|
||||||
|
|
||||||
const directInteriorProgramName = this.directInteriorProgramName();
|
const directInteriorProgramName = this.directInteriorProgramName();
|
||||||
const directInteriorProgram = renderContext.shaderPrograms[directInteriorProgramName];
|
const directInteriorProgram = renderContext.shaderPrograms[directInteriorProgramName];
|
||||||
|
@ -543,3 +609,22 @@ export abstract class Renderer {
|
||||||
this.renderContext.gl.uniformMatrix4fv(uniforms.uTransform, false, transform);
|
this.renderContext.gl.uniformMatrix4fv(uniforms.uTransform, false, transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMeshIndexRange(indexRanges: Range[], pathRange: Range): Range {
|
||||||
|
if (indexRanges.length === 0)
|
||||||
|
return new Range(0, 0);
|
||||||
|
|
||||||
|
let firstIndex;
|
||||||
|
if (pathRange.start - 1 >= indexRanges.length)
|
||||||
|
firstIndex = unwrapUndef(_.last(indexRanges)).end;
|
||||||
|
else
|
||||||
|
firstIndex = indexRanges[pathRange.start - 1].start;
|
||||||
|
|
||||||
|
let lastIndex;
|
||||||
|
if (pathRange.end - 1 >= indexRanges.length)
|
||||||
|
lastIndex = unwrapUndef(_.last(indexRanges)).end;
|
||||||
|
else
|
||||||
|
lastIndex = indexRanges[pathRange.end - 1].start;
|
||||||
|
|
||||||
|
return new Range(firstIndex, lastIndex);
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {expectNotNull, PathfinderError, unwrapNull} from './utils';
|
||||||
|
|
||||||
export interface ShaderMap<T> {
|
export interface ShaderMap<T> {
|
||||||
blit: T;
|
blit: T;
|
||||||
|
compositeAlphaMask: T;
|
||||||
demo3DDistantGlyph: T;
|
demo3DDistantGlyph: T;
|
||||||
demo3DMonument: T;
|
demo3DMonument: T;
|
||||||
directCurve: T;
|
directCurve: T;
|
||||||
|
@ -43,6 +44,7 @@ const COMMON_SHADER_URL: string = '/glsl/gles2/common.inc.glsl';
|
||||||
|
|
||||||
export const SHADER_NAMES: Array<keyof ShaderMap<void>> = [
|
export const SHADER_NAMES: Array<keyof ShaderMap<void>> = [
|
||||||
'blit',
|
'blit',
|
||||||
|
'compositeAlphaMask',
|
||||||
'directCurve',
|
'directCurve',
|
||||||
'directInterior',
|
'directInterior',
|
||||||
'direct3DCurve',
|
'direct3DCurve',
|
||||||
|
@ -69,6 +71,10 @@ const SHADER_URLS: ShaderMap<ShaderProgramURLs> = {
|
||||||
fragment: "/glsl/gles2/blit.fs.glsl",
|
fragment: "/glsl/gles2/blit.fs.glsl",
|
||||||
vertex: "/glsl/gles2/blit.vs.glsl",
|
vertex: "/glsl/gles2/blit.vs.glsl",
|
||||||
},
|
},
|
||||||
|
compositeAlphaMask: {
|
||||||
|
fragment: "/glsl/gles2/composite-alpha-mask.fs.glsl",
|
||||||
|
vertex: "/glsl/gles2/composite-alpha-mask.vs.glsl",
|
||||||
|
},
|
||||||
demo3DDistantGlyph: {
|
demo3DDistantGlyph: {
|
||||||
fragment: "/glsl/gles2/demo-3d-distant-glyph.fs.glsl",
|
fragment: "/glsl/gles2/demo-3d-distant-glyph.fs.glsl",
|
||||||
vertex: "/glsl/gles2/demo-3d-distant-glyph.vs.glsl",
|
vertex: "/glsl/gles2/demo-3d-distant-glyph.vs.glsl",
|
||||||
|
|
|
@ -80,7 +80,7 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareForDirectRendering(renderer: Renderer) {
|
prepareForRendering(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -90,6 +90,18 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
||||||
gl.viewport(0, 0, framebufferSize[0], framebufferSize[1]);
|
gl.viewport(0, 0, framebufferSize[0], framebufferSize[1]);
|
||||||
gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
||||||
gl.enable(gl.SCISSOR_TEST);
|
gl.enable(gl.SCISSOR_TEST);
|
||||||
|
|
||||||
|
const clearColor = renderer.backgroundColor;
|
||||||
|
gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
// TODO(pcwalton)
|
||||||
|
}
|
||||||
|
|
||||||
|
finishDirectlyRenderingObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
// TODO(pcwalton)
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(renderer: Renderer) {}
|
antialias(renderer: Renderer) {}
|
||||||
|
|
|
@ -18,11 +18,12 @@ import PathfinderBufferTexture from "./buffer-texture";
|
||||||
import {OrthographicCamera} from "./camera";
|
import {OrthographicCamera} from "./camera";
|
||||||
import {UniformMap} from './gl-utils';
|
import {UniformMap} from './gl-utils';
|
||||||
import {PathfinderMeshData} from "./meshes";
|
import {PathfinderMeshData} from "./meshes";
|
||||||
|
import {CompositingOperation, RenderTaskType} from './render-task';
|
||||||
import {Renderer} from './renderer';
|
import {Renderer} from './renderer';
|
||||||
import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
||||||
import SSAAStrategy from "./ssaa-strategy";
|
import SSAAStrategy from "./ssaa-strategy";
|
||||||
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
|
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
|
||||||
import {panic, unwrapNull} from './utils';
|
import {panic, Range, unwrapNull} from './utils';
|
||||||
import {DemoView, Timings} from './view';
|
import {DemoView, Timings} from './view';
|
||||||
import {MCAAMulticolorStrategy, XCAAStrategy} from "./xcaa-strategy";
|
import {MCAAMulticolorStrategy, XCAAStrategy} from "./xcaa-strategy";
|
||||||
|
|
||||||
|
@ -127,10 +128,19 @@ class SVGDemoRenderer extends Renderer {
|
||||||
return this.destAllocatedSize;
|
return this.destAllocatedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get backgroundColor(): glmatrix.vec4 {
|
get usesIntermediateRenderTargets(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get backgroundColor(): glmatrix.vec4 {
|
||||||
return glmatrix.vec4.clone([1.0, 1.0, 1.0, 1.0]);
|
return glmatrix.vec4.clone([1.0, 1.0, 1.0, 1.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected get objectCount(): number {
|
||||||
|
const loader = this.renderContext.appController.loader;
|
||||||
|
return loader.renderTasks.length;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(renderContext: SVGDemoView) {
|
constructor(renderContext: SVGDemoView) {
|
||||||
super(renderContext);
|
super(renderContext);
|
||||||
|
|
||||||
|
@ -159,8 +169,14 @@ class SVGDemoRenderer extends Renderer {
|
||||||
this.camera.zoomToFit();
|
this.camera.zoomToFit();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get depthFunction(): GLenum {
|
renderTaskTypeForObject(objectIndex: number): RenderTaskType {
|
||||||
return this.renderContext.gl.GREATER;
|
const loader = this.renderContext.appController.loader;
|
||||||
|
return loader.renderTasks[objectIndex].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
compositingOperationForObject(objectIndex: number): CompositingOperation | null {
|
||||||
|
const loader = this.renderContext.appController.loader;
|
||||||
|
return loader.renderTasks[objectIndex].compositingOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get usedSizeFactor(): glmatrix.vec2 {
|
protected get usedSizeFactor(): glmatrix.vec2 {
|
||||||
|
@ -193,6 +209,15 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import * as _ from 'lodash';
|
||||||
|
|
||||||
import 'path-data-polyfill.js';
|
import 'path-data-polyfill.js';
|
||||||
import {parseServerTiming, PathfinderMeshData} from "./meshes";
|
import {parseServerTiming, PathfinderMeshData} from "./meshes";
|
||||||
|
import {AlphaMaskCompositingOperation, RenderTask, RenderTaskType} from './render-task';
|
||||||
import {panic, Range, unwrapNull, unwrapUndef} from "./utils";
|
import {panic, Range, unwrapNull, unwrapUndef} from "./utils";
|
||||||
|
|
||||||
export const BUILTIN_SVG_URI: string = "/svg/demo";
|
export const BUILTIN_SVG_URI: string = "/svg/demo";
|
||||||
|
@ -65,26 +66,12 @@ export class SVGStroke extends SVGPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SVGRenderTaskType = 'color' | 'clip';
|
|
||||||
|
|
||||||
export class SVGRenderTask {
|
|
||||||
type: SVGRenderTaskType;
|
|
||||||
instanceIndices: Range;
|
|
||||||
clipIndex: number | null;
|
|
||||||
|
|
||||||
constructor(type: SVGRenderTaskType, instanceIndices: Range, clipIndex?: number) {
|
|
||||||
this.type = type;
|
|
||||||
this.instanceIndices = instanceIndices;
|
|
||||||
this.clipIndex = clipIndex != null ? clipIndex : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ClipPathIDTable {
|
interface ClipPathIDTable {
|
||||||
[id: string]: number;
|
[id: string]: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SVGLoader {
|
export class SVGLoader {
|
||||||
renderTasks: SVGRenderTask[];
|
renderTasks: RenderTask[];
|
||||||
pathInstances: SVGPath[];
|
pathInstances: SVGPath[];
|
||||||
scale: number;
|
scale: number;
|
||||||
bounds: glmatrix.vec4;
|
bounds: glmatrix.vec4;
|
||||||
|
@ -202,7 +189,8 @@ export class SVGLoader {
|
||||||
!this.clipPathIDs.hasOwnProperty(matches[1])) {
|
!this.clipPathIDs.hasOwnProperty(matches[1])) {
|
||||||
hasClip = false;
|
hasClip = false;
|
||||||
} else {
|
} else {
|
||||||
currentRenderTask.clipIndex = this.clipPathIDs[matches[1]];
|
currentRenderTask.compositingOperation =
|
||||||
|
new AlphaMaskCompositingOperation(this.clipPathIDs[matches[1]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +219,7 @@ export class SVGLoader {
|
||||||
const currentRenderTask = unwrapUndef(_.last(this.renderTasks));
|
const currentRenderTask = unwrapUndef(_.last(this.renderTasks));
|
||||||
this.pathInstances.push(pathInstance);
|
this.pathInstances.push(pathInstance);
|
||||||
currentRenderTask.instanceIndices.end = Math.max(currentRenderTask.instanceIndices.end,
|
currentRenderTask.instanceIndices.end = Math.max(currentRenderTask.instanceIndices.end,
|
||||||
this.pathInstances.length);
|
this.pathInstances.length + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private popTopRenderTaskIfEmpty(): void {
|
private popTopRenderTaskIfEmpty(): void {
|
||||||
|
@ -240,10 +228,10 @@ export class SVGLoader {
|
||||||
this.renderTasks.pop();
|
this.renderTasks.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private pushNewRenderTask(taskType: SVGRenderTaskType): void {
|
private pushNewRenderTask(taskType: RenderTaskType): void {
|
||||||
this.popTopRenderTaskIfEmpty();
|
this.popTopRenderTaskIfEmpty();
|
||||||
const emptyRange = new Range(this.pathInstances.length, this.pathInstances.length);
|
const emptyRange = new Range(this.pathInstances.length + 1, this.pathInstances.length + 1);
|
||||||
this.renderTasks.push(new SVGRenderTask(taskType, emptyRange));
|
this.renderTasks.push(new RenderTask(taskType, emptyRange));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,10 +109,6 @@ export abstract class TextRenderer extends Renderer {
|
||||||
return glmatrix.vec2.create();
|
return glmatrix.vec2.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get depthFunction(): number {
|
|
||||||
return this.renderContext.gl.GREATER;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get usedSizeFactor(): glmatrix.vec2 {
|
protected get usedSizeFactor(): glmatrix.vec2 {
|
||||||
const usedSize = glmatrix.vec2.create();
|
const usedSize = glmatrix.vec2.create();
|
||||||
glmatrix.vec2.div(usedSize, this.renderContext.atlas.usedSize, ATLAS_SIZE);
|
glmatrix.vec2.div(usedSize, this.renderContext.atlas.usedSize, ATLAS_SIZE);
|
||||||
|
@ -123,6 +119,10 @@ export abstract class TextRenderer extends Renderer {
|
||||||
return this.renderContext.glyphStore.glyphIDs.length * SUBPIXEL_GRANULARITY;
|
return this.renderContext.glyphStore.glyphIDs.length * SUBPIXEL_GRANULARITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected get objectCount(): number {
|
||||||
|
return this.meshes.length;
|
||||||
|
}
|
||||||
|
|
||||||
private stemDarkening: StemDarkeningMode;
|
private stemDarkening: StemDarkeningMode;
|
||||||
private subpixelAA: SubpixelAAType;
|
private subpixelAA: SubpixelAAType;
|
||||||
|
|
||||||
|
|
|
@ -60,16 +60,16 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
this.destFramebufferSize = glmatrix.vec2.create();
|
this.destFramebufferSize = glmatrix.vec2.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
init(renderer: Renderer) {
|
init(renderer: Renderer): void {
|
||||||
super.init(renderer);
|
super.init(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(renderer: Renderer) {
|
attachMeshes(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
this.createResolveVAO(renderer);
|
this.createResolveVAO(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFramebufferSize(renderer: Renderer) {
|
setFramebufferSize(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
|
||||||
this.destFramebufferSize = glmatrix.vec2.clone(renderer.destAllocatedSize);
|
this.destFramebufferSize = glmatrix.vec2.clone(renderer.destAllocatedSize);
|
||||||
|
@ -82,7 +82,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, null);
|
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareForDirectRendering(renderer: Renderer) {
|
prepareForRendering(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -102,7 +102,16 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(renderer: Renderer) {
|
prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
// TODO(pcwalton)
|
||||||
|
this.prepareForRendering(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
finishDirectlyRenderingObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
// TODO(pcwalton)
|
||||||
|
}
|
||||||
|
|
||||||
|
antialias(renderer: Renderer): void {
|
||||||
// Perform early preparations.
|
// Perform early preparations.
|
||||||
this.createPathBoundsBufferTexture(renderer);
|
this.createPathBoundsBufferTexture(renderer);
|
||||||
|
|
||||||
|
@ -116,7 +125,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
this.clearForAA(renderer);
|
this.clearForAA(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(renderer: Renderer) {
|
resolve(renderer: Renderer): void {
|
||||||
// Resolve the antialiasing.
|
// Resolve the antialiasing.
|
||||||
this.resolveAA(renderer);
|
this.resolveAA(renderer);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +134,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
return glmatrix.mat4.create();
|
return glmatrix.mat4.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initDirectFramebufferIfNecessary(renderer: Renderer) {
|
protected initDirectFramebufferIfNecessary(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -156,7 +165,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
renderContext.gl.enable(renderContext.gl.SCISSOR_TEST);
|
renderContext.gl.enable(renderContext.gl.SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAAState(renderer: Renderer) {
|
protected setAAState(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const usedSize = this.supersampledUsedSize(renderer);
|
const usedSize = this.supersampledUsedSize(renderer);
|
||||||
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, this.aaFramebuffer);
|
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, this.aaFramebuffer);
|
||||||
|
@ -170,7 +179,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
this.setAADepthState(renderer);
|
this.setAADepthState(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap) {
|
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -183,7 +192,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
renderer.setHintsUniform(uniforms);
|
renderer.setHintsUniform(uniforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected resolveAA(renderer: Renderer) {
|
protected resolveAA(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -238,7 +247,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
protected abstract setAADepthState(renderer: Renderer): void;
|
protected abstract setAADepthState(renderer: Renderer): void;
|
||||||
protected abstract clearForResolve(renderer: Renderer): void;
|
protected abstract clearForResolve(renderer: Renderer): void;
|
||||||
|
|
||||||
private initAAAlphaFramebuffer(renderer: Renderer) {
|
private initAAAlphaFramebuffer(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
this.aaAlphaTexture = unwrapNull(renderContext.gl.createTexture());
|
this.aaAlphaTexture = unwrapNull(renderContext.gl.createTexture());
|
||||||
renderContext.gl.activeTexture(renderContext.gl.TEXTURE0);
|
renderContext.gl.activeTexture(renderContext.gl.TEXTURE0);
|
||||||
|
@ -262,7 +271,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
this.aaDepthTexture);
|
this.aaDepthTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createPathBoundsBufferTexture(renderer: Renderer) {
|
private createPathBoundsBufferTexture(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const pathBounds = renderer.pathBoundingRects(0);
|
const pathBounds = renderer.pathBoundingRects(0);
|
||||||
this.pathBoundsBufferTexture = new PathfinderBufferTexture(renderContext.gl,
|
this.pathBoundsBufferTexture = new PathfinderBufferTexture(renderContext.gl,
|
||||||
|
@ -270,7 +279,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
this.pathBoundsBufferTexture.upload(renderContext.gl, pathBounds);
|
this.pathBoundsBufferTexture.upload(renderContext.gl, pathBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createResolveVAO(renderer: Renderer) {
|
private createResolveVAO(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
this.resolveVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
this.resolveVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
|
||||||
|
@ -296,7 +305,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
private lineVAOs: FastEdgeVAOs;
|
private lineVAOs: FastEdgeVAOs;
|
||||||
private curveVAOs: FastEdgeVAOs;
|
private curveVAOs: FastEdgeVAOs;
|
||||||
|
|
||||||
attachMeshes(renderer: Renderer) {
|
attachMeshes(renderer: Renderer): void {
|
||||||
super.attachMeshes(renderer);
|
super.attachMeshes(renderer);
|
||||||
|
|
||||||
this.createCoverVAO(renderer);
|
this.createCoverVAO(renderer);
|
||||||
|
@ -304,7 +313,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
this.createCurveVAOs(renderer);
|
this.createCurveVAOs(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(renderer: Renderer) {
|
antialias(renderer: Renderer): void {
|
||||||
super.antialias(renderer);
|
super.antialias(renderer);
|
||||||
|
|
||||||
// Conservatively cover.
|
// Conservatively cover.
|
||||||
|
@ -391,7 +400,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCoverVAO(renderer: Renderer) {
|
private createCoverVAO(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
|
||||||
this.coverVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
this.coverVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
|
@ -445,7 +454,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createLineVAOs(renderer: Renderer) {
|
private createLineVAOs(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const vaos: Partial<FastEdgeVAOs> = {};
|
const vaos: Partial<FastEdgeVAOs> = {};
|
||||||
const lineProgram = renderContext.shaderPrograms.mcaaLine;
|
const lineProgram = renderContext.shaderPrograms.mcaaLine;
|
||||||
|
@ -517,7 +526,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
this.lineVAOs = vaos as FastEdgeVAOs;
|
this.lineVAOs = vaos as FastEdgeVAOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCurveVAOs(renderer: Renderer) {
|
private createCurveVAOs(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const vaos: Partial<FastEdgeVAOs> = {};
|
const vaos: Partial<FastEdgeVAOs> = {};
|
||||||
const curveProgram = renderContext.shaderPrograms.mcaaCurve;
|
const curveProgram = renderContext.shaderPrograms.mcaaCurve;
|
||||||
|
@ -612,14 +621,14 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setBlendModeForAA(renderer: Renderer, direction: 'upper' | 'lower') {
|
private setBlendModeForAA(renderer: Renderer, direction: 'upper' | 'lower'): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD);
|
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD);
|
||||||
renderContext.gl.blendFunc(renderContext.gl.ONE, renderContext.gl.ONE);
|
renderContext.gl.blendFunc(renderContext.gl.ONE, renderContext.gl.ONE);
|
||||||
renderContext.gl.enable(renderContext.gl.BLEND);
|
renderContext.gl.enable(renderContext.gl.BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
private antialiasLines(renderer: Renderer) {
|
private antialiasLines(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
this.setAAState(renderer);
|
this.setAAState(renderer);
|
||||||
|
|
||||||
|
@ -630,7 +639,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
this.antialiasLinesWithProgram(renderer, lineProgram);
|
this.antialiasLinesWithProgram(renderer, lineProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
private antialiasCurves(renderer: Renderer) {
|
private antialiasCurves(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
|
||||||
this.setAAState(renderer);
|
this.setAAState(renderer);
|
||||||
|
@ -641,7 +650,6 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
|
|
||||||
this.antialiasCurvesWithProgram(renderer, curveProgram);
|
this.antialiasCurvesWithProgram(renderer, curveProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ECAAStrategy extends XCAAStrategy {
|
export class ECAAStrategy extends XCAAStrategy {
|
||||||
|
@ -652,14 +660,14 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
return 'none';
|
return 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(renderer: Renderer) {
|
attachMeshes(renderer: Renderer): void {
|
||||||
super.attachMeshes(renderer);
|
super.attachMeshes(renderer);
|
||||||
|
|
||||||
this.createLineVAO(renderer);
|
this.createLineVAO(renderer);
|
||||||
this.createCurveVAO(renderer);
|
this.createCurveVAO(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(renderer: Renderer) {
|
antialias(renderer: Renderer): void {
|
||||||
super.antialias(renderer);
|
super.antialias(renderer);
|
||||||
|
|
||||||
// Antialias.
|
// Antialias.
|
||||||
|
@ -667,7 +675,7 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
this.antialiasCurves(renderer);
|
this.antialiasCurves(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap) {
|
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap): void {
|
||||||
super.setAAUniforms(renderer, uniforms);
|
super.setAAUniforms(renderer, uniforms);
|
||||||
|
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
@ -681,9 +689,9 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
return renderContext.shaderPrograms.xcaaMonoResolve;
|
return renderContext.shaderPrograms.xcaaMonoResolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected maskEdgesIfNecessary(renderer: Renderer) {}
|
protected maskEdgesIfNecessary(renderer: Renderer): void {}
|
||||||
|
|
||||||
protected clearForAA(renderer: Renderer) {
|
protected clearForAA(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
renderContext.gl.clearDepth(0.0);
|
renderContext.gl.clearDepth(0.0);
|
||||||
|
@ -691,25 +699,25 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
renderContext.gl.DEPTH_BUFFER_BIT);
|
renderContext.gl.DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAADepthState(renderer: Renderer) {
|
protected setAADepthState(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForResolve(renderer: Renderer) {
|
protected clearForResolve(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
|
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setBlendModeForAA(renderer: Renderer) {
|
private setBlendModeForAA(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD);
|
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD);
|
||||||
renderContext.gl.blendFunc(renderContext.gl.ONE, renderContext.gl.ONE);
|
renderContext.gl.blendFunc(renderContext.gl.ONE, renderContext.gl.ONE);
|
||||||
renderContext.gl.enable(renderContext.gl.BLEND);
|
renderContext.gl.enable(renderContext.gl.BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createLineVAO(renderer: Renderer) {
|
private createLineVAO(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
|
||||||
const lineProgram = renderContext.shaderPrograms.ecaaLine;
|
const lineProgram = renderContext.shaderPrograms.ecaaLine;
|
||||||
|
@ -786,7 +794,7 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
this.lineVAO = vao;
|
this.lineVAO = vao;
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCurveVAO(renderer: Renderer) {
|
private createCurveVAO(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
|
||||||
const curveProgram = renderContext.shaderPrograms.ecaaCurve;
|
const curveProgram = renderContext.shaderPrograms.ecaaCurve;
|
||||||
|
@ -864,7 +872,7 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
this.curveVAO = vao;
|
this.curveVAO = vao;
|
||||||
}
|
}
|
||||||
|
|
||||||
private antialiasLines(renderer: Renderer) {
|
private antialiasLines(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
|
||||||
this.setAAState(renderer);
|
this.setAAState(renderer);
|
||||||
|
@ -890,7 +898,7 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private antialiasCurves(renderer: Renderer) {
|
private antialiasCurves(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
|
|
||||||
this.setAAState(renderer);
|
this.setAAState(renderer);
|
||||||
|
@ -924,9 +932,9 @@ export class MCAAMonochromeStrategy extends MCAAStrategy {
|
||||||
return renderContext.shaderPrograms.xcaaMonoResolve;
|
return renderContext.shaderPrograms.xcaaMonoResolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected maskEdgesIfNecessary(renderer: Renderer) {}
|
protected maskEdgesIfNecessary(renderer: Renderer): void {}
|
||||||
|
|
||||||
protected clearForAA(renderer: Renderer) {
|
protected clearForAA(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
renderContext.gl.clearDepth(0.0);
|
renderContext.gl.clearDepth(0.0);
|
||||||
|
@ -934,12 +942,12 @@ export class MCAAMonochromeStrategy extends MCAAStrategy {
|
||||||
renderContext.gl.DEPTH_BUFFER_BIT);
|
renderContext.gl.DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAADepthState(renderer: Renderer) {
|
protected setAADepthState(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForResolve(renderer: Renderer) {
|
protected clearForResolve(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
|
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
|
||||||
|
@ -985,8 +993,16 @@ export class AdaptiveMonochromeXCAAStrategy implements AntialiasingStrategy {
|
||||||
return this.mcaaStrategy.transform;
|
return this.mcaaStrategy.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareForDirectRendering(renderer: Renderer): void {
|
prepareForRendering(renderer: Renderer): void {
|
||||||
this.getAppropriateStrategy(renderer).prepareForDirectRendering(renderer);
|
this.getAppropriateStrategy(renderer).prepareForRendering(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareToDirectlyRenderObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
this.getAppropriateStrategy(renderer).prepareToDirectlyRenderObject(renderer, objectIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
finishDirectlyRenderingObject(renderer: Renderer, objectIndex: number): void {
|
||||||
|
this.getAppropriateStrategy(renderer).finishDirectlyRenderingObject(renderer, objectIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(renderer: Renderer): void {
|
antialias(renderer: Renderer): void {
|
||||||
|
@ -1018,9 +1034,9 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
|
||||||
return renderContext.shaderPrograms.xcaaMultiResolve;
|
return renderContext.shaderPrograms.xcaaMultiResolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initDirectFramebufferIfNecessary(renderer: Renderer) {}
|
protected initDirectFramebufferIfNecessary(renderer: Renderer): void {}
|
||||||
|
|
||||||
protected maskEdgesIfNecessary(renderer: Renderer) {
|
protected maskEdgesIfNecessary(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -1053,14 +1069,14 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setCoverDepthState(renderer: Renderer) {
|
protected setCoverDepthState(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.depthMask(false);
|
renderContext.gl.depthMask(false);
|
||||||
renderContext.gl.depthFunc(renderContext.gl.EQUAL);
|
renderContext.gl.depthFunc(renderContext.gl.EQUAL);
|
||||||
renderContext.gl.enable(renderContext.gl.DEPTH_TEST);
|
renderContext.gl.enable(renderContext.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForAA(renderer: Renderer) {
|
protected clearForAA(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -1068,7 +1084,7 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAADepthState(renderer: Renderer) {
|
protected setAADepthState(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
@ -1089,7 +1105,7 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
|
||||||
gl.enable(gl.BLEND);
|
gl.enable(gl.BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForResolve(renderer: Renderer) {}
|
protected clearForResolve(renderer: Renderer): void {}
|
||||||
|
|
||||||
protected setAdditionalStateForResolveIfNecessary(renderer: Renderer,
|
protected setAdditionalStateForResolveIfNecessary(renderer: Renderer,
|
||||||
resolveProgram: PathfinderShaderProgram,
|
resolveProgram: PathfinderShaderProgram,
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// pathfinder/shaders/gles2/composite-alpha-mask.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 sampler2D uMask;
|
||||||
|
|
||||||
|
varying vec2 vTexCoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 color = texture2D(uSource, vTexCoord);
|
||||||
|
float alpha = texture2D(uMask, vTexCoord).a;
|
||||||
|
gl_FragColor = vec4(color.rgb, color.a * alpha);
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// pathfinder/shaders/gles2/composite-alpha-mask.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;
|
||||||
|
|
||||||
|
/// A 3D transform to apply to the scene.
|
||||||
|
uniform mat4 uTransform;
|
||||||
|
|
||||||
|
/// The 2D vertex position.
|
||||||
|
attribute vec2 aPosition;
|
||||||
|
/// The texture coordinate.
|
||||||
|
attribute vec2 aTexCoord;
|
||||||
|
|
||||||
|
varying vec2 vTexCoord;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = uTransform * vec4(aPosition, 0.0, 1.0);
|
||||||
|
vTexCoord = aTexCoord;
|
||||||
|
}
|
Loading…
Reference in New Issue