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 PathfinderBufferTexture from "./buffer-texture";
|
||||
import {PerspectiveCamera} from "./camera";
|
||||
import {UniformMap} from './gl-utils';
|
||||
import {PathfinderMeshData} from "./meshes";
|
||||
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
|
||||
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 {assert, panic, PathfinderError, unwrapNull} from "./utils";
|
||||
import {DemoView, Timings} from "./view";
|
||||
import { UniformMap } from './gl-utils';
|
||||
|
||||
const TEXT_AVAILABLE_WIDTH: number = 150000;
|
||||
const TEXT_PADDING: number = 2000;
|
||||
|
|
|
@ -18,6 +18,7 @@ import {AppController, DemoAppController} from "./app-controller";
|
|||
import PathfinderBufferTexture from './buffer-texture';
|
||||
import {OrthographicCamera} from './camera';
|
||||
import {ECAAMonochromeStrategy, ECAAStrategy} from './ecaa-strategy';
|
||||
import {UniformMap} from './gl-utils';
|
||||
import {PathfinderMeshData} from "./meshes";
|
||||
import {ShaderMap, ShaderProgramSource} from "./shader-loader";
|
||||
import SSAAStrategy from './ssaa-strategy';
|
||||
|
@ -25,7 +26,6 @@ import {BUILTIN_FONT_URI, ExpandedMeshData, GlyphStore, PathfinderFont, TextFram
|
|||
import {TextRun} from "./text";
|
||||
import {assert, PathfinderError, unwrapNull, unwrapUndef} from "./utils";
|
||||
import {DemoView, MonochromeDemoView, Timings } from "./view";
|
||||
import { UniformMap } from './gl-utils';
|
||||
|
||||
const STRING: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import {createFramebufferDepthTexture, setTextureParameters, UniformMap} from '.
|
|||
import {WebGLVertexArrayObject} from './gl-utils';
|
||||
import {B_QUAD_LOWER_INDICES_OFFSET, B_QUAD_SIZE, B_QUAD_UPPER_INDICES_OFFSET} from './meshes';
|
||||
import {PathfinderShaderProgram} from './shader-loader';
|
||||
import {UINT32_SIZE, unwrapNull} from './utils';
|
||||
import {FLOAT32_SIZE, UINT32_SIZE, unwrapNull} from './utils';
|
||||
import {MonochromeDemoView} from './view';
|
||||
|
||||
interface UpperAndLower<T> {
|
||||
|
@ -37,8 +37,6 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
|
||||
protected subpixelAA: SubpixelAAType;
|
||||
|
||||
private bVertexPositionBufferTexture: PathfinderBufferTexture;
|
||||
private bVertexPathIDBufferTexture: PathfinderBufferTexture;
|
||||
private directFramebuffer: WebGLFramebuffer;
|
||||
private aaAlphaTexture: WebGLTexture;
|
||||
private aaFramebuffer: WebGLFramebuffer;
|
||||
|
@ -58,16 +56,11 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
|
||||
init(view: MonochromeDemoView) {
|
||||
super.init(view);
|
||||
this.bVertexPositionBufferTexture = new PathfinderBufferTexture(view.gl,
|
||||
'uBVertexPosition');
|
||||
this.bVertexPathIDBufferTexture = new PathfinderBufferTexture(view.gl, 'uBVertexPathID');
|
||||
}
|
||||
|
||||
attachMeshes(view: MonochromeDemoView) {
|
||||
const bVertexPositions = new Float32Array(view.meshData[0].bVertexPositions);
|
||||
const bVertexPathIDs = new Uint8Array(view.meshData[0].bVertexPathIDs);
|
||||
this.bVertexPositionBufferTexture.upload(view.gl, bVertexPositions);
|
||||
this.bVertexPathIDBufferTexture.upload(view.gl, bVertexPathIDs);
|
||||
|
||||
this.createEdgeDetectVAO(view);
|
||||
this.createCoverVAO(view);
|
||||
|
@ -212,24 +205,33 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
view.gl.useProgram(coverProgram.program);
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
||||
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.vertexAttribPointer(attributes.aUpperPointIndices,
|
||||
4,
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.meshes[0].edgeBoundingBoxVertexPositions);
|
||||
view.gl.vertexAttribPointer(attributes.aUpperLeftPosition,
|
||||
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,
|
||||
false,
|
||||
B_QUAD_SIZE,
|
||||
B_QUAD_UPPER_INDICES_OFFSET);
|
||||
view.gl.vertexAttribPointer(attributes.aLowerPointIndices,
|
||||
4,
|
||||
view.gl.UNSIGNED_SHORT,
|
||||
false,
|
||||
B_QUAD_SIZE,
|
||||
B_QUAD_LOWER_INDICES_OFFSET);
|
||||
0,
|
||||
0);
|
||||
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||
view.gl.enableVertexAttribArray(attributes.aUpperPointIndices);
|
||||
view.gl.enableVertexAttribArray(attributes.aLowerPointIndices);
|
||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aUpperPointIndices, 1);
|
||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLowerPointIndices, 1);
|
||||
view.gl.enableVertexAttribArray(attributes.aUpperLeftPosition);
|
||||
view.gl.enableVertexAttribArray(attributes.aLowerRightPosition);
|
||||
view.gl.enableVertexAttribArray(attributes.aPathID);
|
||||
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.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||
|
@ -244,24 +246,45 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
|
||||
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
|
||||
|
||||
const lineIndexBuffer = {
|
||||
lower: view.meshes[0].edgeLowerLineIndices,
|
||||
upper: view.meshes[0].edgeUpperLineIndices,
|
||||
const lineVertexPositionsBuffer = {
|
||||
lower: view.meshes[0].edgeLowerLineVertexPositions,
|
||||
upper: view.meshes[0].edgeUpperLineVertexPositions,
|
||||
}[direction];
|
||||
const linePathIDsBuffer = {
|
||||
lower: view.meshes[0].edgeLowerLinePathIDs,
|
||||
upper: view.meshes[0].edgeUpperLinePathIDs,
|
||||
}[direction];
|
||||
|
||||
view.gl.useProgram(lineProgram.program);
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
||||
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, lineIndexBuffer);
|
||||
view.gl.vertexAttribPointer(attributes.aLineIndices,
|
||||
4,
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, lineVertexPositionsBuffer);
|
||||
view.gl.vertexAttribPointer(attributes.aLeftPosition,
|
||||
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,
|
||||
false,
|
||||
0,
|
||||
0);
|
||||
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||
view.gl.enableVertexAttribArray(attributes.aLineIndices);
|
||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aLineIndices, 1);
|
||||
view.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -279,32 +302,53 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
vaos[direction] = view.vertexArrayObjectExt.createVertexArrayOES();
|
||||
view.vertexArrayObjectExt.bindVertexArrayOES(vaos[direction]);
|
||||
|
||||
const curveIndexBuffer = {
|
||||
lower: view.meshes[0].edgeLowerCurveIndices,
|
||||
upper: view.meshes[0].edgeUpperCurveIndices,
|
||||
const curveVertexPositionsBuffer = {
|
||||
lower: view.meshes[0].edgeLowerCurveVertexPositions,
|
||||
upper: view.meshes[0].edgeUpperCurveVertexPositions,
|
||||
}[direction];
|
||||
const curvePathIDsBuffer = {
|
||||
lower: view.meshes[0].edgeLowerCurvePathIDs,
|
||||
upper: view.meshes[0].edgeUpperCurvePathIDs,
|
||||
}[direction];
|
||||
|
||||
view.gl.useProgram(curveProgram.program);
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, view.quadPositionsBuffer);
|
||||
view.gl.vertexAttribPointer(attributes.aQuadPosition, 2, view.gl.FLOAT, false, 0, 0);
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curveIndexBuffer);
|
||||
view.gl.vertexAttribPointer(attributes.aCurveEndpointIndices,
|
||||
4,
|
||||
view.gl.UNSIGNED_SHORT,
|
||||
false,
|
||||
UINT32_SIZE * 4,
|
||||
0);
|
||||
view.gl.vertexAttribPointer(attributes.aCurveControlPointIndex,
|
||||
view.gl.bindBuffer(view.gl.ARRAY_BUFFER, curveVertexPositionsBuffer);
|
||||
view.gl.vertexAttribPointer(attributes.aLeftPosition,
|
||||
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,
|
||||
false,
|
||||
UINT32_SIZE * 4,
|
||||
UINT32_SIZE * 2);
|
||||
0,
|
||||
0);
|
||||
view.gl.enableVertexAttribArray(attributes.aQuadPosition);
|
||||
view.gl.enableVertexAttribArray(attributes.aCurveEndpointIndices);
|
||||
view.gl.enableVertexAttribArray(attributes.aCurveControlPointIndex);
|
||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aCurveEndpointIndices, 1);
|
||||
view.instancedArraysExt.vertexAttribDivisorANGLE(attributes.aCurveControlPointIndex, 1);
|
||||
view.gl.enableVertexAttribArray(attributes.aLeftPosition);
|
||||
view.gl.enableVertexAttribArray(attributes.aControlPointPosition);
|
||||
view.gl.enableVertexAttribArray(attributes.aRightPosition);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -376,9 +420,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
private setAAUniforms(view: MonochromeDemoView, uniforms: UniformMap) {
|
||||
view.setTransformSTUniform(uniforms, 0);
|
||||
view.setFramebufferSizeUniform(uniforms);
|
||||
this.bVertexPositionBufferTexture.bind(view.gl, uniforms, 0);
|
||||
this.bVertexPathIDBufferTexture.bind(view.gl, uniforms, 1);
|
||||
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 2);
|
||||
view.pathTransformBufferTextures[0].bind(view.gl, uniforms, 0);
|
||||
view.setHintsUniform(uniforms);
|
||||
}
|
||||
|
||||
|
@ -394,8 +436,8 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
view.vertexArrayObjectExt.bindVertexArrayOES(this.lineVAOs[direction]);
|
||||
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
|
||||
const count = {
|
||||
lower: view.meshData[0].edgeLowerLineIndexCount,
|
||||
upper: view.meshData[0].edgeUpperLineIndexCount,
|
||||
lower: view.meshData[0].edgeLowerLineCount,
|
||||
upper: view.meshData[0].edgeUpperLineCount,
|
||||
}[direction];
|
||||
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
|
||||
6,
|
||||
|
@ -419,8 +461,8 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
|||
view.vertexArrayObjectExt.bindVertexArrayOES(this.curveVAOs[direction]);
|
||||
view.gl.uniform1i(uniforms.uLowerPart, direction === 'lower' ? 1 : 0);
|
||||
const count = {
|
||||
lower: view.meshData[0].edgeLowerCurveIndexCount,
|
||||
upper: view.meshData[0].edgeUpperCurveIndexCount,
|
||||
lower: view.meshData[0].edgeLowerCurveCount,
|
||||
upper: view.meshData[0].edgeUpperCurveCount,
|
||||
}[direction];
|
||||
view.instancedArraysExt.drawElementsInstancedANGLE(view.gl.TRIANGLES,
|
||||
6,
|
||||
|
|
|
@ -18,35 +18,36 @@ interface BufferTypeFourCCTable {
|
|||
[fourCC: string]: keyof Meshes<void>;
|
||||
}
|
||||
|
||||
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',
|
||||
edgeLowerCurveIndices: 'ARRAY_BUFFER',
|
||||
edgeLowerLineIndices: 'ARRAY_BUFFER',
|
||||
edgeUpperCurveIndices: 'ARRAY_BUFFER',
|
||||
edgeUpperLineIndices: 'ARRAY_BUFFER',
|
||||
};
|
||||
interface ArrayLike<T> {
|
||||
[index: number]: T;
|
||||
}
|
||||
|
||||
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()`.
|
||||
const BUFFER_TYPE_FOURCCS: BufferTypeFourCCTable = {
|
||||
bqua: 'bQuads',
|
||||
bvlb: 'bVertexLoopBlinnData',
|
||||
bvpi: 'bVertexPathIDs',
|
||||
bvpo: 'bVertexPositions',
|
||||
cvci: 'coverCurveIndices',
|
||||
cvii: 'coverInteriorIndices',
|
||||
elci: 'edgeLowerCurveIndices',
|
||||
elli: 'edgeLowerLineIndices',
|
||||
euci: 'edgeUpperCurveIndices',
|
||||
euli: 'edgeUpperLineIndices',
|
||||
type PrimitiveType = 'Uint16' | 'Uint32' | 'Float32';
|
||||
|
||||
type PrimitiveTypeArray = Float32Array | Uint16Array | Uint32Array;
|
||||
|
||||
interface MeshBufferTypeDescriptor {
|
||||
type: PrimitiveType;
|
||||
size: number;
|
||||
}
|
||||
|
||||
const PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS = {
|
||||
Float32: Float32Array,
|
||||
Uint16: Uint16Array,
|
||||
Uint32: Uint32Array,
|
||||
};
|
||||
|
||||
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 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';
|
||||
|
||||
export interface Meshes<T> {
|
||||
|
@ -70,10 +135,16 @@ export interface Meshes<T> {
|
|||
readonly bVertexLoopBlinnData: T;
|
||||
readonly coverInteriorIndices: T;
|
||||
readonly coverCurveIndices: T;
|
||||
readonly edgeUpperLineIndices: T;
|
||||
readonly edgeLowerLineIndices: T;
|
||||
readonly edgeUpperCurveIndices: T;
|
||||
readonly edgeLowerCurveIndices: T;
|
||||
readonly edgeBoundingBoxPathIDs: T;
|
||||
readonly edgeBoundingBoxVertexPositions: T;
|
||||
readonly edgeLowerCurvePathIDs: 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> {
|
||||
|
@ -83,16 +154,22 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
|
|||
readonly bVertexLoopBlinnData: ArrayBuffer;
|
||||
readonly coverInteriorIndices: ArrayBuffer;
|
||||
readonly coverCurveIndices: ArrayBuffer;
|
||||
readonly edgeUpperLineIndices: ArrayBuffer;
|
||||
readonly edgeLowerLineIndices: ArrayBuffer;
|
||||
readonly edgeUpperCurveIndices: ArrayBuffer;
|
||||
readonly edgeLowerCurveIndices: ArrayBuffer;
|
||||
readonly edgeBoundingBoxPathIDs: ArrayBuffer;
|
||||
readonly edgeBoundingBoxVertexPositions: ArrayBuffer;
|
||||
readonly edgeLowerCurvePathIDs: 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 edgeUpperLineIndexCount: number;
|
||||
readonly edgeLowerLineIndexCount: number;
|
||||
readonly edgeUpperCurveIndexCount: number;
|
||||
readonly edgeLowerCurveIndexCount: number;
|
||||
readonly edgeLowerCurveCount: number;
|
||||
readonly edgeUpperCurveCount: number;
|
||||
readonly edgeLowerLineCount: number;
|
||||
readonly edgeUpperLineCount: number;
|
||||
|
||||
constructor(meshes: ArrayBuffer | Meshes<ArrayBuffer>) {
|
||||
if (meshes instanceof ArrayBuffer) {
|
||||
|
@ -119,160 +196,104 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer> {
|
|||
}
|
||||
|
||||
this.bQuadCount = this.bQuads.byteLength / B_QUAD_SIZE;
|
||||
this.edgeUpperLineIndexCount = this.edgeUpperLineIndices.byteLength / 8;
|
||||
this.edgeLowerLineIndexCount = this.edgeLowerLineIndices.byteLength / 8;
|
||||
this.edgeUpperCurveIndexCount = this.edgeUpperCurveIndices.byteLength / 16;
|
||||
this.edgeLowerCurveIndexCount = this.edgeLowerCurveIndices.byteLength / 16;
|
||||
this.edgeUpperLineCount = this.edgeUpperLinePathIDs.byteLength / 2;
|
||||
this.edgeLowerLineCount = this.edgeLowerLinePathIDs.byteLength / 2;
|
||||
this.edgeUpperCurveCount = this.edgeUpperCurvePathIDs.byteLength / 2;
|
||||
this.edgeLowerCurveCount = this.edgeLowerCurvePathIDs.byteLength / 2;
|
||||
}
|
||||
|
||||
expand(pathIDs: number[]): PathfinderMeshData {
|
||||
const bQuads = new Uint32Array(this.bQuads);
|
||||
const bVertexPositions = new Float32Array(this.bVertexPositions);
|
||||
const bVertexPathIDs = new Uint16Array(this.bVertexPathIDs);
|
||||
const bVertexLoopBlinnData = new Uint32Array(this.bVertexLoopBlinnData);
|
||||
const tempOriginalBuffers: any = {}, tempExpandedArrays: any = {};
|
||||
for (const key of Object.keys(BUFFER_TYPES) as Array<keyof Meshes<void>>) {
|
||||
const arrayConstructor = PRIMITIVE_TYPE_ARRAY_CONSTRUCTORS[MESH_TYPES[key].type];
|
||||
tempOriginalBuffers[key] = new arrayConstructor(this[key]);
|
||||
tempExpandedArrays[key] = [];
|
||||
}
|
||||
|
||||
const edgeUpperCurveIndices = new Uint32Array(this.edgeUpperCurveIndices);
|
||||
const edgeLowerCurveIndices = new Uint32Array(this.edgeLowerCurveIndices);
|
||||
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 originalBuffers: Meshes<PrimitiveTypeArray> = tempOriginalBuffers;
|
||||
const expandedArrays: Meshes<number[]> = tempExpandedArrays;
|
||||
|
||||
const coverInteriorIndices = new Uint32Array(this.coverInteriorIndices);
|
||||
const coverCurveIndices = new Uint32Array(this.coverCurveIndices);
|
||||
const edgeUpperLineIndices = new Uint32Array(this.edgeUpperLineIndices);
|
||||
const edgeLowerLineIndices = new Uint32Array(this.edgeLowerLineIndices);
|
||||
for (let newPathIndex = 0; newPathIndex < pathIDs.length; newPathIndex++) {
|
||||
const expandedPathID = newPathIndex + 1;
|
||||
const originalPathID = pathIDs[newPathIndex];
|
||||
|
||||
const expandedBQuads: number[] = [];
|
||||
const expandedBVertexPositions: number[] = [];
|
||||
const expandedBVertexPathIDs: number[] = [];
|
||||
const expandedBVertexLoopBlinnData: number[] = [];
|
||||
const expandedCoverInteriorIndices: number[] = [];
|
||||
const expandedCoverCurveIndices: number[] = [];
|
||||
const expandedEdgeUpperCurveIndices: number[] = [];
|
||||
const expandedEdgeUpperLineIndices: number[] = [];
|
||||
const expandedEdgeLowerCurveIndices: number[] = [];
|
||||
const expandedEdgeLowerLineIndices: number[] = [];
|
||||
const bVertexCopyResult =
|
||||
copyVertices(['bVertexPositions', 'bVertexLoopBlinnData'],
|
||||
'bVertexPathIDs',
|
||||
expandedArrays,
|
||||
originalBuffers,
|
||||
expandedPathID,
|
||||
originalPathID);
|
||||
|
||||
let textGlyphIndex = 0;
|
||||
for (const pathID of pathIDs) {
|
||||
const firstBVertexIndex = _.sortedIndex(bVertexPathIDs, pathID);
|
||||
if (firstBVertexIndex < 0)
|
||||
if (bVertexCopyResult == null)
|
||||
continue;
|
||||
|
||||
// Copy over vertices.
|
||||
let bVertexIndex = firstBVertexIndex;
|
||||
const firstExpandedBVertexIndex = expandedBVertexPathIDs.length;
|
||||
while (bVertexIndex < bVertexPathIDs.length &&
|
||||
bVertexPathIDs[bVertexIndex] === pathID) {
|
||||
expandedBVertexPositions.push(bVertexPositions[bVertexIndex * 2 + 0],
|
||||
bVertexPositions[bVertexIndex * 2 + 1]);
|
||||
expandedBVertexPathIDs.push(textGlyphIndex + 1);
|
||||
expandedBVertexLoopBlinnData.push(bVertexLoopBlinnData[bVertexIndex]);
|
||||
bVertexIndex++;
|
||||
const firstExpandedBVertexIndex = bVertexCopyResult.expandedStartIndex;
|
||||
const firstBVertexIndex = bVertexCopyResult.originalStartIndex;
|
||||
const lastBVertexIndex = bVertexCopyResult.originalEndIndex;
|
||||
|
||||
// Copy over edge data.
|
||||
for (const edgeBufferName of EDGE_BUFFER_NAMES) {
|
||||
copyVertices([`edge${edgeBufferName}VertexPositions` as keyof Meshes<void>],
|
||||
`edge${edgeBufferName}PathIDs` as keyof Meshes<void>,
|
||||
expandedArrays,
|
||||
originalBuffers,
|
||||
expandedPathID,
|
||||
originalPathID);
|
||||
}
|
||||
|
||||
// Copy over indices.
|
||||
copyIndices(expandedCoverInteriorIndices,
|
||||
coverInteriorIndices,
|
||||
copyIndices(expandedArrays.coverInteriorIndices,
|
||||
originalBuffers.coverInteriorIndices as Uint32Array,
|
||||
firstExpandedBVertexIndex,
|
||||
firstBVertexIndex,
|
||||
bVertexIndex);
|
||||
copyIndices(expandedCoverCurveIndices,
|
||||
coverCurveIndices,
|
||||
lastBVertexIndex);
|
||||
copyIndices(expandedArrays.coverCurveIndices,
|
||||
originalBuffers.coverCurveIndices as Uint32Array,
|
||||
firstExpandedBVertexIndex,
|
||||
firstBVertexIndex,
|
||||
bVertexIndex);
|
||||
|
||||
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);
|
||||
lastBVertexIndex);
|
||||
|
||||
// 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)
|
||||
firstBQuadIndex = bQuads.length;
|
||||
firstBQuadIndex = originalBuffers.bQuads.length;
|
||||
const indexDelta = firstExpandedBVertexIndex - firstBVertexIndex;
|
||||
for (let bQuadIndex = firstBQuadIndex;
|
||||
bQuadIndex < bQuads.length / B_QUAD_FIELD_COUNT;
|
||||
bQuadIndex < originalBuffers.bQuads.length / B_QUAD_FIELD_COUNT;
|
||||
bQuadIndex++) {
|
||||
const bQuad = bQuads[bQuadIndex];
|
||||
if (bVertexPathIDs[bQuads[bQuadIndex * B_QUAD_FIELD_COUNT]] !== pathID)
|
||||
const bQuad = originalBuffers.bQuads[bQuadIndex];
|
||||
if (originalBuffers.bVertexPathIDs[originalBuffers.bQuads[bQuadIndex *
|
||||
B_QUAD_FIELD_COUNT]] !==
|
||||
originalPathID) {
|
||||
break;
|
||||
}
|
||||
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)
|
||||
expandedBQuads.push(srcIndex);
|
||||
expandedArrays.bQuads.push(srcIndex);
|
||||
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 expandedBVertexLoopBlinnDataBuffer =
|
||||
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,
|
||||
});
|
||||
const expandedBuffers = tempExpandedBuffers as Meshes<ArrayBuffer>;
|
||||
return new PathfinderMeshData(expandedBuffers);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,10 +304,16 @@ export class PathfinderMeshBuffers implements Meshes<WebGLBuffer> {
|
|||
readonly bVertexLoopBlinnData: WebGLBuffer;
|
||||
readonly coverInteriorIndices: WebGLBuffer;
|
||||
readonly coverCurveIndices: WebGLBuffer;
|
||||
readonly edgeUpperLineIndices: WebGLBuffer;
|
||||
readonly edgeUpperCurveIndices: WebGLBuffer;
|
||||
readonly edgeLowerLineIndices: WebGLBuffer;
|
||||
readonly edgeLowerCurveIndices: WebGLBuffer;
|
||||
readonly edgeBoundingBoxPathIDs: WebGLBuffer;
|
||||
readonly edgeBoundingBoxVertexPositions: WebGLBuffer;
|
||||
readonly edgeLowerCurvePathIDs: 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) {
|
||||
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[],
|
||||
srcIndices: Uint32Array,
|
||||
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,
|
||||
bVertexPathIDs: Uint16Array,
|
||||
queryPathID: number):
|
||||
|
|
|
@ -17,13 +17,13 @@ import {DemoAppController} from './app-controller';
|
|||
import PathfinderBufferTexture from "./buffer-texture";
|
||||
import {OrthographicCamera} from "./camera";
|
||||
import {ECAAMulticolorStrategy, ECAAStrategy} from "./ecaa-strategy";
|
||||
import {UniformMap} from './gl-utils';
|
||||
import {PathfinderMeshData} from "./meshes";
|
||||
import {ShaderMap, ShaderProgramSource} from './shader-loader';
|
||||
import SSAAStrategy from "./ssaa-strategy";
|
||||
import {BUILTIN_SVG_URI, SVGLoader} from './svg-loader';
|
||||
import {panic, unwrapNull} from './utils';
|
||||
import {DemoView, Timings} from './view';
|
||||
import { UniformMap } from './gl-utils';
|
||||
|
||||
const parseColor = require('parse-color');
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
|||
app_units = "0.5"
|
||||
base64 = "0.6"
|
||||
bincode = "0.8"
|
||||
env_logger = "0.3"
|
||||
env_logger = "0.4"
|
||||
euclid = "0.15"
|
||||
lazy_static = "0.2"
|
||||
log = "0.3"
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::slice;
|
|||
|
||||
use mesh_library::MeshLibrary;
|
||||
use partitioner::Partitioner;
|
||||
use {BQuad, BVertexLoopBlinnData, CurveIndices, Endpoint, LineIndices, Subpath};
|
||||
use {BQuad, BVertexLoopBlinnData, Endpoint, Subpath};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
|
@ -43,19 +43,6 @@ pub struct CoverIndices {
|
|||
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]
|
||||
pub unsafe extern fn pf_partitioner_new() -> *mut Partitioner<'static> {
|
||||
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;
|
||||
}
|
||||
|
||||
#[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]
|
||||
pub unsafe extern fn pf_init_env_logger() -> u32 {
|
||||
env_logger::init().is_ok() as u32
|
||||
|
|
|
@ -145,57 +145,3 @@ impl BVertexLoopBlinnData {
|
|||
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 std::io::{self, ErrorKind, Seek, SeekFrom, Write};
|
||||
use std::ops::Range;
|
||||
use std::u32;
|
||||
|
||||
use {BQuad, BVertexLoopBlinnData, CurveIndices, LineIndices};
|
||||
use {BQuad, BVertexLoopBlinnData};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MeshLibrary {
|
||||
|
@ -24,7 +25,7 @@ pub struct MeshLibrary {
|
|||
pub b_vertex_path_ids: Vec<u16>,
|
||||
pub b_vertex_loop_blinn_data: Vec<BVertexLoopBlinnData>,
|
||||
pub cover_indices: MeshLibraryCoverIndices,
|
||||
pub edge_indices: MeshLibraryEdgeIndices,
|
||||
pub edge_data: MeshLibraryEdgeData,
|
||||
}
|
||||
|
||||
impl MeshLibrary {
|
||||
|
@ -36,7 +37,7 @@ impl MeshLibrary {
|
|||
b_vertex_path_ids: vec![],
|
||||
b_vertex_loop_blinn_data: vec![],
|
||||
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_loop_blinn_data.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.
|
||||
|
@ -97,10 +160,16 @@ impl MeshLibrary {
|
|||
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"cvci", &self.cover_indices.curve_indices));
|
||||
try!(write_chunk(writer, b"euli", &self.edge_indices.upper_line_indices));
|
||||
try!(write_chunk(writer, b"euci", &self.edge_indices.upper_curve_indices));
|
||||
try!(write_chunk(writer, b"elli", &self.edge_indices.lower_line_indices));
|
||||
try!(write_chunk(writer, b"elci", &self.edge_indices.lower_curve_indices));
|
||||
try!(write_chunk(writer, b"ebbv", &self.edge_data.bounding_box_vertex_positions));
|
||||
try!(write_chunk(writer, b"eulv", &self.edge_data.upper_line_vertex_positions));
|
||||
try!(write_chunk(writer, b"ellv", &self.edge_data.lower_line_vertex_positions));
|
||||
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)));
|
||||
try!(writer.seek(SeekFrom::Start(4)));
|
||||
|
@ -133,10 +202,11 @@ impl MeshLibrary {
|
|||
b_vertices: self.b_vertex_positions.len(),
|
||||
cover_interior_indices: self.cover_indices.interior_indices.len(),
|
||||
cover_curve_indices: self.cover_indices.curve_indices.len(),
|
||||
edge_upper_line_indices: self.edge_indices.upper_line_indices.len(),
|
||||
edge_upper_curve_indices: self.edge_indices.upper_curve_indices.len(),
|
||||
edge_lower_line_indices: self.edge_indices.lower_line_indices.len(),
|
||||
edge_lower_curve_indices: self.edge_indices.lower_curve_indices.len(),
|
||||
edge_bounding_box_indices: self.edge_data.bounding_box_vertex_positions.len(),
|
||||
edge_upper_line_indices: self.edge_data.upper_line_vertex_positions.len(),
|
||||
edge_upper_curve_indices: self.edge_data.upper_curve_vertex_positions.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 {
|
||||
b_quads: usize,
|
||||
b_vertices: usize,
|
||||
cover_interior_indices: usize,
|
||||
cover_curve_indices: usize,
|
||||
edge_bounding_box_indices: usize,
|
||||
edge_upper_line_indices: usize,
|
||||
edge_upper_curve_indices: usize,
|
||||
edge_lower_line_indices: usize,
|
||||
|
@ -205,6 +249,7 @@ pub struct MeshLibraryIndexRanges {
|
|||
pub b_vertices: Range<usize>,
|
||||
pub cover_interior_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_curve_indices: Range<usize>,
|
||||
pub edge_lower_line_indices: Range<usize>,
|
||||
|
@ -219,6 +264,8 @@ impl MeshLibraryIndexRanges {
|
|||
b_vertices: start.b_vertices..end.b_vertices,
|
||||
cover_interior_indices: start.cover_interior_indices..end.cover_interior_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_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,
|
||||
|
@ -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 mesh_library::{MeshLibrary, MeshLibraryIndexRanges};
|
||||
use {BQuad, BVertexLoopBlinnData, BVertexKind, CurveIndices, Endpoint, FillRule};
|
||||
use {LineIndices, Subpath};
|
||||
use {BQuad, BVertexLoopBlinnData, BVertexKind, Endpoint, FillRule, Subpath};
|
||||
|
||||
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 {}",
|
||||
upper_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.middle_point,
|
||||
lower_subdivision.left_curve_left,
|
||||
|
|
|
@ -192,29 +192,11 @@ int unpackUInt16(vec2 packedValue) {
|
|||
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) {
|
||||
ivec2 pixelCoord = ivec2(imod(index, dimensions.x), index / dimensions.x);
|
||||
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) {
|
||||
return vec2(imod(pathID, 256), pathID / 256) / 255.0;
|
||||
}
|
||||
|
|
|
@ -13,47 +13,23 @@ precision highp float;
|
|||
uniform vec4 uTransformST;
|
||||
uniform vec4 uHints;
|
||||
uniform ivec2 uFramebufferSize;
|
||||
uniform ivec2 uBVertexPositionDimensions;
|
||||
uniform ivec2 uBVertexPathIDDimensions;
|
||||
uniform ivec2 uPathTransformDimensions;
|
||||
uniform sampler2D uBVertexPosition;
|
||||
uniform sampler2D uBVertexPathID;
|
||||
uniform sampler2D uPathTransform;
|
||||
|
||||
attribute vec2 aQuadPosition;
|
||||
attribute vec4 aUpperPointIndices;
|
||||
attribute vec4 aLowerPointIndices;
|
||||
attribute vec2 aUpperLeftPosition;
|
||||
attribute vec2 aLowerRightPosition;
|
||||
attribute float aPathID;
|
||||
|
||||
varying vec2 vHorizontalExtents;
|
||||
|
||||
void main() {
|
||||
// Fetch B-vertex positions.
|
||||
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);
|
||||
int pathID = int(aPathID);
|
||||
|
||||
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||
|
||||
upperLeftPosition = hintPosition(upperLeftPosition, uHints);
|
||||
lowerRightPosition = hintPosition(lowerRightPosition, uHints);
|
||||
vec2 upperLeftPosition = hintPosition(aUpperLeftPosition, uHints);
|
||||
vec2 lowerRightPosition = hintPosition(aLowerRightPosition, uHints);
|
||||
|
||||
upperLeftPosition = transformVertexPositionST(upperLeftPosition, transform);
|
||||
lowerRightPosition = transformVertexPositionST(lowerRightPosition, transform);
|
||||
|
|
|
@ -13,37 +13,24 @@ precision highp float;
|
|||
uniform vec4 uTransformST;
|
||||
uniform vec4 uHints;
|
||||
uniform ivec2 uFramebufferSize;
|
||||
uniform ivec2 uBVertexPositionDimensions;
|
||||
uniform ivec2 uBVertexPathIDDimensions;
|
||||
uniform ivec2 uPathTransformDimensions;
|
||||
uniform sampler2D uBVertexPosition;
|
||||
uniform sampler2D uBVertexPathID;
|
||||
uniform sampler2D uPathTransform;
|
||||
uniform bool uLowerPart;
|
||||
|
||||
attribute vec2 aQuadPosition;
|
||||
attribute vec4 aCurveEndpointIndices;
|
||||
attribute vec2 aCurveControlPointIndex;
|
||||
attribute vec2 aLeftPosition;
|
||||
attribute vec2 aControlPointPosition;
|
||||
attribute vec2 aRightPosition;
|
||||
attribute float aPathID;
|
||||
|
||||
varying vec4 vEndpoints;
|
||||
varying vec2 vControlPoint;
|
||||
|
||||
void main() {
|
||||
// Fetch B-vertex positions.
|
||||
ivec3 pointIndices = ivec3(unpackUInt32Attribute(aCurveEndpointIndices.xy),
|
||||
unpackUInt32Attribute(aCurveEndpointIndices.zw),
|
||||
unpackUInt32Attribute(aCurveControlPointIndex));
|
||||
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);
|
||||
vec2 leftPosition = aLeftPosition;
|
||||
vec2 controlPointPosition = aControlPointPosition;
|
||||
vec2 rightPosition = aRightPosition;
|
||||
int pathID = int(aPathID);
|
||||
|
||||
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||
|
||||
|
@ -57,7 +44,7 @@ void main() {
|
|||
transform,
|
||||
uTransformST,
|
||||
uHints)) {
|
||||
controlPointPosition = hintPosition(controlPointPosition, uHints);
|
||||
controlPointPosition = hintPosition(aControlPointPosition, uHints);
|
||||
controlPointPosition = transformVertexPositionST(controlPointPosition, transform);
|
||||
controlPointPosition = transformVertexPositionST(controlPointPosition, uTransformST);
|
||||
controlPointPosition = convertClipToScreenSpace(controlPointPosition, uFramebufferSize);
|
||||
|
|
|
@ -13,31 +13,21 @@ precision highp float;
|
|||
uniform vec4 uTransformST;
|
||||
uniform vec4 uHints;
|
||||
uniform ivec2 uFramebufferSize;
|
||||
uniform ivec2 uBVertexPositionDimensions;
|
||||
uniform ivec2 uBVertexPathIDDimensions;
|
||||
uniform ivec2 uPathTransformDimensions;
|
||||
uniform sampler2D uBVertexPosition;
|
||||
uniform sampler2D uBVertexPathID;
|
||||
uniform sampler2D uPathTransform;
|
||||
uniform bool uLowerPart;
|
||||
|
||||
attribute vec2 aQuadPosition;
|
||||
attribute vec4 aLineIndices;
|
||||
attribute vec2 aLeftPosition;
|
||||
attribute vec2 aRightPosition;
|
||||
attribute float aPathID;
|
||||
|
||||
varying vec4 vEndpoints;
|
||||
|
||||
void main() {
|
||||
// Fetch B-vertex positions.
|
||||
ivec2 pointIndices = ivec2(unpackUInt32Attribute(aLineIndices.xy),
|
||||
unpackUInt32Attribute(aLineIndices.zw));
|
||||
vec2 leftPosition = fetchFloat2Data(uBVertexPosition,
|
||||
pointIndices.x,
|
||||
uBVertexPositionDimensions);
|
||||
vec2 rightPosition = fetchFloat2Data(uBVertexPosition,
|
||||
pointIndices.y,
|
||||
uBVertexPositionDimensions);
|
||||
|
||||
int pathID = fetchUInt16Data(uBVertexPathID, pointIndices.x, uBVertexPathIDDimensions);
|
||||
vec2 leftPosition = aLeftPosition;
|
||||
vec2 rightPosition = aRightPosition;
|
||||
int pathID = int(aPathID);
|
||||
|
||||
vec4 transform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||
|
||||
|
|
Loading…
Reference in New Issue