[core] Use separate attribute component for line normals

Broadcom GPUs don't cope well with using the least significant bit for this.
This commit is contained in:
John Firebaugh
2017-08-01 12:22:16 -07:00
parent 33407591f5
commit 822df3dd51
11 changed files with 47 additions and 46 deletions

View File

@@ -19,7 +19,8 @@ constexpr float tileSize = 512;
*
* Positions are stored as signed 16bit integers.
* One bit is lost for signedness to support features extending past the left edge of the tile.
* 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
*/

View File

@@ -13,14 +13,15 @@
},
"license": "BSD-2-Clause",
"dependencies": {
"node-pre-gyp": "^0.6.28",
"nan": "^2.4.0"
"nan": "^2.4.0",
"node-pre-gyp": "^0.6.36"
},
"devDependencies": {
"aws-sdk": "^2.3.5",
"csscolorparser": "^1.0.2",
"ejs": "^2.4.1",
"express": "^4.11.1",
"flow-remove-types": "^1.2.1",
"lodash": "^4.16.4",
"mapbox-gl-styles": "2.0.2",
"pixelmatch": "^4.0.2",

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env node
const path = require('path');
const fs = require('fs');
require('flow-remove-types/register');
const path = require('path');
const shaders = require('../mapbox-gl-js/src/shaders');
const outputPath = 'src/mbgl/shaders';

View File

@@ -23,6 +23,7 @@ inline uint16_t packUint8Pair(T a, T b) {
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos);
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude);
MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset);
MBGL_DEFINE_ATTRIBUTE(int16_t, 3, a_pos_normal);
MBGL_DEFINE_ATTRIBUTE(float, 3, a_projected_pos);
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_label_pos);
MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_anchor_pos);

View File

@@ -10,7 +10,7 @@ namespace mbgl {
using namespace style;
static_assert(sizeof(LineLayoutVertex) == 8, "expected LineLayoutVertex size");
static_assert(sizeof(LineLayoutVertex) == 10, "expected LineLayoutVertex size");
template <class Values, class...Args>
Values makeValues(const RenderLinePaintProperties::PossiblyEvaluated& properties,

View File

@@ -30,7 +30,7 @@ MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_gl_units_to_pixels);
} // namespace uniforms
struct LineLayoutAttributes : gl::Attributes<
attributes::a_pos,
attributes::a_pos_normal,
attributes::a_data<uint8_t, 4>>
{};
@@ -50,14 +50,16 @@ public:
/*
* @param p vertex position
* @param e extrude normal
* @param t texture normal
* @param round whether the vertex uses a round line cap
* @param up whether the line normal points up or down
* @param dir direction of the line cap (-1/0/1)
*/
static LayoutVertex layoutVertex(Point<int16_t> p, Point<double> e, Point<bool> t, int8_t dir, int32_t linesofar = 0) {
static LayoutVertex layoutVertex(Point<int16_t> p, Point<double> e, bool round, bool up, int8_t dir, int32_t linesofar = 0) {
return LayoutVertex {
{{
static_cast<int16_t>((p.x * 2) | t.x),
static_cast<int16_t>((p.y * 2) | t.y)
p.x,
p.y,
static_cast<int16_t>(attributes::packUint8Pair(round ? 1 : 0, up ? 1 : 0))
}},
{{
// add 128 to store a byte in an unsigned byte

View File

@@ -401,7 +401,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
Point<double> extrude = normal;
if (endLeft)
extrude = extrude - (util::perp(normal) * endLeft);
vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE));
vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, round, false, endLeft, distance * LINE_DISTANCE_SCALE));
e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
@@ -412,7 +412,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
extrude = normal * -1.0;
if (endRight)
extrude = extrude - (util::perp(normal) * endRight);
vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE));
vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, round, true, -endRight, distance * LINE_DISTANCE_SCALE));
e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
@@ -437,7 +437,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex,
std::size_t startVertex,
std::vector<TriangleElement>& triangleStore) {
Point<double> flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0);
vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE));
vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, false, lineTurnsLeft, 0, distance * LINE_DISTANCE_SCALE));
e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);

View File

@@ -21,7 +21,7 @@ const char* line::vertexSource = R"MBGL_SHADER(
// #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;
@@ -131,20 +131,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;
// 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;
@@ -161,9 +162,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;

View File

@@ -23,7 +23,7 @@ const char* line_pattern::vertexSource = R"MBGL_SHADER(
// 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;
@@ -119,19 +119,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;
@@ -148,9 +150,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;

View File

@@ -23,7 +23,7 @@ const char* line_sdf::vertexSource = R"MBGL_SHADER(
// 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;
@@ -157,20 +157,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;
@@ -186,9 +188,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;