linepattern in progress

This commit is contained in:
Lauren Budorick
2014-07-25 18:17:37 -07:00
committed by John Firebaugh
parent c1280f0b38
commit 71c31cee24
9 changed files with 333 additions and 13 deletions

View File

@@ -17,10 +17,11 @@ class LineVertexBuffer;
class TriangleElementsBuffer;
class LineShader;
class LinejoinShader;
class LinepatternShader;
struct pbf;
class LineBucket : public Bucket {
typedef ElementGroup<1> triangle_group_type;
typedef ElementGroup<2> triangle_group_type;
typedef ElementGroup<1> point_group_type;
public:
@@ -38,6 +39,7 @@ public:
bool hasPoints() const;
void drawLines(LineShader& shader);
void drawLinePatterns(LinepatternShader& shader);
void drawPoints(LinejoinShader& shader);
public:

View File

@@ -14,6 +14,7 @@
#include <mbgl/shader/pattern_shader.hpp>
#include <mbgl/shader/line_shader.hpp>
#include <mbgl/shader/linejoin_shader.hpp>
#include <mbgl/shader/linepattern_shader.hpp>
#include <mbgl/shader/icon_shader.hpp>
#include <mbgl/shader/raster_shader.hpp>
#include <mbgl/shader/text_shader.hpp>
@@ -169,6 +170,7 @@ public:
std::unique_ptr<OutlineShader> outlineShader;
std::unique_ptr<LineShader> lineShader;
std::unique_ptr<LinejoinShader> linejoinShader;
std::unique_ptr<LinepatternShader> linepatternShader;
std::unique_ptr<PatternShader> patternShader;
std::unique_ptr<IconShader> iconShader;
std::unique_ptr<RasterShader> rasterShader;

View File

@@ -0,0 +1,59 @@
#ifndef MBGL_SHADER_SHADER_LINEPATTERN
#define MBGL_SHADER_SHADER_LINEPATTERN
#include <mbgl/shader/shader.hpp>
namespace mbgl {
class LinepatternShader : public Shader {
public:
LinepatternShader();
void bind(char *offset);
void setExtrudeMatrix(const std::array<float, 16>& exmatrix);
void setLineWidth(const std::array<float, 2>& linewidth);
void setRatio(float ratio);
void setDebug(float debug);
void setPatternSize(const std::array<float, 2>& new_pattern_size);
void setPatternTopLeft(const std::array<float, 2>& new_pattern_tl);
void setPatternBottomRight(const std::array<float, 2>& new_pattern_br);
void setOffset(const std::array<float, 2>& offset);
void setGamma(float new_gamma);
void setFade(float new_fade);
private:
int32_t a_pos = -1;
int32_t a_extrude = -1;
int32_t a_linesofar = -1;
std::array<float, 16> exmatrix = {{}};
int32_t u_exmatrix = -1;
std::array<float, 2> linewidth = {{}};
int32_t u_linewidth = -1;
float ratio = 0;
int32_t u_ratio = -1;
std::array<float, 2> pattern_size = {{}};
int32_t u_pattern_size = -1;
std::array<float, 2> pattern_tl = {{}};
int32_t u_pattern_tl = -1;
std::array<float, 2> pattern_br = {{}};
int32_t u_pattern_br = -1;
std::array<float, 2> offset = {{}};
int32_t u_offset = -1;
float gamma = 0.0f;
int32_t u_gamma = -1;
float fade = 0;
int32_t u_fade = -1;
};
}
#endif

View File

@@ -374,6 +374,20 @@ void LineBucket::drawLines(LineShader& shader) {
}
}
void LineBucket::drawLinePatterns(LinepatternShader& shader) {
char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
char *elements_index = BUFFER_OFFSET(triangle_elements_start * triangleElementsBuffer.itemSize);
for (triangle_group_type& group : triangleGroups) {
if (!group.elements_length) {
continue;
}
group.array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index);
glDrawElements(GL_TRIANGLES, group.elements_length * 3, GL_UNSIGNED_SHORT, elements_index);
vertex_index += group.vertex_length * vertexBuffer.itemSize;
elements_index += group.elements_length * triangleElementsBuffer.itemSize;
}
}
void LineBucket::drawPoints(LinejoinShader& shader) {
char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
char *elements_index = BUFFER_OFFSET(point_elements_start * pointElementsBuffer.itemSize);

View File

@@ -41,6 +41,7 @@ void Painter::setup() {
assert(outlineShader);
assert(lineShader);
assert(linejoinShader);
assert(linepatternShader);
assert(patternShader);
assert(rasterShader);
assert(textShader);
@@ -70,6 +71,7 @@ void Painter::setupShaders() {
if (!outlineShader) outlineShader = std::make_unique<OutlineShader>();
if (!lineShader) lineShader = std::make_unique<LineShader>();
if (!linejoinShader) linejoinShader = std::make_unique<LinejoinShader>();
if (!linepatternShader) linepatternShader = std::make_unique<LinepatternShader>();
if (!patternShader) patternShader = std::make_unique<PatternShader>();
if (!iconShader) iconShader = std::make_unique<IconShader>();
if (!rasterShader) rasterShader = std::make_unique<RasterShader>();

View File

@@ -1,6 +1,9 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/line_bucket.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/map/map.hpp>
using namespace mbgl;
@@ -60,20 +63,50 @@ void Painter::renderLine(LineBucket& bucket, std::shared_ptr<StyleLayer> layer_d
bucket.drawPoints(*linejoinShader);
}
// var imagePos = properties.image && imageSprite.getPosition(properties.image);
bool imagePos = false;
if (imagePos) {
// var factor = 8 / Math.pow(2, painter.transform.zoom - params.z);
const std::shared_ptr<Sprite> &sprite = map.getSprite();
if (properties.image.size() && sprite) {
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
Rect<uint16_t> imagePos = spriteAtlas.getImage(properties.image, *sprite);
float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
float fade = std::fmod(map.getState().getZoom(), 1.0);
// imageSprite.bind(gl, true);
std::array<float, 2> imageSize = {{
imagePos.w * factor,
imagePos.h * factor
}
};
// //factor = Math.pow(2, 4 - painter.transform.zoom + params.z);
// gl.switchShader(painter.linepatternShader, painter.translatedMatrix || painter.posMatrix, painter.extrudeMatrix);
// shader = painter.linepatternShader;
// glUniform2fv(painter.linepatternShader.u_pattern_size, [imagePos.size[0] * factor, imagePos.size[1] ]);
// glUniform2fv(painter.linepatternShader.u_pattern_tl, imagePos.tl);
// glUniform2fv(painter.linepatternShader.u_pattern_br, imagePos.br);
// glUniform1f(painter.linepatternShader.u_fade, painter.transform.z % 1.0);
std::array<float, 2> offset = {{
(float)std::fmod(id.x * 4096, imageSize[0]),
(float)std::fmod(id.y * 4096, imageSize[1])
}
};
useProgram(linepatternShader->program);
linepatternShader->setMatrix(vtxMatrix);
linepatternShader->setExtrudeMatrix(extrudeMatrix);
lineShader->setDashArray({{ dash_length, dash_gap }});
linepatternShader->setLineWidth({{ outset, inset }});
linepatternShader->setRatio(map.getState().getPixelRatio());
linepatternShader->setPatternSize(imageSize);
linepatternShader->setPatternTopLeft({{
float(imagePos.x) / spriteAtlas.getWidth(),
float(imagePos.y) / spriteAtlas.getHeight(),
}});
linepatternShader->setPatternBottomRight({{
float(imagePos.x + imagePos.w) / spriteAtlas.getWidth(),
float(imagePos.y + imagePos.h) / spriteAtlas.getHeight(),
}});
linepatternShader->setOffset(offset);
linepatternShader->setGamma(map.getState().getPixelRatio());
linepatternShader->setFade(fade);
spriteAtlas.bind(true);
glDepthRange(strata + strata_epsilon, 1.0f); // may or may not matter
bucket.drawLinePatterns(*linepatternShader);
} else {
useProgram(lineShader->program);

View File

@@ -0,0 +1,34 @@
uniform vec2 u_linewidth;
uniform float u_gamma;
uniform float u_fade;
uniform vec2 u_pattern_size;
uniform vec2 u_pattern_tl;
uniform vec2 u_pattern_br;
uniform sampler2D u_image;
varying vec2 v_normal;
varying float v_linesofar;
void main() {
// Calculate the distance of the pixel from the line in pixels.
float dist = length(v_normal) * length(gl_PointCoord * 2.0 - 1.0);
// Calculate the antialiasing fade factor. This is either when fading in
// the line in case of an offset line (v_linewidth.t) or when fading out
// (v_linewidth.s)
float alpha = clamp(min(dist - (u_linewidth.t - 1.0), u_linewidth.s - dist) * u_gamma, 0.0, 1.0);
float x = mod(v_linesofar / u_pattern_size.x, 1.0);
float y = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size.y);
vec2 pos = mix(u_pattern_tl, u_pattern_br, vec2(x, y));
float x2 = mod(x * 2.0, 1.0);
vec2 pos2 = mix(u_pattern_tl, u_pattern_br, vec2(x2, y));
vec4 color = texture2D(u_image, pos) * (1.0 - u_fade) + u_fade * texture2D(u_image, pos2);
color.rgb *= color.a;
gl_FragColor = color * alpha;
}

View File

@@ -0,0 +1,53 @@
// floor(127 / 2) == 63.0
// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is
// stored in a byte (-128..127). we scale regular normals up to length 63, but
// there are also "special" normals that have a bigger length (of up to 126 in
// this case).
#define scale 63.0
attribute vec2 a_pos;
attribute vec2 a_extrude;
attribute float a_linesofar;
// posmatrix is for the vertex position, exmatrix is for rotating and projecting
// the extrusion vector.
uniform mat4 u_matrix;
uniform mat4 u_exmatrix;
// shared
uniform float u_ratio;
uniform vec2 u_linewidth;
uniform vec4 u_color;
varying vec2 v_normal;
varying float v_linesofar;
void main() {
// We store the texture normals in the most insignificant bit
// transform y 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
vec2 normal = mod(a_pos, 2.0);
normal.y = sign(normal.y - 0.5);
v_normal = normal;
// Scale the extrusion vector down to a normal and then up by the line width
// of this vertex.
vec2 extrude = a_extrude / scale;
vec4 dist = vec4(u_linewidth.s * extrude, 0.0, 0.0);
// If the x coordinate is the maximum integer, we move the z coordinates out
// of the view plane so that the triangle gets clipped. This makes it easier
// for us to create degenerate triangle strips.
float z = step(32767.0, a_pos.x);
z += step(1.0, v_normal.y);
// Remove the texture normal bit of the position before scaling it with the
// model/view matrix. Add the extrusion vector *after* the model/view matrix
// because we're extruding the line in pixel space, regardless of the current
// tile's zoom level.
gl_Position = u_matrix * vec4(floor(a_pos / 2.0), 0.0, 1.0) + u_exmatrix * dist;
v_linesofar = a_linesofar; // * u_ratio;
}

View File

@@ -0,0 +1,121 @@
#include <mbgl/shader/linepattern_shader.hpp>
#include <mbgl/shader/shaders.hpp>
#include <mbgl/platform/gl.hpp>
#include <iostream>
#include <cstdio>
using namespace mbgl;
LinepatternShader::LinepatternShader()
: Shader(
"linepattern",
shaders[LINEPATTERN_SHADER].vertex,
shaders[LINEPATTERN_SHADER].fragment
) {
if (!valid) {
fprintf(stderr, "invalid line pattern shader\n");
return;
}
a_pos = glGetAttribLocation(program, "a_pos");
a_extrude = glGetAttribLocation(program, "a_extrude");
a_linesofar = glGetAttribLocation(program, "a_linesofar");
u_matrix = glGetUniformLocation(program, "u_matrix");
u_exmatrix = glGetUniformLocation(program, "u_exmatrix");
u_linewidth = glGetUniformLocation(program, "u_linewidth");
u_ratio = glGetUniformLocation(program, "u_ratio");
u_pattern_size = glGetUniformLocation(program, "u_pattern_size");
u_pattern_tl = glGetUniformLocation(program, "u_pattern_tl");
u_pattern_br = glGetUniformLocation(program, "u_pattern_br");
u_offset = glGetUniformLocation(program, "u_offset");
u_gamma = glGetUniformLocation(program, "u_gamma");
u_fade = glGetUniformLocation(program, "u_fade");
//fprintf(stderr, "LinepatternShader:\n");
//fprintf(stderr, " - u_matrix: %d\n", u_matrix);
//fprintf(stderr, " - u_exmatrix: %d\n", u_exmatrix);
//fprintf(stderr, " - u_linewidth: %d\n", u_linewidth);
//fprintf(stderr, " - u_ratio: %d\n", u_ratio);
//fprintf(stderr, " - u_pattern_size: %d\n", u_pattern_size);
//fprintf(stderr, " - u_pattern_tl: %d\n", u_pattern_tl);
//fprintf(stderr, " - u_pattern_br: %d\n", u_pattern_br);
//fprintf(stderr, " - u_offset: %d\n", u_offset);
//fprintf(stderr, " - u_gamma: %d\n", u_gamma);
}
void LinepatternShader::bind(char *offset) {
glEnableVertexAttribArray(a_pos);
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset + 0);
glEnableVertexAttribArray(a_extrude);
glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 4);
glEnableVertexAttribArray(a_linesofar);
glVertexAttribPointer(a_linesofar, 1, GL_SHORT, false, 8, offset + 6);
}
void LinepatternShader::setExtrudeMatrix(const std::array<float, 16>& new_exmatrix) {
if (exmatrix != new_exmatrix) {
glUniformMatrix4fv(u_exmatrix, 1, GL_FALSE, new_exmatrix.data());
exmatrix = new_exmatrix;
}
}
void LinepatternShader::setPatternSize(const std::array<float, 2>& new_pattern_size) {
if (pattern_size != new_pattern_size) {
glUniform2fv(u_pattern_size, 1, new_pattern_size.data());
pattern_size = new_pattern_size;
}
}
void LinepatternShader::setLineWidth(const std::array<float, 2>& new_linewidth) {
if (linewidth != new_linewidth) {
glUniform2fv(u_linewidth, 1, new_linewidth.data());
linewidth = new_linewidth;
}
}
void LinepatternShader::setRatio(float new_ratio) {
if (ratio != new_ratio) {
glUniform1f(u_ratio, new_ratio);
ratio = new_ratio;
}
}
void LinepatternShader::setPatternTopLeft(const std::array<float, 2>& new_pattern_tl) {
if (pattern_tl != new_pattern_tl) {
glUniform2fv(u_pattern_tl, 1, new_pattern_tl.data());
pattern_tl = new_pattern_tl;
}
}
void LinepatternShader::setPatternBottomRight(const std::array<float, 2>& new_pattern_br) {
if (pattern_br != new_pattern_br) {
glUniform2fv(u_pattern_br, 1, new_pattern_br.data());
pattern_br = new_pattern_br;
}
}
void LinepatternShader::setOffset(const std::array<float, 2>& new_offset) {
if (offset != new_offset) {
glUniform2fv(u_offset, 1, new_offset.data());
offset = new_offset;
}
}
void LinepatternShader::setGamma(float new_gamma) {
if (gamma != new_gamma) {
glUniform1f(u_gamma, new_gamma);
gamma = new_gamma;
}
}
void LinepatternShader::setFade(float new_fade) {
if (fade != new_fade) {
glUniform1f(u_fade, new_fade);
fade = new_fade;
}
};