add antialiased line shader
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "shader-fill.hpp"
|
||||
#include "shader-line.hpp"
|
||||
#include "shader-outline.hpp"
|
||||
|
||||
namespace llmr {
|
||||
|
||||
@@ -38,6 +39,7 @@ private:
|
||||
Shader *currentShader;
|
||||
FillShader *fillShader;
|
||||
LineShader *lineShader;
|
||||
OutlineShader *outlineShader;
|
||||
|
||||
uint32_t tile_stencil_buffer;
|
||||
uint32_t tile_border_buffer;
|
||||
|
||||
20
include/llmr/renderer/shader-outline.hpp
Normal file
20
include/llmr/renderer/shader-outline.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef LLMR_RENDERER_SHADER_OUTLINE
|
||||
#define LLMR_RENDERER_SHADER_OUTLINE
|
||||
|
||||
#include "shader.hpp"
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class OutlineShader : public Shader {
|
||||
public:
|
||||
OutlineShader();
|
||||
|
||||
int32_t a_pos;
|
||||
int32_t u_matrix;
|
||||
int32_t u_color;
|
||||
int32_t u_world;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef LLMR_RENDERER_SHADER
|
||||
#define LLMR_RENDERER_SHADER
|
||||
|
||||
#include <vector>
|
||||
#include <forward_list>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
~Shader();
|
||||
bool valid;
|
||||
uint32_t program;
|
||||
std::vector<uint32_t> attributes;
|
||||
std::forward_list<uint32_t> attributes;
|
||||
|
||||
private:
|
||||
bool compileShader(uint32_t *shader, uint32_t type, const char *source);
|
||||
|
||||
@@ -16,6 +16,7 @@ typedef struct llmr_shader llmr_shader_t;
|
||||
enum {
|
||||
FILL_SHADER,
|
||||
LINE_SHADER,
|
||||
OUTLINE_SHADER,
|
||||
SHADER_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ SET(llmr_SOURCES
|
||||
renderer/painter.cpp
|
||||
renderer/shader-fill.cpp
|
||||
renderer/shader-line.cpp
|
||||
renderer/shader-outline.cpp
|
||||
renderer/shader.cpp
|
||||
shader/shaders.c
|
||||
util/animation.cpp
|
||||
@@ -25,6 +26,7 @@ SET(llmr_HEADERS
|
||||
../include/llmr/renderer/painter.hpp
|
||||
../include/llmr/renderer/shader-fill.hpp
|
||||
../include/llmr/renderer/shader-line.hpp
|
||||
../include/llmr/renderer/shader-outline.hpp
|
||||
../include/llmr/renderer/shader.hpp
|
||||
../include/llmr/util/animation.hpp
|
||||
../include/llmr/util/math.hpp
|
||||
|
||||
@@ -32,7 +32,8 @@ painter::painter(class transform *transform, class settings *settings)
|
||||
settings(settings),
|
||||
currentShader(NULL),
|
||||
fillShader(NULL),
|
||||
lineShader(NULL) {
|
||||
lineShader(NULL),
|
||||
outlineShader(NULL) {
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +42,7 @@ void painter::setup() {
|
||||
|
||||
assert(fillShader);
|
||||
assert(lineShader);
|
||||
assert(outlineShader);
|
||||
|
||||
// Set up the stencil quad we're using to generate the stencil mask.
|
||||
glGenBuffers(1, &tile_stencil_buffer);
|
||||
@@ -63,6 +65,7 @@ void painter::setup() {
|
||||
void painter::setupShaders() {
|
||||
fillShader = new FillShader();
|
||||
lineShader = new LineShader();
|
||||
outlineShader = new OutlineShader();
|
||||
}
|
||||
|
||||
void painter::teardown() {
|
||||
@@ -143,23 +146,21 @@ void painter::render(tile::ptr tile) {
|
||||
|
||||
drawClippingMask();
|
||||
|
||||
switchShader(lineShader);
|
||||
glUniformMatrix4fv(lineShader->u_matrix, 1, GL_FALSE, matrix);
|
||||
|
||||
switchShader(outlineShader);
|
||||
glUniformMatrix4fv(outlineShader->u_matrix, 1, GL_FALSE, matrix);
|
||||
|
||||
glStencilFunc(GL_EQUAL, 0x80, 0x80);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
// glDisable(GL_STENCIL_TEST);
|
||||
|
||||
tile->lineVertex.bind();
|
||||
glVertexAttribPointer(lineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
glUniform4f(lineShader->u_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glLineWidth(1.0f);
|
||||
glVertexAttribPointer(outlineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
glUniform4f(outlineShader->u_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glUniform2f(outlineShader->u_world, transform->width, transform->height);
|
||||
glLineWidth(2.0f);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, tile->lineVertex.length());
|
||||
|
||||
|
||||
|
||||
|
||||
if (settings->debug) {
|
||||
// draw tile outline
|
||||
switchShader(lineShader);
|
||||
@@ -189,36 +190,47 @@ void painter::viewport() {
|
||||
}
|
||||
|
||||
// Switches to a different shader program.
|
||||
void painter::switchShader(Shader *shader) {
|
||||
/**
|
||||
* @return boolean whether the shader was actually switched
|
||||
*/
|
||||
bool painter::switchShader(Shader *shader) {
|
||||
if (currentShader != shader) {
|
||||
glUseProgram(shader->program);
|
||||
|
||||
// Disable all attributes from the existing shader that aren't used in
|
||||
// the new shader. Note: attribute indices are *not* program specific!
|
||||
if (currentShader) {
|
||||
// const std::vector<GLuint> &enabled = currentShader->attributes;
|
||||
// const std::vector<GLuint> &required = shader->attributes;
|
||||
// TODO
|
||||
const std::forward_list<uint32_t> &hitherto = currentShader->attributes;
|
||||
const std::forward_list<uint32_t> &henceforth = shader->attributes;
|
||||
|
||||
// for (var i = 0; i < enabled.length; i++) {
|
||||
// if (required.indexOf(enabled[i]) < 0) {
|
||||
// gl.disableVertexAttribArray(enabled[i]);
|
||||
// }
|
||||
// }
|
||||
// Find all attribute indices that are used in the old shader,
|
||||
// but unused in the new one.
|
||||
for (uint32_t i : hitherto) {
|
||||
if (std::find(henceforth.begin(), henceforth.end(), i) == henceforth.end()) {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
// // Enable all attributes for the new shader.
|
||||
// for (var j = 0; j < required.length; j++) {
|
||||
// if (enabled.indexOf(required[j]) < 0) {
|
||||
// gl.enableVertexAttribArray(required[j]);
|
||||
// }
|
||||
// }
|
||||
// Enable all attributes for the new shader that were not already in
|
||||
// use in the old one.
|
||||
for (uint32_t i : henceforth) {
|
||||
if (std::find(hitherto.begin(), hitherto.end(), i) == hitherto.end()) {
|
||||
glEnableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
currentShader = shader;
|
||||
} else {
|
||||
// Enable all attributes for the new shader.
|
||||
// Enable all attributes for the new shader (== first shader).
|
||||
for (GLuint index : shader->attributes) {
|
||||
glEnableVertexAttribArray(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentShader = shader;
|
||||
currentShader = shader;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,13 @@ FillShader::FillShader()
|
||||
llmr_shaders[FILL_SHADER].vertex,
|
||||
llmr_shaders[FILL_SHADER].fragment
|
||||
) {
|
||||
if (!valid) return;
|
||||
if (!valid) {
|
||||
fprintf(stderr, "invalid fill shader\n");
|
||||
return;
|
||||
}
|
||||
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
attributes.push_back(a_pos);
|
||||
attributes.emplace_front(a_pos);
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_color = glGetUniformLocation(program, "u_color");
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
#include <llmr/shader/shaders.h>
|
||||
#include <llmr/platform/gl.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
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);
|
||||
attributes.emplace_front(a_pos);
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_color = glGetUniformLocation(program, "u_color");
|
||||
|
||||
23
src/renderer/shader-outline.cpp
Normal file
23
src/renderer/shader-outline.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <llmr/renderer/shader-outline.hpp>
|
||||
#include <llmr/shader/shaders.h>
|
||||
#include <llmr/platform/gl.hpp>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
OutlineShader::OutlineShader()
|
||||
: Shader(
|
||||
llmr_shaders[OUTLINE_SHADER].vertex,
|
||||
llmr_shaders[OUTLINE_SHADER].fragment
|
||||
) {
|
||||
if (!valid) {
|
||||
fprintf(stderr, "invalid outline shader\n");
|
||||
return;
|
||||
}
|
||||
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
attributes.emplace_front(a_pos);
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_color = glGetUniformLocation(program, "u_color");
|
||||
u_world = glGetUniformLocation(program, "u_world");
|
||||
}
|
||||
9
src/shader/outline.fragment.glsl
Normal file
9
src/shader/outline.fragment.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
uniform vec4 u_color;
|
||||
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
float dist = length(v_pos - gl_FragCoord.xy);
|
||||
float alpha = smoothstep(1.0, 0.0, dist);
|
||||
gl_FragColor = u_color * alpha;
|
||||
}
|
||||
15
src/shader/outline.vertex.glsl
Normal file
15
src/shader/outline.vertex.glsl
Normal file
@@ -0,0 +1,15 @@
|
||||
attribute vec2 a_pos;
|
||||
uniform mat4 u_matrix;
|
||||
uniform vec2 u_world;
|
||||
|
||||
varying vec2 v_pos;
|
||||
|
||||
void main() {
|
||||
// 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) * 2.0;
|
||||
gl_Position = u_matrix * vec4(a_pos, z, 1);
|
||||
|
||||
v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;
|
||||
}
|
||||
@@ -9,5 +9,9 @@ const llmr_shader_t llmr_shaders[SHADER_COUNT] = {
|
||||
[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",
|
||||
},
|
||||
[OUTLINE_SHADER] = {
|
||||
.vertex = "attribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n\n v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;\n}\n",
|
||||
.fragment = "uniform vec4 u_color;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = smoothstep(1.0, 0.0, dist);\n gl_FragColor = u_color * alpha;\n}\n",
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user