Add support for full 3D transforms, including rotation, to SVG in XCAA mode.
This commit is contained in:
parent
0e9144286e
commit
6942bb51ca
|
@ -21,7 +21,7 @@ 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, unwrapUndef} 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 {ECAAMulticolorStrategy} from './xcaa-strategy';
|
||||||
|
|
||||||
const MAX_PATHS: number = 65535;
|
const MAX_PATHS: number = 65535;
|
||||||
|
|
||||||
|
@ -232,6 +232,12 @@ export abstract class Renderer {
|
||||||
gl.uniform2f(uniforms.uTexScale, usedSize[0], usedSize[1]);
|
gl.uniform2f(uniforms.uTexScale, usedSize[0], usedSize[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTransformUniform(uniforms: UniformMap, objectIndex: number) {
|
||||||
|
const transform = glmatrix.mat4.clone(this.worldTransform);
|
||||||
|
glmatrix.mat4.mul(transform, transform, this.getModelviewTransform(objectIndex));
|
||||||
|
this.renderContext.gl.uniformMatrix4fv(uniforms.uTransform, false, transform);
|
||||||
|
}
|
||||||
|
|
||||||
setTransformSTUniform(uniforms: UniformMap, objectIndex: number): void {
|
setTransformSTUniform(uniforms: UniformMap, objectIndex: number): void {
|
||||||
// FIXME(pcwalton): Lossy conversion from a 4x4 matrix to an ST matrix is ugly and fragile.
|
// FIXME(pcwalton): Lossy conversion from a 4x4 matrix to an ST matrix is ugly and fragile.
|
||||||
// Refactor.
|
// Refactor.
|
||||||
|
@ -444,7 +450,7 @@ export abstract class Renderer {
|
||||||
this.pathTransformBufferTextures[meshIndex]
|
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 ECAAMulticolorStrategy;
|
||||||
strategy.bindEdgeDepthTexture(gl, directInteriorProgram.uniforms, 2);
|
strategy.bindEdgeDepthTexture(gl, directInteriorProgram.uniforms, 2);
|
||||||
}
|
}
|
||||||
const coverInteriorRange = getMeshIndexRange(meshes.coverInteriorIndexRanges, pathRange);
|
const coverInteriorRange = getMeshIndexRange(meshes.coverInteriorIndexRanges, pathRange);
|
||||||
|
@ -486,7 +492,7 @@ export abstract class Renderer {
|
||||||
this.setEmboldenAmountUniform(objectIndex, directCurveProgram.uniforms);
|
this.setEmboldenAmountUniform(objectIndex, directCurveProgram.uniforms);
|
||||||
this.pathTransformBufferTextures[meshIndex].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 ECAAMulticolorStrategy;
|
||||||
strategy.bindEdgeDepthTexture(gl, directCurveProgram.uniforms, 2);
|
strategy.bindEdgeDepthTexture(gl, directCurveProgram.uniforms, 2);
|
||||||
}
|
}
|
||||||
const coverCurveRange = getMeshIndexRange(meshes.coverCurveIndexRanges, pathRange);
|
const coverCurveRange = getMeshIndexRange(meshes.coverCurveIndexRanges, pathRange);
|
||||||
|
@ -687,12 +693,6 @@ export abstract class Renderer {
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, pathIDs, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, pathIDs, gl.STATIC_DRAW);
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTransformUniform(uniforms: UniformMap, objectIndex: number) {
|
|
||||||
const transform = glmatrix.mat4.clone(this.worldTransform);
|
|
||||||
glmatrix.mat4.mul(transform, transform, this.getModelviewTransform(objectIndex));
|
|
||||||
this.renderContext.gl.uniformMatrix4fv(uniforms.uTransform, false, transform);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMeshIndexRange(indexRanges: Range[], pathRange: Range): Range {
|
function getMeshIndexRange(indexRanges: Range[], pathRange: Range): Range {
|
||||||
|
|
|
@ -147,11 +147,11 @@ const SHADER_URLS: ShaderMap<ShaderProgramURLs> = {
|
||||||
},
|
},
|
||||||
xcaaMultiEdgeMaskCurve: {
|
xcaaMultiEdgeMaskCurve: {
|
||||||
fragment: "/glsl/gles2/xcaa-multi-edge-mask-curve.fs.glsl",
|
fragment: "/glsl/gles2/xcaa-multi-edge-mask-curve.fs.glsl",
|
||||||
vertex: "/glsl/gles2/mcaa-curve.vs.glsl",
|
vertex: "/glsl/gles2/ecaa-curve.vs.glsl",
|
||||||
},
|
},
|
||||||
xcaaMultiEdgeMaskLine: {
|
xcaaMultiEdgeMaskLine: {
|
||||||
fragment: "/glsl/gles2/xcaa-multi-edge-mask-line.fs.glsl",
|
fragment: "/glsl/gles2/xcaa-multi-edge-mask-line.fs.glsl",
|
||||||
vertex: "/glsl/gles2/mcaa-line.vs.glsl",
|
vertex: "/glsl/gles2/ecaa-line.vs.glsl",
|
||||||
},
|
},
|
||||||
xcaaMultiResolve: {
|
xcaaMultiResolve: {
|
||||||
fragment: "/glsl/gles2/xcaa-multi-resolve.fs.glsl",
|
fragment: "/glsl/gles2/xcaa-multi-resolve.fs.glsl",
|
||||||
|
@ -198,10 +198,13 @@ export class PathfinderShaderProgram {
|
||||||
readonly uniforms: UniformMap;
|
readonly uniforms: UniformMap;
|
||||||
readonly attributes: AttributeMap;
|
readonly attributes: AttributeMap;
|
||||||
readonly program: WebGLProgram;
|
readonly program: WebGLProgram;
|
||||||
|
readonly programName: string;
|
||||||
|
|
||||||
constructor(gl: WebGLRenderingContext,
|
constructor(gl: WebGLRenderingContext,
|
||||||
programName: string,
|
programName: string,
|
||||||
unlinkedShaderProgram: UnlinkedShaderProgram) {
|
unlinkedShaderProgram: UnlinkedShaderProgram) {
|
||||||
|
this.programName = programName;
|
||||||
|
|
||||||
this.program = expectNotNull(gl.createProgram(), "Failed to create shader program!");
|
this.program = expectNotNull(gl.createProgram(), "Failed to create shader program!");
|
||||||
for (const compiledShader of Object.values(unlinkedShaderProgram))
|
for (const compiledShader of Object.values(unlinkedShaderProgram))
|
||||||
gl.attachShader(this.program, compiledShader);
|
gl.attachShader(this.program, compiledShader);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import SSAAStrategy from "./ssaa-strategy";
|
||||||
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
|
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
|
||||||
import {panic, Range, 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 {ECAAMulticolorStrategy, XCAAStrategy} from "./xcaa-strategy";
|
||||||
|
|
||||||
const parseColor = require('parse-color');
|
const parseColor = require('parse-color');
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ const DEFAULT_FILE: string = 'tiger';
|
||||||
const ANTIALIASING_STRATEGIES: AntialiasingStrategyTable = {
|
const ANTIALIASING_STRATEGIES: AntialiasingStrategyTable = {
|
||||||
none: NoAAStrategy,
|
none: NoAAStrategy,
|
||||||
ssaa: SSAAStrategy,
|
ssaa: SSAAStrategy,
|
||||||
xcaa: MCAAMulticolorStrategy,
|
xcaa: ECAAMulticolorStrategy,
|
||||||
};
|
};
|
||||||
|
|
||||||
interface AntialiasingStrategyTable {
|
interface AntialiasingStrategyTable {
|
||||||
|
@ -82,7 +82,7 @@ class SVGDemoController extends DemoAppController<SVGDemoView> {
|
||||||
private meshesReceived(): void {
|
private meshesReceived(): void {
|
||||||
this.view.then(view => {
|
this.view.then(view => {
|
||||||
view.attachMeshes([this.meshes]);
|
view.attachMeshes([this.meshes]);
|
||||||
view.initCameraBounds(this.loader.bounds);
|
view.initCameraBounds(this.loader.svgBounds);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,8 +157,11 @@ class SVGDemoRenderer extends Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pathBoundingRects(objectIndex: number): Float32Array {
|
pathBoundingRects(objectIndex: number): Float32Array {
|
||||||
// TODO
|
const loader = this.renderContext.appController.loader;
|
||||||
return new Float32Array(0);
|
const boundingRectsBuffer = new Float32Array((loader.pathBounds.length + 1) * 4);
|
||||||
|
for (let pathIndex = 0; pathIndex < loader.pathBounds.length; pathIndex++)
|
||||||
|
boundingRectsBuffer.set(loader.pathBounds[pathIndex], (pathIndex + 1) * 4);
|
||||||
|
return boundingRectsBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(meshes: PathfinderMeshData[]): void {
|
attachMeshes(meshes: PathfinderMeshData[]): void {
|
||||||
|
@ -203,13 +206,11 @@ class SVGDemoRenderer extends Renderer {
|
||||||
glmatrix.mat4.translate(transform, transform, [-1.0, -1.0, 0.0]);
|
glmatrix.mat4.translate(transform, transform, [-1.0, -1.0, 0.0]);
|
||||||
glmatrix.mat4.scale(transform, transform, [2.0 / canvas.width, 2.0 / canvas.height, 1.0]);
|
glmatrix.mat4.scale(transform, transform, [2.0 / canvas.width, 2.0 / canvas.height, 1.0]);
|
||||||
|
|
||||||
if (!(this.antialiasingStrategy instanceof XCAAStrategy)) {
|
const centerPoint = glmatrix.vec3.clone([canvas.width * 0.5, canvas.height * 0.5, 0.0]);
|
||||||
const centerPoint = glmatrix.vec3.clone([canvas.width * 0.5, canvas.height * 0.5, 0.0]);
|
glmatrix.mat4.translate(transform, transform, centerPoint);
|
||||||
glmatrix.mat4.translate(transform, transform, centerPoint);
|
glmatrix.mat4.rotateZ(transform, transform, this.camera.rotationAngle);
|
||||||
glmatrix.mat4.rotateZ(transform, transform, this.camera.rotationAngle);
|
glmatrix.vec3.negate(centerPoint, centerPoint);
|
||||||
glmatrix.vec3.negate(centerPoint, centerPoint);
|
glmatrix.mat4.translate(transform, transform, centerPoint);
|
||||||
glmatrix.mat4.translate(transform, transform, centerPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
const translation = this.camera.translation;
|
const translation = this.camera.translation;
|
||||||
glmatrix.mat4.translate(transform, transform, [translation[0], translation[1], 0]);
|
glmatrix.mat4.translate(transform, transform, [translation[0], translation[1], 0]);
|
||||||
|
|
|
@ -74,7 +74,8 @@ export class SVGLoader {
|
||||||
renderTasks: RenderTask[];
|
renderTasks: RenderTask[];
|
||||||
pathInstances: SVGPath[];
|
pathInstances: SVGPath[];
|
||||||
scale: number;
|
scale: number;
|
||||||
bounds: glmatrix.vec4;
|
pathBounds: glmatrix.vec4[];
|
||||||
|
svgBounds: glmatrix.vec4;
|
||||||
|
|
||||||
private svg: SVGSVGElement;
|
private svg: SVGSVGElement;
|
||||||
private fileData: ArrayBuffer;
|
private fileData: ArrayBuffer;
|
||||||
|
@ -86,8 +87,8 @@ export class SVGLoader {
|
||||||
this.scale = 1.0;
|
this.scale = 1.0;
|
||||||
this.renderTasks = [];
|
this.renderTasks = [];
|
||||||
this.pathInstances = [];
|
this.pathInstances = [];
|
||||||
this.paths = [];
|
this.pathBounds = [];
|
||||||
this.bounds = glmatrix.vec4.create();
|
this.svgBounds = glmatrix.vec4.create();
|
||||||
this.svg = unwrapNull(document.getElementById('pf-svg')) as Element as SVGSVGElement;
|
this.svg = unwrapNull(document.getElementById('pf-svg')) as Element as SVGSVGElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,10 +134,10 @@ export class SVGLoader {
|
||||||
this.scanElement(this.svg);
|
this.scanElement(this.svg);
|
||||||
this.popTopRenderTaskIfEmpty();
|
this.popTopRenderTaskIfEmpty();
|
||||||
|
|
||||||
let minX = 0, minY = 0, maxX = 0, maxY = 0;
|
|
||||||
this.paths = [];
|
this.paths = [];
|
||||||
|
|
||||||
// Extract, normalize, and transform the path data.
|
const svgBottomLeft = glmatrix.vec2.create(), svgTopRight = glmatrix.vec2.create();
|
||||||
|
|
||||||
for (const instance of this.pathInstances) {
|
for (const instance of this.pathInstances) {
|
||||||
const element = instance.element;
|
const element = instance.element;
|
||||||
const svgCTM = element.getCTM();
|
const svgCTM = element.getCTM();
|
||||||
|
@ -146,15 +147,16 @@ export class SVGLoader {
|
||||||
glmatrix.mat2d.scale(ctm, ctm, [1.0, -1.0]);
|
glmatrix.mat2d.scale(ctm, ctm, [1.0, -1.0]);
|
||||||
glmatrix.mat2d.scale(ctm, ctm, [this.scale, this.scale]);
|
glmatrix.mat2d.scale(ctm, ctm, [this.scale, this.scale]);
|
||||||
|
|
||||||
|
const bottomLeft = glmatrix.vec2.create();
|
||||||
|
const topRight = glmatrix.vec2.create();
|
||||||
|
|
||||||
const segments = element.getPathData({ normalize: true }).map(segment => {
|
const segments = element.getPathData({ normalize: true }).map(segment => {
|
||||||
const newValues = _.flatMap(_.chunk(segment.values, 2), coords => {
|
const newValues = _.flatMap(_.chunk(segment.values, 2), coords => {
|
||||||
const point = glmatrix.vec2.create();
|
const point = glmatrix.vec2.create();
|
||||||
glmatrix.vec2.transformMat2d(point, coords, ctm);
|
glmatrix.vec2.transformMat2d(point, coords, ctm);
|
||||||
|
|
||||||
minX = Math.min(point[0], minX);
|
glmatrix.vec2.min(bottomLeft, bottomLeft, point);
|
||||||
minY = Math.min(point[1], minY);
|
glmatrix.vec2.max(topRight, topRight, point);
|
||||||
maxX = Math.max(point[0], maxX);
|
|
||||||
maxY = Math.max(point[1], maxY);
|
|
||||||
|
|
||||||
return [point[0], point[1]];
|
return [point[0], point[1]];
|
||||||
});
|
});
|
||||||
|
@ -164,17 +166,30 @@ export class SVGLoader {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const pathBounds = glmatrix.vec4.clone([
|
||||||
|
bottomLeft[0], bottomLeft[1],
|
||||||
|
topRight[0], topRight[1],
|
||||||
|
]);
|
||||||
|
|
||||||
|
glmatrix.vec2.min(svgBottomLeft, svgBottomLeft, bottomLeft);
|
||||||
|
glmatrix.vec2.max(svgTopRight, svgTopRight, topRight);
|
||||||
|
|
||||||
if (instance instanceof SVGFill) {
|
if (instance instanceof SVGFill) {
|
||||||
this.paths.push({ segments: segments, kind: 'Fill' });
|
this.paths.push({ segments: segments, kind: 'Fill' });
|
||||||
|
this.pathBounds.push(pathBounds);
|
||||||
} else if (instance instanceof SVGStroke) {
|
} else if (instance instanceof SVGStroke) {
|
||||||
this.paths.push({
|
this.paths.push({
|
||||||
kind: { Stroke: Math.max(HAIRLINE_STROKE_WIDTH, instance.width) },
|
kind: { Stroke: Math.max(HAIRLINE_STROKE_WIDTH, instance.width) },
|
||||||
segments: segments,
|
segments: segments,
|
||||||
});
|
});
|
||||||
|
this.pathBounds.push(pathBounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bounds = glmatrix.vec4.clone([minX, minY, maxX, maxY]);
|
this.svgBounds = glmatrix.vec4.clone([
|
||||||
|
svgBottomLeft[0], svgBottomLeft[1],
|
||||||
|
svgTopRight[0], svgTopRight[1],
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private scanElement(element: Element): void {
|
private scanElement(element: Element): void {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {createFramebufferDepthTexture, setTextureParameters, UniformMap} from '.
|
||||||
import {WebGLVertexArrayObject} from './gl-utils';
|
import {WebGLVertexArrayObject} from './gl-utils';
|
||||||
import {B_QUAD_LOWER_INDICES_OFFSET, B_QUAD_SIZE, B_QUAD_UPPER_INDICES_OFFSET} from './meshes';
|
import {B_QUAD_LOWER_INDICES_OFFSET, B_QUAD_SIZE, B_QUAD_UPPER_INDICES_OFFSET} from './meshes';
|
||||||
import {Renderer} from './renderer';
|
import {Renderer} from './renderer';
|
||||||
import {PathfinderShaderProgram} from './shader-loader';
|
import {PathfinderShaderProgram, ShaderMap} from './shader-loader';
|
||||||
import {computeStemDarkeningAmount} from './text';
|
import {computeStemDarkeningAmount} from './text';
|
||||||
import {assert, FLOAT32_SIZE, lerp, Range, UINT16_SIZE, UINT32_SIZE, unwrapNull} from './utils';
|
import {assert, FLOAT32_SIZE, lerp, Range, UINT16_SIZE, UINT32_SIZE, unwrapNull} from './utils';
|
||||||
import {unwrapUndef} from './utils';
|
import {unwrapUndef} from './utils';
|
||||||
|
@ -36,6 +36,8 @@ const DIRECTIONS: Direction[] = ['upper', 'lower'];
|
||||||
export abstract class XCAAStrategy extends AntialiasingStrategy {
|
export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
abstract readonly directRenderingMode: DirectRenderingMode;
|
abstract readonly directRenderingMode: DirectRenderingMode;
|
||||||
|
|
||||||
|
protected abstract get usesDilationTransforms(): boolean;
|
||||||
|
|
||||||
protected pathBoundsBufferTexture: PathfinderBufferTexture;
|
protected pathBoundsBufferTexture: PathfinderBufferTexture;
|
||||||
|
|
||||||
protected supersampledFramebufferSize: glmatrix.vec2;
|
protected supersampledFramebufferSize: glmatrix.vec2;
|
||||||
|
@ -225,7 +227,11 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
renderer.setTransformSTUniform(uniforms, 0);
|
if (this.usesDilationTransforms)
|
||||||
|
renderer.setTransformSTUniform(uniforms, 0);
|
||||||
|
else
|
||||||
|
renderer.setTransformUniform(uniforms, 0);
|
||||||
|
|
||||||
gl.uniform2i(uniforms.uFramebufferSize,
|
gl.uniform2i(uniforms.uFramebufferSize,
|
||||||
this.supersampledFramebufferSize[0],
|
this.supersampledFramebufferSize[0],
|
||||||
this.supersampledFramebufferSize[1]);
|
this.supersampledFramebufferSize[1]);
|
||||||
|
@ -746,9 +752,12 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ECAAStrategy extends XCAAStrategy {
|
export abstract class ECAAStrategy extends XCAAStrategy {
|
||||||
private lineVAO: WebGLVertexArrayObject;
|
protected abstract get lineShaderProgramNames(): Array<keyof ShaderMap<void>>;
|
||||||
private curveVAO: WebGLVertexArrayObject;
|
protected abstract get curveShaderProgramNames(): Array<keyof ShaderMap<void>>;
|
||||||
|
|
||||||
|
private lineVAOs: Partial<ShaderMap<WebGLVertexArrayObject>>;
|
||||||
|
private curveVAOs: Partial<ShaderMap<WebGLVertexArrayObject>>;
|
||||||
|
|
||||||
get directRenderingMode(): DirectRenderingMode {
|
get directRenderingMode(): DirectRenderingMode {
|
||||||
return 'none';
|
return 'none';
|
||||||
|
@ -757,16 +766,23 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
attachMeshes(renderer: Renderer): void {
|
attachMeshes(renderer: Renderer): void {
|
||||||
super.attachMeshes(renderer);
|
super.attachMeshes(renderer);
|
||||||
|
|
||||||
this.createLineVAO(renderer);
|
this.createLineVAOs(renderer);
|
||||||
this.createCurveVAO(renderer);
|
this.createCurveVAOs(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialiasObject(renderer: Renderer, objectIndex: number): void {
|
antialiasObject(renderer: Renderer, objectIndex: number): void {
|
||||||
super.antialiasObject(renderer, objectIndex);
|
super.antialiasObject(renderer, objectIndex);
|
||||||
|
|
||||||
// Antialias.
|
// Antialias.
|
||||||
this.antialiasLinesOfObject(renderer, objectIndex);
|
const shaderPrograms = renderer.renderContext.shaderPrograms;
|
||||||
this.antialiasCurvesOfObject(renderer, objectIndex);
|
this.setAAState(renderer);
|
||||||
|
this.setBlendModeForAA(renderer);
|
||||||
|
this.antialiasLinesOfObjectWithProgram(renderer,
|
||||||
|
objectIndex,
|
||||||
|
this.lineShaderProgramNames[0]);
|
||||||
|
this.antialiasCurvesOfObjectWithProgram(renderer,
|
||||||
|
objectIndex,
|
||||||
|
this.curveShaderProgramNames[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap, objectIndex: number): void {
|
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap, objectIndex: number): void {
|
||||||
|
@ -804,140 +820,10 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setBlendModeForAA(renderer: Renderer): void {
|
protected antialiasLinesOfObjectWithProgram(renderer: Renderer,
|
||||||
const renderContext = renderer.renderContext;
|
objectIndex: number,
|
||||||
const gl = renderContext.gl;
|
programName: keyof ShaderMap<void>):
|
||||||
|
void {
|
||||||
gl.blendEquation(gl.FUNC_ADD);
|
|
||||||
gl.blendFunc(gl.ONE, gl.ONE);
|
|
||||||
gl.enable(gl.BLEND);
|
|
||||||
}
|
|
||||||
|
|
||||||
private createLineVAO(renderer: Renderer): void {
|
|
||||||
if (renderer.meshes == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const renderContext = renderer.renderContext;
|
|
||||||
const gl = renderContext.gl;
|
|
||||||
|
|
||||||
const lineProgram = renderContext.shaderPrograms.ecaaLine;
|
|
||||||
const attributes = lineProgram.attributes;
|
|
||||||
|
|
||||||
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
|
||||||
|
|
||||||
const lineVertexPositionsBuffer = renderer.meshes[0].segmentLines;
|
|
||||||
const linePathIDsBuffer = renderer.meshes[0].segmentLinePathIDs;
|
|
||||||
const lineNormalsBuffer = renderer.meshes[0].segmentLineNormals;
|
|
||||||
|
|
||||||
gl.useProgram(lineProgram.program);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, renderContext.quadPositionsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aQuadPosition, 2, gl.FLOAT, false, 0, 0);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, lineVertexPositionsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aLeftPosition, 2, gl.FLOAT, false, FLOAT32_SIZE * 4, 0);
|
|
||||||
gl.vertexAttribPointer(attributes.aRightPosition,
|
|
||||||
2,
|
|
||||||
gl.FLOAT,
|
|
||||||
false,
|
|
||||||
FLOAT32_SIZE * 4,
|
|
||||||
FLOAT32_SIZE * 2);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, linePathIDsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aPathID, 1, gl.UNSIGNED_SHORT, false, 0, 0);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, lineNormalsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aLeftNormalAngle,
|
|
||||||
1,
|
|
||||||
gl.FLOAT,
|
|
||||||
false,
|
|
||||||
FLOAT32_SIZE * 2,
|
|
||||||
0);
|
|
||||||
gl.vertexAttribPointer(attributes.aRightNormalAngle,
|
|
||||||
1,
|
|
||||||
gl.FLOAT,
|
|
||||||
false,
|
|
||||||
FLOAT32_SIZE * 2,
|
|
||||||
FLOAT32_SIZE);
|
|
||||||
|
|
||||||
gl.enableVertexAttribArray(attributes.aQuadPosition);
|
|
||||||
gl.enableVertexAttribArray(attributes.aLeftPosition);
|
|
||||||
gl.enableVertexAttribArray(attributes.aRightPosition);
|
|
||||||
gl.enableVertexAttribArray(attributes.aPathID);
|
|
||||||
gl.enableVertexAttribArray(attributes.aLeftNormalAngle);
|
|
||||||
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);
|
|
||||||
|
|
||||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
|
|
||||||
|
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
|
||||||
|
|
||||||
this.lineVAO = vao;
|
|
||||||
}
|
|
||||||
|
|
||||||
private createCurveVAO(renderer: Renderer): void {
|
|
||||||
if (renderer.meshes == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const renderContext = renderer.renderContext;
|
|
||||||
const gl = renderContext.gl;
|
|
||||||
|
|
||||||
const curveProgram = renderContext.shaderPrograms.ecaaCurve;
|
|
||||||
const attributes = curveProgram.attributes;
|
|
||||||
|
|
||||||
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
|
||||||
|
|
||||||
const curveVertexPositionsBuffer = renderer.meshes[0].segmentCurves;
|
|
||||||
const curvePathIDsBuffer = renderer.meshes[0].segmentCurvePathIDs;
|
|
||||||
const curveNormalsBuffer = renderer.meshes[0].segmentCurveNormals;
|
|
||||||
|
|
||||||
gl.useProgram(curveProgram.program);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, renderContext.quadPositionsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aQuadPosition, 2, gl.FLOAT, false, 0, 0);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, curveVertexPositionsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aLeftPosition, 2, gl.FLOAT, false, FLOAT32_SIZE * 6, 0);
|
|
||||||
gl.vertexAttribPointer(attributes.aControlPointPosition,
|
|
||||||
2,
|
|
||||||
gl.FLOAT,
|
|
||||||
false,
|
|
||||||
FLOAT32_SIZE * 6,
|
|
||||||
FLOAT32_SIZE * 2);
|
|
||||||
gl.vertexAttribPointer(attributes.aRightPosition,
|
|
||||||
2,
|
|
||||||
gl.FLOAT,
|
|
||||||
false,
|
|
||||||
FLOAT32_SIZE * 6,
|
|
||||||
FLOAT32_SIZE * 4);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, curvePathIDsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aPathID, 1, gl.UNSIGNED_SHORT, false, 0, 0);
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, curveNormalsBuffer);
|
|
||||||
gl.vertexAttribPointer(attributes.aNormalAngles, 3, gl.FLOAT, false, FLOAT32_SIZE * 3, 0);
|
|
||||||
|
|
||||||
gl.enableVertexAttribArray(attributes.aQuadPosition);
|
|
||||||
gl.enableVertexAttribArray(attributes.aLeftPosition);
|
|
||||||
gl.enableVertexAttribArray(attributes.aControlPointPosition);
|
|
||||||
gl.enableVertexAttribArray(attributes.aRightPosition);
|
|
||||||
gl.enableVertexAttribArray(attributes.aPathID);
|
|
||||||
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);
|
|
||||||
|
|
||||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
|
|
||||||
|
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
|
||||||
|
|
||||||
this.curveVAO = vao;
|
|
||||||
}
|
|
||||||
|
|
||||||
private antialiasLinesOfObject(renderer: Renderer, objectIndex: number): void {
|
|
||||||
if (renderer.meshData == null)
|
if (renderer.meshData == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -947,19 +833,14 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
const pathRange = renderer.pathRangeForObject(objectIndex);
|
const pathRange = renderer.pathRangeForObject(objectIndex);
|
||||||
const meshIndex = renderer.meshIndexForObject(objectIndex);
|
const meshIndex = renderer.meshIndexForObject(objectIndex);
|
||||||
|
|
||||||
this.setAAState(renderer);
|
const lineProgram = renderContext.shaderPrograms[programName];
|
||||||
|
|
||||||
const lineProgram = renderContext.shaderPrograms.ecaaLine;
|
|
||||||
|
|
||||||
gl.useProgram(lineProgram.program);
|
gl.useProgram(lineProgram.program);
|
||||||
const uniforms = lineProgram.uniforms;
|
const uniforms = lineProgram.uniforms;
|
||||||
this.setAAUniforms(renderer, uniforms, objectIndex);
|
this.setAAUniforms(renderer, uniforms, objectIndex);
|
||||||
|
|
||||||
const vao = this.lineVAO;
|
const vao = this.lineVAOs[programName];
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
||||||
|
|
||||||
this.setBlendModeForAA(renderer);
|
|
||||||
|
|
||||||
// FIXME(pcwalton): Only render the appropriate instances.
|
// FIXME(pcwalton): Only render the appropriate instances.
|
||||||
const count = renderer.meshData[meshIndex].segmentLineCount;
|
const count = renderer.meshData[meshIndex].segmentLineCount;
|
||||||
renderContext.instancedArraysExt
|
renderContext.instancedArraysExt
|
||||||
|
@ -968,7 +849,10 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private antialiasCurvesOfObject(renderer: Renderer, objectIndex: number): void {
|
protected antialiasCurvesOfObjectWithProgram(renderer: Renderer,
|
||||||
|
objectIndex: number,
|
||||||
|
programName: keyof ShaderMap<void>):
|
||||||
|
void {
|
||||||
if (renderer.meshData == null)
|
if (renderer.meshData == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -978,19 +862,14 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
const pathRange = renderer.pathRangeForObject(objectIndex);
|
const pathRange = renderer.pathRangeForObject(objectIndex);
|
||||||
const meshIndex = renderer.meshIndexForObject(objectIndex);
|
const meshIndex = renderer.meshIndexForObject(objectIndex);
|
||||||
|
|
||||||
this.setAAState(renderer);
|
const curveProgram = renderContext.shaderPrograms[programName];
|
||||||
|
|
||||||
const curveProgram = renderContext.shaderPrograms.ecaaCurve;
|
|
||||||
|
|
||||||
gl.useProgram(curveProgram.program);
|
gl.useProgram(curveProgram.program);
|
||||||
const uniforms = curveProgram.uniforms;
|
const uniforms = curveProgram.uniforms;
|
||||||
this.setAAUniforms(renderer, uniforms, objectIndex);
|
this.setAAUniforms(renderer, uniforms, objectIndex);
|
||||||
|
|
||||||
const vao = this.curveVAO;
|
const vao = this.curveVAOs[programName];
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
||||||
|
|
||||||
this.setBlendModeForAA(renderer);
|
|
||||||
|
|
||||||
// FIXME(pcwalton): Only render the appropriate instances.
|
// FIXME(pcwalton): Only render the appropriate instances.
|
||||||
const count = renderer.meshData[meshIndex].segmentCurveCount;
|
const count = renderer.meshData[meshIndex].segmentCurveCount;
|
||||||
renderContext.instancedArraysExt
|
renderContext.instancedArraysExt
|
||||||
|
@ -998,9 +877,198 @@ export class ECAAStrategy extends XCAAStrategy {
|
||||||
|
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setBlendModeForAA(renderer: Renderer): void {
|
||||||
|
const renderContext = renderer.renderContext;
|
||||||
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
gl.blendEquation(gl.FUNC_ADD);
|
||||||
|
gl.blendFunc(gl.ONE, gl.ONE);
|
||||||
|
gl.enable(gl.BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createLineVAOs(renderer: Renderer): void {
|
||||||
|
if (renderer.meshes == null || renderer.meshData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const renderContext = renderer.renderContext;
|
||||||
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
this.lineVAOs = {};
|
||||||
|
|
||||||
|
for (const programName of this.lineShaderProgramNames) {
|
||||||
|
const lineProgram = renderContext.shaderPrograms[programName];
|
||||||
|
const attributes = lineProgram.attributes;
|
||||||
|
|
||||||
|
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
||||||
|
|
||||||
|
const lineVertexPositionsBuffer = renderer.meshes[0].segmentLines;
|
||||||
|
const linePathIDsBuffer = renderer.meshes[0].segmentLinePathIDs;
|
||||||
|
const lineNormalsBuffer = renderer.meshes[0].segmentLineNormals;
|
||||||
|
|
||||||
|
gl.useProgram(lineProgram.program);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, renderContext.quadPositionsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aQuadPosition, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, lineVertexPositionsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aLeftPosition,
|
||||||
|
2,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 4,
|
||||||
|
0);
|
||||||
|
gl.vertexAttribPointer(attributes.aRightPosition,
|
||||||
|
2,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 4,
|
||||||
|
FLOAT32_SIZE * 2);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, linePathIDsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aPathID, 1, gl.UNSIGNED_SHORT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||||
|
gl.enableVertexAttribArray(attributes.aLeftPosition);
|
||||||
|
gl.enableVertexAttribArray(attributes.aRightPosition);
|
||||||
|
gl.enableVertexAttribArray(attributes.aPathID);
|
||||||
|
|
||||||
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
|
||||||
|
renderContext.instancedArraysExt
|
||||||
|
.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
|
||||||
|
renderContext.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
||||||
|
|
||||||
|
if (renderer.meshData[0].segmentLineNormals.byteLength > 0) {
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, lineNormalsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aLeftNormalAngle,
|
||||||
|
1,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 2,
|
||||||
|
0);
|
||||||
|
gl.vertexAttribPointer(attributes.aRightNormalAngle,
|
||||||
|
1,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 2,
|
||||||
|
FLOAT32_SIZE);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(attributes.aLeftNormalAngle);
|
||||||
|
gl.enableVertexAttribArray(attributes.aRightNormalAngle);
|
||||||
|
|
||||||
|
renderContext.instancedArraysExt
|
||||||
|
.vertexAttribDivisorANGLE(attributes.aLeftNormalAngle, 1);
|
||||||
|
renderContext.instancedArraysExt
|
||||||
|
.vertexAttribDivisorANGLE(attributes.aRightNormalAngle, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
|
||||||
|
|
||||||
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
|
|
||||||
|
this.lineVAOs[programName] = vao;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private createCurveVAOs(renderer: Renderer): void {
|
||||||
|
if (renderer.meshes == null || renderer.meshData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const renderContext = renderer.renderContext;
|
||||||
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
|
this.curveVAOs = {};
|
||||||
|
|
||||||
|
for (const programName of this.curveShaderProgramNames) {
|
||||||
|
const curveProgram = renderContext.shaderPrograms[programName];
|
||||||
|
const attributes = curveProgram.attributes;
|
||||||
|
|
||||||
|
const vao = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
||||||
|
|
||||||
|
const curveVertexPositionsBuffer = renderer.meshes[0].segmentCurves;
|
||||||
|
const curvePathIDsBuffer = renderer.meshes[0].segmentCurvePathIDs;
|
||||||
|
const curveNormalsBuffer = renderer.meshes[0].segmentCurveNormals;
|
||||||
|
|
||||||
|
gl.useProgram(curveProgram.program);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, renderContext.quadPositionsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aQuadPosition, 2, gl.FLOAT, false, 0, 0);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, curveVertexPositionsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aLeftPosition,
|
||||||
|
2,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 6,
|
||||||
|
0);
|
||||||
|
gl.vertexAttribPointer(attributes.aControlPointPosition,
|
||||||
|
2,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 6,
|
||||||
|
FLOAT32_SIZE * 2);
|
||||||
|
gl.vertexAttribPointer(attributes.aRightPosition,
|
||||||
|
2,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 6,
|
||||||
|
FLOAT32_SIZE * 4);
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, curvePathIDsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aPathID, 1, gl.UNSIGNED_SHORT, false, 0, 0);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||||
|
gl.enableVertexAttribArray(attributes.aLeftPosition);
|
||||||
|
gl.enableVertexAttribArray(attributes.aControlPointPosition);
|
||||||
|
gl.enableVertexAttribArray(attributes.aRightPosition);
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (renderer.meshData[0].segmentCurveNormals.byteLength > 0) {
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, curveNormalsBuffer);
|
||||||
|
gl.vertexAttribPointer(attributes.aNormalAngles,
|
||||||
|
3,
|
||||||
|
gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 3,
|
||||||
|
0);
|
||||||
|
|
||||||
|
gl.enableVertexAttribArray(attributes.aNormalAngles);
|
||||||
|
|
||||||
|
renderContext.instancedArraysExt
|
||||||
|
.vertexAttribDivisorANGLE(attributes.aNormalAngles, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderContext.quadElementsBuffer);
|
||||||
|
|
||||||
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
|
|
||||||
|
this.curveVAOs[programName] = vao;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ECAAMonochromeStrategy extends ECAAStrategy {
|
||||||
|
protected get usesDilationTransforms(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get lineShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
||||||
|
return ['ecaaLine'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get curveShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
||||||
|
return ['ecaaCurve'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MCAAMonochromeStrategy extends MCAAStrategy {
|
export class MCAAMonochromeStrategy extends MCAAStrategy {
|
||||||
|
protected get usesDilationTransforms(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected getResolveProgram(renderContext: RenderContext): PathfinderShaderProgram {
|
protected getResolveProgram(renderContext: RenderContext): PathfinderShaderProgram {
|
||||||
if (this.subpixelAA !== 'none')
|
if (this.subpixelAA !== 'none')
|
||||||
return renderContext.shaderPrograms.xcaaMonoSubpixelResolve;
|
return renderContext.shaderPrograms.xcaaMonoSubpixelResolve;
|
||||||
|
@ -1049,7 +1117,7 @@ export class AdaptiveMonochromeXCAAStrategy implements AntialiasingStrategy {
|
||||||
|
|
||||||
constructor(level: number, subpixelAA: SubpixelAAType) {
|
constructor(level: number, subpixelAA: SubpixelAAType) {
|
||||||
this.mcaaStrategy = new MCAAMonochromeStrategy(level, subpixelAA);
|
this.mcaaStrategy = new MCAAMonochromeStrategy(level, subpixelAA);
|
||||||
this.ecaaStrategy = new ECAAStrategy(level, subpixelAA);
|
this.ecaaStrategy = new ECAAMonochromeStrategy(level, subpixelAA);
|
||||||
}
|
}
|
||||||
|
|
||||||
init(renderer: Renderer): void {
|
init(renderer: Renderer): void {
|
||||||
|
@ -1106,7 +1174,19 @@ export class AdaptiveMonochromeXCAAStrategy implements AntialiasingStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MCAAMulticolorStrategy extends MCAAStrategy {
|
export class ECAAMulticolorStrategy extends ECAAStrategy {
|
||||||
|
protected get usesDilationTransforms(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get lineShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
||||||
|
return ['ecaaLine', 'xcaaMultiEdgeMaskLine'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get curveShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
||||||
|
return ['ecaaCurve', 'xcaaMultiEdgeMaskCurve'];
|
||||||
|
}
|
||||||
|
|
||||||
private edgeMaskVAO: WebGLVertexArrayObject;
|
private edgeMaskVAO: WebGLVertexArrayObject;
|
||||||
|
|
||||||
bindEdgeDepthTexture(gl: WebGLRenderingContext, uniforms: UniformMap, textureUnit: number):
|
bindEdgeDepthTexture(gl: WebGLRenderingContext, uniforms: UniformMap, textureUnit: number):
|
||||||
|
@ -1136,7 +1216,7 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
|
||||||
this.supersampledFramebufferSize[0],
|
this.supersampledFramebufferSize[0],
|
||||||
this.supersampledFramebufferSize[1]);
|
this.supersampledFramebufferSize[1]);
|
||||||
|
|
||||||
gl.colorMask(false, false, false, false);
|
gl.colorMask(true, true, true, true);
|
||||||
gl.depthMask(true);
|
gl.depthMask(true);
|
||||||
gl.depthFunc(gl.GREATER);
|
gl.depthFunc(gl.GREATER);
|
||||||
gl.enable(gl.DEPTH_TEST);
|
gl.enable(gl.DEPTH_TEST);
|
||||||
|
@ -1147,12 +1227,9 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
// Perform edge masking.
|
// Perform edge masking.
|
||||||
const edgeMaskLineProgram = renderer.renderContext.shaderPrograms.xcaaMultiEdgeMaskLine;
|
gl.colorMask(false, false, false, false);
|
||||||
gl.useProgram(edgeMaskLineProgram.program);
|
this.antialiasLinesOfObjectWithProgram(renderer, objectIndex, 'xcaaMultiEdgeMaskLine');
|
||||||
this.antialiasLinesOfObjectWithProgram(renderer, objectIndex, edgeMaskLineProgram);
|
this.antialiasCurvesOfObjectWithProgram(renderer, objectIndex, 'xcaaMultiEdgeMaskCurve');
|
||||||
const edgeMaskCurveProgram = renderer.renderContext.shaderPrograms.xcaaMultiEdgeMaskCurve;
|
|
||||||
gl.useProgram(edgeMaskCurveProgram.program);
|
|
||||||
this.antialiasCurvesOfObjectWithProgram(renderer, objectIndex, edgeMaskCurveProgram);
|
|
||||||
|
|
||||||
gl.colorMask(true, true, true, true);
|
gl.colorMask(true, true, true, true);
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
|
@ -1160,17 +1237,19 @@ export class MCAAMulticolorStrategy extends MCAAStrategy {
|
||||||
|
|
||||||
protected setCoverDepthState(renderer: Renderer): void {
|
protected setCoverDepthState(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
const renderContext = renderer.renderContext;
|
||||||
renderContext.gl.depthMask(false);
|
const gl = renderContext.gl;
|
||||||
renderContext.gl.depthFunc(renderContext.gl.EQUAL);
|
|
||||||
renderContext.gl.enable(renderContext.gl.DEPTH_TEST);
|
gl.depthMask(false);
|
||||||
|
gl.depthFunc(gl.EQUAL);
|
||||||
|
gl.enable(gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForAA(renderer: Renderer): void {
|
protected clearForAA(renderer: Renderer): void {
|
||||||
const renderContext = renderer.renderContext;
|
/*const renderContext = renderer.renderContext;
|
||||||
const gl = renderContext.gl;
|
const gl = renderContext.gl;
|
||||||
|
|
||||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAADepthState(renderer: Renderer): void {
|
protected setAADepthState(renderer: Renderer): void {
|
||||||
|
|
|
@ -425,8 +425,9 @@ fn partition_svg_paths(request: Json<PartitionSvgPathsRequest>)
|
||||||
let mut path_buffer = PathBuffer::new();
|
let mut path_buffer = PathBuffer::new();
|
||||||
let mut paths = vec![];
|
let mut paths = vec![];
|
||||||
let mut last_point = Point2D::zero();
|
let mut last_point = Point2D::zero();
|
||||||
|
let mut library = MeshLibrary::new();
|
||||||
|
|
||||||
for path in &request.paths {
|
for (path_index, path) in request.paths.iter().enumerate() {
|
||||||
let mut stream = vec![];
|
let mut stream = vec![];
|
||||||
|
|
||||||
let first_subpath_index = path_buffer.subpaths.len() as u32;
|
let first_subpath_index = path_buffer.subpaths.len() as u32;
|
||||||
|
@ -463,7 +464,9 @@ fn partition_svg_paths(request: Json<PartitionSvgPathsRequest>)
|
||||||
|
|
||||||
match path.kind {
|
match path.kind {
|
||||||
PartitionSvgPathKind::Fill => {
|
PartitionSvgPathKind::Fill => {
|
||||||
path_buffer.add_stream(MonotonicPathCommandStream::new(stream.into_iter()))
|
let stream = MonotonicPathCommandStream::new(stream.into_iter());
|
||||||
|
library.push_segments((path_index + 1) as u16, stream.clone());
|
||||||
|
path_buffer.add_stream(stream)
|
||||||
}
|
}
|
||||||
PartitionSvgPathKind::Stroke(stroke_width) => {
|
PartitionSvgPathKind::Stroke(stroke_width) => {
|
||||||
let mut temp_path_buffer = PathBuffer::new();
|
let mut temp_path_buffer = PathBuffer::new();
|
||||||
|
@ -471,6 +474,7 @@ fn partition_svg_paths(request: Json<PartitionSvgPathsRequest>)
|
||||||
|
|
||||||
let stream = PathBufferStream::new(&temp_path_buffer);
|
let stream = PathBufferStream::new(&temp_path_buffer);
|
||||||
let stream = MonotonicPathCommandStream::new(stream);
|
let stream = MonotonicPathCommandStream::new(stream);
|
||||||
|
library.push_segments((path_index + 1) as u16, stream.clone());
|
||||||
path_buffer.add_stream(stream)
|
path_buffer.add_stream(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,7 +485,7 @@ fn partition_svg_paths(request: Json<PartitionSvgPathsRequest>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partition the paths.
|
// Partition the paths.
|
||||||
let mut partitioner = Partitioner::new(MeshLibrary::new());
|
let mut partitioner = Partitioner::new(library);
|
||||||
partitioner.init_with_path_buffer(&path_buffer);
|
partitioner.init_with_path_buffer(&path_buffer);
|
||||||
let path_partitioning_result = PathPartitioningResult::compute(&mut partitioner, &paths);
|
let path_partitioning_result = PathPartitioningResult::compute(&mut partitioner, &paths);
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ impl PathBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct PathBufferStream<'a> {
|
pub struct PathBufferStream<'a> {
|
||||||
path_buffer: &'a PathBuffer,
|
path_buffer: &'a PathBuffer,
|
||||||
endpoint_index: u32,
|
endpoint_index: u32,
|
||||||
|
|
|
@ -15,6 +15,7 @@ use std::mem;
|
||||||
use PathCommand;
|
use PathCommand;
|
||||||
use curve::Curve;
|
use curve::Curve;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct MonotonicPathCommandStream<I> {
|
pub struct MonotonicPathCommandStream<I> {
|
||||||
inner: I,
|
inner: I,
|
||||||
queue: ArrayVec<[PathCommand; 2]>,
|
queue: ArrayVec<[PathCommand; 2]>,
|
||||||
|
|
|
@ -160,48 +160,60 @@ bool computeECAAQuadPosition(out vec2 outPosition,
|
||||||
vec2 quadPosition,
|
vec2 quadPosition,
|
||||||
ivec2 framebufferSize,
|
ivec2 framebufferSize,
|
||||||
vec4 localTransformST,
|
vec4 localTransformST,
|
||||||
vec4 globalTransformST,
|
mat4 globalTransform,
|
||||||
vec4 hints,
|
vec4 hints,
|
||||||
vec4 bounds,
|
vec4 bounds,
|
||||||
float leftNormalAngle,
|
float leftNormalAngle,
|
||||||
float rightNormalAngle,
|
float rightNormalAngle,
|
||||||
vec2 emboldenAmount) {
|
vec2 emboldenAmount) {
|
||||||
|
vec2 edgeBL = bounds.xy, edgeTL = bounds.xw, edgeTR = bounds.zw, edgeBR = bounds.zy;
|
||||||
|
|
||||||
leftPosition = dilatePosition(leftPosition, leftNormalAngle, emboldenAmount);
|
leftPosition = dilatePosition(leftPosition, leftNormalAngle, emboldenAmount);
|
||||||
rightPosition = dilatePosition(rightPosition, rightNormalAngle, emboldenAmount);
|
rightPosition = dilatePosition(rightPosition, rightNormalAngle, emboldenAmount);
|
||||||
|
|
||||||
leftPosition = hintPosition(leftPosition, hints);
|
leftPosition = hintPosition(leftPosition, hints);
|
||||||
rightPosition = hintPosition(rightPosition, hints);
|
rightPosition = hintPosition(rightPosition, hints);
|
||||||
vec2 edgePosition = hintPosition(bounds.zw, hints);
|
|
||||||
|
|
||||||
leftPosition = transformVertexPositionST(leftPosition, localTransformST);
|
leftPosition = transformVertexPositionST(leftPosition, localTransformST);
|
||||||
rightPosition = transformVertexPositionST(rightPosition, localTransformST);
|
rightPosition = transformVertexPositionST(rightPosition, localTransformST);
|
||||||
edgePosition = transformVertexPositionST(edgePosition, localTransformST);
|
edgeBL = transformVertexPositionST(edgeBL, localTransformST);
|
||||||
|
edgeTL = transformVertexPositionST(edgeTL, localTransformST);
|
||||||
|
edgeBR = transformVertexPositionST(edgeBR, localTransformST);
|
||||||
|
edgeTR = transformVertexPositionST(edgeTR, localTransformST);
|
||||||
|
|
||||||
leftPosition = transformVertexPositionST(leftPosition, globalTransformST);
|
leftPosition = transformVertexPosition(leftPosition, globalTransform);
|
||||||
rightPosition = transformVertexPositionST(rightPosition, globalTransformST);
|
rightPosition = transformVertexPosition(rightPosition, globalTransform);
|
||||||
edgePosition = transformVertexPositionST(edgePosition, globalTransformST);
|
edgeBL = transformVertexPosition(edgeBL, globalTransform);
|
||||||
|
edgeTL = transformVertexPosition(edgeTL, globalTransform);
|
||||||
|
edgeBR = transformVertexPosition(edgeBR, globalTransform);
|
||||||
|
edgeTR = transformVertexPosition(edgeTR, globalTransform);
|
||||||
|
|
||||||
leftPosition = convertClipToScreenSpace(leftPosition, framebufferSize);
|
leftPosition = convertClipToScreenSpace(leftPosition, framebufferSize);
|
||||||
rightPosition = convertClipToScreenSpace(rightPosition, framebufferSize);
|
rightPosition = convertClipToScreenSpace(rightPosition, framebufferSize);
|
||||||
edgePosition = convertClipToScreenSpace(edgePosition, framebufferSize);
|
|
||||||
|
|
||||||
float winding = sign(leftPosition.x - rightPosition.x);
|
float winding = sign(leftPosition.x - rightPosition.x);
|
||||||
|
outWinding = winding;
|
||||||
if (winding > 0.0) {
|
if (winding > 0.0) {
|
||||||
vec2 tmp = leftPosition;
|
vec2 tmp = leftPosition;
|
||||||
leftPosition = rightPosition;
|
leftPosition = rightPosition;
|
||||||
rightPosition = tmp;
|
rightPosition = tmp;
|
||||||
}
|
}
|
||||||
outWinding = winding;
|
|
||||||
|
|
||||||
if (rightPosition.x - leftPosition.x <= EPSILON) {
|
if (rightPosition.x - leftPosition.x <= EPSILON) {
|
||||||
outPosition = vec2(0.0);
|
outPosition = vec2(0.0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the bottom of the path, and convert to clip space.
|
||||||
|
//
|
||||||
|
// FIXME(pcwalton): Speed this up somehow?
|
||||||
|
float pathBottomY = max(max(edgeBL.y, edgeBR.y), max(edgeTL.y, edgeTR.y));
|
||||||
|
pathBottomY = (pathBottomY + 1.0) * 0.5 * float(framebufferSize.y);
|
||||||
|
|
||||||
vec4 roundedExtents = vec4(floor(leftPosition.x),
|
vec4 roundedExtents = vec4(floor(leftPosition.x),
|
||||||
floor(min(leftPosition.y, rightPosition.y)),
|
floor(min(leftPosition.y, rightPosition.y)),
|
||||||
ceil(rightPosition.x),
|
ceil(rightPosition.x),
|
||||||
ceil(edgePosition.y));
|
ceil(pathBottomY));
|
||||||
|
|
||||||
vec2 position = mix(roundedExtents.xy, roundedExtents.zw, quadPosition);
|
vec2 position = mix(roundedExtents.xy, roundedExtents.zw, quadPosition);
|
||||||
outPosition = convertScreenToClipSpace(position, framebufferSize);
|
outPosition = convertScreenToClipSpace(position, framebufferSize);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
uniform vec4 uTransformST;
|
uniform mat4 uTransform;
|
||||||
uniform vec4 uHints;
|
uniform vec4 uHints;
|
||||||
uniform ivec2 uFramebufferSize;
|
uniform ivec2 uFramebufferSize;
|
||||||
uniform ivec2 uPathTransformDimensions;
|
uniform ivec2 uPathTransformDimensions;
|
||||||
|
@ -23,8 +23,8 @@ attribute vec2 aQuadPosition;
|
||||||
attribute vec2 aLeftPosition;
|
attribute vec2 aLeftPosition;
|
||||||
attribute vec2 aControlPointPosition;
|
attribute vec2 aControlPointPosition;
|
||||||
attribute vec2 aRightPosition;
|
attribute vec2 aRightPosition;
|
||||||
attribute vec3 aNormalAngles;
|
|
||||||
attribute float aPathID;
|
attribute float aPathID;
|
||||||
|
attribute vec3 aNormalAngles;
|
||||||
|
|
||||||
varying vec4 vEndpoints;
|
varying vec4 vEndpoints;
|
||||||
varying vec2 vControlPoint;
|
varying vec2 vControlPoint;
|
||||||
|
@ -52,7 +52,7 @@ void main() {
|
||||||
aQuadPosition,
|
aQuadPosition,
|
||||||
uFramebufferSize,
|
uFramebufferSize,
|
||||||
transform,
|
transform,
|
||||||
uTransformST,
|
uTransform,
|
||||||
uHints,
|
uHints,
|
||||||
bounds,
|
bounds,
|
||||||
leftNormalAngle,
|
leftNormalAngle,
|
||||||
|
@ -63,7 +63,7 @@ void main() {
|
||||||
uEmboldenAmount);
|
uEmboldenAmount);
|
||||||
controlPointPosition = hintPosition(controlPointPosition, uHints);
|
controlPointPosition = hintPosition(controlPointPosition, uHints);
|
||||||
controlPointPosition = transformVertexPositionST(controlPointPosition, transform);
|
controlPointPosition = transformVertexPositionST(controlPointPosition, transform);
|
||||||
controlPointPosition = transformVertexPositionST(controlPointPosition, uTransformST);
|
controlPointPosition = transformVertexPosition(controlPointPosition, uTransform);
|
||||||
controlPointPosition = convertClipToScreenSpace(controlPointPosition, uFramebufferSize);
|
controlPointPosition = convertClipToScreenSpace(controlPointPosition, uFramebufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
uniform vec4 uTransformST;
|
uniform mat4 uTransform;
|
||||||
uniform vec4 uHints;
|
uniform vec4 uHints;
|
||||||
uniform ivec2 uFramebufferSize;
|
uniform ivec2 uFramebufferSize;
|
||||||
uniform ivec2 uPathTransformDimensions;
|
uniform ivec2 uPathTransformDimensions;
|
||||||
|
@ -49,7 +49,7 @@ void main() {
|
||||||
aQuadPosition,
|
aQuadPosition,
|
||||||
uFramebufferSize,
|
uFramebufferSize,
|
||||||
transform,
|
transform,
|
||||||
uTransformST,
|
uTransform,
|
||||||
uHints,
|
uHints,
|
||||||
bounds,
|
bounds,
|
||||||
leftNormalAngle,
|
leftNormalAngle,
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
// pathfinder/shaders/gles2/xcaa-edge-detect.fs.glsl
|
|
||||||
//
|
|
||||||
// Copyright (c) 2017 The Pathfinder Project Developers.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
uniform ivec2 uFramebufferSize;
|
|
||||||
uniform ivec2 uPathColorsDimensions;
|
|
||||||
uniform sampler2D uPathID;
|
|
||||||
uniform sampler2D uPathColors;
|
|
||||||
|
|
||||||
varying vec2 vTexCoord;
|
|
||||||
|
|
||||||
void checkFG(out vec2 fgPosition, out int fgPathID, vec2 queryPosition, int queryPathID) {
|
|
||||||
if (queryPathID > fgPathID) {
|
|
||||||
fgPosition = queryPosition;
|
|
||||||
fgPathID = queryPathID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateMinMaxInt(inout ivec2 minMax, int value) {
|
|
||||||
if (value < minMax.x)
|
|
||||||
minMax.x = value;
|
|
||||||
if (value > minMax.y)
|
|
||||||
minMax.y = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
ivec2 minMaxIVec4(ivec4 values) {
|
|
||||||
ivec2 minMax = ivec2(values.x);
|
|
||||||
updateMinMaxInt(minMax, values.y);
|
|
||||||
updateMinMaxInt(minMax, values.z);
|
|
||||||
updateMinMaxInt(minMax, values.w);
|
|
||||||
return minMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// Unpack.
|
|
||||||
vec2 position = vTexCoord;
|
|
||||||
|
|
||||||
// Compute positions.
|
|
||||||
vec2 onePixel = 1.0 / vec2(uFramebufferSize);
|
|
||||||
vec2 positionL = position + vec2(-onePixel.x, 0.0);
|
|
||||||
vec2 positionR = position + vec2( onePixel.x, 0.0);
|
|
||||||
vec2 positionB = position + vec2(0.0, -onePixel.y);
|
|
||||||
vec2 positionT = position + vec2(0.0, onePixel.y);
|
|
||||||
|
|
||||||
// Determine the topmost and bottommost paths.
|
|
||||||
int centerPathID = unpackPathID(texture2D(uPathID, position).rg);
|
|
||||||
ivec4 neighborPathIDs = ivec4(unpackPathID(texture2D(uPathID, positionL).rg),
|
|
||||||
unpackPathID(texture2D(uPathID, positionR).rg),
|
|
||||||
unpackPathID(texture2D(uPathID, positionB).rg),
|
|
||||||
unpackPathID(texture2D(uPathID, positionT).rg));
|
|
||||||
ivec2 pathIDsBGFG = minMaxIVec4(neighborPathIDs);
|
|
||||||
|
|
||||||
// Determine the depth.
|
|
||||||
//
|
|
||||||
// If all colors are the same, avoid touching this pixel in any further passes.
|
|
||||||
float outDepth;
|
|
||||||
if (pathIDsBGFG.x == pathIDsBGFG.y)
|
|
||||||
outDepth = 1.0;
|
|
||||||
else
|
|
||||||
outDepth = convertPathIndexToWindowDepthValue(pathIDsBGFG.y);
|
|
||||||
|
|
||||||
// FIXME(pcwalton): Fetch the background color.
|
|
||||||
// FIXME(pcwalton): Output path ID for debugging. Switch to BG color.
|
|
||||||
//vec2 color = pathIDsBGFG.x == pathIDsBGFG.y ? vec2(1.0) : packPathID(pathIDsBGFG.y);
|
|
||||||
//vec4 color = fetchFloat4Data(uPathColors, pathIDsBGFG.x, uPathColorsDimensions);
|
|
||||||
|
|
||||||
// Output results.
|
|
||||||
//gl_FragColor = vec4(packPathID(pathIDsBGFG.x), 0.0, 1.0);
|
|
||||||
gl_FragColor = vec4(packPathID(pathIDsBGFG.x), packPathID(pathIDsBGFG.y));
|
|
||||||
gl_FragDepthEXT = outDepth;
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
// pathfinder/shaders/gles2/xcaa-edge-detect.vs.glsl
|
|
||||||
//
|
|
||||||
// Copyright (c) 2017 The Pathfinder Project Developers.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
attribute vec2 aPosition;
|
|
||||||
attribute vec2 aTexCoord;
|
|
||||||
|
|
||||||
varying vec2 vTexCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(mix(vec2(-1.0), vec2(1.0), aPosition), 0.0, 1.0);
|
|
||||||
vTexCoord = aTexCoord;
|
|
||||||
}
|
|
|
@ -21,7 +21,7 @@ void main() {
|
||||||
float edgeDepth = texture2D(uAADepth, vTexCoord).r;
|
float edgeDepth = texture2D(uAADepth, vTexCoord).r;
|
||||||
int edgePathID = convertWindowDepthValueToPathIndex(edgeDepth);
|
int edgePathID = convertWindowDepthValueToPathIndex(edgeDepth);
|
||||||
vec4 edgeColor = fetchFloat4Data(uPathColors, edgePathID, uPathColorsDimensions);
|
vec4 edgeColor = fetchFloat4Data(uPathColors, edgePathID, uPathColorsDimensions);
|
||||||
float edgeAlpha = texture2D(uAAAlpha, vTexCoord).r;
|
float edgeAlpha = abs(texture2D(uAAAlpha, vTexCoord).r);
|
||||||
gl_FragColor = vec4(edgeColor.rgb, edgeColor.a * edgeAlpha);
|
gl_FragColor = vec4(edgeColor.rgb, edgeColor.a * edgeAlpha);
|
||||||
gl_FragDepthEXT = edgeDepth;
|
gl_FragDepthEXT = edgeDepth;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue