2017-10-09 17:14:24 -04:00
|
|
|
// pathfinder/client/src/xcaa-strategy.ts
|
2017-08-26 16:47:18 -04:00
|
|
|
//
|
|
|
|
// 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 * as glmatrix from 'gl-matrix';
|
2017-10-09 17:14:24 -04:00
|
|
|
import * as _ from 'lodash';
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-21 01:04:53 -04:00
|
|
|
import {AntialiasingStrategy, DirectRenderingMode, SubpixelAAType} from './aa-strategy';
|
2017-09-28 17:34:48 -04:00
|
|
|
import PathfinderBufferTexture from './buffer-texture';
|
2017-08-26 16:47:18 -04:00
|
|
|
import {createFramebuffer, createFramebufferColorTexture} from './gl-utils';
|
|
|
|
import {createFramebufferDepthTexture, setTextureParameters, UniformMap} from './gl-utils';
|
|
|
|
import {WebGLVertexArrayObject} from './gl-utils';
|
|
|
|
import {B_QUAD_LOWER_INDICES_OFFSET, B_QUAD_SIZE, B_QUAD_UPPER_INDICES_OFFSET} from './meshes';
|
2017-10-16 22:29:13 -04:00
|
|
|
import {Renderer} from './renderer';
|
2017-08-26 16:47:18 -04:00
|
|
|
import {PathfinderShaderProgram} from './shader-loader';
|
2017-10-09 17:14:24 -04:00
|
|
|
import {computeStemDarkeningAmount} from './text';
|
2017-10-20 19:29:05 -04:00
|
|
|
import {assert, FLOAT32_SIZE, lerp, UINT32_SIZE, unwrapNull} from './utils';
|
2017-10-16 22:29:13 -04:00
|
|
|
import {RenderContext} from './view';
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
interface FastEdgeVAOs {
|
|
|
|
upper: WebGLVertexArrayObject;
|
|
|
|
lower: WebGLVertexArrayObject;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
type Direction = 'upper' | 'lower';
|
|
|
|
|
|
|
|
const DIRECTIONS: Direction[] = ['upper', 'lower'];
|
|
|
|
|
|
|
|
export abstract class XCAAStrategy extends AntialiasingStrategy {
|
2017-10-21 01:04:53 -04:00
|
|
|
abstract readonly directRenderingMode: DirectRenderingMode;
|
2017-09-28 17:34:48 -04:00
|
|
|
|
2017-10-21 01:04:53 -04:00
|
|
|
protected directTexture: WebGLTexture;
|
2017-09-28 17:34:48 -04:00
|
|
|
protected aaDepthTexture: WebGLTexture;
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
protected pathBoundsBufferTexture: PathfinderBufferTexture;
|
|
|
|
|
2017-09-28 17:34:48 -04:00
|
|
|
protected supersampledFramebufferSize: glmatrix.vec2;
|
|
|
|
protected destFramebufferSize: glmatrix.vec2;
|
|
|
|
|
2017-09-30 01:12:09 -04:00
|
|
|
protected subpixelAA: SubpixelAAType;
|
2017-09-28 17:34:48 -04:00
|
|
|
|
2017-10-20 19:29:05 -04:00
|
|
|
protected resolveVAO: WebGLVertexArrayObject;
|
|
|
|
protected aaAlphaTexture: WebGLTexture;
|
|
|
|
|
2017-09-28 17:34:48 -04:00
|
|
|
private directFramebuffer: WebGLFramebuffer;
|
|
|
|
private aaFramebuffer: WebGLFramebuffer;
|
|
|
|
|
2017-09-30 01:12:09 -04:00
|
|
|
constructor(level: number, subpixelAA: SubpixelAAType) {
|
2017-08-29 15:29:16 -04:00
|
|
|
super();
|
2017-09-07 17:58:41 -04:00
|
|
|
|
|
|
|
this.subpixelAA = subpixelAA;
|
|
|
|
|
|
|
|
this.supersampledFramebufferSize = glmatrix.vec2.create();
|
|
|
|
this.destFramebufferSize = glmatrix.vec2.create();
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
init(renderer: Renderer) {
|
|
|
|
super.init(renderer);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
attachMeshes(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
this.createEdgeDetectVAO(renderContext);
|
2017-10-16 16:36:22 -04:00
|
|
|
this.createResolveVAO(renderer);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
setFramebufferSize(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.destFramebufferSize = glmatrix.vec2.clone(renderer.destAllocatedSize);
|
2017-09-07 17:58:41 -04:00
|
|
|
glmatrix.vec2.mul(this.supersampledFramebufferSize,
|
|
|
|
this.destFramebufferSize,
|
|
|
|
this.supersampleScale);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.initDirectFramebuffer(renderer);
|
|
|
|
this.initAAAlphaFramebuffer(renderer);
|
2017-10-20 19:29:05 -04:00
|
|
|
this.initEdgeDetectFramebuffer(renderer);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, null);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
prepare(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-21 01:04:53 -04:00
|
|
|
const gl = renderContext.gl;
|
2017-10-16 19:48:02 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const usedSize = this.supersampledUsedSize(renderer);
|
2017-10-21 01:04:53 -04:00
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.directFramebuffer);
|
|
|
|
gl.viewport(0,
|
|
|
|
0,
|
|
|
|
this.supersampledFramebufferSize[0],
|
|
|
|
this.supersampledFramebufferSize[1]);
|
|
|
|
gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
|
|
|
gl.enable(gl.SCISSOR_TEST);
|
2017-09-28 17:34:48 -04:00
|
|
|
|
|
|
|
// Clear out the color and depth textures.
|
2017-10-21 01:04:53 -04:00
|
|
|
gl.clearColor(1.0, 1.0, 1.0, 1.0);
|
|
|
|
gl.clearDepth(0.0);
|
|
|
|
gl.depthMask(true);
|
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
2017-09-28 17:34:48 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
antialias(renderer: Renderer) {
|
2017-09-28 17:34:48 -04:00
|
|
|
// Detect edges if necessary.
|
2017-10-16 16:36:22 -04:00
|
|
|
this.detectEdgesIfNecessary(renderer);
|
2017-09-28 17:34:48 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
// Set up antialiasing.
|
2017-10-16 16:36:22 -04:00
|
|
|
this.prepareAA(renderer);
|
2017-09-28 17:34:48 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
// Clear.
|
2017-10-16 16:36:22 -04:00
|
|
|
this.clear(renderer);
|
2017-09-28 17:34:48 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
resolve(renderer: Renderer) {
|
2017-09-28 17:34:48 -04:00
|
|
|
// Resolve the antialiasing.
|
2017-10-16 16:36:22 -04:00
|
|
|
this.resolveAA(renderer);
|
2017-09-28 17:34:48 -04:00
|
|
|
}
|
|
|
|
|
2017-08-29 15:29:16 -04:00
|
|
|
get transform(): glmatrix.mat4 {
|
2017-08-26 16:47:18 -04:00
|
|
|
return glmatrix.mat4.create();
|
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected initDirectFramebuffer(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-21 01:04:53 -04:00
|
|
|
const gl = renderContext.gl;
|
|
|
|
|
|
|
|
let textureFormat;
|
|
|
|
if (this.directRenderingMode === 'pathID')
|
|
|
|
textureFormat = gl.RGBA;
|
|
|
|
else
|
|
|
|
textureFormat = renderContext.colorAlphaFormat;
|
|
|
|
|
|
|
|
this.directTexture = createFramebufferColorTexture(gl,
|
|
|
|
this.destFramebufferSize,
|
|
|
|
textureFormat);
|
|
|
|
this.directFramebuffer = createFramebuffer(renderContext.gl,
|
|
|
|
this.directTexture,
|
|
|
|
this.directDepthTexture);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected supersampledUsedSize(renderer: Renderer): glmatrix.vec2 {
|
2017-09-28 17:34:48 -04:00
|
|
|
const usedSize = glmatrix.vec2.create();
|
2017-10-16 16:36:22 -04:00
|
|
|
glmatrix.vec2.mul(usedSize, renderer.destUsedSize, this.supersampleScale);
|
2017-09-28 17:34:48 -04:00
|
|
|
return usedSize;
|
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected prepareAA(renderer: Renderer): void {
|
2017-10-09 17:14:24 -04:00
|
|
|
// Set state for antialiasing.
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-16 16:36:22 -04:00
|
|
|
const usedSize = this.supersampledUsedSize(renderer);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, this.aaFramebuffer);
|
|
|
|
renderContext.gl.viewport(0,
|
|
|
|
0,
|
|
|
|
this.supersampledFramebufferSize[0],
|
|
|
|
this.supersampledFramebufferSize[1]);
|
|
|
|
renderContext.gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
|
|
|
renderContext.gl.enable(renderContext.gl.SCISSOR_TEST);
|
2017-10-16 16:36:22 -04:00
|
|
|
|
|
|
|
this.createPathBoundsBufferTexture(renderer);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected setAAState(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-16 16:36:22 -04:00
|
|
|
const usedSize = this.supersampledUsedSize(renderer);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, this.aaFramebuffer);
|
|
|
|
renderContext.gl.viewport(0,
|
|
|
|
0,
|
|
|
|
this.supersampledFramebufferSize[0],
|
|
|
|
this.supersampledFramebufferSize[1]);
|
|
|
|
renderContext.gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
|
|
|
renderContext.gl.enable(renderContext.gl.SCISSOR_TEST);
|
2017-10-16 16:36:22 -04:00
|
|
|
|
|
|
|
this.setAADepthState(renderer);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-16 16:36:22 -04:00
|
|
|
renderer.setTransformSTUniform(uniforms, 0);
|
|
|
|
renderer.setFramebufferSizeUniform(uniforms);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderer.pathTransformBufferTextures[0].bind(renderContext.gl, uniforms, 0);
|
|
|
|
this.pathBoundsBufferTexture.bind(renderContext.gl, uniforms, 1);
|
2017-10-16 16:36:22 -04:00
|
|
|
renderer.setHintsUniform(uniforms);
|
|
|
|
}
|
|
|
|
|
2017-10-20 19:29:05 -04:00
|
|
|
protected resolveAA(renderer: Renderer) {
|
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
const gl = renderContext.gl;
|
|
|
|
|
|
|
|
// Set state for ECAA resolve.
|
|
|
|
const usedSize = renderer.destUsedSize;
|
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, renderer.destFramebuffer);
|
|
|
|
gl.viewport(0, 0, this.destFramebufferSize[0], this.destFramebufferSize[1]);
|
|
|
|
gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
|
|
|
gl.enable(gl.SCISSOR_TEST);
|
|
|
|
gl.disable(gl.DEPTH_TEST);
|
|
|
|
gl.disable(gl.BLEND);
|
|
|
|
|
|
|
|
// Clear out the resolve buffer, if necessary.
|
|
|
|
this.clearForResolve(renderer);
|
|
|
|
|
|
|
|
// Resolve.
|
|
|
|
const resolveProgram = this.getResolveProgram(renderContext);
|
|
|
|
gl.useProgram(resolveProgram.program);
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
|
|
|
|
renderer.setFramebufferSizeUniform(resolveProgram.uniforms);
|
|
|
|
gl.activeTexture(renderContext.gl.TEXTURE0);
|
|
|
|
gl.bindTexture(renderContext.gl.TEXTURE_2D, this.aaAlphaTexture);
|
|
|
|
gl.uniform1i(resolveProgram.uniforms.uAAAlpha, 0);
|
|
|
|
gl.uniform2i(resolveProgram.uniforms.uAAAlphaDimensions,
|
|
|
|
this.supersampledFramebufferSize[0],
|
|
|
|
this.supersampledFramebufferSize[1]);
|
|
|
|
if (renderer.bgColor != null)
|
|
|
|
gl.uniform4fv(resolveProgram.uniforms.uBGColor, renderer.bgColor);
|
|
|
|
if (renderer.fgColor != null)
|
|
|
|
gl.uniform4fv(resolveProgram.uniforms.uFGColor, renderer.fgColor);
|
|
|
|
renderer.setTransformSTAndTexScaleUniformsForDest(resolveProgram.uniforms);
|
|
|
|
gl.drawElements(renderContext.gl.TRIANGLES, 6, renderContext.gl.UNSIGNED_BYTE, 0);
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected abstract clear(renderer: Renderer): void;
|
2017-10-16 19:48:02 -04:00
|
|
|
protected abstract getResolveProgram(renderContext: RenderContext): PathfinderShaderProgram;
|
2017-10-16 16:36:22 -04:00
|
|
|
protected abstract initEdgeDetectFramebuffer(renderer: Renderer): void;
|
2017-10-16 19:48:02 -04:00
|
|
|
protected abstract createEdgeDetectVAO(renderContext: RenderContext): void;
|
2017-10-16 16:36:22 -04:00
|
|
|
protected abstract detectEdgesIfNecessary(renderer: Renderer): void;
|
|
|
|
protected abstract setAADepthState(renderer: Renderer): void;
|
|
|
|
protected abstract clearForResolve(renderer: Renderer): void;
|
|
|
|
|
|
|
|
private initAAAlphaFramebuffer(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
this.aaAlphaTexture = unwrapNull(renderContext.gl.createTexture());
|
|
|
|
renderContext.gl.activeTexture(renderContext.gl.TEXTURE0);
|
|
|
|
renderContext.gl.bindTexture(renderContext.gl.TEXTURE_2D, this.aaAlphaTexture);
|
|
|
|
renderContext.gl.texImage2D(renderContext.gl.TEXTURE_2D,
|
|
|
|
0,
|
|
|
|
renderContext.gl.RGB,
|
|
|
|
this.supersampledFramebufferSize[0],
|
|
|
|
this.supersampledFramebufferSize[1],
|
|
|
|
0,
|
|
|
|
renderContext.gl.RGB,
|
|
|
|
renderContext.textureHalfFloatExt.HALF_FLOAT_OES,
|
|
|
|
null);
|
|
|
|
setTextureParameters(renderContext.gl, renderContext.gl.NEAREST);
|
|
|
|
|
|
|
|
this.aaDepthTexture = createFramebufferDepthTexture(renderContext.gl,
|
2017-09-07 17:58:41 -04:00
|
|
|
this.supersampledFramebufferSize);
|
2017-08-29 01:11:15 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
this.aaFramebuffer = createFramebuffer(renderContext.gl,
|
2017-10-21 01:04:53 -04:00
|
|
|
this.aaAlphaTexture,
|
2017-08-29 01:11:15 -04:00
|
|
|
this.aaDepthTexture);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private createPathBoundsBufferTexture(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-16 16:36:22 -04:00
|
|
|
const pathBounds = renderer.pathBoundingRects(0);
|
2017-10-16 19:48:02 -04:00
|
|
|
this.pathBoundsBufferTexture = new PathfinderBufferTexture(renderContext.gl,
|
|
|
|
'uPathBounds');
|
|
|
|
this.pathBoundsBufferTexture.upload(renderContext.gl, pathBounds);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private createResolveVAO(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
this.resolveVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const resolveProgram = this.getResolveProgram(renderContext);
|
|
|
|
renderContext.gl.useProgram(resolveProgram.program);
|
|
|
|
renderContext.initQuadVAO(resolveProgram.attributes);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
protected get directDepthTexture(): WebGLTexture | null {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected get supersampleScale(): glmatrix.vec2 {
|
|
|
|
return glmatrix.vec2.fromValues(this.subpixelAA !== 'none' ? 3.0 : 1.0, 1.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export abstract class MCAAStrategy extends XCAAStrategy {
|
|
|
|
private coverVAO: WebGLVertexArrayObject;
|
|
|
|
private lineVAOs: FastEdgeVAOs;
|
|
|
|
private curveVAOs: FastEdgeVAOs;
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
attachMeshes(renderer: Renderer) {
|
|
|
|
super.attachMeshes(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.createCoverVAO(renderer);
|
|
|
|
this.createLineVAOs(renderer);
|
|
|
|
this.createCurveVAOs(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
antialias(renderer: Renderer) {
|
|
|
|
super.antialias(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
|
|
|
// Conservatively cover.
|
2017-10-16 16:36:22 -04:00
|
|
|
this.cover(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
|
|
|
// Antialias.
|
2017-10-16 16:36:22 -04:00
|
|
|
this.antialiasLines(renderer);
|
|
|
|
this.antialiasCurves(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected prepareAA(renderer: Renderer): void {
|
|
|
|
super.prepareAA(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setCoverDepthState(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD);
|
|
|
|
renderContext.gl.blendFunc(renderContext.gl.ONE, renderContext.gl.ONE);
|
|
|
|
renderContext.gl.enable(renderContext.gl.BLEND);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.clear(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected setCoverDepthState(renderer: Renderer): void {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private createCoverVAO(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
|
|
|
this.coverVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.coverVAO);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const coverProgram = renderContext.shaderPrograms.mcaaCover;
|
2017-08-26 16:47:18 -04:00
|
|
|
const attributes = coverProgram.attributes;
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(coverProgram.program);
|
2017-10-17 14:58:03 -04:00
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER,
|
|
|
|
renderContext.quadPositionsBuffer);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aQuadPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER,
|
|
|
|
renderer.meshes[0].edgeBoundingBoxVertexPositions);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aUpperLeftPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 4,
|
|
|
|
0);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aLowerRightPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 4,
|
|
|
|
FLOAT32_SIZE * 2);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER,
|
|
|
|
renderer.meshes[0].edgeBoundingBoxPathIDs);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aPathID,
|
|
|
|
1,
|
|
|
|
renderContext.gl.UNSIGNED_SHORT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aUpperLeftPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aLowerRightPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aPathID);
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aUpperLeftPosition, 1);
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aLowerRightPosition, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ELEMENT_ARRAY_BUFFER,
|
|
|
|
renderContext.quadElementsBuffer);
|
|
|
|
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-10-16 16:36:22 -04:00
|
|
|
}
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private createLineVAOs(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-16 16:36:22 -04:00
|
|
|
const vaos: Partial<FastEdgeVAOs> = {};
|
2017-10-16 19:48:02 -04:00
|
|
|
const lineProgram = renderContext.shaderPrograms.mcaaLine;
|
2017-10-16 16:36:22 -04:00
|
|
|
const attributes = lineProgram.attributes;
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
for (const direction of DIRECTIONS) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const lineVertexPositionsBuffer = {
|
|
|
|
lower: renderer.meshes[0].edgeLowerLineVertexPositions,
|
|
|
|
upper: renderer.meshes[0].edgeUpperLineVertexPositions,
|
|
|
|
}[direction];
|
|
|
|
const linePathIDsBuffer = {
|
|
|
|
lower: renderer.meshes[0].edgeLowerLinePathIDs,
|
|
|
|
upper: renderer.meshes[0].edgeUpperLinePathIDs,
|
|
|
|
}[direction];
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(lineProgram.program);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER,
|
|
|
|
renderContext.quadPositionsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aQuadPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, lineVertexPositionsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aLeftPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 4,
|
|
|
|
0);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aRightPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 4,
|
|
|
|
FLOAT32_SIZE * 2);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, linePathIDsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aPathID,
|
|
|
|
1,
|
|
|
|
renderContext.gl.UNSIGNED_SHORT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aRightPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aPathID);
|
|
|
|
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
|
|
|
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ELEMENT_ARRAY_BUFFER,
|
|
|
|
renderContext.quadElementsBuffer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
|
|
|
vaos[direction] = vao;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
this.lineVAOs = vaos as FastEdgeVAOs;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private createCurveVAOs(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-09 17:14:24 -04:00
|
|
|
const vaos: Partial<FastEdgeVAOs> = {};
|
2017-10-16 19:48:02 -04:00
|
|
|
const curveProgram = renderContext.shaderPrograms.mcaaCurve;
|
2017-08-26 16:47:18 -04:00
|
|
|
const attributes = curveProgram.attributes;
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
for (const direction of DIRECTIONS) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-06 19:11:53 -04:00
|
|
|
const curveVertexPositionsBuffer = {
|
2017-10-16 16:36:22 -04:00
|
|
|
lower: renderer.meshes[0].edgeLowerCurveVertexPositions,
|
|
|
|
upper: renderer.meshes[0].edgeUpperCurveVertexPositions,
|
2017-10-06 19:11:53 -04:00
|
|
|
}[direction];
|
|
|
|
const curvePathIDsBuffer = {
|
2017-10-16 16:36:22 -04:00
|
|
|
lower: renderer.meshes[0].edgeLowerCurvePathIDs,
|
|
|
|
upper: renderer.meshes[0].edgeUpperCurvePathIDs,
|
2017-08-26 16:47:18 -04:00
|
|
|
}[direction];
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(curveProgram.program);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER,
|
|
|
|
renderContext.quadPositionsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aQuadPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, curveVertexPositionsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aLeftPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 6,
|
|
|
|
0);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aControlPointPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 6,
|
|
|
|
FLOAT32_SIZE * 2);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aRightPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 6,
|
|
|
|
FLOAT32_SIZE * 4);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, curvePathIDsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aPathID,
|
|
|
|
1,
|
|
|
|
renderContext.gl.UNSIGNED_SHORT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aControlPointPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aRightPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aPathID);
|
|
|
|
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aControlPointPosition, 1);
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
|
|
|
|
2017-10-17 14:58:03 -04:00
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ELEMENT_ARRAY_BUFFER,
|
|
|
|
renderContext.quadElementsBuffer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
|
|
|
vaos[direction] = vao;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
this.curveVAOs = vaos as FastEdgeVAOs;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private cover(renderer: Renderer): void {
|
2017-08-26 16:47:18 -04:00
|
|
|
// Conservatively cover.
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
const coverProgram = renderContext.shaderPrograms.mcaaCover;
|
|
|
|
renderContext.gl.useProgram(coverProgram.program);
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.coverVAO);
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAUniforms(renderer, coverProgram.uniforms);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.drawElementsInstancedANGLE(renderContext.gl.TRIANGLES,
|
|
|
|
6,
|
|
|
|
renderContext.gl.UNSIGNED_BYTE,
|
|
|
|
0,
|
|
|
|
renderer.meshData[0].bQuadCount);
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private setBlendModeForAA(renderer: Renderer, direction: 'upper' | 'lower') {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD);
|
|
|
|
renderContext.gl.blendFunc(renderContext.gl.ONE, renderContext.gl.ONE);
|
|
|
|
renderContext.gl.enable(renderContext.gl.BLEND);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private antialiasLines(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAState(renderer);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const lineProgram = renderContext.shaderPrograms.mcaaLine;
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(lineProgram.program);
|
2017-08-26 16:47:18 -04:00
|
|
|
const uniforms = lineProgram.uniforms;
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAUniforms(renderer, uniforms);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
for (const direction of DIRECTIONS) {
|
|
|
|
const vao = this.lineVAOs[direction];
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setBlendModeForAA(renderer, direction);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.uniform1i(uniforms.uWinding, direction === 'upper' ? 1 : 0);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-08-26 16:47:18 -04:00
|
|
|
const count = {
|
2017-10-16 16:36:22 -04:00
|
|
|
lower: renderer.meshData[0].edgeLowerLineCount,
|
|
|
|
upper: renderer.meshData[0].edgeUpperLineCount,
|
2017-08-26 16:47:18 -04:00
|
|
|
}[direction];
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.drawElementsInstancedANGLE(renderContext.gl.TRIANGLES,
|
|
|
|
6,
|
|
|
|
renderContext.gl.UNSIGNED_BYTE,
|
|
|
|
0,
|
|
|
|
count);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private antialiasCurves(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAState(renderer);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const curveProgram = renderContext.shaderPrograms.mcaaCurve;
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(curveProgram.program);
|
2017-08-26 16:47:18 -04:00
|
|
|
const uniforms = curveProgram.uniforms;
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAUniforms(renderer, uniforms);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
for (const direction of DIRECTIONS) {
|
|
|
|
const vao = this.curveVAOs[direction];
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setBlendModeForAA(renderer, direction);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.uniform1i(uniforms.uWinding, direction === 'upper' ? 1 : 0);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-08-26 16:47:18 -04:00
|
|
|
const count = {
|
2017-10-16 16:36:22 -04:00
|
|
|
lower: renderer.meshData[0].edgeLowerCurveCount,
|
|
|
|
upper: renderer.meshData[0].edgeUpperCurveCount,
|
2017-08-26 16:47:18 -04:00
|
|
|
}[direction];
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.drawElementsInstancedANGLE(renderContext.gl.TRIANGLES,
|
|
|
|
6,
|
|
|
|
renderContext.gl.UNSIGNED_BYTE,
|
|
|
|
0,
|
|
|
|
count);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
export class ECAAStrategy extends XCAAStrategy {
|
2017-10-16 16:36:22 -04:00
|
|
|
private lineVAO: WebGLVertexArrayObject;
|
|
|
|
private curveVAO: WebGLVertexArrayObject;
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-21 01:04:53 -04:00
|
|
|
get directRenderingMode(): DirectRenderingMode {
|
|
|
|
return 'none';
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
attachMeshes(renderer: Renderer) {
|
|
|
|
super.attachMeshes(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.createLineVAO(renderer);
|
|
|
|
this.createCurveVAO(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
antialias(renderer: Renderer) {
|
|
|
|
super.antialias(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
|
|
|
// Antialias.
|
2017-10-16 16:36:22 -04:00
|
|
|
this.antialiasLines(renderer);
|
|
|
|
this.antialiasCurves(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap) {
|
|
|
|
super.setAAUniforms(renderer, uniforms);
|
2017-10-16 19:48:02 -04:00
|
|
|
|
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-16 16:36:22 -04:00
|
|
|
const emboldenAmount = renderer.emboldenAmount;
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.uniform2f(uniforms.uEmboldenAmount, emboldenAmount[0], emboldenAmount[1]);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
protected getResolveProgram(renderContext: RenderContext): PathfinderShaderProgram {
|
2017-10-09 17:14:24 -04:00
|
|
|
if (this.subpixelAA !== 'none')
|
2017-10-16 19:48:02 -04:00
|
|
|
return renderContext.shaderPrograms.xcaaMonoSubpixelResolve;
|
|
|
|
return renderContext.shaderPrograms.xcaaMonoResolve;
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected initEdgeDetectFramebuffer(renderer: Renderer) {}
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
protected createEdgeDetectVAO(renderContext: RenderContext) {}
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected detectEdgesIfNecessary(renderer: Renderer) {}
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected clear(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
renderContext.gl.clearDepth(0.0);
|
|
|
|
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT |
|
|
|
|
renderContext.gl.DEPTH_BUFFER_BIT);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected setAADepthState(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected clearForResolve(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private setBlendModeForAA(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.blendEquation(renderContext.gl.FUNC_ADD);
|
|
|
|
renderContext.gl.blendFunc(renderContext.gl.ONE, renderContext.gl.ONE);
|
|
|
|
renderContext.gl.enable(renderContext.gl.BLEND);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private createLineVAO(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
|
|
|
const lineProgram = renderContext.shaderPrograms.ecaaLine;
|
2017-10-09 17:14:24 -04:00
|
|
|
const attributes = lineProgram.attributes;
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const lineVertexPositionsBuffer = renderer.meshes[0].segmentLines;
|
|
|
|
const linePathIDsBuffer = renderer.meshes[0].segmentLinePathIDs;
|
|
|
|
const lineNormalsBuffer = renderer.meshes[0].segmentLineNormals;
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(lineProgram.program);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER,
|
|
|
|
renderContext.quadPositionsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aQuadPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, lineVertexPositionsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aLeftPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 4,
|
|
|
|
0);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aRightPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 4,
|
|
|
|
FLOAT32_SIZE * 2);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, linePathIDsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aPathID,
|
|
|
|
1,
|
|
|
|
renderContext.gl.UNSIGNED_SHORT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, lineNormalsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aLeftNormalAngle,
|
|
|
|
1,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 2,
|
|
|
|
0);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aRightNormalAngle,
|
|
|
|
1,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 2,
|
|
|
|
FLOAT32_SIZE);
|
|
|
|
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aRightPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aPathID);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aLeftNormalAngle);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aRightNormalAngle);
|
|
|
|
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftNormalAngle, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aRightNormalAngle, 1);
|
|
|
|
|
2017-10-17 14:58:03 -04:00
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ELEMENT_ARRAY_BUFFER,
|
|
|
|
renderContext.quadElementsBuffer);
|
2017-10-16 19:48:02 -04:00
|
|
|
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.lineVAO = vao;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private createCurveVAO(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
|
|
|
const curveProgram = renderContext.shaderPrograms.ecaaCurve;
|
2017-10-09 17:14:24 -04:00
|
|
|
const attributes = curveProgram.attributes;
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const curveVertexPositionsBuffer = renderer.meshes[0].segmentCurves;
|
|
|
|
const curvePathIDsBuffer = renderer.meshes[0].segmentCurvePathIDs;
|
|
|
|
const curveNormalsBuffer = renderer.meshes[0].segmentCurveNormals;
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(curveProgram.program);
|
2017-10-17 14:58:03 -04:00
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER,
|
|
|
|
renderContext.quadPositionsBuffer);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aQuadPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, curveVertexPositionsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aLeftPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 6,
|
|
|
|
0);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aControlPointPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 6,
|
|
|
|
FLOAT32_SIZE * 2);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aRightPosition,
|
|
|
|
2,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 6,
|
|
|
|
FLOAT32_SIZE * 4);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, curvePathIDsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aPathID,
|
|
|
|
1,
|
|
|
|
renderContext.gl.UNSIGNED_SHORT,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ARRAY_BUFFER, curveNormalsBuffer);
|
|
|
|
renderContext.gl.vertexAttribPointer(attributes.aNormalAngles,
|
|
|
|
3,
|
|
|
|
renderContext.gl.FLOAT,
|
|
|
|
false,
|
|
|
|
FLOAT32_SIZE * 3,
|
|
|
|
0);
|
|
|
|
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aControlPointPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aRightPosition);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aPathID);
|
|
|
|
renderContext.gl.enableVertexAttribArray(attributes.aNormalAngles);
|
|
|
|
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
|
|
|
|
renderContext.instancedArraysExt
|
|
|
|
.vertexAttribDivisorANGLE(attributes.aControlPointPosition, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
|
|
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aNormalAngles, 1);
|
|
|
|
|
|
|
|
renderContext.gl.bindBuffer(renderContext.gl.ELEMENT_ARRAY_BUFFER,
|
|
|
|
renderContext.quadElementsBuffer);
|
|
|
|
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.curveVAO = vao;
|
2017-09-05 15:48:08 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private antialiasLines(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAState(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const lineProgram = renderContext.shaderPrograms.ecaaLine;
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(lineProgram.program);
|
2017-10-09 17:14:24 -04:00
|
|
|
const uniforms = lineProgram.uniforms;
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAUniforms(renderer, uniforms);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const vao = this.lineVAO;
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setBlendModeForAA(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const count = renderer.meshData[0].segmentLineCount;
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.instancedArraysExt.drawElementsInstancedANGLE(renderContext.gl.TRIANGLES,
|
|
|
|
6,
|
|
|
|
renderContext.gl.UNSIGNED_BYTE,
|
|
|
|
0,
|
|
|
|
count);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private antialiasCurves(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAState(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const curveProgram = renderContext.shaderPrograms.ecaaCurve;
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.useProgram(curveProgram.program);
|
2017-10-09 17:14:24 -04:00
|
|
|
const uniforms = curveProgram.uniforms;
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setAAUniforms(renderer, uniforms);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const vao = this.curveVAO;
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
this.setBlendModeForAA(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
const count = renderer.meshData[0].segmentCurveCount;
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.instancedArraysExt.drawElementsInstancedANGLE(renderContext.gl.TRIANGLES,
|
|
|
|
6,
|
|
|
|
renderContext.gl.UNSIGNED_BYTE,
|
|
|
|
0,
|
|
|
|
count);
|
2017-10-09 17:14:24 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-09-07 17:58:41 -04:00
|
|
|
}
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
export class MCAAMonochromeStrategy extends MCAAStrategy {
|
2017-10-16 19:48:02 -04:00
|
|
|
protected getResolveProgram(renderContext: RenderContext): PathfinderShaderProgram {
|
2017-09-30 01:12:09 -04:00
|
|
|
if (this.subpixelAA !== 'none')
|
2017-10-16 19:48:02 -04:00
|
|
|
return renderContext.shaderPrograms.xcaaMonoSubpixelResolve;
|
|
|
|
return renderContext.shaderPrograms.xcaaMonoResolve;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected initEdgeDetectFramebuffer(renderer: Renderer) {}
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
protected createEdgeDetectVAO(renderContext: RenderContext) {}
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected detectEdgesIfNecessary(renderer: Renderer) {}
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected clear(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
renderContext.gl.clearDepth(0.0);
|
|
|
|
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT |
|
|
|
|
renderContext.gl.DEPTH_BUFFER_BIT);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected setAADepthState(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected clearForResolve(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-21 01:04:53 -04:00
|
|
|
get directRenderingMode(): DirectRenderingMode {
|
|
|
|
return 'none';
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-09 17:14:24 -04:00
|
|
|
/// Switches between the mesh-based MCAA and ECAA depending on whether stem darkening is enabled.
|
|
|
|
///
|
|
|
|
/// FIXME(pcwalton): Share textures and FBOs between the two strategies.
|
|
|
|
export class AdaptiveMonochromeXCAAStrategy implements AntialiasingStrategy {
|
|
|
|
private mcaaStrategy: MCAAMonochromeStrategy;
|
|
|
|
private ecaaStrategy: ECAAStrategy;
|
|
|
|
|
2017-10-21 01:04:53 -04:00
|
|
|
get directRenderingMode(): DirectRenderingMode {
|
|
|
|
return 'none';
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
constructor(level: number, subpixelAA: SubpixelAAType) {
|
|
|
|
this.mcaaStrategy = new MCAAMonochromeStrategy(level, subpixelAA);
|
|
|
|
this.ecaaStrategy = new ECAAStrategy(level, subpixelAA);
|
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
init(renderer: Renderer): void {
|
|
|
|
this.mcaaStrategy.init(renderer);
|
|
|
|
this.ecaaStrategy.init(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
attachMeshes(renderer: Renderer): void {
|
|
|
|
this.mcaaStrategy.attachMeshes(renderer);
|
|
|
|
this.ecaaStrategy.attachMeshes(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
setFramebufferSize(renderer: Renderer): void {
|
|
|
|
this.mcaaStrategy.setFramebufferSize(renderer);
|
|
|
|
this.ecaaStrategy.setFramebufferSize(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
get transform(): glmatrix.mat4 {
|
|
|
|
return this.mcaaStrategy.transform;
|
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
prepare(renderer: Renderer): void {
|
|
|
|
this.getAppropriateStrategy(renderer).prepare(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
antialias(renderer: Renderer): void {
|
|
|
|
this.getAppropriateStrategy(renderer).antialias(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
resolve(renderer: Renderer): void {
|
|
|
|
this.getAppropriateStrategy(renderer).resolve(renderer);
|
2017-10-09 17:14:24 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
private getAppropriateStrategy(renderer: Renderer): AntialiasingStrategy {
|
|
|
|
if (glmatrix.vec2.equals(renderer.emboldenAmount, [0.0, 0.0]))
|
2017-10-09 17:14:24 -04:00
|
|
|
return this.mcaaStrategy;
|
|
|
|
return this.ecaaStrategy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class MCAAMulticolorStrategy extends MCAAStrategy {
|
2017-09-28 17:34:48 -04:00
|
|
|
private _directDepthTexture: WebGLTexture;
|
|
|
|
|
|
|
|
private edgeDetectFramebuffer: WebGLFramebuffer;
|
|
|
|
private edgeDetectVAO: WebGLVertexArrayObject;
|
2017-10-20 19:29:05 -04:00
|
|
|
private edgePathIDTexture: WebGLTexture;
|
2017-09-28 17:34:48 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
protected getResolveProgram(renderContext: RenderContext): PathfinderShaderProgram {
|
|
|
|
return renderContext.shaderPrograms.xcaaMultiResolve;
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected initDirectFramebuffer(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
this._directDepthTexture = createFramebufferDepthTexture(renderContext.gl,
|
|
|
|
this.supersampledFramebufferSize);
|
2017-10-16 16:36:22 -04:00
|
|
|
super.initDirectFramebuffer(renderer);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected initEdgeDetectFramebuffer(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-20 19:29:05 -04:00
|
|
|
this.edgePathIDTexture = createFramebufferColorTexture(renderContext.gl,
|
|
|
|
this.supersampledFramebufferSize,
|
|
|
|
renderContext.gl.RGBA);
|
2017-10-16 19:48:02 -04:00
|
|
|
this.edgeDetectFramebuffer = createFramebuffer(renderContext.gl,
|
2017-10-21 01:04:53 -04:00
|
|
|
this.edgePathIDTexture,
|
2017-08-29 01:11:15 -04:00
|
|
|
this.aaDepthTexture);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
protected createEdgeDetectVAO(renderContext: RenderContext) {
|
|
|
|
this.edgeDetectVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.edgeDetectVAO);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
const edgeDetectProgram = renderContext.shaderPrograms.xcaaEdgeDetect;
|
|
|
|
renderContext.gl.useProgram(edgeDetectProgram.program);
|
|
|
|
renderContext.initQuadVAO(edgeDetectProgram.attributes);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected detectEdgesIfNecessary(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
2017-10-20 19:29:05 -04:00
|
|
|
const gl = renderContext.gl;
|
2017-10-16 19:48:02 -04:00
|
|
|
|
2017-08-26 16:47:18 -04:00
|
|
|
// Set state for edge detection.
|
2017-10-16 19:48:02 -04:00
|
|
|
const edgeDetectProgram = renderContext.shaderPrograms.xcaaEdgeDetect;
|
2017-10-20 19:29:05 -04:00
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.edgeDetectFramebuffer);
|
|
|
|
gl.viewport(0,
|
|
|
|
0,
|
|
|
|
this.supersampledFramebufferSize[0],
|
|
|
|
this.supersampledFramebufferSize[1]);
|
2017-10-16 16:36:22 -04:00
|
|
|
|
2017-10-20 19:29:05 -04:00
|
|
|
gl.depthMask(true);
|
|
|
|
gl.depthFunc(renderContext.gl.ALWAYS);
|
|
|
|
gl.enable(renderContext.gl.DEPTH_TEST);
|
|
|
|
gl.disable(renderContext.gl.BLEND);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-20 19:29:05 -04:00
|
|
|
gl.clearDepth(0.0);
|
|
|
|
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
2017-08-26 16:47:18 -04:00
|
|
|
|
|
|
|
// Perform edge detection.
|
2017-10-20 19:29:05 -04:00
|
|
|
gl.useProgram(edgeDetectProgram.program);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.edgeDetectVAO);
|
2017-10-16 16:36:22 -04:00
|
|
|
renderer.setFramebufferSizeUniform(edgeDetectProgram.uniforms);
|
|
|
|
renderer.setTransformSTAndTexScaleUniformsForDest(edgeDetectProgram.uniforms);
|
2017-10-20 19:29:05 -04:00
|
|
|
renderer.setPathColorsUniform(0, edgeDetectProgram.uniforms, 0);
|
|
|
|
gl.activeTexture(renderContext.gl.TEXTURE1);
|
2017-10-21 01:04:53 -04:00
|
|
|
gl.bindTexture(renderContext.gl.TEXTURE_2D, this.directTexture);
|
2017-10-20 19:29:05 -04:00
|
|
|
gl.uniform1i(edgeDetectProgram.uniforms.uPathID, 1);
|
|
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
|
|
|
|
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
|
|
|
|
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected resolveAA(renderer: Renderer) {
|
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
const gl = renderContext.gl;
|
|
|
|
|
|
|
|
// Set state for ECAA resolve.
|
|
|
|
const usedSize = renderer.destUsedSize;
|
|
|
|
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, renderer.destFramebuffer);
|
|
|
|
renderContext.gl.viewport(0, 0, this.destFramebufferSize[0], this.destFramebufferSize[1]);
|
|
|
|
renderContext.gl.scissor(0, 0, usedSize[0], usedSize[1]);
|
|
|
|
renderContext.gl.enable(renderContext.gl.SCISSOR_TEST);
|
|
|
|
renderContext.gl.disable(renderContext.gl.DEPTH_TEST);
|
|
|
|
renderContext.gl.disable(renderContext.gl.BLEND);
|
|
|
|
|
|
|
|
// Resolve.
|
|
|
|
const resolveProgram = this.getResolveProgram(renderContext);
|
|
|
|
renderContext.gl.useProgram(resolveProgram.program);
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
|
|
|
|
renderer.setFramebufferSizeUniform(resolveProgram.uniforms);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.activeTexture(renderContext.gl.TEXTURE0);
|
2017-10-20 19:29:05 -04:00
|
|
|
renderContext.gl.bindTexture(renderContext.gl.TEXTURE_2D, this.aaAlphaTexture);
|
|
|
|
renderContext.gl.uniform1i(resolveProgram.uniforms.uAAAlpha, 0);
|
|
|
|
renderContext.gl.uniform2i(resolveProgram.uniforms.uAAAlphaDimensions,
|
|
|
|
this.supersampledFramebufferSize[0],
|
|
|
|
this.supersampledFramebufferSize[1]);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.activeTexture(renderContext.gl.TEXTURE1);
|
2017-10-20 19:29:05 -04:00
|
|
|
renderContext.gl.bindTexture(renderContext.gl.TEXTURE_2D, this.edgePathIDTexture);
|
|
|
|
renderContext.gl.uniform1i(resolveProgram.uniforms.uBGFGPathID, 1);
|
|
|
|
renderer.setPathColorsUniform(0, resolveProgram.uniforms, 2);
|
|
|
|
renderer.setTransformSTAndTexScaleUniformsForDest(resolveProgram.uniforms);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.drawElements(renderContext.gl.TRIANGLES,
|
|
|
|
6,
|
|
|
|
renderContext.gl.UNSIGNED_BYTE,
|
|
|
|
0);
|
|
|
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
2017-10-20 19:29:05 -04:00
|
|
|
|
|
|
|
renderContext.gl.bindFramebuffer(renderContext.gl.FRAMEBUFFER, null);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected setCoverDepthState(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.depthMask(false);
|
2017-10-20 19:29:05 -04:00
|
|
|
renderContext.gl.depthFunc(renderContext.gl.EQUAL);
|
2017-10-16 19:48:02 -04:00
|
|
|
renderContext.gl.enable(renderContext.gl.DEPTH_TEST);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected clear(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
renderContext.gl.clear(renderContext.gl.COLOR_BUFFER_BIT);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected setAADepthState(renderer: Renderer) {
|
2017-10-16 19:48:02 -04:00
|
|
|
const renderContext = renderer.renderContext;
|
|
|
|
renderContext.gl.depthMask(false);
|
|
|
|
renderContext.gl.depthFunc(renderContext.gl.EQUAL);
|
|
|
|
renderContext.gl.enable(renderContext.gl.DEPTH_TEST);
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-10-16 16:36:22 -04:00
|
|
|
protected clearForResolve(renderer: Renderer) {}
|
2017-08-26 16:47:18 -04:00
|
|
|
|
2017-10-21 01:04:53 -04:00
|
|
|
get directRenderingMode(): DirectRenderingMode {
|
|
|
|
return 'pathID';
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|
|
|
|
|
2017-09-05 15:48:08 -04:00
|
|
|
protected get directDepthTexture(): WebGLTexture {
|
|
|
|
return this._directDepthTexture;
|
|
|
|
}
|
2017-08-26 16:47:18 -04:00
|
|
|
}
|