Support stem darkening in SSAA mode.
The normals are incorrect right now in some cases, but it looks OK-ish.
This commit is contained in:
parent
35e59b1a05
commit
8e7eb6ca60
|
@ -23,3 +23,4 @@ Cargo.lock
|
|||
|
||||
# VSCode
|
||||
.vscode
|
||||
*.code-workspace
|
||||
|
|
|
@ -403,7 +403,9 @@ export class PathfinderMeshData implements Meshes<ArrayBuffer>, MeshDataCounts,
|
|||
const expandedPathID = newPathIndex + 1;
|
||||
const originalPathID = pathIDs[newPathIndex];
|
||||
|
||||
const bVertexCopyResult = copyVertices(['bVertexPositions', 'bVertexLoopBlinnData'],
|
||||
const bVertexCopyResult = copyVertices(['bVertexPositions',
|
||||
'bVertexLoopBlinnData',
|
||||
'bVertexNormals'],
|
||||
'bVertexPathRanges',
|
||||
expandedArrays,
|
||||
expandedRanges,
|
||||
|
|
|
@ -285,6 +285,12 @@ export abstract class Renderer {
|
|||
this.pathColorsBufferTextures[meshIndex].bind(gl, uniforms, textureUnit);
|
||||
}
|
||||
|
||||
setEmboldenAmountUniform(objectIndex: number, uniforms: UniformMap): void {
|
||||
const gl = this.renderContext.gl;
|
||||
const emboldenAmount = this.emboldenAmount;
|
||||
gl.uniform2f(uniforms.uEmboldenAmount, emboldenAmount[0], emboldenAmount[1]);
|
||||
}
|
||||
|
||||
renderTaskTypeForObject(objectIndex: number): RenderTaskType {
|
||||
return 'color';
|
||||
}
|
||||
|
@ -420,14 +426,14 @@ export abstract class Renderer {
|
|||
this.setFramebufferSizeUniform(directInteriorProgram.uniforms);
|
||||
this.setHintsUniform(directInteriorProgram.uniforms);
|
||||
this.setPathColorsUniform(objectIndex, directInteriorProgram.uniforms, 0);
|
||||
this.setEmboldenAmountUniform(objectIndex, directInteriorProgram.uniforms);
|
||||
this.pathTransformBufferTextures[meshIndex]
|
||||
.bind(gl, directInteriorProgram.uniforms, 1);
|
||||
if (renderingMode === 'color-depth') {
|
||||
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
|
||||
strategy.bindEdgeDepthTexture(gl, directInteriorProgram.uniforms, 2);
|
||||
}
|
||||
const coverInteriorRange = getMeshIndexRange(meshes.coverInteriorIndexRanges,
|
||||
pathRange);
|
||||
const coverInteriorRange = getMeshIndexRange(meshes.coverInteriorIndexRanges, pathRange);
|
||||
if (!this.pathIDsAreInstanced) {
|
||||
gl.drawElements(gl.TRIANGLES,
|
||||
coverInteriorRange.length,
|
||||
|
@ -458,10 +464,8 @@ export abstract class Renderer {
|
|||
// TODO(pcwalton): Cache these.
|
||||
const directCurveProgramName = this.directCurveProgramName();
|
||||
const directCurveProgram = renderContext.shaderPrograms[directCurveProgramName];
|
||||
if (this.implicitCoverCurveVAO == null) {
|
||||
this.implicitCoverCurveVAO = renderContext.vertexArrayObjectExt
|
||||
.createVertexArrayOES();
|
||||
}
|
||||
if (this.implicitCoverCurveVAO == null)
|
||||
this.implicitCoverCurveVAO = renderContext.vertexArrayObjectExt.createVertexArrayOES();
|
||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.implicitCoverCurveVAO);
|
||||
this.initImplicitCoverCurveVAO(objectIndex, instanceRange);
|
||||
|
||||
|
@ -470,6 +474,7 @@ export abstract class Renderer {
|
|||
this.setFramebufferSizeUniform(directCurveProgram.uniforms);
|
||||
this.setHintsUniform(directCurveProgram.uniforms);
|
||||
this.setPathColorsUniform(objectIndex, directCurveProgram.uniforms, 0);
|
||||
this.setEmboldenAmountUniform(objectIndex, directCurveProgram.uniforms);
|
||||
this.pathTransformBufferTextures[meshIndex].bind(gl, directCurveProgram.uniforms, 1);
|
||||
if (renderingMode === 'color-depth') {
|
||||
const strategy = antialiasingStrategy as MCAAMulticolorStrategy;
|
||||
|
@ -592,10 +597,18 @@ export abstract class Renderer {
|
|||
false,
|
||||
B_LOOP_BLINN_DATA_SIZE,
|
||||
B_LOOP_BLINN_DATA_SIGN_OFFSET);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, meshes.bVertexNormals);
|
||||
gl.vertexAttribPointer(directCurveProgram.attributes.aNormalAngle,
|
||||
1,
|
||||
gl.FLOAT,
|
||||
false,
|
||||
FLOAT32_SIZE,
|
||||
0);
|
||||
gl.enableVertexAttribArray(directCurveProgram.attributes.aPosition);
|
||||
gl.enableVertexAttribArray(directCurveProgram.attributes.aTexCoord);
|
||||
gl.enableVertexAttribArray(directCurveProgram.attributes.aPathID);
|
||||
gl.enableVertexAttribArray(directCurveProgram.attributes.aSign);
|
||||
gl.enableVertexAttribArray(directCurveProgram.attributes.aNormalAngle);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, meshes.coverCurveIndices);
|
||||
}
|
||||
|
||||
|
@ -632,8 +645,17 @@ export abstract class Renderer {
|
|||
.vertexAttribDivisorANGLE(directInteriorProgram.attributes.aPathID, 1);
|
||||
}
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, meshes.bVertexNormals);
|
||||
gl.vertexAttribPointer(directInteriorProgram.attributes.aNormalAngle,
|
||||
1,
|
||||
gl.FLOAT,
|
||||
false,
|
||||
FLOAT32_SIZE,
|
||||
0);
|
||||
|
||||
gl.enableVertexAttribArray(directInteriorProgram.attributes.aPosition);
|
||||
gl.enableVertexAttribArray(directInteriorProgram.attributes.aPathID);
|
||||
gl.enableVertexAttribArray(directInteriorProgram.attributes.aNormalAngle);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, meshes.coverInteriorIndices);
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ export abstract class XCAAStrategy extends AntialiasingStrategy {
|
|||
this.setAADepthState(renderer);
|
||||
}
|
||||
|
||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap): void {
|
||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap, objectIndex: number): void {
|
||||
const renderContext = renderer.renderContext;
|
||||
const gl = renderContext.gl;
|
||||
|
||||
|
@ -395,7 +395,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
|||
|
||||
gl.useProgram(lineProgram.program);
|
||||
const uniforms = lineProgram.uniforms;
|
||||
this.setAAUniforms(renderer, uniforms);
|
||||
this.setAAUniforms(renderer, uniforms, objectIndex);
|
||||
|
||||
for (const direction of DIRECTIONS) {
|
||||
const vao = this.lineVAOs[direction];
|
||||
|
@ -431,7 +431,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
|||
|
||||
gl.useProgram(curveProgram.program);
|
||||
const uniforms = curveProgram.uniforms;
|
||||
this.setAAUniforms(renderer, uniforms);
|
||||
this.setAAUniforms(renderer, uniforms, objectIndex);
|
||||
|
||||
for (const direction of DIRECTIONS) {
|
||||
const vao = this.curveVAOs[direction];
|
||||
|
@ -687,7 +687,7 @@ export abstract class MCAAStrategy extends XCAAStrategy {
|
|||
const coverProgram = renderContext.shaderPrograms.mcaaCover;
|
||||
gl.useProgram(coverProgram.program);
|
||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(this.coverVAO);
|
||||
this.setAAUniforms(renderer, coverProgram.uniforms);
|
||||
this.setAAUniforms(renderer, coverProgram.uniforms, objectIndex);
|
||||
|
||||
const bQuadRange = renderer.meshData[meshIndex].bQuadPathRanges;
|
||||
const count = calculateCountFromIndexRanges(pathRange, bQuadRange);
|
||||
|
@ -751,12 +751,9 @@ export class ECAAStrategy extends XCAAStrategy {
|
|||
this.antialiasCurvesOfObject(renderer, objectIndex);
|
||||
}
|
||||
|
||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap): void {
|
||||
super.setAAUniforms(renderer, uniforms);
|
||||
|
||||
const renderContext = renderer.renderContext;
|
||||
const emboldenAmount = renderer.emboldenAmount;
|
||||
renderContext.gl.uniform2f(uniforms.uEmboldenAmount, emboldenAmount[0], emboldenAmount[1]);
|
||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap, objectIndex: number): void {
|
||||
super.setAAUniforms(renderer, uniforms, objectIndex);
|
||||
renderer.setEmboldenAmountUniform(objectIndex, uniforms);
|
||||
}
|
||||
|
||||
protected getResolveProgram(renderContext: RenderContext): PathfinderShaderProgram {
|
||||
|
@ -929,7 +926,7 @@ export class ECAAStrategy extends XCAAStrategy {
|
|||
|
||||
gl.useProgram(lineProgram.program);
|
||||
const uniforms = lineProgram.uniforms;
|
||||
this.setAAUniforms(renderer, uniforms);
|
||||
this.setAAUniforms(renderer, uniforms, objectIndex);
|
||||
|
||||
const vao = this.lineVAO;
|
||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
||||
|
@ -957,7 +954,7 @@ export class ECAAStrategy extends XCAAStrategy {
|
|||
|
||||
gl.useProgram(curveProgram.program);
|
||||
const uniforms = curveProgram.uniforms;
|
||||
this.setAAUniforms(renderer, uniforms);
|
||||
this.setAAUniforms(renderer, uniforms, objectIndex);
|
||||
|
||||
const vao = this.curveVAO;
|
||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
||||
|
|
|
@ -177,10 +177,24 @@ impl<'a> Partitioner<'a> {
|
|||
let next_active_edge_index = self.find_point_between_active_edges(endpoint_index);
|
||||
|
||||
let endpoint = &self.endpoints[endpoint_index as usize];
|
||||
self.emit_b_quads_around_active_edge(next_active_edge_index, endpoint.position.x);
|
||||
let emission_result = self.emit_b_quads_around_active_edge(next_active_edge_index,
|
||||
endpoint.position.x);
|
||||
|
||||
self.add_new_edges_for_min_point(endpoint_index, next_active_edge_index);
|
||||
|
||||
// Add supporting interior triangles if necessary.
|
||||
match emission_result {
|
||||
BQuadEmissionResult::BQuadEmittedAbove | BQuadEmissionResult::BQuadEmittedAround => {
|
||||
self.add_supporting_interior_triangle(next_active_edge_index,
|
||||
next_active_edge_index - 1,
|
||||
next_active_edge_index + 2);
|
||||
self.add_supporting_interior_triangle(next_active_edge_index + 1,
|
||||
next_active_edge_index - 1,
|
||||
next_active_edge_index + 2);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let prev_endpoint_index = self.prev_endpoint_of(endpoint_index);
|
||||
let next_endpoint_index = self.next_endpoint_of(endpoint_index);
|
||||
let new_point = self.create_point_from_endpoint(next_endpoint_index);
|
||||
|
@ -277,8 +291,28 @@ impl<'a> Partitioner<'a> {
|
|||
|
||||
// TODO(pcwalton): Collapse the two duplicate endpoints that this will create together if
|
||||
// possible (i.e. if they have the same parity).
|
||||
self.emit_b_quads_around_active_edge(active_edge_indices[0], endpoint.position.x);
|
||||
self.emit_b_quads_around_active_edge(active_edge_indices[1], endpoint.position.x);
|
||||
let b_quad_emission_results = [
|
||||
self.emit_b_quads_around_active_edge(active_edge_indices[0], endpoint.position.x),
|
||||
self.emit_b_quads_around_active_edge(active_edge_indices[1], endpoint.position.x),
|
||||
];
|
||||
|
||||
// Add supporting interior triangles if necessary.
|
||||
match b_quad_emission_results[0] {
|
||||
BQuadEmissionResult::BQuadEmittedAbove | BQuadEmissionResult::BQuadEmittedAround => {
|
||||
self.add_supporting_interior_triangle(active_edge_indices[0],
|
||||
active_edge_indices[0] - 1,
|
||||
active_edge_indices[0] + 2)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match b_quad_emission_results[1] {
|
||||
BQuadEmissionResult::BQuadEmittedBelow | BQuadEmissionResult::BQuadEmittedAround => {
|
||||
self.add_supporting_interior_triangle(active_edge_indices[1],
|
||||
active_edge_indices[1] - 2,
|
||||
active_edge_indices[1] + 1)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.heap.pop();
|
||||
|
||||
|
@ -837,6 +871,17 @@ impl<'a> Partitioner<'a> {
|
|||
self.subdivide_active_edge_again_at_t(subdivision, t, bottom)
|
||||
}
|
||||
|
||||
fn add_supporting_interior_triangle(&mut self,
|
||||
active_edge_index: u32,
|
||||
upper_active_edge_index: u32,
|
||||
lower_active_edge_index: u32) {
|
||||
self.library.cover_indices.interior_indices.extend([
|
||||
self.active_edges[active_edge_index as usize].left_vertex_index,
|
||||
self.active_edges[upper_active_edge_index as usize].left_vertex_index,
|
||||
self.active_edges[lower_active_edge_index as usize].left_vertex_index,
|
||||
].into_iter());
|
||||
}
|
||||
|
||||
fn already_visited_point(&self, point: &Point) -> bool {
|
||||
// FIXME(pcwalton): This makes the visited vector too big.
|
||||
let index = point.endpoint_index as usize;
|
||||
|
@ -1093,6 +1138,9 @@ impl<'a> Partitioner<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(pcwalton): This creates incorrect normals for vertical lines. I think we should
|
||||
// probably calculate normals for the path vertices first and then lerp them to calculate these
|
||||
// B-vertex normals. That would be simpler, faster, and more correct, I suspect.
|
||||
fn update_vertex_normals_for_new_b_quad(&mut self, b_quad: &BQuad) {
|
||||
self.update_vertex_normal_for_b_quad_edge(b_quad.upper_left_vertex_index,
|
||||
b_quad.upper_control_point_vertex_index,
|
||||
|
|
|
@ -114,6 +114,10 @@ int convertWindowDepthValueToPathIndex(float depthValue) {
|
|||
return int(pathIndex);
|
||||
}
|
||||
|
||||
vec2 dilatePosition(vec2 position, float normalAngle, vec2 amount) {
|
||||
return position + vec2(cos(normalAngle), -sin(normalAngle)) * amount;
|
||||
}
|
||||
|
||||
bool computeMCAAQuadPosition(out vec2 outPosition,
|
||||
inout vec2 leftPosition,
|
||||
inout vec2 rightPosition,
|
||||
|
@ -164,8 +168,8 @@ bool computeECAAQuadPosition(out vec2 outPosition,
|
|||
float leftNormalAngle,
|
||||
float rightNormalAngle,
|
||||
vec2 emboldenAmount) {
|
||||
leftPosition += vec2(cos(leftNormalAngle), -sin(leftNormalAngle)) * emboldenAmount;
|
||||
rightPosition += vec2(cos(rightNormalAngle), -sin(rightNormalAngle)) * emboldenAmount;
|
||||
leftPosition = dilatePosition(leftPosition, leftNormalAngle, emboldenAmount);
|
||||
rightPosition = dilatePosition(rightPosition, rightNormalAngle, emboldenAmount);
|
||||
|
||||
leftPosition = hintPosition(leftPosition, hints);
|
||||
rightPosition = hintPosition(rightPosition, hints);
|
||||
|
|
|
@ -12,6 +12,7 @@ precision highp float;
|
|||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec4 uHints;
|
||||
uniform vec2 uEmboldenAmount;
|
||||
uniform ivec2 uPathColorsDimensions;
|
||||
uniform ivec2 uPathTransformDimensions;
|
||||
uniform sampler2D uPathColors;
|
||||
|
@ -21,6 +22,7 @@ attribute vec2 aPosition;
|
|||
attribute vec2 aTexCoord;
|
||||
attribute float aPathID;
|
||||
attribute float aSign;
|
||||
attribute float aNormalAngle;
|
||||
|
||||
varying vec4 vColor;
|
||||
varying vec2 vTexCoord;
|
||||
|
@ -31,7 +33,8 @@ void main() {
|
|||
|
||||
vec4 pathTransform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||
|
||||
vec2 position = hintPosition(aPosition, uHints);
|
||||
vec2 position = dilatePosition(aPosition, aNormalAngle, uEmboldenAmount);
|
||||
position = hintPosition(position, uHints);
|
||||
position = transformVertexPositionST(position, pathTransform);
|
||||
position = transformVertexPosition(position, uTransform);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ precision highp float;
|
|||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec4 uHints;
|
||||
uniform vec2 uEmboldenAmount;
|
||||
uniform ivec2 uPathColorsDimensions;
|
||||
uniform ivec2 uPathTransformDimensions;
|
||||
uniform sampler2D uPathColors;
|
||||
|
@ -19,6 +20,7 @@ uniform sampler2D uPathTransform;
|
|||
|
||||
attribute vec2 aPosition;
|
||||
attribute float aPathID;
|
||||
attribute float aNormalAngle;
|
||||
|
||||
varying vec4 vColor;
|
||||
|
||||
|
@ -27,7 +29,8 @@ void main() {
|
|||
|
||||
vec4 pathTransform = fetchFloat4Data(uPathTransform, pathID, uPathTransformDimensions);
|
||||
|
||||
vec2 position = hintPosition(aPosition, uHints);
|
||||
vec2 position = dilatePosition(aPosition, aNormalAngle, uEmboldenAmount);
|
||||
position = hintPosition(position, uHints);
|
||||
position = transformVertexPositionST(position, pathTransform);
|
||||
position = transformVertexPosition(position, uTransform);
|
||||
|
||||
|
|
|
@ -58,9 +58,10 @@ void main() {
|
|||
leftNormalAngle,
|
||||
rightNormalAngle,
|
||||
uEmboldenAmount)) {
|
||||
controlPointPosition += vec2(cos(controlPointNormalAngle),
|
||||
-sin(controlPointNormalAngle)) * uEmboldenAmount;
|
||||
controlPointPosition = hintPosition(aControlPointPosition, uHints);
|
||||
controlPointPosition = dilatePosition(controlPointPosition,
|
||||
controlPointNormalAngle,
|
||||
uEmboldenAmount);
|
||||
controlPointPosition = hintPosition(controlPointPosition, uHints);
|
||||
controlPointPosition = transformVertexPositionST(controlPointPosition, transform);
|
||||
controlPointPosition = transformVertexPositionST(controlPointPosition, uTransformST);
|
||||
controlPointPosition = convertClipToScreenSpace(controlPointPosition, uFramebufferSize);
|
||||
|
|
Loading…
Reference in New Issue