first shot at composited blending
still missing: - stencil+depth mask - alpha compositing
This commit is contained in:
@@ -40,7 +40,10 @@ public:
|
||||
}
|
||||
glBindBuffer(bufferType, buffer);
|
||||
if (force) {
|
||||
assert("Buffer was already deleted" && array != nullptr);
|
||||
if (array == nullptr) {
|
||||
throw std::runtime_error("Buffer was already deleted or doesn't contain elements");
|
||||
}
|
||||
|
||||
glBufferData(bufferType, pos, array, GL_STATIC_DRAW);
|
||||
if (!retainAfterUpload) {
|
||||
cleanup();
|
||||
@@ -58,11 +61,15 @@ public:
|
||||
protected:
|
||||
// increase the buffer size by at least /required/ bytes.
|
||||
inline void *addElement() {
|
||||
assert("Buffer is already bound to GPU" && buffer == 0);
|
||||
if (buffer != 0) {
|
||||
throw std::runtime_error("Can't add elements after buffer was bound to GPU");
|
||||
}
|
||||
if (length < pos + itemSize) {
|
||||
while (length < pos + itemSize) length += defaultLength;
|
||||
array = realloc(array, length);
|
||||
assert("Buffer reallocation failed" && array != nullptr);
|
||||
if (array == nullptr) {
|
||||
throw std::runtime_error("Buffer reallocation failed¯");
|
||||
}
|
||||
}
|
||||
pos += itemSize;
|
||||
return static_cast<char *>(array) + (pos - itemSize);
|
||||
@@ -70,7 +77,9 @@ protected:
|
||||
|
||||
// Get a pointer to the item at a given index.
|
||||
inline void *getElement(size_t index) {
|
||||
assert("Buffer was deleted" && array != nullptr);
|
||||
if (array == nullptr) {
|
||||
throw std::runtime_error("Buffer was already deleted or doesn't contain elements");
|
||||
}
|
||||
|
||||
if (index * itemSize >= pos) {
|
||||
throw new std::runtime_error("Can't get element after array bounds");
|
||||
|
||||
@@ -123,6 +123,11 @@ private:
|
||||
void renderLayers(const std::vector<LayerDescription>& layers);
|
||||
void renderLayer(const LayerDescription& layer_desc, RenderPass pass);
|
||||
|
||||
void clearFramebuffers();
|
||||
void bindFramebuffer();
|
||||
void pushFramebuffer();
|
||||
GLuint popFramebuffer();
|
||||
|
||||
private:
|
||||
// If cleared, the next time the render thread attempts to render the map, it will *actually*
|
||||
// render the map.
|
||||
@@ -154,6 +159,10 @@ private:
|
||||
|
||||
int indent = 0;
|
||||
|
||||
std::vector<GLuint> fbos;
|
||||
std::vector<GLuint> fbos_color;
|
||||
int fbo_level = -1;
|
||||
|
||||
private:
|
||||
bool async = false;
|
||||
uv_loop_t *loop = nullptr;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <llmr/shader/raster_shader.hpp>
|
||||
#include <llmr/shader/text_shader.hpp>
|
||||
#include <llmr/shader/dot_shader.hpp>
|
||||
#include <llmr/shader/composite_shader.hpp>
|
||||
|
||||
#include <llmr/map/transform_state.hpp>
|
||||
|
||||
@@ -86,6 +87,8 @@ public:
|
||||
void drawClippingMask(const mat4& matrix, const ClipID& clip);
|
||||
void finishClippingMask();
|
||||
|
||||
void drawComposite(GLuint texture, const CompositeProperties &properties);
|
||||
|
||||
bool needsAnimation() const;
|
||||
private:
|
||||
void setupShaders();
|
||||
@@ -127,6 +130,7 @@ private:
|
||||
std::unique_ptr<RasterShader> rasterShader;
|
||||
std::unique_ptr<TextShader> textShader;
|
||||
std::unique_ptr<DotShader> dotShader;
|
||||
std::unique_ptr<CompositeShader> compositeShader;
|
||||
|
||||
// Set up the stencil quad we're using to generate the stencil mask.
|
||||
VertexBuffer tileStencilBuffer = {
|
||||
@@ -144,6 +148,8 @@ private:
|
||||
VertexArrayObject coveringPlainArray;
|
||||
VertexArrayObject coveringPatternArray;
|
||||
VertexArrayObject coveringRasterArray;
|
||||
|
||||
VertexArrayObject compositeArray;
|
||||
VertexArrayObject matteArray;
|
||||
|
||||
// Set up the tile boundary lines we're using to draw the tile outlines.
|
||||
|
||||
29
include/llmr/shader/composite_shader.hpp
Normal file
29
include/llmr/shader/composite_shader.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef LLMR_SHADER_COMPOSITE_SHADER
|
||||
#define LLMR_SHADER_COMPOSITE_SHADER
|
||||
|
||||
#include <llmr/shader/shader.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class CompositeShader : public Shader {
|
||||
public:
|
||||
CompositeShader();
|
||||
|
||||
void bind(char *offset);
|
||||
|
||||
void setImage(int32_t image);
|
||||
void setOpacity(float opacity);
|
||||
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
|
||||
int32_t image = 0;
|
||||
int32_t u_image = -1;
|
||||
|
||||
float opacity = 0;
|
||||
int32_t u_opacity = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,10 +17,11 @@ public:
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
|
||||
int32_t image = -1;
|
||||
int32_t image = 0;
|
||||
int32_t u_image = -1;
|
||||
float opacity = 0.0f;
|
||||
float u_opacity = 0.0f;
|
||||
|
||||
float opacity = 0;
|
||||
int32_t u_opacity = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
std::map<std::string, IconClass> icon;
|
||||
std::map<std::string, TextClass> text;
|
||||
std::map<std::string, RasterClass> raster;
|
||||
std::map<std::string, CompositeClass> composite;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -180,6 +180,16 @@ struct RasterProperties {
|
||||
float opacity = 1.0;
|
||||
};
|
||||
|
||||
struct CompositeClass {
|
||||
FunctionProperty enabled = true;
|
||||
FunctionProperty opacity = 1;
|
||||
};
|
||||
|
||||
struct CompositeProperties {
|
||||
bool enabled = true;
|
||||
float opacity = 1.0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
std::map<std::string, IconProperties> icons;
|
||||
std::map<std::string, TextProperties> texts;
|
||||
std::map<std::string, RasterProperties> rasters;
|
||||
std::map<std::string, CompositeProperties> composites;
|
||||
} computed;
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ private:
|
||||
TextClass parseTextClass(JSVal value);
|
||||
BackgroundClass parseBackgroundClass(JSVal value);
|
||||
RasterClass parseRasterClass(JSVal value);
|
||||
CompositeClass parseCompositeClass(JSVal value);
|
||||
|
||||
bool parseBoolean(JSVal value);
|
||||
std::string parseString(JSVal value);
|
||||
|
||||
@@ -14,9 +14,9 @@ extern const float tileSize;
|
||||
|
||||
namespace debug {
|
||||
|
||||
const bool styleParseWarnings = true;
|
||||
const bool renderWarnings = true;
|
||||
const bool renderTree = true;
|
||||
extern const bool styleParseWarnings;
|
||||
extern const bool renderWarnings;
|
||||
extern const bool renderTree;
|
||||
|
||||
}
|
||||
|
||||
|
||||
119
src/map/map.cpp
119
src/map/map.cpp
@@ -35,6 +35,8 @@ Map::Map(View& view)
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
clearFramebuffers();
|
||||
|
||||
uv_loop_delete(loop);
|
||||
loop = nullptr;
|
||||
}
|
||||
@@ -513,38 +515,59 @@ void Map::renderLayers(const std::vector<LayerDescription>& layers) {
|
||||
}
|
||||
|
||||
template <typename Styles>
|
||||
bool is_invisible(const Styles &styles, const LayerDescription &layer_desc) {
|
||||
typename Styles::const_iterator find_style(const Styles &styles, const LayerDescription &layer_desc) {
|
||||
auto it = styles.find(layer_desc.name);
|
||||
if (it == styles.end()) {
|
||||
if (debug::renderWarnings) {
|
||||
fprintf(stderr, "[WARNING] can't find class named '%s' in style\n",
|
||||
layer_desc.name.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const auto &properties = it->second;
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename Properties>
|
||||
bool is_invisible(const Properties &properties) {
|
||||
if (!properties.enabled) { return true; }
|
||||
if (properties.opacity <= 0) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Styles>
|
||||
bool is_invisible(const Styles &styles, const LayerDescription &layer_desc) {
|
||||
auto it = find_style(styles, layer_desc);
|
||||
if (it == styles.end()) { return true; }
|
||||
return is_invisible(it->second);
|
||||
}
|
||||
|
||||
void Map::renderLayer(const LayerDescription& layer_desc, RenderPass pass) {
|
||||
if (layer_desc.child_layer.size()) {
|
||||
// This is a layer group. We render them during our translucent render pass.
|
||||
if (pass == Translucent) {
|
||||
gl::group group(std::string("group: ") + layer_desc.name);
|
||||
auto it = find_style(style.computed.composites, layer_desc);
|
||||
if (it != style.computed.composites.end() && !is_invisible(it->second)) {
|
||||
const CompositeProperties &properties = it->second;
|
||||
gl::group group(std::string("group: ") + layer_desc.name);
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "+ " << layer_desc.name
|
||||
<< " (Composite) {" << std::endl;
|
||||
}
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "+ " << layer_desc.name
|
||||
<< " (Composite) {" << std::endl;
|
||||
}
|
||||
|
||||
// TODO: create framebuffer
|
||||
renderLayers(layer_desc.child_layer);
|
||||
// TODO: render framebuffer on previous framebuffer
|
||||
pushFramebuffer();
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
renderLayers(layer_desc.child_layer);
|
||||
|
||||
GLuint texture = popFramebuffer();
|
||||
|
||||
// Render the previous texture onto the screen.
|
||||
painter.drawComposite(texture, properties);
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (layer_desc.bucket_name == "background") {
|
||||
@@ -607,3 +630,73 @@ void Map::renderLayer(const LayerDescription& layer_desc, RenderPass pass) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::clearFramebuffers() {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
// Delete any framebuffers that we might have allocated
|
||||
glDeleteTextures(fbos_color.size(), fbos.data());
|
||||
fbos_color.clear();
|
||||
|
||||
glDeleteFramebuffersEXT(fbos.size(), fbos.data());
|
||||
fbos.clear();
|
||||
}
|
||||
|
||||
void Map::bindFramebuffer() {
|
||||
if (fbo_level < 0) {
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
} else if (fbos.size() > (size_t)fbo_level) {
|
||||
GLuint fbo = fbos[fbo_level];
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
||||
} else {
|
||||
// TODO: Convert this to textures so we can composite them and use them in blend operations
|
||||
|
||||
GLuint fbo_color;
|
||||
glGenTextures(1, &fbo_color);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo_color);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, state.getFramebufferWidth(), state.getFramebufferHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
fbos_color.emplace_back(fbo_color);
|
||||
|
||||
// TODO: Stencil/Depth buffer
|
||||
|
||||
// Allocate new framebuffer
|
||||
GLuint fbo = 0;
|
||||
glGenFramebuffersEXT(1, &fbo);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
||||
fbos.emplace_back(fbo);
|
||||
|
||||
// Assemble the FBO
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_color, 0);
|
||||
// TODO: Stencil/Depth buffer
|
||||
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
fprintf(stderr, "Couldn't create framebuffer: ");
|
||||
switch (status) {
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: fprintf(stderr, "incomplete attachment\n"); break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: fprintf(stderr, "incomplete missing attachment\n"); break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: fprintf(stderr, "incomplete draw buffer\n"); break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED: fprintf(stderr, "unsupported\n"); break;
|
||||
default: fprintf(stderr, "other\n"); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::pushFramebuffer() {
|
||||
fbo_level++;
|
||||
bindFramebuffer();
|
||||
}
|
||||
|
||||
GLuint Map::popFramebuffer() {
|
||||
GLuint texture = fbos_color[fbo_level];
|
||||
fbo_level--;
|
||||
bindFramebuffer();
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -360,6 +360,9 @@ void LineBucket::drawLines(LineShader& 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.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;
|
||||
@@ -371,6 +374,9 @@ void LineBucket::drawPoints(LinejoinShader& shader) {
|
||||
char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
|
||||
char *elements_index = BUFFER_OFFSET(point_elements_start * pointElementsBuffer.itemSize);
|
||||
for (point_group_type& group : pointGroups) {
|
||||
if (!group.elements_length) {
|
||||
continue;
|
||||
}
|
||||
group.array.bind(shader, vertexBuffer, pointElementsBuffer, vertex_index);
|
||||
glDrawElements(GL_POINTS, group.elements_length, GL_UNSIGNED_SHORT, elements_index);
|
||||
vertex_index += group.vertex_length * vertexBuffer.itemSize;
|
||||
|
||||
@@ -38,6 +38,7 @@ void Painter::setup() {
|
||||
assert(rasterShader);
|
||||
assert(textShader);
|
||||
assert(dotShader);
|
||||
assert(compositeShader);
|
||||
|
||||
|
||||
// Blending
|
||||
@@ -67,6 +68,7 @@ void Painter::setupShaders() {
|
||||
rasterShader = std::make_unique<RasterShader>();
|
||||
textShader = std::make_unique<TextShader>();
|
||||
dotShader = std::make_unique<DotShader>();
|
||||
compositeShader = std::make_unique<CompositeShader>();
|
||||
}
|
||||
|
||||
void Painter::resize() {
|
||||
|
||||
25
src/renderer/painter_composite.cpp
Normal file
25
src/renderer/painter_composite.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <llmr/renderer/painter.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
void Painter::drawComposite(GLuint texture, const CompositeProperties &properties) {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
useProgram(compositeShader->program);
|
||||
compositeShader->setMatrix(nativeMatrix);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
compositeShader->setImage(0);
|
||||
|
||||
// TODO: layerstyle
|
||||
compositeShader->setOpacity(properties.opacity);
|
||||
|
||||
// Draw the clipping mask
|
||||
compositeArray.bind(*compositeShader, tileStencilBuffer, BUFFER_OFFSET(0));
|
||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index());
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
}
|
||||
8
src/shader/composite.fragment.glsl
Normal file
8
src/shader/composite.fragment.glsl
Normal file
@@ -0,0 +1,8 @@
|
||||
uniform sampler2D u_image;
|
||||
uniform float u_opacity;
|
||||
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(u_image, v_pos / 2.0 + 0.5) * u_opacity;
|
||||
}
|
||||
9
src/shader/composite.vertex.glsl
Normal file
9
src/shader/composite.vertex.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
attribute vec2 a_pos;
|
||||
|
||||
uniform mat4 u_matrix;
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
v_pos = gl_Position.xy;
|
||||
}
|
||||
48
src/shader/composite_shader.cpp
Normal file
48
src/shader/composite_shader.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <llmr/shader/composite_shader.hpp>
|
||||
#include <llmr/shader/shaders.hpp>
|
||||
#include <llmr/platform/gl.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
CompositeShader::CompositeShader()
|
||||
: Shader(
|
||||
shaders[COMPOSITE_SHADER].vertex,
|
||||
shaders[COMPOSITE_SHADER].fragment
|
||||
) {
|
||||
if (!valid) {
|
||||
fprintf(stderr, "invalid composite shader\n");
|
||||
return;
|
||||
}
|
||||
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_image = glGetUniformLocation(program, "u_image");
|
||||
u_opacity = glGetUniformLocation(program, "u_opacity");
|
||||
|
||||
// fprintf(stderr, "CompositeShader:\n");
|
||||
// fprintf(stderr, " - u_matrix: %d\n", u_matrix);
|
||||
// fprintf(stderr, " - u_image: %d\n", u_image);
|
||||
// fprintf(stderr, " - u_opacity: %f\n", u_opacity);
|
||||
}
|
||||
|
||||
void CompositeShader::bind(char *offset) {
|
||||
glEnableVertexAttribArray(a_pos);
|
||||
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
|
||||
}
|
||||
|
||||
void CompositeShader::setImage(int32_t new_image) {
|
||||
if (image != new_image) {
|
||||
glUniform1i(u_image, new_image);
|
||||
image = new_image;
|
||||
}
|
||||
}
|
||||
|
||||
void CompositeShader::setOpacity(float new_opacity) {
|
||||
if (opacity != new_opacity) {
|
||||
glUniform1f(u_opacity, new_opacity);
|
||||
opacity = new_opacity;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ RasterShader::RasterShader()
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_image = glGetUniformLocation(program, "u_image");
|
||||
u_opacity = glGetUniformLocation(program, "u_opacity");
|
||||
|
||||
// fprintf(stderr, "RasterShader:\n");
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
using namespace llmr;
|
||||
|
||||
const shader_source llmr::shaders[SHADER_COUNT] = {
|
||||
{
|
||||
"#version 120\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nvarying vec2 v_pos;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n vec4 tmpvar_2;\n tmpvar_2 = (u_matrix * tmpvar_1);\n gl_Position = tmpvar_2;\n v_pos = tmpvar_2.xy;\n}\n\n",
|
||||
"#version 120\nuniform sampler2D u_image;\nuniform float u_opacity;\nvarying vec2 v_pos;\nvoid main ()\n{\n gl_FragColor = (texture2D (u_image, ((v_pos / 2.0) + 0.5)) * u_opacity);\n}\n\n",
|
||||
},
|
||||
{
|
||||
"#version 120\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform float u_size;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_matrix * tmpvar_1);\n gl_PointSize = u_size;\n}\n\n",
|
||||
"#version 120\nuniform vec4 u_color;\nuniform float u_blur;\nvoid main ()\n{\n vec2 x_1;\n x_1 = (gl_PointCoord - 0.5);\n float tmpvar_2;\n tmpvar_2 = clamp (((\n sqrt(dot (x_1, x_1))\n - 0.5) / (\n (0.5 - u_blur)\n - 0.5)), 0.0, 1.0);\n gl_FragColor = (u_color * (tmpvar_2 * (tmpvar_2 * \n (3.0 - (2.0 * tmpvar_2))\n )));\n}\n\n",
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
using namespace llmr;
|
||||
|
||||
const shader_source llmr::shaders[SHADER_COUNT] = {
|
||||
{
|
||||
"precision highp float;\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nvarying highp vec2 v_pos;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n vec4 tmpvar_2;\n tmpvar_2 = (u_matrix * tmpvar_1);\n gl_Position = tmpvar_2;\n v_pos = tmpvar_2.xy;\n}\n\n",
|
||||
"precision highp float;\nuniform sampler2D u_image;\nuniform float u_opacity;\nvarying vec2 v_pos;\nvoid main ()\n{\n lowp vec4 tmpvar_1;\n tmpvar_1 = (texture2D (u_image, ((v_pos / 2.0) + 0.5)) * u_opacity);\n gl_FragColor = tmpvar_1;\n}\n\n",
|
||||
},
|
||||
{
|
||||
"precision highp float;\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform float u_size;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_matrix * tmpvar_1);\n gl_PointSize = u_size;\n}\n\n",
|
||||
"precision highp float;\nuniform vec4 u_color;\nuniform float u_blur;\nvoid main ()\n{\n mediump vec2 x_1;\n x_1 = (gl_PointCoord - 0.5);\n mediump float tmpvar_2;\n tmpvar_2 = clamp (((\n sqrt(dot (x_1, x_1))\n - 0.5) / (\n (0.5 - u_blur)\n - 0.5)), 0.0, 1.0);\n gl_FragColor = (u_color * (tmpvar_2 * (tmpvar_2 * \n (3.0 - (2.0 * tmpvar_2))\n )));\n}\n\n",
|
||||
|
||||
@@ -18,6 +18,7 @@ void Style::reset() {
|
||||
computed.icons.clear();
|
||||
computed.texts.clear();
|
||||
computed.rasters.clear();
|
||||
computed.composites.clear();
|
||||
}
|
||||
|
||||
void Style::cascade(float z) {
|
||||
@@ -130,6 +131,19 @@ void Style::cascade(float z) {
|
||||
raster.opacity = layer.opacity.evaluate<float>(z);
|
||||
}
|
||||
|
||||
// Cascade composite classes
|
||||
for (const auto& composite_pair : sheetClass.composite) {
|
||||
const std::string& layer_name = composite_pair.first;
|
||||
const llmr::CompositeClass& layer = composite_pair.second;
|
||||
|
||||
// TODO: This should be restricted to composite styles that have actual
|
||||
// values so as to not override with default values.
|
||||
llmr::CompositeProperties& composite = computed.composites[layer_name];
|
||||
composite.enabled = layer.enabled.evaluate<bool>(z);
|
||||
composite.opacity = layer.opacity.evaluate<float>(z);
|
||||
}
|
||||
|
||||
|
||||
// Cascade background
|
||||
computed.background.color = sheetClass.background.color;
|
||||
computed.background.opacity = sheetClass.background.opacity.evaluate<float>(z);
|
||||
|
||||
@@ -297,6 +297,9 @@ void StyleParser::parseClass(const std::string &name, JSVal value, ClassDescript
|
||||
if (bucket_name == "background") {
|
||||
// background buckets are fake
|
||||
class_desc.background = parseBackgroundClass(value);
|
||||
} else if (bucket_name.length() == 0) {
|
||||
// no bucket name == composite bucket.
|
||||
class_desc.composite.insert({ name, std::forward<CompositeClass>(parseCompositeClass(value)) });
|
||||
} else {
|
||||
auto bucket_it = buckets.find(bucket_name);
|
||||
if (bucket_it == buckets.end()) {
|
||||
@@ -655,6 +658,20 @@ RasterClass StyleParser::parseRasterClass(JSVal value) {
|
||||
return klass;
|
||||
}
|
||||
|
||||
CompositeClass StyleParser::parseCompositeClass(JSVal value) {
|
||||
CompositeClass klass;
|
||||
|
||||
if (value.HasMember("enabled")) {
|
||||
klass.enabled = parseFunction(value["enabled"]);
|
||||
}
|
||||
|
||||
if (value.HasMember("opacity")) {
|
||||
klass.opacity = parseFunction(value["opacity"]);
|
||||
}
|
||||
|
||||
return klass;
|
||||
}
|
||||
|
||||
BackgroundClass StyleParser::parseBackgroundClass(JSVal value) {
|
||||
BackgroundClass klass;
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#include <llmr/util/constants.hpp>
|
||||
|
||||
const float llmr::util::tileSize = 512.0f;
|
||||
|
||||
const bool llmr::debug::styleParseWarnings = true;
|
||||
const bool llmr::debug::renderWarnings = true;
|
||||
const bool llmr::debug::renderTree = false;
|
||||
|
||||
Reference in New Issue
Block a user