Move pen line bounds calculation to vertex shader
This commit is contained in:
@@ -217,8 +217,8 @@ class PenSkin extends Skin {
|
||||
|
||||
this._drawLineOnBuffer(
|
||||
penAttributes,
|
||||
x0 + offset, -y0 + offset,
|
||||
x1 + offset, -y1 + offset
|
||||
x0 + offset, y0 + offset,
|
||||
x1 + offset, y1 + offset
|
||||
);
|
||||
|
||||
this._silhouetteDirty = true;
|
||||
@@ -297,28 +297,6 @@ class PenSkin extends Skin {
|
||||
|
||||
this._renderer.enterDrawRegion(this._lineOnBufferDrawRegionId);
|
||||
|
||||
const diameter = penAttributes.diameter || DefaultPenAttributes.diameter;
|
||||
const radius = diameter / 2;
|
||||
// Expand line bounds by sqrt(2) / 2 each side-- this ensures that all antialiased pixels
|
||||
// fall within the quad, even at a 45-degree diagonal
|
||||
const expandedRadius = radius + 1.4142135623730951;
|
||||
|
||||
const lineLength = Math.hypot(x1 - x0, y1 - y0);
|
||||
const lineAngle = Math.atan2(y1 - y0, x1 - x0);
|
||||
|
||||
const halfWidth = this._bounds.width * 0.5;
|
||||
const halfHeight = this._bounds.height * 0.5;
|
||||
|
||||
const transformMatrix = __modelMatrix;
|
||||
twgl.m4.identity(transformMatrix);
|
||||
// Apply view transform to matrix
|
||||
twgl.m4.scale(transformMatrix, [1 / halfWidth, 1 / halfHeight, 1], transformMatrix);
|
||||
|
||||
twgl.m4.translate(transformMatrix, [x0, y0, 0], transformMatrix);
|
||||
twgl.m4.rotateZ(transformMatrix, lineAngle, transformMatrix);
|
||||
twgl.m4.translate(transformMatrix, [-expandedRadius, -expandedRadius, 0], transformMatrix);
|
||||
twgl.m4.scale(transformMatrix, [lineLength + (expandedRadius * 2), (expandedRadius * 2), 1], transformMatrix);
|
||||
|
||||
// Premultiply pen color by pen transparency
|
||||
const penColor = penAttributes.color4f || DefaultPenAttributes.color4f;
|
||||
__premultipliedColor[0] = penColor[0] * penColor[3];
|
||||
@@ -327,10 +305,9 @@ class PenSkin extends Skin {
|
||||
__premultipliedColor[3] = penColor[3];
|
||||
|
||||
const uniforms = {
|
||||
u_modelMatrix: transformMatrix,
|
||||
u_lineColor: __premultipliedColor,
|
||||
u_lineThickness: diameter,
|
||||
u_penPoints: [x0 + halfWidth, y0 + halfHeight, x1 + halfWidth, y1 + halfHeight],
|
||||
u_lineThickness: penAttributes.diameter || DefaultPenAttributes.diameter,
|
||||
u_penPoints: [x0, -y0, x1, -y1],
|
||||
u_stageSize: this.size
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
uniform mat4 u_modelMatrix;
|
||||
precision mediump float;
|
||||
|
||||
#ifdef DRAW_MODE_line
|
||||
uniform vec2 u_stageSize;
|
||||
uniform float u_lineThickness;
|
||||
uniform vec4 u_penPoints;
|
||||
|
||||
// Add this to divisors to prevent division by 0, which results in NaNs propagating through calculations.
|
||||
// Smaller values can cause problems on some mobile devices.
|
||||
const float epsilon = 1e-3;
|
||||
#endif
|
||||
|
||||
#ifndef DRAW_MODE_line
|
||||
uniform mat4 u_projectionMatrix;
|
||||
uniform mat4 u_modelMatrix;
|
||||
attribute vec2 a_texCoord;
|
||||
#endif
|
||||
|
||||
@@ -14,13 +21,37 @@ attribute vec2 a_position;
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main() {
|
||||
#ifdef DRAW_MODE_line
|
||||
vec4 screenCoord = u_modelMatrix * vec4(a_position, 0, 1);
|
||||
#ifdef DRAW_MODE_line
|
||||
// Calculate a rotated ("tight") bounding box around the two pen points.
|
||||
// Yes, we're doing this 6 times (once per vertex), but on actual GPU hardware,
|
||||
// it's still faster than doing it in JS combined with the cost of uniformMatrix4fv.
|
||||
|
||||
gl_Position = screenCoord;
|
||||
v_texCoord = ((screenCoord.xy * 0.5) + 0.5) * u_stageSize;
|
||||
#else
|
||||
gl_Position = u_projectionMatrix * u_modelMatrix * vec4(a_position, 0, 1);
|
||||
v_texCoord = a_texCoord;
|
||||
#endif
|
||||
// Expand line bounds by sqrt(2) / 2 each side-- this ensures that all antialiased pixels
|
||||
// fall within the quad, even at a 45-degree diagonal
|
||||
vec2 position = a_position;
|
||||
float expandedRadius = (u_lineThickness * 0.5) + 1.4142135623730951;
|
||||
|
||||
float lineLength = length(u_penPoints.zw - u_penPoints.xy);
|
||||
|
||||
position.x *= lineLength + (2.0 * expandedRadius);
|
||||
position.y *= 2.0 * expandedRadius;
|
||||
|
||||
// Center around first pen point
|
||||
position -= expandedRadius;
|
||||
|
||||
// Rotate quad to line angle
|
||||
vec2 normalized = (u_penPoints.zw - u_penPoints.xy + epsilon) / (lineLength + epsilon);
|
||||
position = mat2(normalized.x, normalized.y, -normalized.y, normalized.x) * position;
|
||||
// Translate quad
|
||||
position += u_penPoints.xy;
|
||||
|
||||
// Apply view transform
|
||||
position *= 2.0 / u_stageSize;
|
||||
|
||||
gl_Position = vec4(position, 0, 1);
|
||||
v_texCoord = position * 0.5 * u_stageSize;
|
||||
#else
|
||||
gl_Position = u_projectionMatrix * u_modelMatrix * vec4(a_position, 0, 1);
|
||||
v_texCoord = a_texCoord;
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user