Use regular VBOs instead of textures to store vertex positions for ECAA.
This improves performance at small font sizes a bit by reducing vertex shading load.
This commit is contained in:
parent
6a7c013e61
commit
2a236319d4
|
@ -18,6 +18,7 @@ import {SubpixelAAType} from "./aa-strategy";
|
||||||
import {DemoAppController} from "./app-controller";
|
import {DemoAppController} from "./app-controller";
|
||||||
import PathfinderBufferTexture from "./buffer-texture";
|
import PathfinderBufferTexture from "./buffer-texture";
|
||||||
import {PerspectiveCamera} from "./camera";
|
import {PerspectiveCamera} from "./camera";
|
||||||
|
import {UniformMap} from './gl-utils';
|
||||||
import {PathfinderMeshData} from "./meshes";
|
import {PathfinderMeshData} from "./meshes";
|
||||||
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
|
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
|
||||||
import SSAAStrategy from "./ssaa-strategy";
|
import SSAAStrategy from "./ssaa-strategy";
|
||||||
|
@ -25,7 +26,6 @@ import {BUILTIN_FONT_URI, ExpandedMeshData} from "./text";
|
||||||
import {GlyphStore, Hint, PathfinderFont, TextFrame, TextRun} from "./text";
|
import {GlyphStore, Hint, PathfinderFont, TextFrame, TextRun} from "./text";
|
||||||
import {assert, panic, PathfinderError, unwrapNull} from "./utils";
|
import {assert, panic, PathfinderError, unwrapNull} from "./utils";
|
||||||
import {DemoView, Timings} from "./view";
|
import {DemoView, Timings} from "./view";
|
||||||
import { UniformMap } from './gl-utils';
|
|
||||||
|
|
||||||
const TEXT_AVAILABLE_WIDTH: number = 150000;
|
const TEXT_AVAILABLE_WIDTH: number = 150000;
|
||||||
const TEXT_PADDING: number = 2000;
|
const TEXT_PADDING: number = 2000;
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {AppController, DemoAppController} from "./app-controller";
|
||||||
import PathfinderBufferTexture from './buffer-texture';
|
import PathfinderBufferTexture from './buffer-texture';
|
||||||
import {OrthographicCamera} from './camera';
|
import {OrthographicCamera} from './camera';
|
||||||
import {ECAAMonochromeStrategy, ECAAStrategy} from './ecaa-strategy';
|
import {ECAAMonochromeStrategy, ECAAStrategy} from './ecaa-strategy';
|
||||||
|
import {UniformMap} from './gl-utils';
|
||||||
import {PathfinderMeshData} from "./meshes";
|
import {PathfinderMeshData} from "./meshes";
|
||||||
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
|
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
|
||||||
import SSAAStrategy from './ssaa-strategy';
|
import SSAAStrategy from './ssaa-strategy';
|
||||||
|
@ -25,7 +26,6 @@ import {BUILTIN_FONT_URI, ExpandedMeshData, GlyphStore, PathfinderFont, TextFram
|
||||||
import {TextRun} from "./text";
|
import {TextRun} from "./text";
|
||||||
import {assert, PathfinderError, unwrapNull, unwrapUndef} from "./utils";
|
import {assert, PathfinderError, unwrapNull, unwrapUndef} from "./utils";
|
||||||
import {DemoView, MonochromeDemoView, Timings } from "./view";
|
import {DemoView, MonochromeDemoView, Timings } from "./view";
|
||||||
import { UniformMap } from './gl-utils';
|
|
||||||
|
|
||||||
const STRING: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
const STRING: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,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 {PathfinderShaderProgram} from './shader-loader';
|
import {PathfinderShaderProgram} from './shader-loader';
|
||||||
import {UINT32_SIZE, unwrapNull} from './utils';
|
import {FLOAT32_SIZE, UINT32_SIZE, unwrapNull} from './utils';
|
||||||
import {MonochromeDemoView} from './view';
|
import {MonochromeDemoView} from './view';
|
||||||
|
|
||||||
interface UpperAndLower<T> {
|
interface UpperAndLower<T> {
|
||||||
|
@ -37,8 +37,6 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
|
|
||||||
protected subpixelAA: SubpixelAAType;
|
protected subpixelAA: SubpixelAAType;
|
||||||
|
|
||||||
private bVertexPositionBufferTexture: PathfinderBufferTexture;
|
|
||||||
private bVertexPathIDBufferTexture: PathfinderBufferTexture;
|
|
||||||
private directFramebuffer: WebGLFramebuffer;
|
private directFramebuffer: WebGLFramebuffer;
|
||||||
private aaAlphaTexture: WebGLTexture;
|
private aaAlphaTexture: WebGLTexture;
|
||||||
private aaFramebuffer: WebGLFramebuffer;
|
private aaFramebuffer: WebGLFramebuffer;
|
||||||
|
@ -58,16 +56,11 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
|
|
||||||
init(view: MonochromeDemoView) {
|
init(view: MonochromeDemoView) {
|
||||||
super.init(view);
|
super.init(view);
|
||||||
this.bVertexPositionBufferTexture = new PathfinderBufferTexture(view.gl,
|
|
||||||
'uBVertexPosition');
|
|
||||||
this.bVertexPathIDBufferTexture = new PathfinderBufferTexture(view.gl, 'uBVertexPathID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(view: MonochromeDemoView) {
|
attachMeshes(view: MonochromeDemoView) {
|
||||||
const bVertexPositions = new Float32Array(view.meshData[0].bVertexPositions);
|
const bVertexPositions = new Float32Array(view.meshData[0].bVertexPositions);
|
||||||
const bVertexPathIDs = new Uint8Array(view.meshData[0].bVertexPathIDs);
|
const bVertexPathIDs = new Uint8Array(view.meshData[0].bVertexPathIDs);
|
||||||
this.bVertexPositionBufferTexture.upload(view.gl, bVertexPositions);
|
|
||||||
this.bVertexPathIDBufferTexture.upload(view.gl, bVertexPathIDs);
|
|
||||||
|
|
||||||
this.createEdgeDetectVAO(view);
|
this.createEdgeDetectVAO(view);
|
||||||
this.createCoverVAO(view);
|
this.createCoverVAO(view);
|
||||||
|
@ -212,24 +205,33 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.gl.useProgram(coverProgram.program);
|
view.gl.useProgram(coverProgram.program);
|
||||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
||||||
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
||||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.meshes[0].bQuads);
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.meshes[0].edgeBoundingBoxVertexPositions);
|
||||||
view.gl.vertexAttribPointer(attributes.aUpperPointIndices,
|
view.gl.vertexAttribPointer(attributes.aUpperLeftPosition,
|
||||||
4,
|
2,
|
||||||
|
view.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 4,
|
||||||
|
0);
|
||||||
|
view.gl.vertexAttribPointer(attributes.aLowerRightPosition,
|
||||||
|
2,
|
||||||
|
view.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 4,
|
||||||
|
FLOAT32_SIZE * 2);
|
||||||
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.meshes[0].edgeBoundingBoxPathIDs);
|
||||||
|
view.gl.vertexAttribPointer(attributes.aPathID,
|
||||||
|
1,
|
||||||
view.gl.UNSIGNED_SHORT,
|
view.gl.UNSIGNED_SHORT,
|
||||||
false,
|
false,
|
||||||
B_QUAD_SIZE,
|
0,
|
||||||
B_QUAD_UPPER_INDICES_OFFSET);
|
0);
|
||||||
view.gl.vertexAttribPointer(attributes.aLowerPointIndices,
|
|
||||||
4,
|
|
||||||
view.gl.UNSIGNED_SHORT,
|
|
||||||
false,
|
|
||||||
B_QUAD_SIZE,
|
|
||||||
B_QUAD_LOWER_INDICES_OFFSET);
|
|
||||||
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||||
view.gl.enableVertexAttribArray(attributes.aUpperPointIndices);
|
view.gl.enableVertexAttribArray(attributes.aUpperLeftPosition);
|
||||||
view.gl.enableVertexAttribArray(attributes.aLowerPointIndices);
|
view.gl.enableVertexAttribArray(attributes.aLowerRightPosition);
|
||||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aUpperPointIndices, 1);
|
view.gl.enableVertexAttribArray(attributes.aPathID);
|
||||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLowerPointIndices, 1);
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aUpperLeftPosition, 1);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLowerRightPosition, 1);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
||||||
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
|
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
|
||||||
|
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
|
@ -244,24 +246,45 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
|
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
|
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
|
||||||
|
|
||||||
const lineIndexBuffer = {
|
const lineVertexPositionsBuffer = {
|
||||||
lower: view.meshes[0].edgeLowerLineIndices,
|
lower: view.meshes[0].edgeLowerLineVertexPositions,
|
||||||
upper: view.meshes[0].edgeUpperLineIndices,
|
upper: view.meshes[0].edgeUpperLineVertexPositions,
|
||||||
|
}[direction];
|
||||||
|
const linePathIDsBuffer = {
|
||||||
|
lower: view.meshes[0].edgeLowerLinePathIDs,
|
||||||
|
upper: view.meshes[0].edgeUpperLinePathIDs,
|
||||||
}[direction];
|
}[direction];
|
||||||
|
|
||||||
view.gl.useProgram(lineProgram.program);
|
view.gl.useProgram(lineProgram.program);
|
||||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
||||||
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
||||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, lineIndexBuffer);
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, lineVertexPositionsBuffer);
|
||||||
view.gl.vertexAttribPointer(attributes.aLineIndices,
|
view.gl.vertexAttribPointer(attributes.aLeftPosition,
|
||||||
4,
|
2,
|
||||||
|
view.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 4,
|
||||||
|
0);
|
||||||
|
view.gl.vertexAttribPointer(attributes.aRightPosition,
|
||||||
|
2,
|
||||||
|
view.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 4,
|
||||||
|
FLOAT32_SIZE * 2);
|
||||||
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, linePathIDsBuffer);
|
||||||
|
view.gl.vertexAttribPointer(attributes.aPathID,
|
||||||
|
1,
|
||||||
view.gl.UNSIGNED_SHORT,
|
view.gl.UNSIGNED_SHORT,
|
||||||
false,
|
false,
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||||
view.gl.enableVertexAttribArray(attributes.aLineIndices);
|
view.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
||||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLineIndices, 1);
|
view.gl.enableVertexAttribArray(attributes.aRightPosition);
|
||||||
|
view.gl.enableVertexAttribArray(attributes.aPathID);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
||||||
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
|
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,32 +302,53 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
|
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
|
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
|
||||||
|
|
||||||
const curveIndexBuffer = {
|
const curveVertexPositionsBuffer = {
|
||||||
lower: view.meshes[0].edgeLowerCurveIndices,
|
lower: view.meshes[0].edgeLowerCurveVertexPositions,
|
||||||
upper: view.meshes[0].edgeUpperCurveIndices,
|
upper: view.meshes[0].edgeUpperCurveVertexPositions,
|
||||||
|
}[direction];
|
||||||
|
const curvePathIDsBuffer = {
|
||||||
|
lower: view.meshes[0].edgeLowerCurvePathIDs,
|
||||||
|
upper: view.meshes[0].edgeUpperCurvePathIDs,
|
||||||
}[direction];
|
}[direction];
|
||||||
|
|
||||||
view.gl.useProgram(curveProgram.program);
|
view.gl.useProgram(curveProgram.program);
|
||||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
||||||
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
||||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curveIndexBuffer);
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curveVertexPositionsBuffer);
|
||||||
view.gl.vertexAttribPointer(attributes.aCurveEndpointIndices,
|
view.gl.vertexAttribPointer(attributes.aLeftPosition,
|
||||||
4,
|
|
||||||
view.gl.UNSIGNED_SHORT,
|
|
||||||
false,
|
|
||||||
UINT32_SIZE * 4,
|
|
||||||
0);
|
|
||||||
view.gl.vertexAttribPointer(attributes.aCurveControlPointIndex,
|
|
||||||
2,
|
2,
|
||||||
|
view.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 6,
|
||||||
|
0);
|
||||||
|
view.gl.vertexAttribPointer(attributes.aControlPointPosition,
|
||||||
|
2,
|
||||||
|
view.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 6,
|
||||||
|
FLOAT32_SIZE * 2);
|
||||||
|
view.gl.vertexAttribPointer(attributes.aRightPosition,
|
||||||
|
2,
|
||||||
|
view.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
FLOAT32_SIZE * 6,
|
||||||
|
FLOAT32_SIZE * 4);
|
||||||
|
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curvePathIDsBuffer);
|
||||||
|
view.gl.vertexAttribPointer(attributes.aPathID,
|
||||||
|
1,
|
||||||
view.gl.UNSIGNED_SHORT,
|
view.gl.UNSIGNED_SHORT,
|
||||||
false,
|
false,
|
||||||
UINT32_SIZE * 4,
|
0,
|
||||||
UINT32_SIZE * 2);
|
0);
|
||||||
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||||
view.gl.enableVertexAttribArray(attributes.aCurveEndpointIndices);
|
view.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
||||||
view.gl.enableVertexAttribArray(attributes.aCurveControlPointIndex);
|
view.gl.enableVertexAttribArray(attributes.aControlPointPosition);
|
||||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aCurveEndpointIndices, 1);
|
view.gl.enableVertexAttribArray(attributes.aRightPosition);
|
||||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aCurveControlPointIndex, 1);
|
view.gl.enableVertexAttribArray(attributes.aPathID);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLeftPosition, 1);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aControlPointPosition, 1);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aRightPosition, 1);
|
||||||
|
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aPathID, 1);
|
||||||
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
|
view.gl.bindBuffer(view.gl.ELEMENT_ARRAY_BUFFER, view.quadElementsBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,9 +420,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
private setAAUniforms(view: MonochromeDemoView, uniforms: UniformMap) {
|
private setAAUniforms(view: MonochromeDemoView, uniforms: UniformMap) {
|
||||||
view.setTransformSTUniform(uniforms, 0);
|
view.setTransformSTUniform(uniforms, 0);
|
||||||
view.setFramebufferSizeUniform(uniforms);
|
view.setFramebufferSizeUniform(uniforms);
|
||||||
this.bVertexPositionBufferTexture.bind(view.gl, uniforms, 0);
|
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 0);
|
||||||
this.bVertexPathIDBufferTexture.bind(view.gl, uniforms, 1);
|
|
||||||
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 2);
|
|
||||||
view.setHintsUniform(uniforms);
|
view.setHintsUniform(uniforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,8 +436,8 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(this.lineVAOs[direction]);
|
view.vertexArrayObjectExt.bindVertexArrayOES(this.lineVAOs[direction]);
|
||||||
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
|
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
|
||||||
const count = {
|
const count = {
|
||||||
lower: view.meshData[0].edgeLowerLineIndexCount,
|
lower: view.meshData[0].edgeLowerLineCount,
|
||||||
upper: view.meshData[0].edgeUpperLineIndexCount,
|
upper: view.meshData[0].edgeUpperLineCount,
|
||||||
}[direction];
|
}[direction];
|
||||||
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
|
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
|
||||||
6,
|
6,
|
||||||
|
@ -419,8 +461,8 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(this.curveVAOs[direction]);
|
view.vertexArrayObjectExt.bindVertexArrayOES(this.curveVAOs[direction]);
|
||||||
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
|
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
|
||||||
const count = {
|
const count = {
|
||||||
lower: view.meshData[0].edgeLowerCurveIndexCount,
|
lower: view.meshData[0].edgeLowerCurveCount,
|
||||||
upper: view.meshData[0].edgeUpperCurveIndexCount,
|
upper: view.meshData[0].edgeUpperCurveCount,
|
||||||
}[direction];
|
}[direction];
|
||||||
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
|
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
|
||||||
6,
|
6,
|
||||||
|
|
|
@ -18,35 +18,36 @@ interface BufferTypeFourCCTable {
|
||||||
[fourCC: string]: keyof Meshes<void>;
|
[fourCC: string]: keyof Meshes<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BUFFER_TYPES: Meshes<BufferType> = {
|
interface ArrayLike<T> {
|
||||||
bQuads: 'ARRAY_BUFFER',
|
[index: number]: T;
|
||||||
bVertexLoopBlinnData: 'ARRAY_BUFFER',
|
}
|
||||||
bVertexPathIDs: 'ARRAY_BUFFER',
|
|
||||||
bVertexPositions: 'ARRAY_BUFFER',
|
|
||||||
coverCurveIndices: 'ELEMENT_ARRAY_BUFFER',
|
|
||||||
coverInteriorIndices: 'ELEMENT_ARRAY_BUFFER',
|
|
||||||
edgeLowerCurveIndices: 'ARRAY_BUFFER',
|
|
||||||
edgeLowerLineIndices: 'ARRAY_BUFFER',
|
|
||||||
edgeUpperCurveIndices: 'ARRAY_BUFFER',
|
|
||||||
edgeUpperLineIndices: 'ARRAY_BUFFER',
|
|
||||||
};
|
|
||||||
|
|
||||||
const RIFF_FOURCC: string = 'RIFF';
|
interface VertexExpansionDescriptor<T> {
|
||||||
|
expanded: T[];
|
||||||
|
original: ArrayLike<T>;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
|
||||||
const MESH_LIBRARY_FOURCC: string = 'PFML';
|
interface VertexCopyResult {
|
||||||
|
originalStartIndex: number;
|
||||||
|
originalEndIndex: number;
|
||||||
|
expandedStartIndex: number;
|
||||||
|
expandedEndIndex: number;
|
||||||
|
}
|
||||||
|
|
||||||
// Must match the FourCCs in `pathfinder_partitioner::mesh_library::MeshLibrary::serialize_into()`.
|
type PrimitiveType = 'Uint16' | 'Uint32' | 'Float32';
|
||||||
const BUFFER_TYPE_FOURCCS: BufferTypeFourCCTable = {
|
|
||||||
bqua: 'bQuads',
|
type PrimitiveTypeArray = Float32Array | Uint16Array | Uint32Array;
|
||||||
bvlb: 'bVertexLoopBlinnData',
|
|
||||||
bvpi: 'bVertexPathIDs',
|
interface MeshBufferTypeDescriptor {
|
||||||
bvpo: 'bVertexPositions',
|
type: PrimitiveType;
|
||||||
cvci: 'coverCurveIndices',
|
size: number;
|
||||||
cvii: 'coverInteriorIndices',
|
}
|
||||||
elci: 'edgeLowerCurveIndices',
|
|
||||||
elli: 'edgeLowerLineIndices',
|
const PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS = {
|
||||||
euci: 'edgeUpperCurveIndices',
|
Float32: Float32Array,
|
||||||
euli: 'edgeUpperLineIndices',
|
Uint16: Uint16Array,
|
||||||
|
Uint32: Uint32Array,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const B_QUAD_SIZE: number = 4 * 8;
|
export const B_QUAD_SIZE: number = 4 * 8;
|
||||||
|
@ -61,6 +62,70 @@ export const B_QUAD_LOWER_INDICES_OFFSET: number = B_QUAD_LOWER_LEFT_VERTEX_OFFS
|
||||||
|
|
||||||
const B_QUAD_FIELD_COUNT: number = B_QUAD_SIZE / UINT32_SIZE;
|
const B_QUAD_FIELD_COUNT: number = B_QUAD_SIZE / UINT32_SIZE;
|
||||||
|
|
||||||
|
const MESH_TYPES: Meshes<MeshBufferTypeDescriptor> = {
|
||||||
|
bQuads: { type: 'Uint32', size: B_QUAD_FIELD_COUNT },
|
||||||
|
bVertexLoopBlinnData: { type: 'Uint32', size: 1 },
|
||||||
|
bVertexPathIDs: { type: 'Uint16', size: 1 },
|
||||||
|
bVertexPositions: { type: 'Float32', size: 2 },
|
||||||
|
coverCurveIndices: { type: 'Uint32', size: 1 },
|
||||||
|
coverInteriorIndices: { type: 'Uint32', size: 1 },
|
||||||
|
edgeBoundingBoxPathIDs: { type: 'Uint16', size: 1 },
|
||||||
|
edgeBoundingBoxVertexPositions: { type: 'Float32', size: 4 },
|
||||||
|
edgeLowerCurvePathIDs: { type: 'Uint16', size: 1 },
|
||||||
|
edgeLowerCurveVertexPositions: { type: 'Float32', size: 6 },
|
||||||
|
edgeLowerLinePathIDs: { type: 'Uint16', size: 1 },
|
||||||
|
edgeLowerLineVertexPositions: { type: 'Float32', size: 4 },
|
||||||
|
edgeUpperCurvePathIDs: { type: 'Uint16', size: 1 },
|
||||||
|
edgeUpperCurveVertexPositions: { type: 'Float32', size: 6 },
|
||||||
|
edgeUpperLinePathIDs: { type: 'Uint16', size: 1 },
|
||||||
|
edgeUpperLineVertexPositions: { type: 'Float32', size: 4 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const BUFFER_TYPES: Meshes<BufferType> = {
|
||||||
|
bQuads: 'ARRAY_BUFFER',
|
||||||
|
bVertexLoopBlinnData: 'ARRAY_BUFFER',
|
||||||
|
bVertexPathIDs: 'ARRAY_BUFFER',
|
||||||
|
bVertexPositions: 'ARRAY_BUFFER',
|
||||||
|
coverCurveIndices: 'ELEMENT_ARRAY_BUFFER',
|
||||||
|
coverInteriorIndices: 'ELEMENT_ARRAY_BUFFER',
|
||||||
|
edgeBoundingBoxPathIDs: 'ARRAY_BUFFER',
|
||||||
|
edgeBoundingBoxVertexPositions: 'ARRAY_BUFFER',
|
||||||
|
edgeLowerCurvePathIDs: 'ARRAY_BUFFER',
|
||||||
|
edgeLowerCurveVertexPositions: 'ARRAY_BUFFER',
|
||||||
|
edgeLowerLinePathIDs: 'ARRAY_BUFFER',
|
||||||
|
edgeLowerLineVertexPositions: 'ARRAY_BUFFER',
|
||||||
|
edgeUpperCurvePathIDs: 'ARRAY_BUFFER',
|
||||||
|
edgeUpperCurveVertexPositions: 'ARRAY_BUFFER',
|
||||||
|
edgeUpperLinePathIDs: 'ARRAY_BUFFER',
|
||||||
|
edgeUpperLineVertexPositions: 'ARRAY_BUFFER',
|
||||||
|
};
|
||||||
|
|
||||||
|
const EDGE_BUFFER_NAMES = ['BoundingBox', 'UpperLine', 'UpperCurve', 'LowerLine', 'LowerCurve'];
|
||||||
|
|
||||||
|
const RIFF_FOURCC: string = 'RIFF';
|
||||||
|
|
||||||
|
const MESH_LIBRARY_FOURCC: string = 'PFML';
|
||||||
|
|
||||||
|
// Must match the FourCCs in `pathfinder_partitioner::mesh_library::MeshLibrary::serialize_into()`.
|
||||||
|
const BUFFER_TYPE_FOURCCS: BufferTypeFourCCTable = {
|
||||||
|
bqua: 'bQuads',
|
||||||
|
bvlb: 'bVertexLoopBlinnData',
|
||||||
|
bvpi: 'bVertexPathIDs',
|
||||||
|
bvpo: 'bVertexPositions',
|
||||||
|
cvci: 'coverCurveIndices',
|
||||||
|
cvii: 'coverInteriorIndices',
|
||||||
|
ebbp: 'edgeBoundingBoxPathIDs',
|
||||||
|
ebbv: 'edgeBoundingBoxVertexPositions',
|
||||||
|
elcp: 'edgeLowerCurvePathIDs',
|
||||||
|
elcv: 'edgeLowerCurveVertexPositions',
|
||||||
|
ellp: 'edgeLowerLinePathIDs',
|
||||||
|
ellv: 'edgeLowerLineVertexPositions',
|
||||||
|
eucp: 'edgeUpperCurvePathIDs',
|
||||||
|
eucv: 'edgeUpperCurveVertexPositions',
|
||||||
|
eulp: 'edgeUpperLinePathIDs',
|
||||||
|
eulv: 'edgeUpperLineVertexPositions',
|
||||||
|
};
|
||||||
|
|
||||||
type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
|
type BufferType = 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER';
|
||||||
|
|
||||||
export interface Meshes<T> {
|
export interface Meshes<T> {
|
||||||
|
@ -70,10 +135,16 @@ export interface Meshes<T> {
|
||||||
readonly bVertexLoopBlinnData: T;
|
readonly bVertexLoopBlinnData: T;
|
||||||
readonly coverInteriorIndices: T;
|
readonly coverInteriorIndices: T;
|
||||||
readonly coverCurveIndices: T;
|
readonly coverCurveIndices: T;
|
||||||
readonly edgeUpperLineIndices: T;
|
readonly edgeBoundingBoxPathIDs: T;
|
||||||
readonly edgeLowerLineIndices: T;
|
readonly edgeBoundingBoxVertexPositions: T;
|
||||||
readonly edgeUpperCurveIndices: T;
|
readonly edgeLowerCurvePathIDs: T;
|
||||||
readonly edgeLowerCurveIndices: T;
|
readonly edgeLowerCurveVertexPositions: T;
|
||||||
|
readonly edgeLowerLinePathIDs: T;
|
||||||
|
readonly edgeLowerLineVertexPositions: T;
|
||||||
|
readonly edgeUpperCurvePathIDs: T;
|
||||||
|
readonly edgeUpperCurveVertexPositions: T;
|
||||||
|
readonly edgeUpperLinePathIDs: T;
|
||||||
|
readonly edgeUpperLineVertexPositions: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PathfinderMeshData implements Meshes<ArrayBuffer> {
|
export class PathfinderMeshData implements Meshes<ArrayBuffer> {
|
||||||
|
@ -83,16 +154,22 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
|
||||||
readonly bVertexLoopBlinnData: ArrayBuffer;
|
readonly bVertexLoopBlinnData: ArrayBuffer;
|
||||||
readonly coverInteriorIndices: ArrayBuffer;
|
readonly coverInteriorIndices: ArrayBuffer;
|
||||||
readonly coverCurveIndices: ArrayBuffer;
|
readonly coverCurveIndices: ArrayBuffer;
|
||||||
readonly edgeUpperLineIndices: ArrayBuffer;
|
readonly edgeBoundingBoxPathIDs: ArrayBuffer;
|
||||||
readonly edgeLowerLineIndices: ArrayBuffer;
|
readonly edgeBoundingBoxVertexPositions: ArrayBuffer;
|
||||||
readonly edgeUpperCurveIndices: ArrayBuffer;
|
readonly edgeLowerCurvePathIDs: ArrayBuffer;
|
||||||
readonly edgeLowerCurveIndices: ArrayBuffer;
|
readonly edgeLowerCurveVertexPositions: ArrayBuffer;
|
||||||
|
readonly edgeLowerLinePathIDs: ArrayBuffer;
|
||||||
|
readonly edgeLowerLineVertexPositions: ArrayBuffer;
|
||||||
|
readonly edgeUpperCurvePathIDs: ArrayBuffer;
|
||||||
|
readonly edgeUpperCurveVertexPositions: ArrayBuffer;
|
||||||
|
readonly edgeUpperLinePathIDs: ArrayBuffer;
|
||||||
|
readonly edgeUpperLineVertexPositions: ArrayBuffer;
|
||||||
|
|
||||||
readonly bQuadCount: number;
|
readonly bQuadCount: number;
|
||||||
readonly edgeUpperLineIndexCount: number;
|
readonly edgeLowerCurveCount: number;
|
||||||
readonly edgeLowerLineIndexCount: number;
|
readonly edgeUpperCurveCount: number;
|
||||||
readonly edgeUpperCurveIndexCount: number;
|
readonly edgeLowerLineCount: number;
|
||||||
readonly edgeLowerCurveIndexCount: number;
|
readonly edgeUpperLineCount: number;
|
||||||
|
|
||||||
constructor(meshes: ArrayBuffer | Meshes<ArrayBuffer>) {
|
constructor(meshes: ArrayBuffer | Meshes<ArrayBuffer>) {
|
||||||
if (meshes instanceof ArrayBuffer) {
|
if (meshes instanceof ArrayBuffer) {
|
||||||
|
@ -119,160 +196,104 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bQuadCount = this.bQuads.byteLength / B_QUAD_SIZE;
|
this.bQuadCount = this.bQuads.byteLength / B_QUAD_SIZE;
|
||||||
this.edgeUpperLineIndexCount = this.edgeUpperLineIndices.byteLength / 8;
|
this.edgeUpperLineCount = this.edgeUpperLinePathIDs.byteLength / 2;
|
||||||
this.edgeLowerLineIndexCount = this.edgeLowerLineIndices.byteLength / 8;
|
this.edgeLowerLineCount = this.edgeLowerLinePathIDs.byteLength / 2;
|
||||||
this.edgeUpperCurveIndexCount = this.edgeUpperCurveIndices.byteLength / 16;
|
this.edgeUpperCurveCount = this.edgeUpperCurvePathIDs.byteLength / 2;
|
||||||
this.edgeLowerCurveIndexCount = this.edgeLowerCurveIndices.byteLength / 16;
|
this.edgeLowerCurveCount = this.edgeLowerCurvePathIDs.byteLength / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
expand(pathIDs: number[]): PathfinderMeshData {
|
expand(pathIDs: number[]): PathfinderMeshData {
|
||||||
const bQuads = new Uint32Array(this.bQuads);
|
const tempOriginalBuffers: any = {}, tempExpandedArrays: any = {};
|
||||||
const bVertexPositions = new Float32Array(this.bVertexPositions);
|
for (const key of Object.keys(BUFFER_TYPES) as Array<keyof Meshes<void>>) {
|
||||||
const bVertexPathIDs = new Uint16Array(this.bVertexPathIDs);
|
const arrayConstructor = PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS[MESH_TYPES[key].type];
|
||||||
const bVertexLoopBlinnData = new Uint32Array(this.bVertexLoopBlinnData);
|
tempOriginalBuffers[key] = new arrayConstructor(this[key]);
|
||||||
|
tempExpandedArrays[key] = [];
|
||||||
|
}
|
||||||
|
|
||||||
const edgeUpperCurveIndices = new Uint32Array(this.edgeUpperCurveIndices);
|
const originalBuffers: Meshes<PrimitiveTypeArray> = tempOriginalBuffers;
|
||||||
const edgeLowerCurveIndices = new Uint32Array(this.edgeLowerCurveIndices);
|
const expandedArrays: Meshes<number[]> = tempExpandedArrays;
|
||||||
for (let indexIndex = 3; indexIndex < edgeUpperCurveIndices.length; indexIndex += 4)
|
|
||||||
edgeUpperCurveIndices[indexIndex] = 0;
|
|
||||||
for (let indexIndex = 3; indexIndex < edgeLowerCurveIndices.length; indexIndex += 4)
|
|
||||||
edgeLowerCurveIndices[indexIndex] = 0;
|
|
||||||
|
|
||||||
const coverInteriorIndices = new Uint32Array(this.coverInteriorIndices);
|
for (let newPathIndex = 0; newPathIndex < pathIDs.length; newPathIndex++) {
|
||||||
const coverCurveIndices = new Uint32Array(this.coverCurveIndices);
|
const expandedPathID = newPathIndex + 1;
|
||||||
const edgeUpperLineIndices = new Uint32Array(this.edgeUpperLineIndices);
|
const originalPathID = pathIDs[newPathIndex];
|
||||||
const edgeLowerLineIndices = new Uint32Array(this.edgeLowerLineIndices);
|
|
||||||
|
|
||||||
const expandedBQuads: number[] = [];
|
const bVertexCopyResult =
|
||||||
const expandedBVertexPositions: number[] = [];
|
copyVertices(['bVertexPositions', 'bVertexLoopBlinnData'],
|
||||||
const expandedBVertexPathIDs: number[] = [];
|
'bVertexPathIDs',
|
||||||
const expandedBVertexLoopBlinnData: number[] = [];
|
expandedArrays,
|
||||||
const expandedCoverInteriorIndices: number[] = [];
|
originalBuffers,
|
||||||
const expandedCoverCurveIndices: number[] = [];
|
expandedPathID,
|
||||||
const expandedEdgeUpperCurveIndices: number[] = [];
|
originalPathID);
|
||||||
const expandedEdgeUpperLineIndices: number[] = [];
|
|
||||||
const expandedEdgeLowerCurveIndices: number[] = [];
|
|
||||||
const expandedEdgeLowerLineIndices: number[] = [];
|
|
||||||
|
|
||||||
let textGlyphIndex = 0;
|
if (bVertexCopyResult == null)
|
||||||
for (const pathID of pathIDs) {
|
|
||||||
const firstBVertexIndex = _.sortedIndex(bVertexPathIDs, pathID);
|
|
||||||
if (firstBVertexIndex < 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Copy over vertices.
|
const firstExpandedBVertexIndex = bVertexCopyResult.expandedStartIndex;
|
||||||
let bVertexIndex = firstBVertexIndex;
|
const firstBVertexIndex = bVertexCopyResult.originalStartIndex;
|
||||||
const firstExpandedBVertexIndex = expandedBVertexPathIDs.length;
|
const lastBVertexIndex = bVertexCopyResult.originalEndIndex;
|
||||||
while (bVertexIndex < bVertexPathIDs.length &&
|
|
||||||
bVertexPathIDs[bVertexIndex] === pathID) {
|
// Copy over edge data.
|
||||||
expandedBVertexPositions.push(bVertexPositions[bVertexIndex * 2 + 0],
|
for (const edgeBufferName of EDGE_BUFFER_NAMES) {
|
||||||
bVertexPositions[bVertexIndex * 2 + 1]);
|
copyVertices([`edge${edgeBufferName}VertexPositions` as keyof Meshes<void>],
|
||||||
expandedBVertexPathIDs.push(textGlyphIndex + 1);
|
`edge${edgeBufferName}PathIDs` as keyof Meshes<void>,
|
||||||
expandedBVertexLoopBlinnData.push(bVertexLoopBlinnData[bVertexIndex]);
|
expandedArrays,
|
||||||
bVertexIndex++;
|
originalBuffers,
|
||||||
|
expandedPathID,
|
||||||
|
originalPathID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over indices.
|
// Copy over indices.
|
||||||
copyIndices(expandedCoverInteriorIndices,
|
copyIndices(expandedArrays.coverInteriorIndices,
|
||||||
coverInteriorIndices,
|
originalBuffers.coverInteriorIndices as Uint32Array,
|
||||||
firstExpandedBVertexIndex,
|
firstExpandedBVertexIndex,
|
||||||
firstBVertexIndex,
|
firstBVertexIndex,
|
||||||
bVertexIndex);
|
lastBVertexIndex);
|
||||||
copyIndices(expandedCoverCurveIndices,
|
copyIndices(expandedArrays.coverCurveIndices,
|
||||||
coverCurveIndices,
|
originalBuffers.coverCurveIndices as Uint32Array,
|
||||||
firstExpandedBVertexIndex,
|
firstExpandedBVertexIndex,
|
||||||
firstBVertexIndex,
|
firstBVertexIndex,
|
||||||
bVertexIndex);
|
lastBVertexIndex);
|
||||||
|
|
||||||
copyIndices(expandedEdgeUpperLineIndices,
|
|
||||||
edgeUpperLineIndices,
|
|
||||||
firstExpandedBVertexIndex,
|
|
||||||
firstBVertexIndex,
|
|
||||||
bVertexIndex);
|
|
||||||
copyIndices(expandedEdgeUpperCurveIndices,
|
|
||||||
edgeUpperCurveIndices,
|
|
||||||
firstExpandedBVertexIndex,
|
|
||||||
firstBVertexIndex,
|
|
||||||
bVertexIndex,
|
|
||||||
indexIndex => indexIndex % 4 < 3);
|
|
||||||
copyIndices(expandedEdgeLowerLineIndices,
|
|
||||||
edgeLowerLineIndices,
|
|
||||||
firstExpandedBVertexIndex,
|
|
||||||
firstBVertexIndex,
|
|
||||||
bVertexIndex);
|
|
||||||
copyIndices(expandedEdgeLowerCurveIndices,
|
|
||||||
edgeLowerCurveIndices,
|
|
||||||
firstExpandedBVertexIndex,
|
|
||||||
firstBVertexIndex,
|
|
||||||
bVertexIndex,
|
|
||||||
indexIndex => indexIndex % 4 < 3);
|
|
||||||
|
|
||||||
// Copy over B-quads.
|
// Copy over B-quads.
|
||||||
let firstBQuadIndex = findFirstBQuadIndex(bQuads, bVertexPathIDs, pathID);
|
let firstBQuadIndex =
|
||||||
|
findFirstBQuadIndex(originalBuffers.bQuads as Uint32Array,
|
||||||
|
originalBuffers.bVertexPathIDs as Uint16Array,
|
||||||
|
originalPathID);
|
||||||
if (firstBQuadIndex == null)
|
if (firstBQuadIndex == null)
|
||||||
firstBQuadIndex = bQuads.length;
|
firstBQuadIndex = originalBuffers.bQuads.length;
|
||||||
const indexDelta = firstExpandedBVertexIndex - firstBVertexIndex;
|
const indexDelta = firstExpandedBVertexIndex - firstBVertexIndex;
|
||||||
for (let bQuadIndex = firstBQuadIndex;
|
for (let bQuadIndex = firstBQuadIndex;
|
||||||
bQuadIndex < bQuads.length / B_QUAD_FIELD_COUNT;
|
bQuadIndex < originalBuffers.bQuads.length / B_QUAD_FIELD_COUNT;
|
||||||
bQuadIndex++) {
|
bQuadIndex++) {
|
||||||
const bQuad = bQuads[bQuadIndex];
|
const bQuad = originalBuffers.bQuads[bQuadIndex];
|
||||||
if (bVertexPathIDs[bQuads[bQuadIndex * B_QUAD_FIELD_COUNT]] !== pathID)
|
if (originalBuffers.bVertexPathIDs[originalBuffers.bQuads[bQuadIndex *
|
||||||
|
B_QUAD_FIELD_COUNT]] !==
|
||||||
|
originalPathID) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
for (let indexIndex = 0; indexIndex < B_QUAD_FIELD_COUNT; indexIndex++) {
|
for (let indexIndex = 0; indexIndex < B_QUAD_FIELD_COUNT; indexIndex++) {
|
||||||
const srcIndex = bQuads[bQuadIndex * B_QUAD_FIELD_COUNT + indexIndex];
|
const srcIndex = originalBuffers.bQuads[bQuadIndex * B_QUAD_FIELD_COUNT +
|
||||||
|
indexIndex];
|
||||||
if (srcIndex === UINT32_MAX)
|
if (srcIndex === UINT32_MAX)
|
||||||
expandedBQuads.push(srcIndex);
|
expandedArrays.bQuads.push(srcIndex);
|
||||||
else
|
else
|
||||||
expandedBQuads.push(srcIndex + indexDelta);
|
expandedArrays.bQuads.push(srcIndex + indexDelta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textGlyphIndex++;
|
const tempExpandedBuffers: any = {};
|
||||||
|
for (const key of Object.keys(MESH_TYPES) as Array<keyof Meshes<void>>) {
|
||||||
|
const bufferType = MESH_TYPES[key].type;
|
||||||
|
const arrayConstructor = PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS[bufferType];
|
||||||
|
const expandedBuffer = new ArrayBuffer(expandedArrays[key].length *
|
||||||
|
sizeOfPrimitive(bufferType));
|
||||||
|
(new arrayConstructor(expandedBuffer)).set(expandedArrays[key]);
|
||||||
|
tempExpandedBuffers[key] = expandedBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const expandedBQuadsBuffer = new ArrayBuffer(expandedBQuads.length * UINT32_SIZE);
|
const expandedBuffers = tempExpandedBuffers as Meshes<ArrayBuffer>;
|
||||||
const expandedBVertexLoopBlinnDataBuffer =
|
return new PathfinderMeshData(expandedBuffers);
|
||||||
new ArrayBuffer(expandedBVertexLoopBlinnData.length * UINT32_SIZE);
|
|
||||||
const expandedBVertexPathIDsBuffer =
|
|
||||||
new ArrayBuffer(expandedBVertexPathIDs.length * UINT16_SIZE);
|
|
||||||
const expandedBVertexPositionsBuffer =
|
|
||||||
new ArrayBuffer(expandedBVertexPositions.length * FLOAT32_SIZE);
|
|
||||||
const expandedCoverCurveIndicesBuffer =
|
|
||||||
new ArrayBuffer(expandedCoverCurveIndices.length * UINT32_SIZE);
|
|
||||||
const expandedCoverInteriorIndicesBuffer =
|
|
||||||
new ArrayBuffer(expandedCoverInteriorIndices.length * UINT32_SIZE);
|
|
||||||
const expandedEdgeLowerCurveIndicesBuffer =
|
|
||||||
new ArrayBuffer(expandedEdgeLowerCurveIndices.length * UINT32_SIZE);
|
|
||||||
const expandedEdgeLowerLineIndicesBuffer =
|
|
||||||
new ArrayBuffer(expandedEdgeLowerLineIndices.length * UINT32_SIZE);
|
|
||||||
const expandedEdgeUpperCurveIndicesBuffer =
|
|
||||||
new ArrayBuffer(expandedEdgeUpperCurveIndices.length * UINT32_SIZE);
|
|
||||||
const expandedEdgeUpperLineIndicesBuffer =
|
|
||||||
new ArrayBuffer(expandedEdgeUpperLineIndices.length * UINT32_SIZE);
|
|
||||||
|
|
||||||
(new Uint32Array(expandedBQuadsBuffer)).set(expandedBQuads);
|
|
||||||
(new Uint32Array(expandedBVertexLoopBlinnDataBuffer)).set(expandedBVertexLoopBlinnData);
|
|
||||||
(new Uint16Array(expandedBVertexPathIDsBuffer)).set(expandedBVertexPathIDs);
|
|
||||||
(new Float32Array(expandedBVertexPositionsBuffer)).set(expandedBVertexPositions);
|
|
||||||
(new Uint32Array(expandedCoverCurveIndicesBuffer)).set(expandedCoverCurveIndices);
|
|
||||||
(new Uint32Array(expandedCoverInteriorIndicesBuffer)).set(expandedCoverInteriorIndices);
|
|
||||||
(new Uint32Array(expandedEdgeLowerCurveIndicesBuffer)).set(expandedEdgeLowerCurveIndices);
|
|
||||||
(new Uint32Array(expandedEdgeLowerLineIndicesBuffer)).set(expandedEdgeLowerLineIndices);
|
|
||||||
(new Uint32Array(expandedEdgeUpperCurveIndicesBuffer)).set(expandedEdgeUpperCurveIndices);
|
|
||||||
(new Uint32Array(expandedEdgeUpperLineIndicesBuffer)).set(expandedEdgeUpperLineIndices);
|
|
||||||
|
|
||||||
return new PathfinderMeshData({
|
|
||||||
bQuads: expandedBQuadsBuffer,
|
|
||||||
bVertexLoopBlinnData: expandedBVertexLoopBlinnDataBuffer,
|
|
||||||
bVertexPathIDs: expandedBVertexPathIDsBuffer,
|
|
||||||
bVertexPositions: expandedBVertexPositionsBuffer,
|
|
||||||
coverCurveIndices: expandedCoverCurveIndicesBuffer,
|
|
||||||
coverInteriorIndices: expandedCoverInteriorIndicesBuffer,
|
|
||||||
edgeLowerCurveIndices: expandedEdgeLowerCurveIndicesBuffer,
|
|
||||||
edgeLowerLineIndices: expandedEdgeLowerLineIndicesBuffer,
|
|
||||||
edgeUpperCurveIndices: expandedEdgeUpperCurveIndicesBuffer,
|
|
||||||
edgeUpperLineIndices: expandedEdgeUpperLineIndicesBuffer,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,10 +304,16 @@ export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
|
||||||
readonly bVertexLoopBlinnData: WebGLBuffer;
|
readonly bVertexLoopBlinnData: WebGLBuffer;
|
||||||
readonly coverInteriorIndices: WebGLBuffer;
|
readonly coverInteriorIndices: WebGLBuffer;
|
||||||
readonly coverCurveIndices: WebGLBuffer;
|
readonly coverCurveIndices: WebGLBuffer;
|
||||||
readonly edgeUpperLineIndices: WebGLBuffer;
|
readonly edgeBoundingBoxPathIDs: WebGLBuffer;
|
||||||
readonly edgeUpperCurveIndices: WebGLBuffer;
|
readonly edgeBoundingBoxVertexPositions: WebGLBuffer;
|
||||||
readonly edgeLowerLineIndices: WebGLBuffer;
|
readonly edgeLowerCurvePathIDs: WebGLBuffer;
|
||||||
readonly edgeLowerCurveIndices: WebGLBuffer;
|
readonly edgeLowerCurveVertexPositions: WebGLBuffer;
|
||||||
|
readonly edgeLowerLinePathIDs: WebGLBuffer;
|
||||||
|
readonly edgeLowerLineVertexPositions: WebGLBuffer;
|
||||||
|
readonly edgeUpperCurvePathIDs: WebGLBuffer;
|
||||||
|
readonly edgeUpperCurveVertexPositions: WebGLBuffer;
|
||||||
|
readonly edgeUpperLinePathIDs: WebGLBuffer;
|
||||||
|
readonly edgeUpperLineVertexPositions: WebGLBuffer;
|
||||||
|
|
||||||
constructor(gl: WebGLRenderingContext, meshData: PathfinderMeshData) {
|
constructor(gl: WebGLRenderingContext, meshData: PathfinderMeshData) {
|
||||||
for (const bufferName of Object.keys(BUFFER_TYPES) as Array<keyof PathfinderMeshBuffers>) {
|
for (const bufferName of Object.keys(BUFFER_TYPES) as Array<keyof PathfinderMeshBuffers>) {
|
||||||
|
@ -299,6 +326,48 @@ export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyVertices<T>(vertexBufferNames: Array<keyof Meshes<void>>,
|
||||||
|
pathIDBufferName: keyof Meshes<void>,
|
||||||
|
expandedMeshes: Meshes<number[]>,
|
||||||
|
originalMeshes: Meshes<PrimitiveTypeArray>,
|
||||||
|
expandedPathID: number,
|
||||||
|
originalPathID: number):
|
||||||
|
VertexCopyResult | null {
|
||||||
|
const expandedPathIDs = expandedMeshes[pathIDBufferName];
|
||||||
|
const originalPathIDs = originalMeshes[pathIDBufferName];
|
||||||
|
|
||||||
|
const firstOriginalVertexIndex = _.sortedIndex(originalPathIDs, originalPathID);
|
||||||
|
if (firstOriginalVertexIndex < 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
const firstExpandedVertexIndex = expandedPathIDs.length;
|
||||||
|
let lastOriginalVertexIndex = firstOriginalVertexIndex;
|
||||||
|
|
||||||
|
while (lastOriginalVertexIndex < originalPathIDs.length &&
|
||||||
|
originalPathIDs[lastOriginalVertexIndex] === originalPathID) {
|
||||||
|
for (const vertexBufferName of vertexBufferNames) {
|
||||||
|
const expanded = expandedMeshes[vertexBufferName];
|
||||||
|
const original = originalMeshes[vertexBufferName];
|
||||||
|
const size = MESH_TYPES[vertexBufferName].size;
|
||||||
|
for (let elementIndex = 0; elementIndex < size; elementIndex++) {
|
||||||
|
const globalIndex = size * lastOriginalVertexIndex + elementIndex;
|
||||||
|
expanded.push(original[globalIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expandedPathIDs.push(expandedPathID);
|
||||||
|
|
||||||
|
lastOriginalVertexIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
expandedEndIndex: expandedPathIDs.length,
|
||||||
|
expandedStartIndex: firstExpandedVertexIndex,
|
||||||
|
originalEndIndex: lastOriginalVertexIndex,
|
||||||
|
originalStartIndex: firstOriginalVertexIndex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function copyIndices(destIndices: number[],
|
function copyIndices(destIndices: number[],
|
||||||
srcIndices: Uint32Array,
|
srcIndices: Uint32Array,
|
||||||
firstExpandedIndex: number,
|
firstExpandedIndex: number,
|
||||||
|
@ -327,6 +396,14 @@ function copyIndices(destIndices: number[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sizeOfPrimitive(primitiveType: PrimitiveType): number {
|
||||||
|
switch (primitiveType) {
|
||||||
|
case 'Uint16': return UINT16_SIZE;
|
||||||
|
case 'Uint32': return UINT32_SIZE;
|
||||||
|
case 'Float32': return FLOAT32_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function findFirstBQuadIndex(bQuads: Uint32Array,
|
function findFirstBQuadIndex(bQuads: Uint32Array,
|
||||||
bVertexPathIDs: Uint16Array,
|
bVertexPathIDs: Uint16Array,
|
||||||
queryPathID: number):
|
queryPathID: number):
|
||||||
|
|
|
@ -17,13 +17,13 @@ import {DemoAppController} from './app-controller';
|
||||||
import PathfinderBufferTexture from "./buffer-texture";
|
import PathfinderBufferTexture from "./buffer-texture";
|
||||||
import {OrthographicCamera} from "./camera";
|
import {OrthographicCamera} from "./camera";
|
||||||
import {ECAAMulticolorStrategy, ECAAStrategy} from "./ecaa-strategy";
|
import {ECAAMulticolorStrategy, ECAAStrategy} from "./ecaa-strategy";
|
||||||
|
import {UniformMap} from './gl-utils';
|
||||||
import {PathfinderMeshData} from "./meshes";
|
import {PathfinderMeshData} from "./meshes";
|
||||||
import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
||||||
import SSAAStrategy from "./ssaa-strategy";
|
import SSAAStrategy from "./ssaa-strategy";
|
||||||
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
|
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
|
||||||
import {panic, unwrapNull} from './utils';
|
import {panic, unwrapNull} from './utils';
|
||||||
import {DemoView, Timings} from './view';
|
import {DemoView, Timings} from './view';
|
||||||
import { UniformMap } from './gl-utils';
|
|
||||||
|
|
||||||
const parseColor = require('parse-color');
|
const parseColor = require('parse-color');
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||||
app_units = "0.5"
|
app_units = "0.5"
|
||||||
base64 = "0.6"
|
base64 = "0.6"
|
||||||
bincode = "0.8"
|
bincode = "0.8"
|
||||||
env_logger = "0.3"
|
env_logger = "0.4"
|
||||||
euclid = "0.15"
|
euclid = "0.15"
|
||||||
lazy_static = "0.2"
|
lazy_static = "0.2"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::slice;
|
||||||
|
|
||||||
use mesh_library::MeshLibrary;
|
use mesh_library::MeshLibrary;
|
||||||
use partitioner::Partitioner;
|
use partitioner::Partitioner;
|
||||||
use {BQuad, BVertexLoopBlinnData, CurveIndices, Endpoint, LineIndices, Subpath};
|
use {BQuad, BVertexLoopBlinnData, Endpoint, Subpath};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -43,19 +43,6 @@ pub struct CoverIndices {
|
||||||
pub curve_indices_len: u32,
|
pub curve_indices_len: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct EdgeIndices {
|
|
||||||
pub upper_line_indices: *const LineIndices,
|
|
||||||
pub upper_line_indices_len: u32,
|
|
||||||
pub upper_curve_indices: *const CurveIndices,
|
|
||||||
pub upper_curve_indices_len: u32,
|
|
||||||
pub lower_line_indices: *const LineIndices,
|
|
||||||
pub lower_line_indices_len: u32,
|
|
||||||
pub lower_curve_indices: *const CurveIndices,
|
|
||||||
pub lower_curve_indices_len: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern fn pf_partitioner_new() -> *mut Partitioner<'static> {
|
pub unsafe extern fn pf_partitioner_new() -> *mut Partitioner<'static> {
|
||||||
let mut partitioner = Box::new(Partitioner::new(MeshLibrary::new()));
|
let mut partitioner = Box::new(Partitioner::new(MeshLibrary::new()));
|
||||||
|
@ -146,20 +133,6 @@ pub unsafe extern fn pf_partitioner_cover_indices<'a>(partitioner: *const Partit
|
||||||
(*out_cover_indices).curve_indices_len = cover_indices.curve_indices.len() as u32;
|
(*out_cover_indices).curve_indices_len = cover_indices.curve_indices.len() as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern fn pf_partitioner_edge_indices<'a>(partitioner: *const Partitioner<'a>,
|
|
||||||
out_edge_indices: *mut EdgeIndices) {
|
|
||||||
let edge_indices = &(*partitioner).library().edge_indices;
|
|
||||||
(*out_edge_indices).upper_line_indices = edge_indices.upper_line_indices.as_ptr();
|
|
||||||
(*out_edge_indices).upper_line_indices_len = edge_indices.upper_line_indices.len() as u32;
|
|
||||||
(*out_edge_indices).upper_curve_indices = edge_indices.upper_curve_indices.as_ptr();
|
|
||||||
(*out_edge_indices).upper_curve_indices_len = edge_indices.upper_curve_indices.len() as u32;
|
|
||||||
(*out_edge_indices).lower_line_indices = edge_indices.lower_line_indices.as_ptr();
|
|
||||||
(*out_edge_indices).lower_line_indices_len = edge_indices.lower_line_indices.len() as u32;
|
|
||||||
(*out_edge_indices).lower_curve_indices = edge_indices.lower_curve_indices.as_ptr();
|
|
||||||
(*out_edge_indices).lower_curve_indices_len = edge_indices.lower_curve_indices.len() as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern fn pf_init_env_logger() -> u32 {
|
pub unsafe extern fn pf_init_env_logger() -> u32 {
|
||||||
env_logger::init().is_ok() as u32
|
env_logger::init().is_ok() as u32
|
||||||
|
|
|
@ -145,57 +145,3 @@ impl BVertexLoopBlinnData {
|
||||||
BVertexLoopBlinnData::new(endpoint_kind)
|
BVertexLoopBlinnData::new(endpoint_kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct LineIndices {
|
|
||||||
pub left_vertex_index: u32,
|
|
||||||
pub right_vertex_index: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LineIndices {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(left_vertex_index: u32, right_vertex_index: u32) -> LineIndices {
|
|
||||||
LineIndices {
|
|
||||||
left_vertex_index: left_vertex_index,
|
|
||||||
right_vertex_index: right_vertex_index,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn offset(&mut self, delta: u32) {
|
|
||||||
self.left_vertex_index += delta;
|
|
||||||
self.right_vertex_index += delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct CurveIndices {
|
|
||||||
pub left_vertex_index: u32,
|
|
||||||
pub right_vertex_index: u32,
|
|
||||||
pub control_point_vertex_index: u32,
|
|
||||||
pad: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CurveIndices {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(left_vertex_index: u32, control_point_vertex_index: u32, right_vertex_index: u32)
|
|
||||||
-> CurveIndices {
|
|
||||||
CurveIndices {
|
|
||||||
left_vertex_index: left_vertex_index,
|
|
||||||
right_vertex_index: right_vertex_index,
|
|
||||||
control_point_vertex_index: control_point_vertex_index,
|
|
||||||
pad: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn offset(&mut self, delta: u32) {
|
|
||||||
self.left_vertex_index += delta;
|
|
||||||
self.right_vertex_index += delta;
|
|
||||||
if self.control_point_vertex_index < u32::MAX {
|
|
||||||
self.control_point_vertex_index += delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,8 +14,9 @@ use euclid::Point2D;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::io::{self, ErrorKind, Seek, SeekFrom, Write};
|
use std::io::{self, ErrorKind, Seek, SeekFrom, Write};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
use std::u32;
|
||||||
|
|
||||||
use {BQuad, BVertexLoopBlinnData, CurveIndices, LineIndices};
|
use {BQuad, BVertexLoopBlinnData};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MeshLibrary {
|
pub struct MeshLibrary {
|
||||||
|
@ -24,7 +25,7 @@ pub struct MeshLibrary {
|
||||||
pub b_vertex_path_ids: Vec<u16>,
|
pub b_vertex_path_ids: Vec<u16>,
|
||||||
pub b_vertex_loop_blinn_data: Vec<BVertexLoopBlinnData>,
|
pub b_vertex_loop_blinn_data: Vec<BVertexLoopBlinnData>,
|
||||||
pub cover_indices: MeshLibraryCoverIndices,
|
pub cover_indices: MeshLibraryCoverIndices,
|
||||||
pub edge_indices: MeshLibraryEdgeIndices,
|
pub edge_data: MeshLibraryEdgeData,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeshLibrary {
|
impl MeshLibrary {
|
||||||
|
@ -36,7 +37,7 @@ impl MeshLibrary {
|
||||||
b_vertex_path_ids: vec![],
|
b_vertex_path_ids: vec![],
|
||||||
b_vertex_loop_blinn_data: vec![],
|
b_vertex_loop_blinn_data: vec![],
|
||||||
cover_indices: MeshLibraryCoverIndices::new(),
|
cover_indices: MeshLibraryCoverIndices::new(),
|
||||||
edge_indices: MeshLibraryEdgeIndices::new(),
|
edge_data: MeshLibraryEdgeData::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +47,69 @@ impl MeshLibrary {
|
||||||
self.b_vertex_path_ids.clear();
|
self.b_vertex_path_ids.clear();
|
||||||
self.b_vertex_loop_blinn_data.clear();
|
self.b_vertex_loop_blinn_data.clear();
|
||||||
self.cover_indices.clear();
|
self.cover_indices.clear();
|
||||||
self.edge_indices.clear();
|
self.edge_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_b_quad(&mut self, b_quad: &BQuad) {
|
||||||
|
self.b_quads.push(*b_quad);
|
||||||
|
|
||||||
|
let path_id = self.b_vertex_path_ids[b_quad.upper_left_vertex_index as usize];
|
||||||
|
|
||||||
|
let upper_left_position =
|
||||||
|
&self.b_vertex_positions[b_quad.upper_left_vertex_index as usize];
|
||||||
|
let upper_right_position =
|
||||||
|
&self.b_vertex_positions[b_quad.upper_right_vertex_index as usize];
|
||||||
|
let lower_left_position =
|
||||||
|
&self.b_vertex_positions[b_quad.lower_left_vertex_index as usize];
|
||||||
|
let lower_right_position =
|
||||||
|
&self.b_vertex_positions[b_quad.lower_right_vertex_index as usize];
|
||||||
|
|
||||||
|
let upper_left_bounding_box_position =
|
||||||
|
Point2D::new(upper_left_position.x,
|
||||||
|
f32::min(upper_left_position.y, upper_right_position.y));
|
||||||
|
let lower_right_bounding_box_position =
|
||||||
|
Point2D::new(lower_right_position.x,
|
||||||
|
f32::max(lower_left_position.y, lower_right_position.y));
|
||||||
|
|
||||||
|
self.edge_data.bounding_box_vertex_positions.push(EdgeBoundingBoxVertexPositions {
|
||||||
|
upper_left: upper_left_bounding_box_position,
|
||||||
|
lower_right: lower_right_bounding_box_position,
|
||||||
|
});
|
||||||
|
self.edge_data.bounding_box_path_ids.push(path_id);
|
||||||
|
|
||||||
|
if b_quad.upper_control_point_vertex_index == u32::MAX {
|
||||||
|
self.edge_data.upper_line_vertex_positions.push(EdgeLineVertexPositions {
|
||||||
|
left: *upper_left_position,
|
||||||
|
right: *upper_right_position,
|
||||||
|
});
|
||||||
|
self.edge_data.upper_line_path_ids.push(path_id);
|
||||||
|
} else {
|
||||||
|
let upper_control_point_position =
|
||||||
|
&self.b_vertex_positions[b_quad.upper_control_point_vertex_index as usize];
|
||||||
|
self.edge_data.upper_curve_vertex_positions.push(EdgeCurveVertexPositions {
|
||||||
|
left: *upper_left_position,
|
||||||
|
control_point: *upper_control_point_position,
|
||||||
|
right: *upper_right_position,
|
||||||
|
});
|
||||||
|
self.edge_data.upper_curve_path_ids.push(path_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if b_quad.lower_control_point_vertex_index == u32::MAX {
|
||||||
|
self.edge_data.lower_line_vertex_positions.push(EdgeLineVertexPositions {
|
||||||
|
left: *lower_left_position,
|
||||||
|
right: *lower_right_position,
|
||||||
|
});
|
||||||
|
self.edge_data.lower_line_path_ids.push(path_id);
|
||||||
|
} else {
|
||||||
|
let lower_control_point_position =
|
||||||
|
&self.b_vertex_positions[b_quad.lower_control_point_vertex_index as usize];
|
||||||
|
self.edge_data.lower_curve_vertex_positions.push(EdgeCurveVertexPositions {
|
||||||
|
left: *lower_left_position,
|
||||||
|
control_point: *lower_control_point_position,
|
||||||
|
right: *lower_right_position,
|
||||||
|
});
|
||||||
|
self.edge_data.lower_curve_path_ids.push(path_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reverses interior indices so that they draw front-to-back.
|
/// Reverses interior indices so that they draw front-to-back.
|
||||||
|
@ -97,10 +160,16 @@ impl MeshLibrary {
|
||||||
try!(write_chunk(writer, b"bvlb", &self.b_vertex_loop_blinn_data));
|
try!(write_chunk(writer, b"bvlb", &self.b_vertex_loop_blinn_data));
|
||||||
try!(write_chunk(writer, b"cvii", &self.cover_indices.interior_indices));
|
try!(write_chunk(writer, b"cvii", &self.cover_indices.interior_indices));
|
||||||
try!(write_chunk(writer, b"cvci", &self.cover_indices.curve_indices));
|
try!(write_chunk(writer, b"cvci", &self.cover_indices.curve_indices));
|
||||||
try!(write_chunk(writer, b"euli", &self.edge_indices.upper_line_indices));
|
try!(write_chunk(writer, b"ebbv", &self.edge_data.bounding_box_vertex_positions));
|
||||||
try!(write_chunk(writer, b"euci", &self.edge_indices.upper_curve_indices));
|
try!(write_chunk(writer, b"eulv", &self.edge_data.upper_line_vertex_positions));
|
||||||
try!(write_chunk(writer, b"elli", &self.edge_indices.lower_line_indices));
|
try!(write_chunk(writer, b"ellv", &self.edge_data.lower_line_vertex_positions));
|
||||||
try!(write_chunk(writer, b"elci", &self.edge_indices.lower_curve_indices));
|
try!(write_chunk(writer, b"eucv", &self.edge_data.upper_curve_vertex_positions));
|
||||||
|
try!(write_chunk(writer, b"elcv", &self.edge_data.lower_curve_vertex_positions));
|
||||||
|
try!(write_chunk(writer, b"ebbp", &self.edge_data.bounding_box_path_ids));
|
||||||
|
try!(write_chunk(writer, b"eulp", &self.edge_data.upper_line_path_ids));
|
||||||
|
try!(write_chunk(writer, b"ellp", &self.edge_data.lower_line_path_ids));
|
||||||
|
try!(write_chunk(writer, b"eucp", &self.edge_data.upper_curve_path_ids));
|
||||||
|
try!(write_chunk(writer, b"elcp", &self.edge_data.lower_curve_path_ids));
|
||||||
|
|
||||||
let total_length = try!(writer.seek(SeekFrom::Current(0)));
|
let total_length = try!(writer.seek(SeekFrom::Current(0)));
|
||||||
try!(writer.seek(SeekFrom::Start(4)));
|
try!(writer.seek(SeekFrom::Start(4)));
|
||||||
|
@ -133,10 +202,11 @@ impl MeshLibrary {
|
||||||
b_vertices: self.b_vertex_positions.len(),
|
b_vertices: self.b_vertex_positions.len(),
|
||||||
cover_interior_indices: self.cover_indices.interior_indices.len(),
|
cover_interior_indices: self.cover_indices.interior_indices.len(),
|
||||||
cover_curve_indices: self.cover_indices.curve_indices.len(),
|
cover_curve_indices: self.cover_indices.curve_indices.len(),
|
||||||
edge_upper_line_indices: self.edge_indices.upper_line_indices.len(),
|
edge_bounding_box_indices: self.edge_data.bounding_box_vertex_positions.len(),
|
||||||
edge_upper_curve_indices: self.edge_indices.upper_curve_indices.len(),
|
edge_upper_line_indices: self.edge_data.upper_line_vertex_positions.len(),
|
||||||
edge_lower_line_indices: self.edge_indices.lower_line_indices.len(),
|
edge_upper_curve_indices: self.edge_data.upper_curve_vertex_positions.len(),
|
||||||
edge_lower_curve_indices: self.edge_indices.lower_curve_indices.len(),
|
edge_lower_line_indices: self.edge_data.lower_line_vertex_positions.len(),
|
||||||
|
edge_lower_curve_indices: self.edge_data.lower_curve_vertex_positions.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,38 +232,12 @@ impl MeshLibraryCoverIndices {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct MeshLibraryEdgeIndices {
|
|
||||||
pub upper_line_indices: Vec<LineIndices>,
|
|
||||||
pub upper_curve_indices: Vec<CurveIndices>,
|
|
||||||
pub lower_line_indices: Vec<LineIndices>,
|
|
||||||
pub lower_curve_indices: Vec<CurveIndices>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MeshLibraryEdgeIndices {
|
|
||||||
#[inline]
|
|
||||||
fn new() -> MeshLibraryEdgeIndices {
|
|
||||||
MeshLibraryEdgeIndices {
|
|
||||||
upper_line_indices: vec![],
|
|
||||||
upper_curve_indices: vec![],
|
|
||||||
lower_line_indices: vec![],
|
|
||||||
lower_curve_indices: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&mut self) {
|
|
||||||
self.upper_line_indices.clear();
|
|
||||||
self.upper_curve_indices.clear();
|
|
||||||
self.lower_line_indices.clear();
|
|
||||||
self.lower_curve_indices.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct MeshLibraryLengths {
|
pub(crate) struct MeshLibraryLengths {
|
||||||
b_quads: usize,
|
b_quads: usize,
|
||||||
b_vertices: usize,
|
b_vertices: usize,
|
||||||
cover_interior_indices: usize,
|
cover_interior_indices: usize,
|
||||||
cover_curve_indices: usize,
|
cover_curve_indices: usize,
|
||||||
|
edge_bounding_box_indices: usize,
|
||||||
edge_upper_line_indices: usize,
|
edge_upper_line_indices: usize,
|
||||||
edge_upper_curve_indices: usize,
|
edge_upper_curve_indices: usize,
|
||||||
edge_lower_line_indices: usize,
|
edge_lower_line_indices: usize,
|
||||||
|
@ -205,6 +249,7 @@ pub struct MeshLibraryIndexRanges {
|
||||||
pub b_vertices: Range<usize>,
|
pub b_vertices: Range<usize>,
|
||||||
pub cover_interior_indices: Range<usize>,
|
pub cover_interior_indices: Range<usize>,
|
||||||
pub cover_curve_indices: Range<usize>,
|
pub cover_curve_indices: Range<usize>,
|
||||||
|
pub edge_bounding_box_indices: Range<usize>,
|
||||||
pub edge_upper_line_indices: Range<usize>,
|
pub edge_upper_line_indices: Range<usize>,
|
||||||
pub edge_upper_curve_indices: Range<usize>,
|
pub edge_upper_curve_indices: Range<usize>,
|
||||||
pub edge_lower_line_indices: Range<usize>,
|
pub edge_lower_line_indices: Range<usize>,
|
||||||
|
@ -219,6 +264,8 @@ impl MeshLibraryIndexRanges {
|
||||||
b_vertices: start.b_vertices..end.b_vertices,
|
b_vertices: start.b_vertices..end.b_vertices,
|
||||||
cover_interior_indices: start.cover_interior_indices..end.cover_interior_indices,
|
cover_interior_indices: start.cover_interior_indices..end.cover_interior_indices,
|
||||||
cover_curve_indices: start.cover_curve_indices..end.cover_curve_indices,
|
cover_curve_indices: start.cover_curve_indices..end.cover_curve_indices,
|
||||||
|
edge_bounding_box_indices:
|
||||||
|
start.edge_bounding_box_indices..end.edge_bounding_box_indices,
|
||||||
edge_upper_line_indices: start.edge_upper_line_indices..end.edge_upper_line_indices,
|
edge_upper_line_indices: start.edge_upper_line_indices..end.edge_upper_line_indices,
|
||||||
edge_upper_curve_indices: start.edge_upper_curve_indices..end.edge_upper_curve_indices,
|
edge_upper_curve_indices: start.edge_upper_curve_indices..end.edge_upper_curve_indices,
|
||||||
edge_lower_line_indices: start.edge_lower_line_indices..end.edge_lower_line_indices,
|
edge_lower_line_indices: start.edge_lower_line_indices..end.edge_lower_line_indices,
|
||||||
|
@ -226,3 +273,66 @@ impl MeshLibraryIndexRanges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct MeshLibraryEdgeData {
|
||||||
|
pub bounding_box_vertex_positions: Vec<EdgeBoundingBoxVertexPositions>,
|
||||||
|
pub upper_line_vertex_positions: Vec<EdgeLineVertexPositions>,
|
||||||
|
pub lower_line_vertex_positions: Vec<EdgeLineVertexPositions>,
|
||||||
|
pub upper_curve_vertex_positions: Vec<EdgeCurveVertexPositions>,
|
||||||
|
pub lower_curve_vertex_positions: Vec<EdgeCurveVertexPositions>,
|
||||||
|
pub bounding_box_path_ids: Vec<u16>,
|
||||||
|
pub upper_line_path_ids: Vec<u16>,
|
||||||
|
pub lower_line_path_ids: Vec<u16>,
|
||||||
|
pub upper_curve_path_ids: Vec<u16>,
|
||||||
|
pub lower_curve_path_ids: Vec<u16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MeshLibraryEdgeData {
|
||||||
|
fn new() -> MeshLibraryEdgeData {
|
||||||
|
MeshLibraryEdgeData {
|
||||||
|
bounding_box_vertex_positions: vec![],
|
||||||
|
upper_line_vertex_positions: vec![],
|
||||||
|
lower_line_vertex_positions: vec![],
|
||||||
|
upper_curve_vertex_positions: vec![],
|
||||||
|
lower_curve_vertex_positions: vec![],
|
||||||
|
bounding_box_path_ids: vec![],
|
||||||
|
upper_line_path_ids: vec![],
|
||||||
|
lower_line_path_ids: vec![],
|
||||||
|
upper_curve_path_ids: vec![],
|
||||||
|
lower_curve_path_ids: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.bounding_box_vertex_positions.clear();
|
||||||
|
self.upper_line_vertex_positions.clear();
|
||||||
|
self.upper_curve_vertex_positions.clear();
|
||||||
|
self.lower_line_vertex_positions.clear();
|
||||||
|
self.lower_curve_vertex_positions.clear();
|
||||||
|
self.bounding_box_path_ids.clear();
|
||||||
|
self.upper_line_path_ids.clear();
|
||||||
|
self.upper_curve_path_ids.clear();
|
||||||
|
self.lower_line_path_ids.clear();
|
||||||
|
self.lower_curve_path_ids.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct EdgeBoundingBoxVertexPositions {
|
||||||
|
pub upper_left: Point2D<f32>,
|
||||||
|
pub lower_right: Point2D<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct EdgeLineVertexPositions {
|
||||||
|
pub left: Point2D<f32>,
|
||||||
|
pub right: Point2D<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct EdgeCurveVertexPositions {
|
||||||
|
pub left: Point2D<f32>,
|
||||||
|
pub control_point: Point2D<f32>,
|
||||||
|
pub right: Point2D<f32>,
|
||||||
|
}
|
||||||
|
|
|
@ -22,8 +22,7 @@ use std::iter;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
use mesh_library::{MeshLibrary, MeshLibraryIndexRanges};
|
use mesh_library::{MeshLibrary, MeshLibraryIndexRanges};
|
||||||
use {BQuad, BVertexLoopBlinnData, BVertexKind, CurveIndices, Endpoint, FillRule};
|
use {BQuad, BVertexLoopBlinnData, BVertexKind, Endpoint, FillRule, Subpath};
|
||||||
use {LineIndices, Subpath};
|
|
||||||
|
|
||||||
const MAX_B_QUAD_SUBDIVISIONS: u8 = 8;
|
const MAX_B_QUAD_SUBDIVISIONS: u8 = 8;
|
||||||
|
|
||||||
|
@ -610,41 +609,6 @@ impl<'a> Partitioner<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match upper_shape {
|
|
||||||
Shape::Flat => {
|
|
||||||
self.library
|
|
||||||
.edge_indices
|
|
||||||
.upper_line_indices
|
|
||||||
.push(LineIndices::new(upper_subdivision.left_curve_left,
|
|
||||||
upper_subdivision.middle_point))
|
|
||||||
}
|
|
||||||
Shape::Convex | Shape::Concave => {
|
|
||||||
self.library
|
|
||||||
.edge_indices
|
|
||||||
.upper_curve_indices
|
|
||||||
.push(CurveIndices::new(upper_subdivision.left_curve_left,
|
|
||||||
upper_subdivision.left_curve_control_point,
|
|
||||||
upper_subdivision.middle_point))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match lower_shape {
|
|
||||||
Shape::Flat => {
|
|
||||||
self.library
|
|
||||||
.edge_indices
|
|
||||||
.lower_line_indices
|
|
||||||
.push(LineIndices::new(lower_subdivision.left_curve_left,
|
|
||||||
lower_subdivision.middle_point))
|
|
||||||
}
|
|
||||||
Shape::Convex | Shape::Concave => {
|
|
||||||
self.library
|
|
||||||
.edge_indices
|
|
||||||
.lower_curve_indices
|
|
||||||
.push(CurveIndices::new(lower_subdivision.left_curve_left,
|
|
||||||
lower_subdivision.left_curve_control_point,
|
|
||||||
lower_subdivision.middle_point))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("... emitting B-quad: UL {} BL {} UR {} BR {}",
|
debug!("... emitting B-quad: UL {} BL {} UR {} BR {}",
|
||||||
upper_subdivision.left_curve_left,
|
upper_subdivision.left_curve_left,
|
||||||
lower_subdivision.left_curve_left,
|
lower_subdivision.left_curve_left,
|
||||||
|
@ -773,7 +737,7 @@ impl<'a> Partitioner<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.library.b_quads.push(BQuad::new(upper_subdivision.left_curve_left,
|
self.library.add_b_quad(&BQuad::new(upper_subdivision.left_curve_left,
|
||||||
upper_subdivision.left_curve_control_point,
|
upper_subdivision.left_curve_control_point,
|
||||||
upper_subdivision.middle_point,
|
upper_subdivision.middle_point,
|
||||||
lower_subdivision.left_curve_left,
|
lower_subdivision.left_curve_left,
|
||||||
|
|
|
@ -192,29 +192,11 @@ int unpackUInt16(vec2 packedValue) {
|
||||||
return valueBytes.y * 256 + valueBytes.x;
|
return valueBytes.y * 256 + valueBytes.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unpackUInt32Attribute(vec2 packedValue) {
|
|
||||||
ivec2 valueWords = ivec2(packedValue);
|
|
||||||
return valueWords.y * 65536 + valueWords.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 fetchFloat4Data(sampler2D dataTexture, int index, ivec2 dimensions) {
|
vec4 fetchFloat4Data(sampler2D dataTexture, int index, ivec2 dimensions) {
|
||||||
ivec2 pixelCoord = ivec2(imod(index, dimensions.x), index / dimensions.x);
|
ivec2 pixelCoord = ivec2(imod(index, dimensions.x), index / dimensions.x);
|
||||||
return texture2D(dataTexture, (vec2(pixelCoord) + 0.5) / vec2(dimensions));
|
return texture2D(dataTexture, (vec2(pixelCoord) + 0.5) / vec2(dimensions));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 fetchFloat4NormIndexedData(sampler2D dataTexture, float normIndex, ivec2 dimensions) {
|
|
||||||
return fetchFloat4Data(dataTexture, int(normIndex * float(dimensions.x)), dimensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 fetchFloat2Data(sampler2D dataTexture, int index, ivec2 dimensions) {
|
|
||||||
vec4 float4Data = fetchFloat4Data(dataTexture, index / 2, dimensions);
|
|
||||||
return index / 2 * 2 == index ? float4Data.xy : float4Data.zw;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fetchUInt16Data(sampler2D dataTexture, int index, ivec2 dimensions) {
|
|
||||||
return unpackUInt16(fetchFloat2Data(dataTexture, index, dimensions));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 packPathID(int pathID) {
|
vec2 packPathID(int pathID) {
|
||||||
return vec2(imod(pathID, 256), pathID / 256) / 255.0;
|
return vec2(imod(pathID, 256), pathID / 256) / 255.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,47 +13,23 @@ precision highp float;
|
||||||
uniform vec4 uTransformST;
|
uniform vec4 uTransformST;
|
||||||
uniform vec4 uHints;
|
uniform vec4 uHints;
|
||||||
uniform ivec2 uFramebufferSize;
|
uniform ivec2 uFramebufferSize;
|
||||||
uniform ivec2 uBVertexPositionDimensions;
|
|
||||||
uniform ivec2 uBVertexPathIDDimensions;
|
|
||||||
uniform ivec2 uPathTransformDimensions;
|
uniform ivec2 uPathTransformDimensions;
|
||||||
uniform sampler2D uBVertexPosition;
|
|
||||||
uniform sampler2D uBVertexPathID;
|
|
||||||
uniform sampler2D uPathTransform;
|
uniform sampler2D uPathTransform;
|
||||||
|
|
||||||
attribute vec2 aQuadPosition;
|
attribute vec2 aQuadPosition;
|
||||||
attribute vec4 aUpperPointIndices;
|
attribute vec2 aUpperLeftPosition;
|
||||||
attribute vec4 aLowerPointIndices;
|
attribute vec2 aLowerRightPosition;
|
||||||
|
attribute float aPathID;
|
||||||
|
|
||||||
varying vec2 vHorizontalExtents;
|
varying vec2 vHorizontalExtents;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Fetch B-vertex positions.
|
int pathID = int(aPathID);
|
||||||
ivec4 pointIndices = ivec4(unpackUInt32Attribute(aUpperPointIndices.xy),
|
|
||||||
unpackUInt32Attribute(aUpperPointIndices.zw),
|
|
||||||
unpackUInt32Attribute(aLowerPointIndices.xy),
|
|
||||||
unpackUInt32Attribute(aLowerPointIndices.zw));
|
|
||||||
vec2 upperLeftPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.x,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
vec2 upperRightPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.y,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
vec2 lowerLeftPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.z,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
vec2 lowerRightPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.w,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
|
|
||||||
upperLeftPosition.y = min(upperLeftPosition.y, upperRightPosition.y);
|
|
||||||
lowerRightPosition.y = max(lowerLeftPosition.y, lowerRightPosition.y);
|
|
||||||
|
|
||||||
int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
|
|
||||||
|
|
||||||
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||||
|
|
||||||
upperLeftPosition = hintPosition(upperLeftPosition, uHints);
|
vec2 upperLeftPosition = hintPosition(aUpperLeftPosition, uHints);
|
||||||
lowerRightPosition = hintPosition(lowerRightPosition, uHints);
|
vec2 lowerRightPosition = hintPosition(aLowerRightPosition, uHints);
|
||||||
|
|
||||||
upperLeftPosition = transformVertexPositionST(upperLeftPosition, transform);
|
upperLeftPosition = transformVertexPositionST(upperLeftPosition, transform);
|
||||||
lowerRightPosition = transformVertexPositionST(lowerRightPosition, transform);
|
lowerRightPosition = transformVertexPositionST(lowerRightPosition, transform);
|
||||||
|
|
|
@ -13,37 +13,24 @@ precision highp float;
|
||||||
uniform vec4 uTransformST;
|
uniform vec4 uTransformST;
|
||||||
uniform vec4 uHints;
|
uniform vec4 uHints;
|
||||||
uniform ivec2 uFramebufferSize;
|
uniform ivec2 uFramebufferSize;
|
||||||
uniform ivec2 uBVertexPositionDimensions;
|
|
||||||
uniform ivec2 uBVertexPathIDDimensions;
|
|
||||||
uniform ivec2 uPathTransformDimensions;
|
uniform ivec2 uPathTransformDimensions;
|
||||||
uniform sampler2D uBVertexPosition;
|
|
||||||
uniform sampler2D uBVertexPathID;
|
|
||||||
uniform sampler2D uPathTransform;
|
uniform sampler2D uPathTransform;
|
||||||
uniform bool uLowerPart;
|
uniform bool uLowerPart;
|
||||||
|
|
||||||
attribute vec2 aQuadPosition;
|
attribute vec2 aQuadPosition;
|
||||||
attribute vec4 aCurveEndpointIndices;
|
attribute vec2 aLeftPosition;
|
||||||
attribute vec2 aCurveControlPointIndex;
|
attribute vec2 aControlPointPosition;
|
||||||
|
attribute vec2 aRightPosition;
|
||||||
|
attribute float aPathID;
|
||||||
|
|
||||||
varying vec4 vEndpoints;
|
varying vec4 vEndpoints;
|
||||||
varying vec2 vControlPoint;
|
varying vec2 vControlPoint;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Fetch B-vertex positions.
|
vec2 leftPosition = aLeftPosition;
|
||||||
ivec3 pointIndices = ivec3(unpackUInt32Attribute(aCurveEndpointIndices.xy),
|
vec2 controlPointPosition = aControlPointPosition;
|
||||||
unpackUInt32Attribute(aCurveEndpointIndices.zw),
|
vec2 rightPosition = aRightPosition;
|
||||||
unpackUInt32Attribute(aCurveControlPointIndex));
|
int pathID = int(aPathID);
|
||||||
vec2 leftPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.x,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
vec2 rightPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.y,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
vec2 controlPointPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.z,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
|
|
||||||
int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
|
|
||||||
|
|
||||||
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||||
|
|
||||||
|
@ -57,7 +44,7 @@ void main() {
|
||||||
transform,
|
transform,
|
||||||
uTransformST,
|
uTransformST,
|
||||||
uHints)) {
|
uHints)) {
|
||||||
controlPointPosition = hintPosition(controlPointPosition, uHints);
|
controlPointPosition = hintPosition(aControlPointPosition, uHints);
|
||||||
controlPointPosition = transformVertexPositionST(controlPointPosition, transform);
|
controlPointPosition = transformVertexPositionST(controlPointPosition, transform);
|
||||||
controlPointPosition = transformVertexPositionST(controlPointPosition, uTransformST);
|
controlPointPosition = transformVertexPositionST(controlPointPosition, uTransformST);
|
||||||
controlPointPosition = convertClipToScreenSpace(controlPointPosition, uFramebufferSize);
|
controlPointPosition = convertClipToScreenSpace(controlPointPosition, uFramebufferSize);
|
||||||
|
|
|
@ -13,31 +13,21 @@ precision highp float;
|
||||||
uniform vec4 uTransformST;
|
uniform vec4 uTransformST;
|
||||||
uniform vec4 uHints;
|
uniform vec4 uHints;
|
||||||
uniform ivec2 uFramebufferSize;
|
uniform ivec2 uFramebufferSize;
|
||||||
uniform ivec2 uBVertexPositionDimensions;
|
|
||||||
uniform ivec2 uBVertexPathIDDimensions;
|
|
||||||
uniform ivec2 uPathTransformDimensions;
|
uniform ivec2 uPathTransformDimensions;
|
||||||
uniform sampler2D uBVertexPosition;
|
|
||||||
uniform sampler2D uBVertexPathID;
|
|
||||||
uniform sampler2D uPathTransform;
|
uniform sampler2D uPathTransform;
|
||||||
uniform bool uLowerPart;
|
uniform bool uLowerPart;
|
||||||
|
|
||||||
attribute vec2 aQuadPosition;
|
attribute vec2 aQuadPosition;
|
||||||
attribute vec4 aLineIndices;
|
attribute vec2 aLeftPosition;
|
||||||
|
attribute vec2 aRightPosition;
|
||||||
|
attribute float aPathID;
|
||||||
|
|
||||||
varying vec4 vEndpoints;
|
varying vec4 vEndpoints;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Fetch B-vertex positions.
|
vec2 leftPosition = aLeftPosition;
|
||||||
ivec2 pointIndices = ivec2(unpackUInt32Attribute(aLineIndices.xy),
|
vec2 rightPosition = aRightPosition;
|
||||||
unpackUInt32Attribute(aLineIndices.zw));
|
int pathID = int(aPathID);
|
||||||
vec2 leftPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.x,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
vec2 rightPosition = fetchFloat2Data(uBVertexPosition,
|
|
||||||
pointIndices.y,
|
|
||||||
uBVertexPositionDimensions);
|
|
||||||
|
|
||||||
int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
|
|
||||||
|
|
||||||
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue