summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <github@kkaefer.com>2014-01-07 16:52:23 +0100
committerKonstantin Käfer <github@kkaefer.com>2014-01-07 16:52:23 +0100
commit528eaf475e084508cb2d2d26df7d4136f1eb5e04 (patch)
tree87f9a7ecec23cb7cc37450e7cd5f34fa6248f750
parent044a7b5dcd92b1ba095f0768d24aa504fdf71a16 (diff)
downloadqtlocation-mapboxgl-528eaf475e084508cb2d2d26df7d4136f1eb5e04.tar.gz
emscripten support
-rw-r--r--.gitignore3
-rw-r--r--Makefile20
-rw-r--r--README.md30
-rwxr-xr-xbin/build-shaders.js77
-rw-r--r--emscripten/main.cpp154
-rw-r--r--emscripten/main.html9
-rw-r--r--include/llmr/geometry/linevertexbuffer.hpp4
-rw-r--r--include/llmr/platform/gl.hpp4
-rw-r--r--include/llmr/platform/platform.hpp2
-rw-r--r--include/llmr/renderer/painter.hpp14
-rw-r--r--include/llmr/renderer/shader-fill.hpp8
-rw-r--r--include/llmr/renderer/shader-line.hpp8
-rw-r--r--include/llmr/renderer/shader.hpp9
-rw-r--r--include/llmr/shader/shaders.h28
-rw-r--r--macosx/main.mm33
-rw-r--r--src/geometry/linevertexbuffer.cpp1
-rw-r--r--src/map/pbf.hpp9
-rw-r--r--src/map/tile.cpp8
-rw-r--r--src/renderer/painter.cpp20
-rw-r--r--src/renderer/shader-fill.cpp9
-rw-r--r--src/renderer/shader-line.cpp20
-rw-r--r--src/renderer/shader.cpp16
-rw-r--r--src/shader/line.fragment.glsl1
-rw-r--r--src/shader/shaders.c13
24 files changed, 406 insertions, 94 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..6bc0b9d208
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+/emscripten/main.js
+/emscripten/main.js.map \ No newline at end of file
diff --git a/Makefile b/Makefile
index a43f4f5f6c..3c3269d791 100644
--- a/Makefile
+++ b/Makefile
@@ -12,17 +12,17 @@ SRCS += src/renderer/painter.cpp
SRCS += src/renderer/shader.cpp
SRCS += src/renderer/shader-fill.cpp
SRCS += src/renderer/shader-line.cpp
+SRCS += src/shader/shaders.c
SRCS += src/util/mat4.c
-OBJS = $(patsubst %.mm,%.o,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS))))
+# OBJS = $(patsubst %.mm,%.o,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS))))
main: macosx
-library: $(OBJS)
-
macosx: SRCS += macosx/main.mm
-macosx: library
- $(CXX) $(OBJS) $(INCLUDE) -lglfw3 -framework OpenGL -framework Foundation -o macosx/main
+emscripten: SRCS += emscripten/main.cpp
+
+macosx emscripten: OBJS = $(patsubst %.mm,%.o,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS))))
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE) -c -o $@ $^
@@ -33,8 +33,16 @@ macosx: library
%.o: %.c
$(CC) $(CPPFLAGS) $(INCLUDE) -c -o $@ $^
+
+.SECONDEXPANSION:
+macosx: $$(OBJS)
+ $(CXX) $(OBJS) $(INCLUDE) -lglfw3 -framework OpenGL -framework Foundation -o macosx/main
+
+emscripten: $$(OBJS)
+ $(CXX) $(OBJS) $(INCLUDE) -o emscripten/main.js
+
clean:
rm -rf src/*/*.o
rm -rf macosx/main
-.PHONY: macosx
+.PHONY: macosx emscripten
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..47db97996c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+
+
+# Build instructions
+
+## Mac OS X
+
+```
+make
+```
+
+
+## Emscripten
+
+```
+emmake make emscripten
+```
+
+Note that mousewheel support requires a hacked emscripten:
+
+In `src/library_glfw.js`, replace the first part of the mousewheel function with
+
+```js
+ GLFW.wheelPos = (event.detail || -event.deltaY);
+```
+
+In `system/include/GL/glfw.h`, replace the wheel callback typedef with
+
+```c
+typedef void (GLFWCALL * GLFWmousewheelfun)(float);
+```
diff --git a/bin/build-shaders.js b/bin/build-shaders.js
new file mode 100755
index 0000000000..d8d7a46bbb
--- /dev/null
+++ b/bin/build-shaders.js
@@ -0,0 +1,77 @@
+#!/usr/bin/env node
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+module.exports = function() {
+ var name;
+ var shaders = {};
+
+ var shaderFiles = fs.readdirSync('src/shader');
+
+ for (var i = 0; i < shaderFiles.length; i++) {
+ var parts = shaderFiles[i].match(/^(.+)\.(vertex|fragment)\.glsl$/);
+ if (parts) {
+ name = parts[1];
+ var type = parts[2];
+ if (!(name in shaders)) {
+ shaders[name] = {};
+ }
+ shaders[name][type] = fs.readFileSync(path.join('src/shader', shaderFiles[i]), 'utf8');
+ }
+ }
+
+ var lines = [];
+ var consts = [];
+ for (var name in shaders) {
+ consts.push(name.toUpperCase() + '_SHADER');
+
+ var line = '';
+ line += ' [' + name.toUpperCase() + '_SHADER] = {\n';
+ line += ' .vertex = ' + JSON.stringify(shaders[name].vertex) + ',\n';
+ line += ' .fragment = ' + JSON.stringify(shaders[name].fragment) + ',\n';
+ line += ' }';
+ lines.push(line);
+ }
+
+ var header = '// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.\n\n';
+ header += '#ifndef LLMR_SHADER_SHADERS\n';
+ header += '#define LLMR_SHADER_SHADERS\n';
+ header += '\n';
+ header += '#ifdef __cplusplus\n';
+ header += 'extern "C" {\n';
+ header += '#endif\n';
+ header += '\n';
+ header += 'struct llmr_shader {\n';
+ header += ' const char *vertex;\n';
+ header += ' const char *fragment;\n';
+ header += '};\n';
+ header += 'typedef struct llmr_shader llmr_shader_t;\n'
+ header += '\n';
+ header += 'enum {\n';
+ consts.push('SHADER_COUNT');
+ header += ' ' + consts.join(',\n ') + '\n';
+ header += '};\n';
+ header += '\n';
+ header += 'extern const llmr_shader_t llmr_shaders[SHADER_COUNT];\n';
+ header += '\n';
+ header += '#ifdef __cplusplus\n';
+ header += '}\n';
+ header += '#endif\n';
+ header += '\n';
+ header += '#endif\n';
+ fs.writeFileSync('include/llmr/shader/shaders.h', header);
+
+
+ var code = '// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.\n';
+ code += '#include <llmr/shader/shaders.h>\n';
+ code += '\n';
+ code += 'const llmr_shader_t llmr_shaders[SHADER_COUNT] = {\n';
+ code += lines.join(',\n');
+ code += '\n};\n';
+
+ fs.writeFileSync('src/shader/shaders.c', code);
+};
+
+module.exports();
diff --git a/emscripten/main.cpp b/emscripten/main.cpp
new file mode 100644
index 0000000000..20e9212baf
--- /dev/null
+++ b/emscripten/main.cpp
@@ -0,0 +1,154 @@
+#include <emscripten/emscripten.h>
+#include <GL/glfw.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+
+#include <llmr/llmr.hpp>
+#include <llmr/map/tile.hpp>
+
+bool dirty = true;
+
+class MapView;
+
+static MapView *view;
+
+class MapView {
+public:
+ MapView() :
+ dirty(true),
+ platform(new llmr::platform(this)),
+ painter(new llmr::painter(platform)),
+ map(new llmr::map(platform, painter)) {
+
+ // Initialize GLFW
+ if (!glfwInit()) {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(1);
+ }
+
+ int width, height;
+ emscripten_get_canvas_size(&width, &height, NULL);
+
+ glfwSetMousePosCallback(mousemove);
+ glfwSetMouseButtonCallback(mouseclick);
+ glfwSetMouseWheelCallback(scroll);
+
+ // Open a window and create its OpenGL context
+ if (!glfwOpenWindow(width, height, 8, 8, 8, 8, 16, 8, GLFW_WINDOW)) {
+ fprintf(stderr, "Failed to open GLFW window\n");
+
+ glfwTerminate();
+ exit(1);
+ }
+
+ painter->setup();
+ painter->resize(width, height);
+
+ }
+
+ ~MapView() {
+ delete map;
+ delete painter;
+ delete platform;
+ glfwTerminate();
+ }
+
+ static void mousemove(int x, int y) {
+ if (view->tracking) {
+ view->map->moveBy(x - view->last_x, y - view->last_y);
+ }
+ view->last_x = x;
+ view->last_y = y;
+ }
+
+ static void scroll(float pos) {
+ double delta = pos;
+
+ bool is_wheel = delta != 0 && fmod(delta, 4.000244140625) == 0;
+
+ double absdelta = delta < 0 ? -delta : delta;
+ double scale = 2.0 / (1.0 + exp(-absdelta / 100.0));
+
+ // Make the scroll wheel a bit slower.
+ // if (!is_wheel) {
+ // scale = (scale - 1.0) / 2.0 + 1.0;
+ // }
+
+ // Zooming out.
+ if (delta < 0 && scale != 0) {
+ scale = 1.0 / scale;
+ }
+
+ view->map->scaleBy(scale, view->last_x, view->last_y);
+ }
+
+ static void mouseclick(int button, int action) {
+ if (button == GLFW_MOUSE_BUTTON_1) {
+ view->tracking = action == GLFW_PRESS;
+ }
+ }
+
+ int run() {
+ emscripten_set_main_loop(render, 60, 1);
+ return 0;
+ }
+
+ static void render() {
+ if (view->dirty) {
+ view->map->render();
+ // glClearColor(1, 1, 0, 1);
+ // glClear(GL_COLOR_BUFFER_BIT);
+
+ view->dirty = false;
+ }
+ }
+
+ bool dirty;
+ double last_x, last_y;
+ bool tracking;
+
+
+ llmr::platform *platform;
+ llmr::painter *painter;
+ llmr::map *map;
+
+};
+
+
+void llmr::platform::restart() {
+ view->dirty = true;
+}
+
+void ontileload(void* custom, void* bytes, int length) {
+ fprintf(stderr, "data loaded successfully: length: %d\n", length);
+ llmr::tile *tile = (llmr::tile *)custom;
+ tile->setData((uint8_t *)bytes, length);
+ if (tile->parse()) {
+ view->map->tileLoaded(tile);
+ return;
+ }
+}
+
+void ontileerror(void* custom) {
+ fprintf(stderr, "data load error\n");
+ llmr::tile *tile = (llmr::tile *)custom;
+ view->map->tileFailed(tile);
+}
+
+void llmr::platform::request(tile *tile) {
+ const char *urlTemplate = "http://api.tiles.mapbox.com/v3/mapbox.mapbox-streets-v4/%d/%d/%d.vector.pbf";
+ char urlString[255];
+ snprintf(urlString, 255, urlTemplate, tile->z, tile->x, tile->y);
+ fprintf(stderr, "requesting %s\n", urlString);
+
+ emscripten_async_wget_data(urlString, tile, ontileload, ontileerror);
+}
+
+
+int main() {
+ view = new MapView();
+ int ret = view->run();
+ delete view;
+ return ret;
+}
diff --git a/emscripten/main.html b/emscripten/main.html
new file mode 100644
index 0000000000..9676130527
--- /dev/null
+++ b/emscripten/main.html
@@ -0,0 +1,9 @@
+<body>
+<script>
+var canvas = document.createElement('canvas');
+canvas.width = 600;
+canvas.height = 400;
+document.body.appendChild(canvas);
+Module = { canvas: canvas };
+</script>
+<script src="main.js"></script>
diff --git a/include/llmr/geometry/linevertexbuffer.hpp b/include/llmr/geometry/linevertexbuffer.hpp
index 8d5c6b335c..4d23de9154 100644
--- a/include/llmr/geometry/linevertexbuffer.hpp
+++ b/include/llmr/geometry/linevertexbuffer.hpp
@@ -1,8 +1,6 @@
#ifndef LLMR_GEOMETRY_LINEVERTEXBUFFER
#define LLMR_GEOMETRY_LINEVERTEXBUFFER
-#include "../platform/gl.hpp"
-
#include <vector>
namespace llmr {
@@ -18,7 +16,7 @@ public:
void bind();
private:
std::vector<uint16_t> array;
- GLuint buffer;
+ uint32_t buffer;
};
}
diff --git a/include/llmr/platform/gl.hpp b/include/llmr/platform/gl.hpp
index 4fa0cf4775..58d9099c70 100644
--- a/include/llmr/platform/gl.hpp
+++ b/include/llmr/platform/gl.hpp
@@ -1,7 +1,9 @@
#ifndef LLMR_RENDERER_GL
#define LLMR_RENDERER_GL
-#ifdef __APPLE__
+#ifdef EMSCRIPTEN
+ #include <GLES2/gl2.h>
+#elif __APPLE__
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
#include <OpenGLES/ES2/gl.h>
diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp
index 46a1383c42..e8aa972d7b 100644
--- a/include/llmr/platform/platform.hpp
+++ b/include/llmr/platform/platform.hpp
@@ -8,8 +8,6 @@ class tile;
class platform {
public:
platform(void *obj) : obj(obj) {}
-
- const char *shaderSource(const char *name, const char *extension);
void restart();
void request(tile *tile);
diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp
index ac6012b0d0..6c75171846 100644
--- a/include/llmr/renderer/painter.hpp
+++ b/include/llmr/renderer/painter.hpp
@@ -1,8 +1,6 @@
#ifndef LLMR_RENDERER_PAINTER
#define LLMR_RENDERER_PAINTER
-#include "../platform/gl.hpp"
-
#include "shader-fill.hpp"
#include "shader-line.hpp"
@@ -19,7 +17,7 @@ public:
void setup();
void teardown();
- void resize(GLuint new_width, GLuint new_height);
+ void resize(uint32_t new_width, uint32_t new_height);
void viewport();
@@ -38,16 +36,16 @@ public:
private:
platform *platform;
transform *transform;
- GLuint width, height;
- GLfloat matrix[16];
+ uint32_t width, height;
+ float matrix[16];
Shader *currentShader;
FillShader *fillShader;
LineShader *lineShader;
- GLuint vertexArray;
- GLuint triangleVertexBuffer;
- GLuint fillVertexBuffer;
+ uint32_t vertexArray;
+ uint32_t triangleVertexBuffer;
+ uint32_t fillVertexBuffer;
};
}
diff --git a/include/llmr/renderer/shader-fill.hpp b/include/llmr/renderer/shader-fill.hpp
index 165266e4b5..440f3011c6 100644
--- a/include/llmr/renderer/shader-fill.hpp
+++ b/include/llmr/renderer/shader-fill.hpp
@@ -7,11 +7,11 @@ namespace llmr {
class FillShader : public Shader {
public:
- FillShader(const GLchar *vertex, const GLchar *fragment);
+ FillShader();
- GLint a_pos;
- GLint u_matrix;
- GLint u_color;
+ int32_t a_pos;
+ int32_t u_matrix;
+ int32_t u_color;
};
}
diff --git a/include/llmr/renderer/shader-line.hpp b/include/llmr/renderer/shader-line.hpp
index 60e27146f9..b40ca0e0a7 100644
--- a/include/llmr/renderer/shader-line.hpp
+++ b/include/llmr/renderer/shader-line.hpp
@@ -7,11 +7,11 @@ namespace llmr {
class LineShader : public Shader {
public:
- LineShader(const GLchar *vertex, const GLchar *fragment);
+ LineShader();
- GLint a_pos;
- GLint u_matrix;
- GLint u_color;
+ int32_t a_pos;
+ int32_t u_matrix;
+ int32_t u_color;
};
}
diff --git a/include/llmr/renderer/shader.hpp b/include/llmr/renderer/shader.hpp
index d178a1d9c8..2968ad59fe 100644
--- a/include/llmr/renderer/shader.hpp
+++ b/include/llmr/renderer/shader.hpp
@@ -1,21 +1,20 @@
#ifndef LLMR_RENDERER_SHADER
#define LLMR_RENDERER_SHADER
-#include "../platform/gl.hpp"
#include <vector>
namespace llmr {
class Shader {
public:
- Shader(const GLchar *vertex, const GLchar *fragment);
+ Shader(const char *vertex, const char *fragment);
~Shader();
bool valid;
- GLuint program;
- std::vector<GLuint> attributes;
+ uint32_t program;
+ std::vector<uint32_t> attributes;
private:
- bool compileShader(GLuint *shader, GLenum type, const GLchar *source);
+ bool compileShader(uint32_t *shader, uint32_t type, const char *source);
};
}
diff --git a/include/llmr/shader/shaders.h b/include/llmr/shader/shaders.h
new file mode 100644
index 0000000000..038f07a2e9
--- /dev/null
+++ b/include/llmr/shader/shaders.h
@@ -0,0 +1,28 @@
+// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
+
+#ifndef LLMR_SHADER_SHADERS
+#define LLMR_SHADER_SHADERS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct llmr_shader {
+ const char *vertex;
+ const char *fragment;
+};
+typedef struct llmr_shader llmr_shader_t;
+
+enum {
+ FILL_SHADER,
+ LINE_SHADER,
+ SHADER_COUNT
+};
+
+extern const llmr_shader_t llmr_shaders[SHADER_COUNT];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/macosx/main.mm b/macosx/main.mm
index 2462d2e34e..caa56d999e 100644
--- a/macosx/main.mm
+++ b/macosx/main.mm
@@ -1,8 +1,6 @@
#include <llmr/llmr.hpp>
#include <GLFW/glfw3.h>
-#include <cstdlib>
#import <Foundation/Foundation.h>
-
#include <llmr/platform/platform.hpp>
#include <llmr/map/tile.hpp>
@@ -143,37 +141,6 @@ public:
llmr::map *map;
};
-
-
-
-
-
-const char *llmr::platform::shaderSource(const char *name, const char *type) {
- char filename[80];
- snprintf(filename, 80, "src/shader/%s.%s", name, type);
-
- FILE *file = fopen(filename, "rb");
- if (!file) {
- fprintf(stderr, "Could not open file %s", filename);
- return NULL;
- }
-
- fseek(file, 0, SEEK_END);
- long size = ftell(file);
- fseek(file, 0, SEEK_SET);
- char *shader = (char *)malloc(size + 1);
- if (!fread(shader, size, 1, file)) {
- fclose(file);
- free(shader);
- shader = 0;
- fprintf(stderr, "Failed to read file %s\n", filename);
- return NULL;
- }
- fclose(file);
- shader[size] = 0;
- return shader;
-}
-
void llmr::platform::restart() {
((MapView *)obj)->dirty = true;
}
diff --git a/src/geometry/linevertexbuffer.cpp b/src/geometry/linevertexbuffer.cpp
index 7d48f79604..04fd1c6c23 100644
--- a/src/geometry/linevertexbuffer.cpp
+++ b/src/geometry/linevertexbuffer.cpp
@@ -1,4 +1,5 @@
#include <llmr/geometry/linevertexbuffer.hpp>
+#include <llmr/platform/gl.hpp>
#include <cstdio>
diff --git a/src/map/pbf.hpp b/src/map/pbf.hpp
index faf0aadf91..29c252e115 100644
--- a/src/map/pbf.hpp
+++ b/src/map/pbf.hpp
@@ -21,7 +21,7 @@ struct pbf {
// inline pbf(const std::string& buffer);
inline bool next();
- inline uint64_t varint();
+ template <typename T = uint32_t> inline T varint();
inline int64_t svarint();
inline std::string string();
inline float float32();
@@ -68,17 +68,18 @@ bool pbf::next()
}
-uint64_t pbf::varint()
+template <typename T>
+T pbf::varint()
{
uint8_t byte = 0x80;
- uint64_t result = 0;
+ T result = 0;
int bitpos;
for (bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
if (data >= end) {
fprintf(stderr, "unterminated varint, unexpected end of buffer");
exit(1);
}
- result |= ((uint64_t)(byte = *data) & 0x7F) << bitpos;
+ result |= ((T)(byte = *data) & 0x7F) << bitpos;
data++;
}
diff --git a/src/map/tile.cpp b/src/map/tile.cpp
index a27f6e5ba8..ce56cd6134 100644
--- a/src/map/tile.cpp
+++ b/src/map/tile.cpp
@@ -69,15 +69,15 @@ void tile::parseFeature(const uint8_t *data, uint32_t bytes) {
pbf feature(data, bytes);
while (feature.next()) {
if (feature.tag == 1) {
- uint64_t id = feature.varint();
+ uint32_t id = feature.varint();
} else if (feature.tag == 2) {
const uint8_t *tag_end = feature.data + feature.varint();
while (feature.data < tag_end) {
- uint32_t key = (uint32_t)feature.varint();
- uint32_t value = (uint32_t)feature.varint();
+ uint32_t key = feature.varint();
+ uint32_t value = feature.varint();
}
} else if (feature.tag == 3) {
- uint32_t type = (uint32_t)feature.varint();
+ uint32_t type = feature.varint();
} else if (feature.tag == 4) {
uint32_t bytes = (uint32_t)feature.varint();
loadGeometry(feature.data, bytes);
diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp
index b43e92d5ea..1a3fde50ab 100644
--- a/src/renderer/painter.cpp
+++ b/src/renderer/painter.cpp
@@ -5,6 +5,7 @@
#include <llmr/platform/platform.hpp>
#include <llmr/map/transform.hpp>
#include <llmr/map/tile.hpp>
+#include <llmr/platform/gl.hpp>
using namespace llmr;
@@ -44,6 +45,7 @@ void painter::setup() {
assert(fillShader);
+ assert(lineShader);
@@ -62,20 +64,8 @@ void painter::setup() {
}
void painter::setupShaders() {
- const GLchar *vertexSource, *fragmentSource;
-
- vertexSource = platform->shaderSource("fill", "vertex.glsl");
- assert((vertexSource, "Missing fill vertex shader source"));
- fragmentSource = platform->shaderSource("fill", "fragment.glsl");
- assert((fragmentSource, "Missing fill fragment shader source"));
-
- fillShader = new FillShader(vertexSource, fragmentSource);
-
- vertexSource = platform->shaderSource("line", "vertex.glsl");
- assert((vertexSource, "Missing line vertex shader source"));
- fragmentSource = platform->shaderSource("line", "fragment.glsl");
- assert((fragmentSource, "Missing line fragment shader source"));
- lineShader = new LineShader(vertexSource, fragmentSource);
+ fillShader = new FillShader();
+ lineShader = new LineShader();
}
void painter::teardown() {
@@ -108,6 +98,8 @@ void painter::resize(GLuint new_width, GLuint new_height) {
void painter::changeMatrix() {
assert(transform);
+ assert(width);
+ assert(height);
// Initialize projection matrix
float projMatrix[16];
diff --git a/src/renderer/shader-fill.cpp b/src/renderer/shader-fill.cpp
index 763c7e2fcf..e1380bfad8 100644
--- a/src/renderer/shader-fill.cpp
+++ b/src/renderer/shader-fill.cpp
@@ -1,9 +1,14 @@
#include <llmr/renderer/shader-fill.hpp>
+#include <llmr/shader/shaders.h>
+#include <llmr/platform/gl.hpp>
using namespace llmr;
-FillShader::FillShader(const GLchar *vertSource, const GLchar *fragSource)
- : Shader(vertSource, fragSource) {
+FillShader::FillShader()
+ : Shader(
+ llmr_shaders[FILL_SHADER].vertex,
+ llmr_shaders[FILL_SHADER].fragment
+ ) {
if (!valid) return;
a_pos = glGetAttribLocation(program, "a_pos");
diff --git a/src/renderer/shader-line.cpp b/src/renderer/shader-line.cpp
index 2f3381bf5b..658e244d56 100644
--- a/src/renderer/shader-line.cpp
+++ b/src/renderer/shader-line.cpp
@@ -1,10 +1,24 @@
#include <llmr/renderer/shader-line.hpp>
+#include <llmr/shader/shaders.h>
+#include <llmr/platform/gl.hpp>
+
+#include <cstdio>
using namespace llmr;
-LineShader::LineShader(const GLchar *vertSource, const GLchar *fragSource)
- : Shader(vertSource, fragSource) {
- if (!valid) return;
+LineShader::LineShader()
+ : Shader(
+ llmr_shaders[LINE_SHADER].vertex,
+ llmr_shaders[LINE_SHADER].fragment
+ ),
+ a_pos(42) {
+ if (!valid) {
+ fprintf(stderr, "invalid line shader\n");
+ return;
+ }
+
+ GLint pos = glGetAttribLocation(program, "a_pos");
+ fprintf(stderr, "a_pos: %d\n", pos);
a_pos = glGetAttribLocation(program, "a_pos");
attributes.push_back(a_pos);
diff --git a/src/renderer/shader.cpp b/src/renderer/shader.cpp
index 00af17e607..d9614c0ad9 100644
--- a/src/renderer/shader.cpp
+++ b/src/renderer/shader.cpp
@@ -1,4 +1,5 @@
- #include <llmr/renderer/shader.hpp>
+#include <llmr/renderer/shader.hpp>
+#include <llmr/platform/gl.hpp>
#include <cstdlib>
#include <cstdio>
@@ -102,7 +103,20 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
GLint status;
*shader = glCreateShader(type);
+
+#ifdef EMSCRIPTEN
+ // Add WebGL GSLSL precision premable
+ const char *preamble = "precision mediump float;\n\n";
+ int preamble_length = strlen(preamble);
+ int source_length = strlen(source);
+ char *modified_source = (char *)malloc(preamble_length + source_length);
+ strncpy(&modified_source[0], preamble, preamble_length);
+ strncpy(&modified_source[preamble_length], source, source_length);
+ glShaderSource(*shader, 1, (const GLchar **)(&modified_source), NULL);
+#else
glShaderSource(*shader, 1, &source, NULL);
+#endif
+
glCompileShader(*shader);
#if defined(DEBUG)
diff --git a/src/shader/line.fragment.glsl b/src/shader/line.fragment.glsl
index 8df552c171..0656051313 100644
--- a/src/shader/line.fragment.glsl
+++ b/src/shader/line.fragment.glsl
@@ -1,3 +1,4 @@
+
uniform vec4 u_color;
void main() {
diff --git a/src/shader/shaders.c b/src/shader/shaders.c
new file mode 100644
index 0000000000..e505fac3f0
--- /dev/null
+++ b/src/shader/shaders.c
@@ -0,0 +1,13 @@
+// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
+#include <llmr/shader/shaders.h>
+
+const llmr_shader_t llmr_shaders[SHADER_COUNT] = {
+ [FILL_SHADER] = {
+ .vertex = "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n",
+ .fragment = "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n",
+ },
+ [LINE_SHADER] = {
+ .vertex = "attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n }\n",
+ .fragment = "uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n",
+ }
+};