Fix rotation artefacts by rendering curves in two passes, clipping at X
inflection points as necessary.
This commit is contained in:
parent
801c25305f
commit
9b59ce2443
|
@ -23,6 +23,7 @@ export interface ShaderMap<T> {
|
||||||
direct3DInterior: T;
|
direct3DInterior: T;
|
||||||
ecaaLine: T;
|
ecaaLine: T;
|
||||||
ecaaCurve: T;
|
ecaaCurve: T;
|
||||||
|
ecaaTransformedCurve: T;
|
||||||
mcaaCover: T;
|
mcaaCover: T;
|
||||||
mcaaLine: T;
|
mcaaLine: T;
|
||||||
mcaaCurve: T;
|
mcaaCurve: T;
|
||||||
|
@ -32,6 +33,7 @@ export interface ShaderMap<T> {
|
||||||
xcaaMultiDirectCurve: T;
|
xcaaMultiDirectCurve: T;
|
||||||
xcaaMultiDirectInterior: T;
|
xcaaMultiDirectInterior: T;
|
||||||
xcaaMultiEdgeMaskCurve: T;
|
xcaaMultiEdgeMaskCurve: T;
|
||||||
|
xcaaMultiEdgeMaskTransformedCurve: T;
|
||||||
xcaaMultiEdgeMaskLine: T;
|
xcaaMultiEdgeMaskLine: T;
|
||||||
xcaaMultiResolve: T;
|
xcaaMultiResolve: T;
|
||||||
}
|
}
|
||||||
|
@ -57,11 +59,13 @@ export const SHADER_NAMES: Array<keyof ShaderMap<void>> = [
|
||||||
'mcaaCurve',
|
'mcaaCurve',
|
||||||
'ecaaLine',
|
'ecaaLine',
|
||||||
'ecaaCurve',
|
'ecaaCurve',
|
||||||
|
'ecaaTransformedCurve',
|
||||||
'xcaaMonoResolve',
|
'xcaaMonoResolve',
|
||||||
'xcaaMonoSubpixelResolve',
|
'xcaaMonoSubpixelResolve',
|
||||||
'xcaaMultiDirectCurve',
|
'xcaaMultiDirectCurve',
|
||||||
'xcaaMultiDirectInterior',
|
'xcaaMultiDirectInterior',
|
||||||
'xcaaMultiEdgeMaskCurve',
|
'xcaaMultiEdgeMaskCurve',
|
||||||
|
'xcaaMultiEdgeMaskTransformedCurve',
|
||||||
'xcaaMultiEdgeMaskLine',
|
'xcaaMultiEdgeMaskLine',
|
||||||
'xcaaMultiResolve',
|
'xcaaMultiResolve',
|
||||||
'demo3DDistantGlyph',
|
'demo3DDistantGlyph',
|
||||||
|
@ -113,6 +117,10 @@ const SHADER_URLS: ShaderMap<ShaderProgramURLs> = {
|
||||||
fragment: "/glsl/gles2/xcaa-line.fs.glsl",
|
fragment: "/glsl/gles2/xcaa-line.fs.glsl",
|
||||||
vertex: "/glsl/gles2/ecaa-line.vs.glsl",
|
vertex: "/glsl/gles2/ecaa-line.vs.glsl",
|
||||||
},
|
},
|
||||||
|
ecaaTransformedCurve: {
|
||||||
|
fragment: "/glsl/gles2/xcaa-curve.fs.glsl",
|
||||||
|
vertex: "/glsl/gles2/ecaa-transformed-curve.vs.glsl",
|
||||||
|
},
|
||||||
mcaaCover: {
|
mcaaCover: {
|
||||||
fragment: "/glsl/gles2/mcaa-cover.fs.glsl",
|
fragment: "/glsl/gles2/mcaa-cover.fs.glsl",
|
||||||
vertex: "/glsl/gles2/mcaa-cover.vs.glsl",
|
vertex: "/glsl/gles2/mcaa-cover.vs.glsl",
|
||||||
|
@ -153,6 +161,10 @@ const SHADER_URLS: ShaderMap<ShaderProgramURLs> = {
|
||||||
fragment: "/glsl/gles2/xcaa-multi-edge-mask-line.fs.glsl",
|
fragment: "/glsl/gles2/xcaa-multi-edge-mask-line.fs.glsl",
|
||||||
vertex: "/glsl/gles2/ecaa-multi-edge-mask-line.vs.glsl",
|
vertex: "/glsl/gles2/ecaa-multi-edge-mask-line.vs.glsl",
|
||||||
},
|
},
|
||||||
|
xcaaMultiEdgeMaskTransformedCurve: {
|
||||||
|
fragment: "/glsl/gles2/xcaa-multi-edge-mask-curve.fs.glsl",
|
||||||
|
vertex: "/glsl/gles2/ecaa-multi-edge-mask-transformed-curve.vs.glsl",
|
||||||
|
},
|
||||||
xcaaMultiResolve: {
|
xcaaMultiResolve: {
|
||||||
fragment: "/glsl/gles2/xcaa-multi-resolve.fs.glsl",
|
fragment: "/glsl/gles2/xcaa-multi-resolve.fs.glsl",
|
||||||
vertex: "/glsl/gles2/xcaa-multi-resolve.vs.glsl",
|
vertex: "/glsl/gles2/xcaa-multi-resolve.vs.glsl",
|
||||||
|
|
|
@ -781,9 +781,10 @@ export abstract class ECAAStrategy extends XCAAStrategy {
|
||||||
this.antialiasLinesOfObjectWithProgram(renderer,
|
this.antialiasLinesOfObjectWithProgram(renderer,
|
||||||
objectIndex,
|
objectIndex,
|
||||||
this.lineShaderProgramNames[0]);
|
this.lineShaderProgramNames[0]);
|
||||||
this.antialiasCurvesOfObjectWithProgram(renderer,
|
this.antialiasCurvesOfObjectWithPrograms(renderer,
|
||||||
objectIndex,
|
objectIndex,
|
||||||
this.curveShaderProgramNames[0]);
|
this.curveShaderProgramNames[0],
|
||||||
|
this.curveShaderProgramNames[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap, objectIndex: number): void {
|
protected setAAUniforms(renderer: Renderer, uniforms: UniformMap, objectIndex: number): void {
|
||||||
|
@ -850,9 +851,24 @@ export abstract class ECAAStrategy extends XCAAStrategy {
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected antialiasCurvesOfObjectWithProgram(renderer: Renderer,
|
protected antialiasCurvesOfObjectWithPrograms(renderer: Renderer,
|
||||||
objectIndex: number,
|
objectIndex: number,
|
||||||
programName: keyof ShaderMap<void>):
|
stProgram: keyof ShaderMap<void>,
|
||||||
|
transformedProgram: keyof ShaderMap<void>):
|
||||||
|
void {
|
||||||
|
if (renderer.usesSTTransform) {
|
||||||
|
this.antialiasCurvesOfObjectWithProgram(renderer, objectIndex, stProgram, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.antialiasCurvesOfObjectWithProgram(renderer, objectIndex, transformedProgram, 0);
|
||||||
|
this.antialiasCurvesOfObjectWithProgram(renderer, objectIndex, transformedProgram, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private antialiasCurvesOfObjectWithProgram(renderer: Renderer,
|
||||||
|
objectIndex: number,
|
||||||
|
programName: keyof ShaderMap<void>,
|
||||||
|
passIndex: number):
|
||||||
void {
|
void {
|
||||||
if (renderer.meshData == null)
|
if (renderer.meshData == null)
|
||||||
return;
|
return;
|
||||||
|
@ -867,6 +883,7 @@ export abstract class ECAAStrategy extends XCAAStrategy {
|
||||||
gl.useProgram(curveProgram.program);
|
gl.useProgram(curveProgram.program);
|
||||||
const uniforms = curveProgram.uniforms;
|
const uniforms = curveProgram.uniforms;
|
||||||
this.setAAUniforms(renderer, uniforms, objectIndex);
|
this.setAAUniforms(renderer, uniforms, objectIndex);
|
||||||
|
gl.uniform1i(uniforms.uPassIndex, passIndex);
|
||||||
|
|
||||||
const vao = this.curveVAOs[programName];
|
const vao = this.curveVAOs[programName];
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(vao);
|
||||||
|
@ -1061,7 +1078,7 @@ export class ECAAMonochromeStrategy extends ECAAStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get curveShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
protected get curveShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
||||||
return ['ecaaCurve'];
|
return ['ecaaCurve', 'ecaaTransformedCurve'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1188,7 +1205,12 @@ export class ECAAMulticolorStrategy extends ECAAStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get curveShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
protected get curveShaderProgramNames(): Array<keyof ShaderMap<void>> {
|
||||||
return ['ecaaCurve', 'xcaaMultiEdgeMaskCurve'];
|
return [
|
||||||
|
'ecaaCurve',
|
||||||
|
'ecaaTransformedCurve',
|
||||||
|
'xcaaMultiEdgeMaskCurve',
|
||||||
|
'xcaaMultiEdgeMaskTransformedCurve',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private edgeMaskVAO: WebGLVertexArrayObject;
|
private edgeMaskVAO: WebGLVertexArrayObject;
|
||||||
|
@ -1233,7 +1255,10 @@ export class ECAAMulticolorStrategy extends ECAAStrategy {
|
||||||
// Perform edge masking.
|
// Perform edge masking.
|
||||||
gl.colorMask(false, false, false, false);
|
gl.colorMask(false, false, false, false);
|
||||||
this.antialiasLinesOfObjectWithProgram(renderer, objectIndex, 'xcaaMultiEdgeMaskLine');
|
this.antialiasLinesOfObjectWithProgram(renderer, objectIndex, 'xcaaMultiEdgeMaskLine');
|
||||||
this.antialiasCurvesOfObjectWithProgram(renderer, objectIndex, 'xcaaMultiEdgeMaskCurve');
|
this.antialiasCurvesOfObjectWithPrograms(renderer,
|
||||||
|
objectIndex,
|
||||||
|
'xcaaMultiEdgeMaskCurve',
|
||||||
|
'xcaaMultiEdgeMaskTransformedCurve');
|
||||||
|
|
||||||
gl.colorMask(true, true, true, true);
|
gl.colorMask(true, true, true, true);
|
||||||
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
renderContext.vertexArrayObjectExt.bindVertexArrayOES(null);
|
||||||
|
|
|
@ -126,17 +126,6 @@ vec2 computeXCAAClipSpaceQuadPosition(vec4 extents, vec2 quadPosition, ivec2 fra
|
||||||
return convertScreenToClipSpace(position, framebufferSize);
|
return convertScreenToClipSpace(position, framebufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 computeXCAAEdgeBoundedClipSpaceQuadPosition(vec2 leftPosition,
|
|
||||||
vec2 rightPosition,
|
|
||||||
vec2 quadPosition,
|
|
||||||
ivec2 framebufferSize) {
|
|
||||||
vec4 extents = vec4(leftPosition.x,
|
|
||||||
min(leftPosition.y, rightPosition.y),
|
|
||||||
rightPosition.x,
|
|
||||||
max(leftPosition.y, rightPosition.y));
|
|
||||||
return computeXCAAClipSpaceQuadPosition(extents, quadPosition, framebufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 computeMCAAPosition(vec2 position,
|
vec2 computeMCAAPosition(vec2 position,
|
||||||
vec4 hints,
|
vec4 hints,
|
||||||
vec4 localTransformST,
|
vec4 localTransformST,
|
||||||
|
@ -172,10 +161,11 @@ bool computeMCAAQuadPosition(out vec2 outPosition,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
outPosition = computeXCAAEdgeBoundedClipSpaceQuadPosition(leftPosition,
|
vec4 extents = vec4(leftPosition.x,
|
||||||
rightPosition,
|
min(leftPosition.y, rightPosition.y),
|
||||||
quadPosition,
|
rightPosition.x,
|
||||||
framebufferSize);
|
max(leftPosition.y, rightPosition.y));
|
||||||
|
outPosition = computeXCAAClipSpaceQuadPosition(extents, quadPosition, framebufferSize);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +218,31 @@ float computeECAAWinding(inout vec2 leftPosition, inout vec2 rightPosition) {
|
||||||
return rightPosition.x - leftPosition.x > EPSILON ? winding : 0.0;
|
return rightPosition.x - leftPosition.x > EPSILON ? winding : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2 computeECAAQuadPositionFromTransformedPositions(vec2 leftPosition,
|
||||||
|
vec2 rightPosition,
|
||||||
|
vec2 quadPosition,
|
||||||
|
ivec2 framebufferSize,
|
||||||
|
vec4 localTransformST,
|
||||||
|
vec2 localTransformExt,
|
||||||
|
mat4 globalTransform,
|
||||||
|
vec4 bounds,
|
||||||
|
vec3 leftTopRightEdges) {
|
||||||
|
vec2 edgeBL = bounds.xy, edgeTL = bounds.xw, edgeTR = bounds.zw, edgeBR = bounds.zy;
|
||||||
|
edgeBL = transformECAAPosition(edgeBL, localTransformST, localTransformExt, globalTransform);
|
||||||
|
edgeBR = transformECAAPosition(edgeBR, localTransformST, localTransformExt, globalTransform);
|
||||||
|
edgeTL = transformECAAPosition(edgeTL, localTransformST, localTransformExt, globalTransform);
|
||||||
|
edgeTR = transformECAAPosition(edgeTR, localTransformST, localTransformExt, globalTransform);
|
||||||
|
|
||||||
|
// Find the bottom of the path, and convert to clip space.
|
||||||
|
//
|
||||||
|
// FIXME(pcwalton): Speed this up somehow?
|
||||||
|
float pathBottomY = max(max(edgeBL.y, edgeBR.y), max(edgeTL.y, edgeTR.y));
|
||||||
|
pathBottomY = (pathBottomY + 1.0) * 0.5 * float(framebufferSize.y);
|
||||||
|
|
||||||
|
vec4 extents = vec4(leftTopRightEdges, pathBottomY);
|
||||||
|
return computeXCAAClipSpaceQuadPosition(extents, quadPosition, framebufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Clean up this signature somehow?
|
// FIXME(pcwalton): Clean up this signature somehow?
|
||||||
bool computeECAAQuadPosition(out vec2 outPosition,
|
bool computeECAAQuadPosition(out vec2 outPosition,
|
||||||
out float outWinding,
|
out float outWinding,
|
||||||
|
@ -259,12 +274,6 @@ bool computeECAAQuadPosition(out vec2 outPosition,
|
||||||
globalTransform,
|
globalTransform,
|
||||||
framebufferSize);
|
framebufferSize);
|
||||||
|
|
||||||
vec2 edgeBL = bounds.xy, edgeTL = bounds.xw, edgeTR = bounds.zw, edgeBR = bounds.zy;
|
|
||||||
edgeBL = transformECAAPosition(edgeBL, localTransformST, localTransformExt, globalTransform);
|
|
||||||
edgeBR = transformECAAPosition(edgeBR, localTransformST, localTransformExt, globalTransform);
|
|
||||||
edgeTL = transformECAAPosition(edgeTL, localTransformST, localTransformExt, globalTransform);
|
|
||||||
edgeTR = transformECAAPosition(edgeTR, localTransformST, localTransformExt, globalTransform);
|
|
||||||
|
|
||||||
float winding = computeECAAWinding(leftPosition, rightPosition);
|
float winding = computeECAAWinding(leftPosition, rightPosition);
|
||||||
outWinding = winding;
|
outWinding = winding;
|
||||||
if (winding == 0.0) {
|
if (winding == 0.0) {
|
||||||
|
@ -272,49 +281,54 @@ bool computeECAAQuadPosition(out vec2 outPosition,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the bottom of the path, and convert to clip space.
|
vec3 leftTopRightEdges = vec3(leftPosition.x,
|
||||||
//
|
|
||||||
// FIXME(pcwalton): Speed this up somehow?
|
|
||||||
float pathBottomY = max(max(edgeBL.y, edgeBR.y), max(edgeTL.y, edgeTR.y));
|
|
||||||
pathBottomY = (pathBottomY + 1.0) * 0.5 * float(framebufferSize.y);
|
|
||||||
|
|
||||||
vec4 extents = vec4(leftPosition.x,
|
|
||||||
min(leftPosition.y, rightPosition.y),
|
min(leftPosition.y, rightPosition.y),
|
||||||
rightPosition.x,
|
rightPosition.x);
|
||||||
pathBottomY);
|
outPosition = computeECAAQuadPositionFromTransformedPositions(leftPosition,
|
||||||
outPosition = computeXCAAClipSpaceQuadPosition(extents, quadPosition, framebufferSize);
|
rightPosition,
|
||||||
|
quadPosition,
|
||||||
|
framebufferSize,
|
||||||
|
localTransformST,
|
||||||
|
localTransformExt,
|
||||||
|
globalTransform,
|
||||||
|
bounds,
|
||||||
|
leftTopRightEdges);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool computeECAAMultiEdgeMaskQuadPosition(out vec2 outPosition,
|
bool splitCurveAndComputeECAAWinding(out float outWinding,
|
||||||
|
out vec3 outLeftTopRightEdges,
|
||||||
inout vec2 leftPosition,
|
inout vec2 leftPosition,
|
||||||
inout vec2 rightPosition,
|
inout vec2 rightPosition,
|
||||||
vec2 quadPosition,
|
vec2 controlPointPosition,
|
||||||
ivec2 framebufferSize,
|
int passIndex) {
|
||||||
vec4 localTransformST,
|
// Split at the X inflection point if necessary.
|
||||||
vec2 localTransformExt,
|
float num = leftPosition.x - controlPointPosition.x;
|
||||||
mat4 globalTransform) {
|
float denom = leftPosition.x - 2.0 * controlPointPosition.x + rightPosition.x;
|
||||||
leftPosition = transformECAAPositionToScreenSpace(leftPosition,
|
float inflectionT = num / denom;
|
||||||
localTransformST,
|
if (inflectionT > EPSILON && inflectionT < 1.0 - EPSILON) {
|
||||||
localTransformExt,
|
vec2 newCP0 = mix(leftPosition, controlPointPosition, inflectionT);
|
||||||
globalTransform,
|
vec2 newCP1 = mix(controlPointPosition, rightPosition, inflectionT);
|
||||||
framebufferSize);
|
vec2 inflectionPoint = mix(newCP0, newCP1, inflectionT);
|
||||||
rightPosition = transformECAAPositionToScreenSpace(rightPosition,
|
if (passIndex == 0) {
|
||||||
localTransformST,
|
controlPointPosition = newCP0;
|
||||||
localTransformExt,
|
rightPosition = inflectionPoint;
|
||||||
globalTransform,
|
} else {
|
||||||
framebufferSize);
|
controlPointPosition = newCP1;
|
||||||
|
leftPosition = inflectionPoint;
|
||||||
float winding = computeECAAWinding(leftPosition, rightPosition);
|
}
|
||||||
if (winding == 0.0) {
|
} else if (passIndex != 0) {
|
||||||
outPosition = vec2(0.0);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
outPosition = computeXCAAEdgeBoundedClipSpaceQuadPosition(leftPosition,
|
float winding = computeECAAWinding(leftPosition, rightPosition);
|
||||||
rightPosition,
|
outWinding = winding;
|
||||||
quadPosition,
|
if (winding == 0.0)
|
||||||
framebufferSize);
|
return false;
|
||||||
|
|
||||||
|
outLeftTopRightEdges = vec3(min(leftPosition.x, controlPointPosition.x),
|
||||||
|
min(min(leftPosition.y, controlPointPosition.y), rightPosition.y),
|
||||||
|
max(rightPosition.x, controlPointPosition.x));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ uniform ivec2 uPathTransformSTDimensions;
|
||||||
uniform sampler2D uPathTransformST;
|
uniform sampler2D uPathTransformST;
|
||||||
uniform ivec2 uPathTransformExtDimensions;
|
uniform ivec2 uPathTransformExtDimensions;
|
||||||
uniform sampler2D uPathTransformExt;
|
uniform sampler2D uPathTransformExt;
|
||||||
|
uniform int uPassIndex;
|
||||||
|
|
||||||
attribute vec2 aQuadPosition;
|
attribute vec2 aQuadPosition;
|
||||||
attribute vec2 aLeftPosition;
|
attribute vec2 aLeftPosition;
|
||||||
|
@ -40,23 +41,35 @@ void main() {
|
||||||
uPathTransformExtDimensions,
|
uPathTransformExtDimensions,
|
||||||
pathID);
|
pathID);
|
||||||
|
|
||||||
// Transform the points, and compute the position of this vertex.
|
// Transform the points.
|
||||||
vec2 position;
|
leftPosition = transformECAAPositionToScreenSpace(leftPosition,
|
||||||
if (computeECAAMultiEdgeMaskQuadPosition(position,
|
|
||||||
leftPosition,
|
|
||||||
rightPosition,
|
|
||||||
aQuadPosition,
|
|
||||||
uFramebufferSize,
|
|
||||||
pathTransformST,
|
pathTransformST,
|
||||||
pathTransformExt,
|
pathTransformExt,
|
||||||
uTransform)) {
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
rightPosition = transformECAAPositionToScreenSpace(rightPosition,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
controlPointPosition = transformECAAPositionToScreenSpace(controlPointPosition,
|
controlPointPosition = transformECAAPositionToScreenSpace(controlPointPosition,
|
||||||
pathTransformST,
|
pathTransformST,
|
||||||
pathTransformExt,
|
pathTransformExt,
|
||||||
uTransform,
|
uTransform,
|
||||||
uFramebufferSize);
|
uFramebufferSize);
|
||||||
|
|
||||||
|
float winding = computeECAAWinding(leftPosition, rightPosition);
|
||||||
|
if (winding == 0.0) {
|
||||||
|
gl_Position = vec4(0.0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec4 extents = vec4(leftPosition.x,
|
||||||
|
min(leftPosition.y, rightPosition.y),
|
||||||
|
rightPosition.y,
|
||||||
|
max(leftPosition.y, rightPosition.y));
|
||||||
|
vec2 position = computeXCAAClipSpaceQuadPosition(extents, aQuadPosition, uFramebufferSize);
|
||||||
|
|
||||||
float depth = convertPathIndexToViewportDepthValue(pathID);
|
float depth = convertPathIndexToViewportDepthValue(pathID);
|
||||||
|
|
||||||
gl_Position = vec4(position, depth, 1.0);
|
gl_Position = vec4(position, depth, 1.0);
|
||||||
|
|
|
@ -38,16 +38,29 @@ void main() {
|
||||||
uPathTransformExtDimensions,
|
uPathTransformExtDimensions,
|
||||||
pathID);
|
pathID);
|
||||||
|
|
||||||
// Transform the points, and compute the position of this vertex.
|
// Transform the points.
|
||||||
vec2 position;
|
leftPosition = transformECAAPositionToScreenSpace(leftPosition,
|
||||||
computeECAAMultiEdgeMaskQuadPosition(position,
|
|
||||||
leftPosition,
|
|
||||||
rightPosition,
|
|
||||||
aQuadPosition,
|
|
||||||
uFramebufferSize,
|
|
||||||
pathTransformST,
|
pathTransformST,
|
||||||
pathTransformExt,
|
pathTransformExt,
|
||||||
uTransform);
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
rightPosition = transformECAAPositionToScreenSpace(rightPosition,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
|
||||||
|
float winding = computeECAAWinding(leftPosition, rightPosition);
|
||||||
|
if (winding == 0.0) {
|
||||||
|
gl_Position = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 extents = vec4(min(leftPosition.x, rightPosition.x),
|
||||||
|
min(leftPosition.y, rightPosition.y),
|
||||||
|
max(rightPosition.x, rightPosition.x),
|
||||||
|
max(leftPosition.y, rightPosition.y));
|
||||||
|
vec2 position = computeXCAAClipSpaceQuadPosition(extents, aQuadPosition, uFramebufferSize);
|
||||||
|
|
||||||
float depth = convertPathIndexToViewportDepthValue(pathID);
|
float depth = convertPathIndexToViewportDepthValue(pathID);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
// pathfinder/shaders/gles2/ecaa-multi-edge-mask-transformed-curve.vs.glsl
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
uniform mat4 uTransform;
|
||||||
|
uniform ivec2 uFramebufferSize;
|
||||||
|
uniform ivec2 uPathTransformSTDimensions;
|
||||||
|
uniform sampler2D uPathTransformST;
|
||||||
|
uniform ivec2 uPathTransformExtDimensions;
|
||||||
|
uniform sampler2D uPathTransformExt;
|
||||||
|
uniform int uPassIndex;
|
||||||
|
|
||||||
|
attribute vec2 aQuadPosition;
|
||||||
|
attribute vec2 aLeftPosition;
|
||||||
|
attribute vec2 aControlPointPosition;
|
||||||
|
attribute vec2 aRightPosition;
|
||||||
|
attribute float aPathID;
|
||||||
|
|
||||||
|
varying vec4 vEndpoints;
|
||||||
|
varying vec2 vControlPoint;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 leftPosition = aLeftPosition;
|
||||||
|
vec2 controlPointPosition = aControlPointPosition;
|
||||||
|
vec2 rightPosition = aRightPosition;
|
||||||
|
int pathID = int(aPathID);
|
||||||
|
|
||||||
|
vec2 pathTransformExt;
|
||||||
|
vec4 pathTransformST = fetchPathAffineTransform(pathTransformExt,
|
||||||
|
uPathTransformST,
|
||||||
|
uPathTransformSTDimensions,
|
||||||
|
uPathTransformExt,
|
||||||
|
uPathTransformExtDimensions,
|
||||||
|
pathID);
|
||||||
|
|
||||||
|
// Transform the points.
|
||||||
|
leftPosition = transformECAAPositionToScreenSpace(leftPosition,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
rightPosition = transformECAAPositionToScreenSpace(rightPosition,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
controlPointPosition = transformECAAPositionToScreenSpace(controlPointPosition,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
|
||||||
|
float winding;
|
||||||
|
vec3 leftTopRightEdges;
|
||||||
|
if (!splitCurveAndComputeECAAWinding(winding,
|
||||||
|
leftTopRightEdges,
|
||||||
|
leftPosition,
|
||||||
|
rightPosition,
|
||||||
|
controlPointPosition,
|
||||||
|
uPassIndex)) {
|
||||||
|
gl_Position = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 extents = vec4(leftTopRightEdges,
|
||||||
|
max(max(leftPosition.y, rightPosition.y), controlPointPosition.y));
|
||||||
|
vec2 position = computeXCAAClipSpaceQuadPosition(extents, aQuadPosition, uFramebufferSize);
|
||||||
|
|
||||||
|
float depth = convertPathIndexToViewportDepthValue(pathID);
|
||||||
|
|
||||||
|
gl_Position = vec4(position, depth, 1.0);
|
||||||
|
vEndpoints = vec4(leftPosition, rightPosition);
|
||||||
|
vControlPoint = controlPointPosition;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
// pathfinder/shaders/gles2/ecaa-transformed-curve.vs.glsl
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 The Pathfinder Project Developers.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
uniform mat4 uTransform;
|
||||||
|
uniform vec4 uHints;
|
||||||
|
uniform ivec2 uFramebufferSize;
|
||||||
|
uniform ivec2 uPathTransformSTDimensions;
|
||||||
|
uniform sampler2D uPathTransformST;
|
||||||
|
uniform ivec2 uPathTransformExtDimensions;
|
||||||
|
uniform sampler2D uPathTransformExt;
|
||||||
|
uniform ivec2 uPathBoundsDimensions;
|
||||||
|
uniform sampler2D uPathBounds;
|
||||||
|
uniform vec2 uEmboldenAmount;
|
||||||
|
uniform int uPassIndex;
|
||||||
|
|
||||||
|
attribute vec2 aQuadPosition;
|
||||||
|
attribute vec2 aLeftPosition;
|
||||||
|
attribute vec2 aControlPointPosition;
|
||||||
|
attribute vec2 aRightPosition;
|
||||||
|
attribute float aPathID;
|
||||||
|
attribute vec3 aNormalAngles;
|
||||||
|
|
||||||
|
varying vec4 vEndpoints;
|
||||||
|
varying vec2 vControlPoint;
|
||||||
|
varying float vWinding;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 leftPosition = aLeftPosition;
|
||||||
|
vec2 controlPointPosition = aControlPointPosition;
|
||||||
|
vec2 rightPosition = aRightPosition;
|
||||||
|
int pathID = int(aPathID);
|
||||||
|
|
||||||
|
vec2 pathTransformExt;
|
||||||
|
vec4 pathTransformST = fetchPathAffineTransform(pathTransformExt,
|
||||||
|
uPathTransformST,
|
||||||
|
uPathTransformSTDimensions,
|
||||||
|
uPathTransformExt,
|
||||||
|
uPathTransformExtDimensions,
|
||||||
|
pathID);
|
||||||
|
vec4 bounds = fetchFloat4Data(uPathBounds, pathID, uPathBoundsDimensions);
|
||||||
|
|
||||||
|
// Transform the points.
|
||||||
|
leftPosition = computeECAAPosition(leftPosition,
|
||||||
|
aNormalAngles.x,
|
||||||
|
uEmboldenAmount,
|
||||||
|
uHints,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
rightPosition = computeECAAPosition(rightPosition,
|
||||||
|
aNormalAngles.z,
|
||||||
|
uEmboldenAmount,
|
||||||
|
uHints,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
controlPointPosition = computeECAAPosition(controlPointPosition,
|
||||||
|
aNormalAngles.y,
|
||||||
|
uEmboldenAmount,
|
||||||
|
uHints,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
uFramebufferSize);
|
||||||
|
|
||||||
|
float winding;
|
||||||
|
vec3 leftTopRightEdges;
|
||||||
|
if (!splitCurveAndComputeECAAWinding(winding,
|
||||||
|
leftTopRightEdges,
|
||||||
|
leftPosition,
|
||||||
|
rightPosition,
|
||||||
|
controlPointPosition,
|
||||||
|
uPassIndex)) {
|
||||||
|
gl_Position = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 position = computeECAAQuadPositionFromTransformedPositions(leftPosition,
|
||||||
|
rightPosition,
|
||||||
|
aQuadPosition,
|
||||||
|
uFramebufferSize,
|
||||||
|
pathTransformST,
|
||||||
|
pathTransformExt,
|
||||||
|
uTransform,
|
||||||
|
bounds,
|
||||||
|
leftTopRightEdges);
|
||||||
|
|
||||||
|
float depth = convertPathIndexToViewportDepthValue(pathID);
|
||||||
|
|
||||||
|
gl_Position = vec4(position, depth, 1.0);
|
||||||
|
vEndpoints = vec4(leftPosition, rightPosition);
|
||||||
|
vControlPoint = controlPointPosition;
|
||||||
|
vWinding = winding;
|
||||||
|
}
|
Loading…
Reference in New Issue