Use instanced rendering in the 3D demo.
This massively decreases the load time and memory usage in exchange for more draw calls.
This commit is contained in:
parent
b631fec80f
commit
157292175b
|
@ -24,7 +24,7 @@ import SSAAStrategy from "./ssaa-strategy";
|
||||||
import {BUILTIN_FONT_URI, ExpandedMeshData} from "./text";
|
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 {PathfinderDemoView, Timings} from "./view";
|
import {DemoView, Timings} from "./view";
|
||||||
|
|
||||||
const TEXT_AVAILABLE_WIDTH: number = 150000;
|
const TEXT_AVAILABLE_WIDTH: number = 150000;
|
||||||
const TEXT_PADDING: number = 2000;
|
const TEXT_PADDING: number = 2000;
|
||||||
|
@ -94,12 +94,19 @@ interface MonumentSide {
|
||||||
lines: TextLine[];
|
lines: TextLine[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MeshDescriptor {
|
||||||
|
glyphID: number;
|
||||||
|
textFrameIndex: number;
|
||||||
|
positions: glmatrix.vec2[];
|
||||||
|
}
|
||||||
|
|
||||||
class ThreeDController extends DemoAppController<ThreeDView> {
|
class ThreeDController extends DemoAppController<ThreeDView> {
|
||||||
textFrames: TextFrame[];
|
textFrames: TextFrame[];
|
||||||
glyphStore: GlyphStore;
|
glyphStore: GlyphStore;
|
||||||
|
meshDescriptors: MeshDescriptor[];
|
||||||
|
|
||||||
private baseMeshes: PathfinderMeshData;
|
private baseMeshes: PathfinderMeshData;
|
||||||
private expandedMeshes: ExpandedMeshData[];
|
private expandedMeshes: PathfinderMeshData[];
|
||||||
|
|
||||||
private monumentPromise: Promise<MonumentSide[]>;
|
private monumentPromise: Promise<MonumentSide[]>;
|
||||||
|
|
||||||
|
@ -196,20 +203,64 @@ class ThreeDController extends DemoAppController<ThreeDView> {
|
||||||
|
|
||||||
this.glyphStore = new GlyphStore(font, glyphsNeeded);
|
this.glyphStore = new GlyphStore(font, glyphsNeeded);
|
||||||
this.glyphStore.partition().then(result => {
|
this.glyphStore.partition().then(result => {
|
||||||
|
const hint = new Hint(this.glyphStore.font, PIXELS_PER_UNIT, false);
|
||||||
|
|
||||||
this.baseMeshes = result.meshes;
|
this.baseMeshes = result.meshes;
|
||||||
this.expandedMeshes = this.textFrames.map(textFrame => {
|
|
||||||
return textFrame.expandMeshes(this.baseMeshes, glyphsNeeded);
|
this.meshDescriptors = [];
|
||||||
|
|
||||||
|
for (let textFrameIndex = 0;
|
||||||
|
textFrameIndex < this.textFrames.length;
|
||||||
|
textFrameIndex++) {
|
||||||
|
const textFrame = this.textFrames[textFrameIndex];
|
||||||
|
|
||||||
|
let glyphDescriptors = [];
|
||||||
|
for (const run of textFrame.runs) {
|
||||||
|
for (let glyphIndex = 0; glyphIndex < run.glyphIDs.length; glyphIndex++) {
|
||||||
|
glyphDescriptors.push({
|
||||||
|
glyphID: run.glyphIDs[glyphIndex],
|
||||||
|
position: run.calculatePixelOriginForGlyphAt(glyphIndex,
|
||||||
|
PIXELS_PER_UNIT,
|
||||||
|
hint),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glyphDescriptors = _.sortBy(glyphDescriptors, descriptor => descriptor.glyphID);
|
||||||
|
|
||||||
|
let currentMeshDescriptor: (MeshDescriptor | null) = null;
|
||||||
|
for (const glyphDescriptor of glyphDescriptors) {
|
||||||
|
if (currentMeshDescriptor == null ||
|
||||||
|
glyphDescriptor.glyphID !== currentMeshDescriptor.glyphID) {
|
||||||
|
if (currentMeshDescriptor != null)
|
||||||
|
this.meshDescriptors.push(currentMeshDescriptor);
|
||||||
|
currentMeshDescriptor = {
|
||||||
|
glyphID: glyphDescriptor.glyphID,
|
||||||
|
positions: [],
|
||||||
|
textFrameIndex: textFrameIndex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
currentMeshDescriptor.positions.push(glyphDescriptor.position);
|
||||||
|
}
|
||||||
|
if (currentMeshDescriptor != null)
|
||||||
|
this.meshDescriptors.push(currentMeshDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.expandedMeshes = this.meshDescriptors.map(meshDescriptor => {
|
||||||
|
const glyphIndex = _.sortedIndexOf(glyphsNeeded, meshDescriptor.glyphID);
|
||||||
|
return this.baseMeshes.expand([glyphIndex + 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.view.then(view => {
|
this.view.then(view => {
|
||||||
view.uploadPathColors(this.expandedMeshes.length);
|
view.uploadPathColors(this.expandedMeshes.length);
|
||||||
view.uploadPathTransforms(this.expandedMeshes.length);
|
view.uploadPathTransforms(this.expandedMeshes.length);
|
||||||
view.attachMeshes(this.expandedMeshes.map(meshes => meshes.meshes));
|
view.attachMeshes(this.expandedMeshes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThreeDView extends PathfinderDemoView {
|
class ThreeDView extends DemoView {
|
||||||
destFramebuffer: WebGLFramebuffer | null = null;
|
destFramebuffer: WebGLFramebuffer | null = null;
|
||||||
|
|
||||||
camera: PerspectiveCamera;
|
camera: PerspectiveCamera;
|
||||||
|
@ -221,6 +272,10 @@ class ThreeDView extends PathfinderDemoView {
|
||||||
|
|
||||||
protected depthFunction: number = this.gl.LESS;
|
protected depthFunction: number = this.gl.LESS;
|
||||||
|
|
||||||
|
protected get pathIDsAreInstanced(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private _scale: number;
|
private _scale: number;
|
||||||
|
|
||||||
private appController: ThreeDController;
|
private appController: ThreeDController;
|
||||||
|
@ -249,38 +304,18 @@ class ThreeDView extends PathfinderDemoView {
|
||||||
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, CUBE_INDICES, this.gl.STATIC_DRAW);
|
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, CUBE_INDICES, this.gl.STATIC_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected pathColorsForObject(textFrameIndex: number): Uint8Array {
|
protected pathColorsForObject(objectIndex: number): Uint8Array {
|
||||||
const textFrame = this.appController.textFrames[textFrameIndex];
|
return TEXT_COLOR;
|
||||||
const pathCount = textFrame.totalGlyphCount;
|
|
||||||
|
|
||||||
const pathColors = new Uint8Array(4 * (pathCount + 1));
|
|
||||||
for (let pathIndex = 0; pathIndex < pathCount; pathIndex++)
|
|
||||||
pathColors.set(TEXT_COLOR, (pathIndex + 1) * 4);
|
|
||||||
|
|
||||||
return pathColors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected pathTransformsForObject(textFrameIndex: number): Float32Array {
|
protected pathTransformsForObject(objectIndex: number): Float32Array {
|
||||||
const textFrame = this.appController.textFrames[textFrameIndex];
|
const meshDescriptor = this.appController.meshDescriptors[objectIndex];
|
||||||
const pathCount = textFrame.totalGlyphCount;
|
const pathCount = meshDescriptor.positions.length;
|
||||||
|
|
||||||
const hint = new Hint(this.appController.glyphStore.font, PIXELS_PER_UNIT, false);
|
|
||||||
|
|
||||||
const pathTransforms = new Float32Array(4 * (pathCount + 1));
|
const pathTransforms = new Float32Array(4 * (pathCount + 1));
|
||||||
|
for (let pathIndex = 0; pathIndex < pathCount; pathIndex++) {
|
||||||
let globalPathIndex = 0;
|
const glyphOrigin = meshDescriptor.positions[pathIndex];
|
||||||
for (const run of textFrame.runs) {
|
pathTransforms.set([1, 1, glyphOrigin[0], glyphOrigin[1]], (pathIndex + 1) * 4);
|
||||||
for (let pathIndex = 0;
|
|
||||||
pathIndex < run.glyphIDs.length;
|
|
||||||
pathIndex++, globalPathIndex++) {
|
|
||||||
const glyphOrigin = run.calculatePixelOriginForGlyphAt(pathIndex,
|
|
||||||
PIXELS_PER_UNIT,
|
|
||||||
hint);
|
|
||||||
pathTransforms.set([1, 1, glyphOrigin[0], glyphOrigin[1]],
|
|
||||||
(globalPathIndex + 1) * 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pathTransforms;
|
return pathTransforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,17 +378,19 @@ class ThreeDView extends PathfinderDemoView {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getModelviewTransform(objectIndex: number): glmatrix.mat4 {
|
protected getModelviewTransform(objectIndex: number): glmatrix.mat4 {
|
||||||
|
const textFrameIndex = this.appController.meshDescriptors[objectIndex].textFrameIndex;
|
||||||
const transform = glmatrix.mat4.create();
|
const transform = glmatrix.mat4.create();
|
||||||
glmatrix.mat4.rotateY(transform, transform, Math.PI / 2.0 * objectIndex);
|
glmatrix.mat4.rotateY(transform, transform, Math.PI / 2.0 * textFrameIndex);
|
||||||
glmatrix.mat4.translate(transform, transform, TEXT_TRANSLATION);
|
glmatrix.mat4.translate(transform, transform, TEXT_TRANSLATION);
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cheap but effective backface culling.
|
// Cheap but effective backface culling.
|
||||||
protected shouldRenderObject(objectIndex: number): boolean {
|
protected shouldRenderObject(objectIndex: number): boolean {
|
||||||
|
const textFrameIndex = this.appController.meshDescriptors[objectIndex].textFrameIndex;
|
||||||
const translation = this.camera.translation;
|
const translation = this.camera.translation;
|
||||||
const extent = TEXT_TRANSLATION[2] * TEXT_SCALE[2];
|
const extent = TEXT_TRANSLATION[2] * TEXT_SCALE[2];
|
||||||
switch (objectIndex) {
|
switch (textFrameIndex) {
|
||||||
case 0: return translation[2] < -extent;
|
case 0: return translation[2] < -extent;
|
||||||
case 1: return translation[0] < -extent;
|
case 1: return translation[0] < -extent;
|
||||||
case 2: return translation[2] > extent;
|
case 2: return translation[2] > extent;
|
||||||
|
@ -361,6 +398,10 @@ class ThreeDView extends PathfinderDemoView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected meshInstanceCountForObject(objectIndex: number): number {
|
||||||
|
return this.appController.meshDescriptors[objectIndex].positions.length;
|
||||||
|
}
|
||||||
|
|
||||||
get destAllocatedSize(): glmatrix.vec2 {
|
get destAllocatedSize(): glmatrix.vec2 {
|
||||||
return glmatrix.vec2.fromValues(this.canvas.width, this.canvas.height);
|
return glmatrix.vec2.fromValues(this.canvas.width, this.canvas.height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
import * as glmatrix from 'gl-matrix';
|
import * as glmatrix from 'gl-matrix';
|
||||||
|
|
||||||
import {PathfinderDemoView} from './view';
|
import {DemoView} from './view';
|
||||||
|
|
||||||
export type AntialiasingStrategyName = 'none' | 'ssaa' | 'ecaa';
|
export type AntialiasingStrategyName = 'none' | 'ssaa' | 'ecaa';
|
||||||
|
|
||||||
|
@ -21,15 +21,15 @@ export abstract class AntialiasingStrategy {
|
||||||
shouldRenderDirect: boolean;
|
shouldRenderDirect: boolean;
|
||||||
|
|
||||||
// Prepares any OpenGL data. This is only called on startup and canvas resize.
|
// Prepares any OpenGL data. This is only called on startup and canvas resize.
|
||||||
init(view: PathfinderDemoView): void {
|
init(view: DemoView): void {
|
||||||
this.setFramebufferSize(view);
|
this.setFramebufferSize(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uploads any mesh data. This is called whenever a new set of meshes is supplied.
|
// Uploads any mesh data. This is called whenever a new set of meshes is supplied.
|
||||||
abstract attachMeshes(view: PathfinderDemoView): void;
|
abstract attachMeshes(view: DemoView): void;
|
||||||
|
|
||||||
// This is called whenever the framebuffer has changed.
|
// This is called whenever the framebuffer has changed.
|
||||||
abstract setFramebufferSize(view: PathfinderDemoView): void;
|
abstract setFramebufferSize(view: DemoView): void;
|
||||||
|
|
||||||
// Returns the transformation matrix that should be applied when directly rendering.
|
// Returns the transformation matrix that should be applied when directly rendering.
|
||||||
abstract get transform(): glmatrix.mat4;
|
abstract get transform(): glmatrix.mat4;
|
||||||
|
@ -37,17 +37,17 @@ export abstract class AntialiasingStrategy {
|
||||||
// Called before direct rendering.
|
// Called before direct rendering.
|
||||||
//
|
//
|
||||||
// Typically, this redirects direct rendering to a framebuffer of some sort.
|
// Typically, this redirects direct rendering to a framebuffer of some sort.
|
||||||
abstract prepare(view: PathfinderDemoView): void;
|
abstract prepare(view: DemoView): void;
|
||||||
|
|
||||||
// Called after direct rendering.
|
// Called after direct rendering.
|
||||||
//
|
//
|
||||||
// This usually performs the actual antialiasing.
|
// This usually performs the actual antialiasing.
|
||||||
abstract antialias(view: PathfinderDemoView): void;
|
abstract antialias(view: DemoView): void;
|
||||||
|
|
||||||
// Called after antialiasing.
|
// Called after antialiasing.
|
||||||
//
|
//
|
||||||
// This usually blits to the real framebuffer.
|
// This usually blits to the real framebuffer.
|
||||||
abstract resolve(view: PathfinderDemoView): void;
|
abstract resolve(view: DemoView): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NoAAStrategy extends AntialiasingStrategy {
|
export class NoAAStrategy extends AntialiasingStrategy {
|
||||||
|
@ -58,9 +58,9 @@ export class NoAAStrategy extends AntialiasingStrategy {
|
||||||
this.framebufferSize = glmatrix.vec2.create();
|
this.framebufferSize = glmatrix.vec2.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(view: PathfinderDemoView) {}
|
attachMeshes(view: DemoView) {}
|
||||||
|
|
||||||
setFramebufferSize(view: PathfinderDemoView) {
|
setFramebufferSize(view: DemoView) {
|
||||||
this.framebufferSize = view.destAllocatedSize;
|
this.framebufferSize = view.destAllocatedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,15 +68,15 @@ export class NoAAStrategy extends AntialiasingStrategy {
|
||||||
return glmatrix.mat4.create();
|
return glmatrix.mat4.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare(view: PathfinderDemoView) {
|
prepare(view: DemoView) {
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.destFramebuffer);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.destFramebuffer);
|
||||||
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
|
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
|
||||||
view.gl.disable(view.gl.SCISSOR_TEST);
|
view.gl.disable(view.gl.SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(view: PathfinderDemoView) {}
|
antialias(view: DemoView) {}
|
||||||
|
|
||||||
resolve(view: PathfinderDemoView) {}
|
resolve(view: DemoView) {}
|
||||||
|
|
||||||
get shouldRenderDirect() {
|
get shouldRenderDirect() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { AntialiasingStrategyName, SubpixelAAType } from "./aa-strategy";
|
||||||
import {FilePickerView} from "./file-picker";
|
import {FilePickerView} from "./file-picker";
|
||||||
import {ShaderLoader, ShaderMap, ShaderProgramSource} from './shader-loader';
|
import {ShaderLoader, ShaderMap, ShaderProgramSource} from './shader-loader';
|
||||||
import {expectNotNull, unwrapNull, unwrapUndef} from './utils';
|
import {expectNotNull, unwrapNull, unwrapUndef} from './utils';
|
||||||
import {PathfinderDemoView, Timings, TIMINGS} from "./view";
|
import {DemoView, Timings, TIMINGS} from "./view";
|
||||||
|
|
||||||
export abstract class AppController {
|
export abstract class AppController {
|
||||||
protected canvas: HTMLCanvasElement;
|
protected canvas: HTMLCanvasElement;
|
||||||
|
@ -45,7 +45,7 @@ export abstract class AppController {
|
||||||
protected abstract get defaultFile(): string;
|
protected abstract get defaultFile(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class DemoAppController<View extends PathfinderDemoView> extends AppController {
|
export abstract class DemoAppController<View extends DemoView> extends AppController {
|
||||||
view: Promise<View>;
|
view: Promise<View>;
|
||||||
|
|
||||||
protected abstract readonly builtinFileURI: string;
|
protected abstract readonly builtinFileURI: string;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import SSAAStrategy from './ssaa-strategy';
|
||||||
import {BUILTIN_FONT_URI, ExpandedMeshData, GlyphStore, PathfinderFont, TextFrame} from "./text";
|
import {BUILTIN_FONT_URI, ExpandedMeshData, GlyphStore, PathfinderFont, TextFrame} from "./text";
|
||||||
import {TextRun} from "./text";
|
import {TextRun} from "./text";
|
||||||
import {assert, PathfinderError, unwrapNull} from "./utils";
|
import {assert, PathfinderError, unwrapNull} from "./utils";
|
||||||
import {MonochromePathfinderView, PathfinderDemoView, Timings } from "./view";
|
import {DemoView, MonochromeDemoView, Timings } from "./view";
|
||||||
|
|
||||||
const STRING: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
const STRING: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ class BenchmarkAppController extends DemoAppController<BenchmarkTestView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BenchmarkTestView extends MonochromePathfinderView {
|
class BenchmarkTestView extends MonochromeDemoView {
|
||||||
destFramebuffer: WebGLFramebuffer | null = null;
|
destFramebuffer: WebGLFramebuffer | null = null;
|
||||||
|
|
||||||
renderingPromiseCallback: ((time: number) => void) | null;
|
renderingPromiseCallback: ((time: number) => void) | null;
|
||||||
|
|
|
@ -18,7 +18,7 @@ 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 {UINT32_SIZE, unwrapNull} from './utils';
|
||||||
import {MonochromePathfinderView} from './view';
|
import {MonochromeDemoView} from './view';
|
||||||
|
|
||||||
interface UpperAndLower<T> {
|
interface UpperAndLower<T> {
|
||||||
upper: T;
|
upper: T;
|
||||||
|
@ -56,14 +56,14 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
this.destFramebufferSize = glmatrix.vec2.create();
|
this.destFramebufferSize = glmatrix.vec2.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
init(view: MonochromePathfinderView) {
|
init(view: MonochromeDemoView) {
|
||||||
super.init(view);
|
super.init(view);
|
||||||
this.bVertexPositionBufferTexture = new PathfinderBufferTexture(view.gl,
|
this.bVertexPositionBufferTexture = new PathfinderBufferTexture(view.gl,
|
||||||
'uBVertexPosition');
|
'uBVertexPosition');
|
||||||
this.bVertexPathIDBufferTexture = new PathfinderBufferTexture(view.gl, 'uBVertexPathID');
|
this.bVertexPathIDBufferTexture = new PathfinderBufferTexture(view.gl, 'uBVertexPathID');
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(view: MonochromePathfinderView) {
|
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.bVertexPositionBufferTexture.upload(view.gl, bVertexPositions);
|
||||||
|
@ -76,7 +76,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
this.createResolveVAO(view);
|
this.createResolveVAO(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFramebufferSize(view: MonochromePathfinderView) {
|
setFramebufferSize(view: MonochromeDemoView) {
|
||||||
this.destFramebufferSize = glmatrix.vec2.clone(view.destAllocatedSize);
|
this.destFramebufferSize = glmatrix.vec2.clone(view.destAllocatedSize);
|
||||||
glmatrix.vec2.mul(this.supersampledFramebufferSize,
|
glmatrix.vec2.mul(this.supersampledFramebufferSize,
|
||||||
this.destFramebufferSize,
|
this.destFramebufferSize,
|
||||||
|
@ -88,7 +88,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, null);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare(view: MonochromePathfinderView) {
|
prepare(view: MonochromeDemoView) {
|
||||||
const usedSize = this.supersampledUsedSize(view);
|
const usedSize = this.supersampledUsedSize(view);
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.directFramebuffer);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.directFramebuffer);
|
||||||
view.gl.viewport(0,
|
view.gl.viewport(0,
|
||||||
|
@ -123,7 +123,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(view: MonochromePathfinderView) {
|
antialias(view: MonochromeDemoView) {
|
||||||
// Detect edges if necessary.
|
// Detect edges if necessary.
|
||||||
this.detectEdgesIfNecessary(view);
|
this.detectEdgesIfNecessary(view);
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
this.antialiasCurves(view);
|
this.antialiasCurves(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(view: MonochromePathfinderView) {
|
resolve(view: MonochromeDemoView) {
|
||||||
// Resolve the antialiasing.
|
// Resolve the antialiasing.
|
||||||
this.resolveAA(view);
|
this.resolveAA(view);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
return glmatrix.mat4.create();
|
return glmatrix.mat4.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initDirectFramebuffer(view: MonochromePathfinderView) {
|
protected initDirectFramebuffer(view: MonochromeDemoView) {
|
||||||
this.directColorTexture = createFramebufferColorTexture(view.gl, this.destFramebufferSize);
|
this.directColorTexture = createFramebufferColorTexture(view.gl, this.destFramebufferSize);
|
||||||
this.directPathIDTexture = createFramebufferColorTexture(view.gl,
|
this.directPathIDTexture = createFramebufferColorTexture(view.gl,
|
||||||
this.destFramebufferSize);
|
this.destFramebufferSize);
|
||||||
|
@ -155,31 +155,31 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
this.directDepthTexture);
|
this.directDepthTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setCoverDepthState(view: MonochromePathfinderView): void {
|
protected setCoverDepthState(view: MonochromeDemoView): void {
|
||||||
view.gl.disable(view.gl.DEPTH_TEST);
|
view.gl.disable(view.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setResolveDepthState(view: MonochromePathfinderView): void {
|
protected setResolveDepthState(view: MonochromeDemoView): void {
|
||||||
view.gl.disable(view.gl.DEPTH_TEST);
|
view.gl.disable(view.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected supersampledUsedSize(view: MonochromePathfinderView): glmatrix.vec2 {
|
protected supersampledUsedSize(view: MonochromeDemoView): glmatrix.vec2 {
|
||||||
const usedSize = glmatrix.vec2.create();
|
const usedSize = glmatrix.vec2.create();
|
||||||
glmatrix.vec2.mul(usedSize, view.destUsedSize, this.supersampleScale);
|
glmatrix.vec2.mul(usedSize, view.destUsedSize, this.supersampleScale);
|
||||||
return usedSize;
|
return usedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract getResolveProgram(view: MonochromePathfinderView): PathfinderShaderProgram;
|
protected abstract getResolveProgram(view: MonochromeDemoView): PathfinderShaderProgram;
|
||||||
protected abstract initEdgeDetectFramebuffer(view: MonochromePathfinderView): void;
|
protected abstract initEdgeDetectFramebuffer(view: MonochromeDemoView): void;
|
||||||
protected abstract createEdgeDetectVAO(view: MonochromePathfinderView): void;
|
protected abstract createEdgeDetectVAO(view: MonochromeDemoView): void;
|
||||||
protected abstract detectEdgesIfNecessary(view: MonochromePathfinderView): void;
|
protected abstract detectEdgesIfNecessary(view: MonochromeDemoView): void;
|
||||||
protected abstract clearForCover(view: MonochromePathfinderView): void;
|
protected abstract clearForCover(view: MonochromeDemoView): void;
|
||||||
protected abstract setAADepthState(view: MonochromePathfinderView): void;
|
protected abstract setAADepthState(view: MonochromeDemoView): void;
|
||||||
protected abstract clearForResolve(view: MonochromePathfinderView): void;
|
protected abstract clearForResolve(view: MonochromeDemoView): void;
|
||||||
protected abstract setResolveUniforms(view: MonochromePathfinderView,
|
protected abstract setResolveUniforms(view: MonochromeDemoView,
|
||||||
program: PathfinderShaderProgram): void;
|
program: PathfinderShaderProgram): void;
|
||||||
|
|
||||||
private initAAAlphaFramebuffer(view: MonochromePathfinderView) {
|
private initAAAlphaFramebuffer(view: MonochromeDemoView) {
|
||||||
this.aaAlphaTexture = unwrapNull(view.gl.createTexture());
|
this.aaAlphaTexture = unwrapNull(view.gl.createTexture());
|
||||||
view.gl.activeTexture(view.gl.TEXTURE0);
|
view.gl.activeTexture(view.gl.TEXTURE0);
|
||||||
view.gl.bindTexture(view.gl.TEXTURE_2D, this.aaAlphaTexture);
|
view.gl.bindTexture(view.gl.TEXTURE_2D, this.aaAlphaTexture);
|
||||||
|
@ -203,7 +203,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
this.aaDepthTexture);
|
this.aaDepthTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCoverVAO(view: MonochromePathfinderView) {
|
private createCoverVAO(view: MonochromeDemoView) {
|
||||||
this.coverVAO = view.vertexArrayObjectExt.createVertexArrayOES();
|
this.coverVAO = view.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(this.coverVAO);
|
view.vertexArrayObjectExt.bindVertexArrayOES(this.coverVAO);
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createLineVAOs(view: MonochromePathfinderView) {
|
private createLineVAOs(view: MonochromeDemoView) {
|
||||||
const lineProgram = view.shaderPrograms.ecaaLine;
|
const lineProgram = view.shaderPrograms.ecaaLine;
|
||||||
const attributes = lineProgram.attributes;
|
const attributes = lineProgram.attributes;
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
this.lineVAOs = vaos as UpperAndLower<WebGLVertexArrayObject>;
|
this.lineVAOs = vaos as UpperAndLower<WebGLVertexArrayObject>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCurveVAOs(view: MonochromePathfinderView) {
|
private createCurveVAOs(view: MonochromeDemoView) {
|
||||||
const curveProgram = view.shaderPrograms.ecaaCurve;
|
const curveProgram = view.shaderPrograms.ecaaCurve;
|
||||||
const attributes = curveProgram.attributes;
|
const attributes = curveProgram.attributes;
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
this.curveVAOs = vaos as UpperAndLower<WebGLVertexArrayObject>;
|
this.curveVAOs = vaos as UpperAndLower<WebGLVertexArrayObject>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private createResolveVAO(view: MonochromePathfinderView) {
|
private createResolveVAO(view: MonochromeDemoView) {
|
||||||
this.resolveVAO = view.vertexArrayObjectExt.createVertexArrayOES();
|
this.resolveVAO = view.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
|
view.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private cover(view: MonochromePathfinderView) {
|
private cover(view: MonochromeDemoView) {
|
||||||
// Set state for conservative coverage.
|
// Set state for conservative coverage.
|
||||||
const coverProgram = view.shaderPrograms.ecaaCover;
|
const coverProgram = view.shaderPrograms.ecaaCover;
|
||||||
const usedSize = this.supersampledUsedSize(view);
|
const usedSize = this.supersampledUsedSize(view);
|
||||||
|
@ -356,7 +356,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setAAState(view: MonochromePathfinderView) {
|
private setAAState(view: MonochromeDemoView) {
|
||||||
const usedSize = this.supersampledUsedSize(view);
|
const usedSize = this.supersampledUsedSize(view);
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.aaFramebuffer);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.aaFramebuffer);
|
||||||
view.gl.viewport(0,
|
view.gl.viewport(0,
|
||||||
|
@ -373,7 +373,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.gl.enable(view.gl.BLEND);
|
view.gl.enable(view.gl.BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setAAUniforms(view: MonochromePathfinderView, 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);
|
this.bVertexPositionBufferTexture.bind(view.gl, uniforms, 0);
|
||||||
|
@ -383,7 +383,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.pathHintsBufferTexture.bind(view.gl, uniforms, 3);
|
view.pathHintsBufferTexture.bind(view.gl, uniforms, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private antialiasLines(view: MonochromePathfinderView) {
|
private antialiasLines(view: MonochromeDemoView) {
|
||||||
this.setAAState(view);
|
this.setAAState(view);
|
||||||
|
|
||||||
const lineProgram = view.shaderPrograms.ecaaLine;
|
const lineProgram = view.shaderPrograms.ecaaLine;
|
||||||
|
@ -408,7 +408,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private antialiasCurves(view: MonochromePathfinderView) {
|
private antialiasCurves(view: MonochromeDemoView) {
|
||||||
this.setAAState(view);
|
this.setAAState(view);
|
||||||
|
|
||||||
const curveProgram = view.shaderPrograms.ecaaCurve;
|
const curveProgram = view.shaderPrograms.ecaaCurve;
|
||||||
|
@ -433,7 +433,7 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveAA(view: MonochromePathfinderView) {
|
private resolveAA(view: MonochromeDemoView) {
|
||||||
// Set state for ECAA resolve.
|
// Set state for ECAA resolve.
|
||||||
const usedSize = view.destUsedSize;
|
const usedSize = view.destUsedSize;
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.destFramebuffer);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.destFramebuffer);
|
||||||
|
@ -477,34 +477,34 @@ export abstract class ECAAStrategy extends AntialiasingStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ECAAMonochromeStrategy extends ECAAStrategy {
|
export class ECAAMonochromeStrategy extends ECAAStrategy {
|
||||||
protected getResolveProgram(view: MonochromePathfinderView): PathfinderShaderProgram {
|
protected getResolveProgram(view: MonochromeDemoView): PathfinderShaderProgram {
|
||||||
if (this.subpixelAA !== 'none')
|
if (this.subpixelAA !== 'none')
|
||||||
return view.shaderPrograms.ecaaMonoSubpixelResolve;
|
return view.shaderPrograms.ecaaMonoSubpixelResolve;
|
||||||
return view.shaderPrograms.ecaaMonoResolve;
|
return view.shaderPrograms.ecaaMonoResolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initEdgeDetectFramebuffer(view: MonochromePathfinderView) {}
|
protected initEdgeDetectFramebuffer(view: MonochromeDemoView) {}
|
||||||
|
|
||||||
protected createEdgeDetectVAO(view: MonochromePathfinderView) {}
|
protected createEdgeDetectVAO(view: MonochromeDemoView) {}
|
||||||
|
|
||||||
protected detectEdgesIfNecessary(view: MonochromePathfinderView) {}
|
protected detectEdgesIfNecessary(view: MonochromeDemoView) {}
|
||||||
|
|
||||||
protected clearForCover(view: MonochromePathfinderView) {
|
protected clearForCover(view: MonochromeDemoView) {
|
||||||
view.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
view.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
view.gl.clearDepth(0.0);
|
view.gl.clearDepth(0.0);
|
||||||
view.gl.clear(view.gl.COLOR_BUFFER_BIT | view.gl.DEPTH_BUFFER_BIT);
|
view.gl.clear(view.gl.COLOR_BUFFER_BIT | view.gl.DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAADepthState(view: MonochromePathfinderView) {
|
protected setAADepthState(view: MonochromeDemoView) {
|
||||||
view.gl.disable(view.gl.DEPTH_TEST);
|
view.gl.disable(view.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForResolve(view: MonochromePathfinderView) {
|
protected clearForResolve(view: MonochromeDemoView) {
|
||||||
view.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
view.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
view.gl.clear(view.gl.COLOR_BUFFER_BIT);
|
view.gl.clear(view.gl.COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setResolveUniforms(view: MonochromePathfinderView, program: PathfinderShaderProgram) {
|
protected setResolveUniforms(view: MonochromeDemoView, program: PathfinderShaderProgram) {
|
||||||
view.gl.uniform4fv(program.uniforms.uBGColor, view.bgColor);
|
view.gl.uniform4fv(program.uniforms.uBGColor, view.bgColor);
|
||||||
view.gl.uniform4fv(program.uniforms.uFGColor, view.fgColor);
|
view.gl.uniform4fv(program.uniforms.uFGColor, view.fgColor);
|
||||||
}
|
}
|
||||||
|
@ -522,17 +522,17 @@ export class ECAAMulticolorStrategy extends ECAAStrategy {
|
||||||
private bgColorTexture: WebGLTexture;
|
private bgColorTexture: WebGLTexture;
|
||||||
private fgColorTexture: WebGLTexture;
|
private fgColorTexture: WebGLTexture;
|
||||||
|
|
||||||
protected getResolveProgram(view: MonochromePathfinderView): PathfinderShaderProgram {
|
protected getResolveProgram(view: MonochromeDemoView): PathfinderShaderProgram {
|
||||||
return view.shaderPrograms.ecaaMultiResolve;
|
return view.shaderPrograms.ecaaMultiResolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initDirectFramebuffer(view: MonochromePathfinderView) {
|
protected initDirectFramebuffer(view: MonochromeDemoView) {
|
||||||
this._directDepthTexture =
|
this._directDepthTexture =
|
||||||
createFramebufferDepthTexture(view.gl, this.supersampledFramebufferSize);
|
createFramebufferDepthTexture(view.gl, this.supersampledFramebufferSize);
|
||||||
super.initDirectFramebuffer(view);
|
super.initDirectFramebuffer(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initEdgeDetectFramebuffer(view: MonochromePathfinderView) {
|
protected initEdgeDetectFramebuffer(view: MonochromeDemoView) {
|
||||||
this.bgColorTexture = createFramebufferColorTexture(view.gl,
|
this.bgColorTexture = createFramebufferColorTexture(view.gl,
|
||||||
this.supersampledFramebufferSize);
|
this.supersampledFramebufferSize);
|
||||||
this.fgColorTexture = createFramebufferColorTexture(view.gl,
|
this.fgColorTexture = createFramebufferColorTexture(view.gl,
|
||||||
|
@ -543,7 +543,7 @@ export class ECAAMulticolorStrategy extends ECAAStrategy {
|
||||||
this.aaDepthTexture);
|
this.aaDepthTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected createEdgeDetectVAO(view: MonochromePathfinderView) {
|
protected createEdgeDetectVAO(view: MonochromeDemoView) {
|
||||||
this.edgeDetectVAO = view.vertexArrayObjectExt.createVertexArrayOES();
|
this.edgeDetectVAO = view.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(this.edgeDetectVAO);
|
view.vertexArrayObjectExt.bindVertexArrayOES(this.edgeDetectVAO);
|
||||||
|
|
||||||
|
@ -554,7 +554,7 @@ export class ECAAMulticolorStrategy extends ECAAStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected detectEdgesIfNecessary(view: MonochromePathfinderView) {
|
protected detectEdgesIfNecessary(view: MonochromeDemoView) {
|
||||||
// Set state for edge detection.
|
// Set state for edge detection.
|
||||||
const edgeDetectProgram = view.shaderPrograms.ecaaEdgeDetect;
|
const edgeDetectProgram = view.shaderPrograms.ecaaEdgeDetect;
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.edgeDetectFramebuffer);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.edgeDetectFramebuffer);
|
||||||
|
@ -593,32 +593,32 @@ export class ECAAMulticolorStrategy extends ECAAStrategy {
|
||||||
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
view.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setCoverDepthState(view: MonochromePathfinderView) {
|
protected setCoverDepthState(view: MonochromeDemoView) {
|
||||||
view.gl.depthMask(false);
|
view.gl.depthMask(false);
|
||||||
view.gl.depthFunc(view.gl.ALWAYS);
|
view.gl.depthFunc(view.gl.ALWAYS);
|
||||||
view.gl.enable(view.gl.DEPTH_TEST);
|
view.gl.enable(view.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForCover(view: MonochromePathfinderView) {
|
protected clearForCover(view: MonochromeDemoView) {
|
||||||
view.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
view.gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
view.gl.clear(view.gl.COLOR_BUFFER_BIT);
|
view.gl.clear(view.gl.COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAADepthState(view: MonochromePathfinderView) {
|
protected setAADepthState(view: MonochromeDemoView) {
|
||||||
view.gl.depthMask(false);
|
view.gl.depthMask(false);
|
||||||
view.gl.depthFunc(view.gl.EQUAL);
|
view.gl.depthFunc(view.gl.EQUAL);
|
||||||
view.gl.enable(view.gl.DEPTH_TEST);
|
view.gl.enable(view.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setResolveDepthState(view: MonochromePathfinderView) {
|
protected setResolveDepthState(view: MonochromeDemoView) {
|
||||||
view.gl.depthMask(false);
|
view.gl.depthMask(false);
|
||||||
view.gl.depthFunc(view.gl.NOTEQUAL);
|
view.gl.depthFunc(view.gl.NOTEQUAL);
|
||||||
view.gl.enable(view.gl.DEPTH_TEST);
|
view.gl.enable(view.gl.DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected clearForResolve(view: MonochromePathfinderView) {}
|
protected clearForResolve(view: MonochromeDemoView) {}
|
||||||
|
|
||||||
protected setResolveUniforms(view: MonochromePathfinderView, program: PathfinderShaderProgram) {
|
protected setResolveUniforms(view: MonochromeDemoView, program: PathfinderShaderProgram) {
|
||||||
view.gl.activeTexture(view.gl.TEXTURE1);
|
view.gl.activeTexture(view.gl.TEXTURE1);
|
||||||
view.gl.bindTexture(view.gl.TEXTURE_2D, this.bgColorTexture);
|
view.gl.bindTexture(view.gl.TEXTURE_2D, this.bgColorTexture);
|
||||||
view.gl.uniform1i(program.uniforms.uBGColor, 1);
|
view.gl.uniform1i(program.uniforms.uBGColor, 1);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import * as glmatrix from 'gl-matrix';
|
||||||
import {AntialiasingStrategy, SubpixelAAType} from './aa-strategy';
|
import {AntialiasingStrategy, SubpixelAAType} from './aa-strategy';
|
||||||
import {createFramebuffer, createFramebufferDepthTexture, setTextureParameters} from './gl-utils';
|
import {createFramebuffer, createFramebufferDepthTexture, setTextureParameters} from './gl-utils';
|
||||||
import {unwrapNull} from './utils';
|
import {unwrapNull} from './utils';
|
||||||
import {PathfinderDemoView} from './view';
|
import {DemoView} from './view';
|
||||||
|
|
||||||
export default class SSAAStrategy extends AntialiasingStrategy {
|
export default class SSAAStrategy extends AntialiasingStrategy {
|
||||||
private level: number;
|
private level: number;
|
||||||
|
@ -33,9 +33,9 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
||||||
this.supersampledFramebufferSize = glmatrix.vec2.create();
|
this.supersampledFramebufferSize = glmatrix.vec2.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMeshes(view: PathfinderDemoView) {}
|
attachMeshes(view: DemoView) {}
|
||||||
|
|
||||||
setFramebufferSize(view: PathfinderDemoView) {
|
setFramebufferSize(view: DemoView) {
|
||||||
this.destFramebufferSize = glmatrix.vec2.clone(view.destAllocatedSize);
|
this.destFramebufferSize = glmatrix.vec2.clone(view.destAllocatedSize);
|
||||||
|
|
||||||
this.supersampledFramebufferSize = glmatrix.vec2.create();
|
this.supersampledFramebufferSize = glmatrix.vec2.create();
|
||||||
|
@ -77,7 +77,7 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare(view: PathfinderDemoView) {
|
prepare(view: DemoView) {
|
||||||
const framebufferSize = this.supersampledFramebufferSize;
|
const framebufferSize = this.supersampledFramebufferSize;
|
||||||
const usedSize = this.usedSupersampledFramebufferSize(view);
|
const usedSize = this.usedSupersampledFramebufferSize(view);
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.supersampledFramebuffer);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.supersampledFramebuffer);
|
||||||
|
@ -86,9 +86,9 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
||||||
view.gl.enable(view.gl.SCISSOR_TEST);
|
view.gl.enable(view.gl.SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
antialias(view: PathfinderDemoView) {}
|
antialias(view: DemoView) {}
|
||||||
|
|
||||||
resolve(view: PathfinderDemoView) {
|
resolve(view: DemoView) {
|
||||||
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.destFramebuffer);
|
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.destFramebuffer);
|
||||||
view.gl.viewport(0, 0, view.destAllocatedSize[0], view.destAllocatedSize[1]);
|
view.gl.viewport(0, 0, view.destAllocatedSize[0], view.destAllocatedSize[1]);
|
||||||
view.gl.disable(view.gl.DEPTH_TEST);
|
view.gl.disable(view.gl.DEPTH_TEST);
|
||||||
|
@ -123,7 +123,7 @@ export default class SSAAStrategy extends AntialiasingStrategy {
|
||||||
return glmatrix.vec2.clone([this.subpixelAA !== 'none' ? 3 : 2, this.level === 2 ? 1 : 2]);
|
return glmatrix.vec2.clone([this.subpixelAA !== 'none' ? 3 : 2, this.level === 2 ? 1 : 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private usedSupersampledFramebufferSize(view: PathfinderDemoView): glmatrix.vec2 {
|
private usedSupersampledFramebufferSize(view: DemoView): glmatrix.vec2 {
|
||||||
const result = glmatrix.vec2.create();
|
const result = glmatrix.vec2.create();
|
||||||
glmatrix.vec2.mul(result, view.destUsedSize, this.supersampleScale);
|
glmatrix.vec2.mul(result, view.destUsedSize, this.supersampleScale);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -22,7 +22,7 @@ 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 {PathfinderDemoView, Timings} from './view';
|
import {DemoView, Timings} from './view';
|
||||||
|
|
||||||
const parseColor = require('parse-color');
|
const parseColor = require('parse-color');
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ class SVGDemoController extends DemoAppController<SVGDemoView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SVGDemoView extends PathfinderDemoView {
|
class SVGDemoView extends DemoView {
|
||||||
camera: OrthographicCamera;
|
camera: OrthographicCamera;
|
||||||
|
|
||||||
protected depthFunction: number = this.gl.GREATER;
|
protected depthFunction: number = this.gl.GREATER;
|
||||||
|
|
|
@ -30,7 +30,7 @@ import {calculatePixelDescent, calculatePixelRectForGlyph, PathfinderFont} from
|
||||||
import {BUILTIN_FONT_URI, calculatePixelXMin, GlyphStore, Hint, SimpleTextLayout} from "./text";
|
import {BUILTIN_FONT_URI, calculatePixelXMin, GlyphStore, Hint, SimpleTextLayout} from "./text";
|
||||||
import {assert, expectNotNull, panic, PathfinderError, scaleRect, UINT32_SIZE} from './utils';
|
import {assert, expectNotNull, panic, PathfinderError, scaleRect, UINT32_SIZE} from './utils';
|
||||||
import {unwrapNull} from './utils';
|
import {unwrapNull} from './utils';
|
||||||
import {MonochromePathfinderView, Timings, TIMINGS} from './view';
|
import {MonochromeDemoView, Timings, TIMINGS} from './view';
|
||||||
|
|
||||||
const DEFAULT_TEXT: string =
|
const DEFAULT_TEXT: string =
|
||||||
`’Twas brillig, and the slithy toves
|
`’Twas brillig, and the slithy toves
|
||||||
|
@ -268,7 +268,7 @@ class TextDemoController extends DemoAppController<TextDemoView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextDemoView extends MonochromePathfinderView {
|
class TextDemoView extends MonochromeDemoView {
|
||||||
atlasFramebuffer: WebGLFramebuffer;
|
atlasFramebuffer: WebGLFramebuffer;
|
||||||
atlasDepthTexture: WebGLTexture;
|
atlasDepthTexture: WebGLTexture;
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,13 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// FIXME(pcwalton): This is turning into a fragile inheritance hierarchy. See if we can refactor to
|
||||||
|
// use composition more.
|
||||||
|
|
||||||
import * as glmatrix from 'gl-matrix';
|
import * as glmatrix from 'gl-matrix';
|
||||||
|
|
||||||
import { AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy, SubpixelAAType } from "./aa-strategy";
|
import {AntialiasingStrategy, AntialiasingStrategyName, NoAAStrategy} from "./aa-strategy";
|
||||||
|
import {SubpixelAAType} from "./aa-strategy";
|
||||||
import PathfinderBufferTexture from './buffer-texture';
|
import PathfinderBufferTexture from './buffer-texture';
|
||||||
import {Camera} from "./camera";
|
import {Camera} from "./camera";
|
||||||
import {QUAD_ELEMENTS, UniformMap} from './gl-utils';
|
import {QUAD_ELEMENTS, UniformMap} from './gl-utils';
|
||||||
|
@ -19,6 +23,8 @@ import {PathfinderShaderProgram, SHADER_NAMES, ShaderMap} from './shader-loader'
|
||||||
import {ShaderProgramSource, UnlinkedShaderProgram} from './shader-loader';
|
import {ShaderProgramSource, UnlinkedShaderProgram} from './shader-loader';
|
||||||
import {expectNotNull, PathfinderError, UINT32_SIZE, unwrapNull} from './utils';
|
import {expectNotNull, PathfinderError, UINT32_SIZE, unwrapNull} from './utils';
|
||||||
|
|
||||||
|
const MAX_PATHS: number = 65535;
|
||||||
|
|
||||||
const TIME_INTERVAL_DELAY: number = 32;
|
const TIME_INTERVAL_DELAY: number = 32;
|
||||||
|
|
||||||
const B_LOOP_BLINN_DATA_SIZE: number = 4;
|
const B_LOOP_BLINN_DATA_SIZE: number = 4;
|
||||||
|
@ -115,7 +121,7 @@ export abstract class PathfinderView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class PathfinderDemoView extends PathfinderView {
|
export abstract class DemoView extends PathfinderView {
|
||||||
gl: WebGLRenderingContext;
|
gl: WebGLRenderingContext;
|
||||||
|
|
||||||
shaderPrograms: ShaderMap<PathfinderShaderProgram>;
|
shaderPrograms: ShaderMap<PathfinderShaderProgram>;
|
||||||
|
@ -143,6 +149,12 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
|
|
||||||
protected lastTimings: Timings;
|
protected lastTimings: Timings;
|
||||||
|
|
||||||
|
protected get pathIDsAreInstanced(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private instancedPathIDVBO: WebGLBuffer | null;
|
||||||
|
|
||||||
private atlasRenderingTimerQuery: WebGLQuery;
|
private atlasRenderingTimerQuery: WebGLQuery;
|
||||||
private compositingTimerQuery: WebGLQuery;
|
private compositingTimerQuery: WebGLQuery;
|
||||||
private timerQueryPollInterval: number | null;
|
private timerQueryPollInterval: number | null;
|
||||||
|
@ -162,6 +174,9 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
this.pathTransformBufferTextures = [];
|
this.pathTransformBufferTextures = [];
|
||||||
this.pathColorsBufferTextures = [];
|
this.pathColorsBufferTextures = [];
|
||||||
|
|
||||||
|
if (this.pathIDsAreInstanced)
|
||||||
|
this.initInstancedPathIDVBO();
|
||||||
|
|
||||||
this.wantsScreenshot = false;
|
this.wantsScreenshot = false;
|
||||||
|
|
||||||
this.antialiasingStrategy = new NoAAStrategy(0, 'none');
|
this.antialiasingStrategy = new NoAAStrategy(0, 'none');
|
||||||
|
@ -390,6 +405,10 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
|
|
||||||
protected abstract compositeIfNecessary(): void;
|
protected abstract compositeIfNecessary(): void;
|
||||||
|
|
||||||
|
protected meshInstanceCountForObject(objectIndex: number): number {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
private compileShaders(commonSource: string, shaderSources: ShaderMap<ShaderProgramSource>):
|
private compileShaders(commonSource: string, shaderSources: ShaderMap<ShaderProgramSource>):
|
||||||
ShaderMap<UnlinkedShaderProgram> {
|
ShaderMap<UnlinkedShaderProgram> {
|
||||||
const shaders: Partial<ShaderMap<Partial<UnlinkedShaderProgram>>> = {};
|
const shaders: Partial<ShaderMap<Partial<UnlinkedShaderProgram>>> = {};
|
||||||
|
@ -434,6 +453,17 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
return shaderProgramMap as ShaderMap<PathfinderShaderProgram>;
|
return shaderProgramMap as ShaderMap<PathfinderShaderProgram>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initInstancedPathIDVBO(): void {
|
||||||
|
const pathIDs = new Uint16Array(MAX_PATHS);
|
||||||
|
for (let pathIndex = 0; pathIndex < MAX_PATHS; pathIndex++)
|
||||||
|
pathIDs[pathIndex] = pathIndex + 1;
|
||||||
|
|
||||||
|
this.instancedPathIDVBO = this.gl.createBuffer();
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.instancedPathIDVBO);
|
||||||
|
this.gl.bufferData(this.gl.ARRAY_BUFFER, pathIDs, this.gl.STATIC_DRAW);
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);
|
||||||
|
}
|
||||||
|
|
||||||
private setTransformUniform(uniforms: UniformMap, objectIndex: number) {
|
private setTransformUniform(uniforms: UniformMap, objectIndex: number) {
|
||||||
const transform = glmatrix.mat4.clone(this.worldTransform);
|
const transform = glmatrix.mat4.clone(this.worldTransform);
|
||||||
glmatrix.mat4.mul(transform, transform, this.getModelviewTransform(objectIndex));
|
glmatrix.mat4.mul(transform, transform, this.getModelviewTransform(objectIndex));
|
||||||
|
@ -447,6 +477,12 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
|
|
||||||
const meshes = this.meshes[objectIndex];
|
const meshes = this.meshes[objectIndex];
|
||||||
|
|
||||||
|
let instanceCount: number | null;
|
||||||
|
if (!this.pathIDsAreInstanced)
|
||||||
|
instanceCount = null;
|
||||||
|
else
|
||||||
|
instanceCount = this.meshInstanceCountForObject(objectIndex);
|
||||||
|
|
||||||
// Set up implicit cover state.
|
// Set up implicit cover state.
|
||||||
this.gl.depthFunc(this.depthFunction);
|
this.gl.depthFunc(this.depthFunction);
|
||||||
this.gl.depthMask(true);
|
this.gl.depthMask(true);
|
||||||
|
@ -454,25 +490,12 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
this.gl.disable(this.gl.BLEND);
|
this.gl.disable(this.gl.BLEND);
|
||||||
|
|
||||||
// Set up the implicit cover interior VAO.
|
// Set up the implicit cover interior VAO.
|
||||||
|
//
|
||||||
|
// TODO(pcwalton): Cache these.
|
||||||
const directInteriorProgram = this.shaderPrograms[this.directInteriorProgramName];
|
const directInteriorProgram = this.shaderPrograms[this.directInteriorProgramName];
|
||||||
this.gl.useProgram(directInteriorProgram.program);
|
const implicitCoverInteriorVAO = this.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPositions);
|
this.vertexArrayObjectExt.bindVertexArrayOES(implicitCoverInteriorVAO);
|
||||||
this.gl.vertexAttribPointer(directInteriorProgram.attributes.aPosition,
|
this.initImplicitCoverInteriorVAO(objectIndex);
|
||||||
2,
|
|
||||||
this.gl.FLOAT,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPathIDs);
|
|
||||||
this.gl.vertexAttribPointer(directInteriorProgram.attributes.aPathID,
|
|
||||||
1,
|
|
||||||
this.gl.UNSIGNED_SHORT,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPosition);
|
|
||||||
this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPathID);
|
|
||||||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, meshes.coverInteriorIndices);
|
|
||||||
|
|
||||||
// Draw direct interior parts.
|
// Draw direct interior parts.
|
||||||
this.setTransformUniform(directInteriorProgram.uniforms, objectIndex);
|
this.setTransformUniform(directInteriorProgram.uniforms, objectIndex);
|
||||||
|
@ -487,7 +510,15 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
this.pathHintsBufferTexture.bind(this.gl, directInteriorProgram.uniforms, 2);
|
this.pathHintsBufferTexture.bind(this.gl, directInteriorProgram.uniforms, 2);
|
||||||
let indexCount = this.gl.getBufferParameter(this.gl.ELEMENT_ARRAY_BUFFER,
|
let indexCount = this.gl.getBufferParameter(this.gl.ELEMENT_ARRAY_BUFFER,
|
||||||
this.gl.BUFFER_SIZE) / UINT32_SIZE;
|
this.gl.BUFFER_SIZE) / UINT32_SIZE;
|
||||||
this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_INT, 0);
|
if (instanceCount == null) {
|
||||||
|
this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_INT, 0);
|
||||||
|
} else {
|
||||||
|
this.instancedArraysExt.drawElementsInstancedANGLE(this.gl.TRIANGLES,
|
||||||
|
indexCount,
|
||||||
|
this.gl.UNSIGNED_INT,
|
||||||
|
0,
|
||||||
|
instanceCount);
|
||||||
|
}
|
||||||
|
|
||||||
// Set up direct curve state.
|
// Set up direct curve state.
|
||||||
this.gl.depthMask(false);
|
this.gl.depthMask(false);
|
||||||
|
@ -497,40 +528,12 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
this.gl.ONE, this.gl.ONE);
|
this.gl.ONE, this.gl.ONE);
|
||||||
|
|
||||||
// Set up the direct curve VAO.
|
// Set up the direct curve VAO.
|
||||||
|
//
|
||||||
|
// TODO(pcwalton): Cache these.
|
||||||
const directCurveProgram = this.shaderPrograms[this.directCurveProgramName];
|
const directCurveProgram = this.shaderPrograms[this.directCurveProgramName];
|
||||||
this.gl.useProgram(directCurveProgram.program);
|
const implicitCoverCurveVAO = this.vertexArrayObjectExt.createVertexArrayOES();
|
||||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPositions);
|
this.vertexArrayObjectExt.bindVertexArrayOES(implicitCoverCurveVAO);
|
||||||
this.gl.vertexAttribPointer(directCurveProgram.attributes.aPosition,
|
this.initImplicitCoverCurveVAO(objectIndex);
|
||||||
2,
|
|
||||||
this.gl.FLOAT,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPathIDs);
|
|
||||||
this.gl.vertexAttribPointer(directCurveProgram.attributes.aPathID,
|
|
||||||
1,
|
|
||||||
this.gl.UNSIGNED_SHORT,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexLoopBlinnData);
|
|
||||||
this.gl.vertexAttribPointer(directCurveProgram.attributes.aTexCoord,
|
|
||||||
2,
|
|
||||||
this.gl.UNSIGNED_BYTE,
|
|
||||||
false,
|
|
||||||
B_LOOP_BLINN_DATA_SIZE,
|
|
||||||
B_LOOP_BLINN_DATA_TEX_COORD_OFFSET);
|
|
||||||
this.gl.vertexAttribPointer(directCurveProgram.attributes.aSign,
|
|
||||||
1,
|
|
||||||
this.gl.BYTE,
|
|
||||||
false,
|
|
||||||
B_LOOP_BLINN_DATA_SIZE,
|
|
||||||
B_LOOP_BLINN_DATA_SIGN_OFFSET);
|
|
||||||
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPosition);
|
|
||||||
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aTexCoord);
|
|
||||||
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPathID);
|
|
||||||
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aSign);
|
|
||||||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, meshes.coverCurveIndices);
|
|
||||||
|
|
||||||
// Draw direct curve parts.
|
// Draw direct curve parts.
|
||||||
this.setTransformUniform(directCurveProgram.uniforms, objectIndex);
|
this.setTransformUniform(directCurveProgram.uniforms, objectIndex);
|
||||||
|
@ -545,10 +548,101 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
this.pathHintsBufferTexture.bind(this.gl, directCurveProgram.uniforms, 2);
|
this.pathHintsBufferTexture.bind(this.gl, directCurveProgram.uniforms, 2);
|
||||||
indexCount = this.gl.getBufferParameter(this.gl.ELEMENT_ARRAY_BUFFER,
|
indexCount = this.gl.getBufferParameter(this.gl.ELEMENT_ARRAY_BUFFER,
|
||||||
this.gl.BUFFER_SIZE) / UINT32_SIZE;
|
this.gl.BUFFER_SIZE) / UINT32_SIZE;
|
||||||
this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_INT, 0);
|
if (instanceCount == null) {
|
||||||
|
this.gl.drawElements(this.gl.TRIANGLES, indexCount, this.gl.UNSIGNED_INT, 0);
|
||||||
|
} else {
|
||||||
|
this.instancedArraysExt.drawElementsInstancedANGLE(this.gl.TRIANGLES,
|
||||||
|
indexCount,
|
||||||
|
this.gl.UNSIGNED_INT,
|
||||||
|
0,
|
||||||
|
instanceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initImplicitCoverInteriorVAO(objectIndex: number): void {
|
||||||
|
const meshes = this.meshes[objectIndex];
|
||||||
|
|
||||||
|
const directInteriorProgram = this.shaderPrograms[this.directInteriorProgramName];
|
||||||
|
this.gl.useProgram(directInteriorProgram.program);
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPositions);
|
||||||
|
this.gl.vertexAttribPointer(directInteriorProgram.attributes.aPosition,
|
||||||
|
2,
|
||||||
|
this.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (this.pathIDsAreInstanced)
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.instancedPathIDVBO);
|
||||||
|
else
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPathIDs);
|
||||||
|
this.gl.vertexAttribPointer(directInteriorProgram.attributes.aPathID,
|
||||||
|
1,
|
||||||
|
this.gl.UNSIGNED_SHORT,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (this.pathIDsAreInstanced) {
|
||||||
|
this.instancedArraysExt
|
||||||
|
.vertexAttribDivisorANGLE(directInteriorProgram.attributes.aPathID, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPosition);
|
||||||
|
this.gl.enableVertexAttribArray(directInteriorProgram.attributes.aPathID);
|
||||||
|
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, meshes.coverInteriorIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
private initImplicitCoverCurveVAO(objectIndex: number): void {
|
||||||
|
const meshes = this.meshes[objectIndex];
|
||||||
|
|
||||||
|
const directCurveProgram = this.shaderPrograms[this.directCurveProgramName];
|
||||||
|
this.gl.useProgram(directCurveProgram.program);
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPositions);
|
||||||
|
this.gl.vertexAttribPointer(directCurveProgram.attributes.aPosition,
|
||||||
|
2,
|
||||||
|
this.gl.FLOAT,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (this.pathIDsAreInstanced)
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.instancedPathIDVBO);
|
||||||
|
else
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexPathIDs);
|
||||||
|
this.gl.vertexAttribPointer(directCurveProgram.attributes.aPathID,
|
||||||
|
1,
|
||||||
|
this.gl.UNSIGNED_SHORT,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
if (this.pathIDsAreInstanced) {
|
||||||
|
this.instancedArraysExt
|
||||||
|
.vertexAttribDivisorANGLE(directCurveProgram.attributes.aPathID, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, meshes.bVertexLoopBlinnData);
|
||||||
|
this.gl.vertexAttribPointer(directCurveProgram.attributes.aTexCoord,
|
||||||
|
2,
|
||||||
|
this.gl.UNSIGNED_BYTE,
|
||||||
|
false,
|
||||||
|
B_LOOP_BLINN_DATA_SIZE,
|
||||||
|
B_LOOP_BLINN_DATA_TEX_COORD_OFFSET);
|
||||||
|
this.gl.vertexAttribPointer(directCurveProgram.attributes.aSign,
|
||||||
|
1,
|
||||||
|
this.gl.BYTE,
|
||||||
|
false,
|
||||||
|
B_LOOP_BLINN_DATA_SIZE,
|
||||||
|
B_LOOP_BLINN_DATA_SIGN_OFFSET);
|
||||||
|
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPosition);
|
||||||
|
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aTexCoord);
|
||||||
|
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aPathID);
|
||||||
|
this.gl.enableVertexAttribArray(directCurveProgram.attributes.aSign);
|
||||||
|
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, meshes.coverCurveIndices);
|
||||||
|
}
|
||||||
|
|
||||||
private finishTiming() {
|
private finishTiming() {
|
||||||
if (this.timerQueryPollInterval != null)
|
if (this.timerQueryPollInterval != null)
|
||||||
return;
|
return;
|
||||||
|
@ -613,7 +707,7 @@ export abstract class PathfinderDemoView extends PathfinderView {
|
||||||
protected abstract get directInteriorProgramName(): keyof ShaderMap<void>;
|
protected abstract get directInteriorProgramName(): keyof ShaderMap<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class MonochromePathfinderView extends PathfinderDemoView {
|
export abstract class MonochromeDemoView extends DemoView {
|
||||||
abstract get bgColor(): glmatrix.vec4;
|
abstract get bgColor(): glmatrix.vec4;
|
||||||
abstract get fgColor(): glmatrix.vec4;
|
abstract get fgColor(): glmatrix.vec4;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue