Skip to content

Commit

Permalink
Use separate attribute coponent for line normals (#5073)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfirebaugh authored Aug 8, 2017
1 parent fbd948f commit 94ded74
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 46 deletions.
28 changes: 14 additions & 14 deletions src/data/bucket/line_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const createElementArrayType = require('../element_array_type');
const loadGeometry = require('../load_geometry');
const EXTENT = require('../extent');
const vectorTileFeatureTypes = require('@mapbox/vector-tile').VectorTileFeature.types;
const {packUint8ToFloat} = require('../../shaders/encode_attribute');

import type {BucketParameters} from '../bucket';
import type {ProgramInterface} from '../program_configuration';
Expand Down Expand Up @@ -46,7 +47,7 @@ const MAX_LINE_DISTANCE = Math.pow(2, LINE_DISTANCE_BUFFER_BITS - 1) / LINE_DIST

const lineInterface = {
layoutAttributes: [
{name: 'a_pos', components: 2, type: 'Int16'},
{name: 'a_pos_normal', components: 3, type: 'Int16'},
{name: 'a_data', components: 4, type: 'Uint8'}
],
paintAttributes: [
Expand All @@ -61,11 +62,12 @@ const lineInterface = {
elementArrayType: createElementArrayType()
};

function addLineVertex(layoutVertexBuffer, point, extrude, tx, ty, dir, linesofar) {
function addLineVertex(layoutVertexBuffer, point: Point, extrude: Point, round: boolean, up: boolean, dir: number, linesofar: number) {
layoutVertexBuffer.emplaceBack(
// a_pos
(point.x << 1) | tx,
(point.y << 1) | ty,
// a_pos_normal
point.x,
point.y,
packUint8ToFloat(round ? 1 : 0, up ? 1 : 0),
// a_data
// add 128 to store a byte in an unsigned byte
Math.round(EXTRUDE_SCALE * extrude.x) + 128,
Expand Down Expand Up @@ -391,15 +393,14 @@ class LineBucket extends Bucket {
endRight: number,
round: boolean,
segment: Segment) {
const tx = round ? 1 : 0;
let extrude;
const arrays = this.arrays;
const layoutVertexArray = arrays.layoutVertexArray;
const elementArray = arrays.elementArray;

extrude = normal.clone();
if (endLeft) extrude._sub(normal.perp()._mult(endLeft));
addLineVertex(layoutVertexArray, currentVertex, extrude, tx, 0, endLeft, distance);
addLineVertex(layoutVertexArray, currentVertex, extrude, round, false, endLeft, distance);
this.e3 = segment.vertexLength++;
if (this.e1 >= 0 && this.e2 >= 0) {
elementArray.emplaceBack(this.e1, this.e2, this.e3);
Expand All @@ -410,7 +411,7 @@ class LineBucket extends Bucket {

extrude = normal.mult(-1);
if (endRight) extrude._sub(normal.perp()._mult(endRight));
addLineVertex(layoutVertexArray, currentVertex, extrude, tx, 1, -endRight, distance);
addLineVertex(layoutVertexArray, currentVertex, extrude, round, true, -endRight, distance);
this.e3 = segment.vertexLength++;
if (this.e1 >= 0 && this.e2 >= 0) {
elementArray.emplaceBack(this.e1, this.e2, this.e3);
Expand All @@ -433,24 +434,23 @@ class LineBucket extends Bucket {
* Add a single new vertex and a triangle using two previous vertices.
* This adds a pie slice triangle near a join to simulate round joins
*
* @param {Object} currentVertex the line vertex to add buffer vertices for
* @param {number} distance the distance from the beggining of the line to the vertex
* @param {Object} extrude the offset of the new vertex from the currentVertex
* @param {boolean} whether the line is turning left or right at this angle
* @param currentVertex the line vertex to add buffer vertices for
* @param distance the distance from the beggining of the line to the vertex
* @param extrude the offset of the new vertex from the currentVertex
* @param lineTurnsLeft whether the line is turning left or right at this angle
* @private
*/
addPieSliceVertex(currentVertex: Point,
distance: number,
extrude: Point,
lineTurnsLeft: boolean,
segment: Segment) {
const ty = lineTurnsLeft ? 1 : 0;
extrude = extrude.mult(lineTurnsLeft ? -1 : 1);
const arrays = this.arrays;
const layoutVertexArray = arrays.layoutVertexArray;
const elementArray = arrays.elementArray;

addLineVertex(layoutVertexArray, currentVertex, extrude, 0, ty, 0, distance);
addLineVertex(layoutVertexArray, currentVertex, extrude, false, lineTurnsLeft, 0, distance);
this.e3 = segment.vertexLength++;
if (this.e1 >= 0 && this.e2 >= 0) {
elementArray.emplaceBack(this.e1, this.e2, this.e3);
Expand Down
3 changes: 2 additions & 1 deletion src/data/extent.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
*
* * Vertex buffer store positions as signed 16 bit integers.
* * One bit is lost for signedness to support tile buffers.
* * One bit is lost because the line vertex buffer packs 1 bit of other data into the int.
* * One bit is lost because the line vertex buffer used to pack 1 bit of other data into the int.
* This is no longer the case but we're reserving this bit anyway.
* * One bit is lost to support features extending past the extent on the right edge of the tile.
* * This leaves us with 2^13 = 8192
*
Expand Down
20 changes: 9 additions & 11 deletions src/shaders/line.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// #define scale 63.0
#define scale 0.015873016

attribute vec2 a_pos;
attribute vec3 a_pos_normal;
attribute vec4 a_data;

uniform mat4 u_matrix;
Expand Down Expand Up @@ -41,20 +41,21 @@ void main() {
vec2 a_extrude = a_data.xy - 128.0;
float a_direction = mod(a_data.z, 4.0) - 1.0;

// We store the texture normals in the most insignificant bit
// transform y so that 0 => -1 and 1 => 1
vec2 pos = a_pos_normal.xy;

// transform y normal so that 0 => -1 and 1 => 1
// In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap
// y is 1 if the normal points up, and -1 if it points down
mediump vec2 normal = mod(a_pos, 2.0);
mediump vec2 normal = unpack_float(a_pos_normal.z);
normal.y = sign(normal.y - 0.5);
v_normal = normal;

v_normal = normal;

// these transformations used to be applied in the JS and native code bases.
// moved them into the shader for clarity and simplicity.
// these transformations used to be applied in the JS and native code bases.
// moved them into the shader for clarity and simplicity.
gapwidth = gapwidth / 2.0;
float halfwidth = width / 2.0;
offset = -1.0 * offset;
offset = -1.0 * offset;

float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);
float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;
Expand All @@ -71,9 +72,6 @@ void main() {
mediump float t = 1.0 - abs(u);
mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);

// Remove the texture normal bit to get the position
vec2 pos = floor(a_pos * 0.5);

vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);
gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;

Expand Down
19 changes: 9 additions & 10 deletions src/shaders/line_pattern.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// Retina devices need a smaller distance to avoid aliasing.
#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0

attribute vec2 a_pos;
attribute vec3 a_pos_normal;
attribute vec4 a_data;

uniform mat4 u_matrix;
Expand Down Expand Up @@ -43,19 +43,21 @@ void main() {
float a_direction = mod(a_data.z, 4.0) - 1.0;
float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE;

// We store the texture normals in the most insignificant bit
// transform y so that 0 => -1 and 1 => 1
vec2 pos = a_pos_normal.xy;

// transform y normal so that 0 => -1 and 1 => 1
// In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap
// y is 1 if the normal points up, and -1 if it points down
mediump vec2 normal = mod(a_pos, 2.0);
mediump vec2 normal = unpack_float(a_pos_normal.z);
normal.y = sign(normal.y - 0.5);

v_normal = normal;

// these transformations used to be applied in the JS and native code bases.
// moved them into the shader for clarity and simplicity.
// these transformations used to be applied in the JS and native code bases.
// moved them into the shader for clarity and simplicity.
gapwidth = gapwidth / 2.0;
float halfwidth = width / 2.0;
offset = -1.0 * offset;
offset = -1.0 * offset;

float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);
float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;
Expand All @@ -72,9 +74,6 @@ void main() {
mediump float t = 1.0 - abs(u);
mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);

// Remove the texture normal bit to get the position
vec2 pos = floor(a_pos * 0.5);

vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);
gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;

Expand Down
19 changes: 9 additions & 10 deletions src/shaders/line_sdf.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// Retina devices need a smaller distance to avoid aliasing.
#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0

attribute vec2 a_pos;
attribute vec3 a_pos_normal;
attribute vec4 a_data;

uniform mat4 u_matrix;
Expand Down Expand Up @@ -52,20 +52,22 @@ void main() {
float a_direction = mod(a_data.z, 4.0) - 1.0;
float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE;

// We store the texture normals in the most insignificant bit
// transform y so that 0 => -1 and 1 => 1
vec2 pos = a_pos_normal.xy;

// transform y normal so that 0 => -1 and 1 => 1
// In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap
// y is 1 if the normal points up, and -1 if it points down
mediump vec2 normal = mod(a_pos, 2.0);
mediump vec2 normal = unpack_float(a_pos_normal.z);
normal.y = sign(normal.y - 0.5);

v_normal = normal;

// these transformations used to be applied in the JS and native code bases.
// moved them into the shader for clarity and simplicity.
// these transformations used to be applied in the JS and native code bases.
// moved them into the shader for clarity and simplicity.
gapwidth = gapwidth / 2.0;
float halfwidth = width / 2.0;
offset = -1.0 * offset;

float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);
float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;

Expand All @@ -81,9 +83,6 @@ void main() {
mediump float t = 1.0 - abs(u);
mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);

// Remove the texture normal bit to get the position
vec2 pos = floor(a_pos * 0.5);

vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);
gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;

Expand Down

0 comments on commit 94ded74

Please sign in to comment.