aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--shaders/rect.frag36
-rw-r--r--shaders/rect.vert18
-rw-r--r--test/pugl_gl3_test.c76
-rw-r--r--wscript7
4 files changed, 94 insertions, 43 deletions
diff --git a/shaders/rect.frag b/shaders/rect.frag
new file mode 100644
index 0000000..d128f37
--- /dev/null
+++ b/shaders/rect.frag
@@ -0,0 +1,36 @@
+#version 330
+
+/* The fragment shader uses the UV coordinates to calculate whether it is in
+ the T, R, B, or L border. These are then mixed with the border color, and
+ their inverse is mixed with the fill color, to calculate the fragment color.
+ For example, if we are in the top border, then T=1, so the border mix factor
+ TRBL=1, and the fill mix factor (1-TRBL) is 0.
+
+ The use of pixel units here is handy because the border width can be
+ specified precisely in pixels to draw sharp lines. The border width is just
+ hardcoded, but could be made a uniform or vertex attribute easily enough. */
+
+uniform vec2 u_size;
+uniform vec4 u_borderColor;
+uniform vec4 u_fillColor;
+
+noperspective in vec2 f_uv;
+
+layout(location = 0) out vec4 FragColor;
+
+void
+main()
+{
+ const float border_width = 2.0;
+
+ float t = step(border_width, f_uv[1]);
+ float r = step(border_width, u_size.x - f_uv[0]);
+ float b = step(border_width, u_size.y - f_uv[1]);
+ float l = step(border_width, f_uv[0]);
+ float fill_mix = t * r * b * l;
+ float border_mix = 1.0 - fill_mix;
+ vec4 fill = fill_mix * u_fillColor;
+ vec4 border = border_mix * u_borderColor;
+
+ FragColor = fill + border;
+}
diff --git a/shaders/rect.vert b/shaders/rect.vert
new file mode 100644
index 0000000..34fe0b3
--- /dev/null
+++ b/shaders/rect.vert
@@ -0,0 +1,18 @@
+#version 330
+
+/* The vertex shader is trivial, but forwards scaled UV coordinates (in pixels)
+ to the fragment shader for drawing the border. */
+
+uniform mat4 MVP;
+uniform vec2 u_size;
+
+in vec2 v_position;
+
+noperspective out vec2 f_uv;
+
+void
+main()
+{
+ f_uv = v_position * u_size;
+ gl_Position = MVP * vec4(v_position, 0.0, 1.0);
+}
diff --git a/test/pugl_gl3_test.c b/test/pugl_gl3_test.c
index 8dea5a1..9ddf7db 100644
--- a/test/pugl_gl3_test.c
+++ b/test/pugl_gl3_test.c
@@ -73,49 +73,6 @@ static const GLfloat rectVertices[] = {
static const GLuint rectIndices[4] = {0, 1, 2, 3};
-/* The vertex shader is trivial, but forwards scaled UV coordinates (in pixels)
- to the fragment shader for drawing the border. */
-static const char* vertexSource = //
- "#version 330\n"
- "uniform mat4 MVP;\n"
- "uniform vec2 u_size;\n"
- "in vec2 v_position;\n"
- "noperspective out vec2 f_uv;\n"
- "void main() {\n"
- " f_uv = v_position * u_size;\n"
- " gl_Position = MVP * vec4(v_position, 0.0, 1.0);\n"
- "}\n";
-
-/* The fragment shader uses the UV coordinates to calculate whether it is in
- the T, R, B, or L border. These are then mixed with the border color, and
- their inverse is mixed with the fill color, to calculate the fragment color.
- For example, if we are in the top border, then T=1, so the border mix factor
- TRBL=1, and the fill mix factor (1-TRBL) is 0.
-
- The use of pixel units here is handy because the border width can be
- specified precisely in pixels to draw sharp lines. The border width is just
- hardcoded, but could be made a uniform or vertex attribute easily enough. */
-static const char* fragmentSource = //
- "#version 330\n"
- "uniform vec2 u_size;\n"
- "uniform vec4 u_borderColor;\n"
- "uniform vec4 u_fillColor;\n"
- "noperspective in vec2 f_uv;\n"
- "layout(location = 0) out vec4 FragColor;\n"
- "void main() {\n"
- " const float border_width = 2.0;\n"
- "\n"
- " float t = step(border_width, f_uv[1]);\n"
- " float r = step(border_width, u_size.x - f_uv[0]);\n"
- " float b = step(border_width, u_size.y - f_uv[1]);\n"
- " float l = step(border_width, f_uv[0]);\n"
- " float fill_mix = t * r * b * l;\n"
- " float border_mix = 1.0 - fill_mix;\n"
- " vec4 fill = fill_mix * u_fillColor;\n"
- " vec4 border = border_mix * u_borderColor;\n"
- " FragColor = fill + border;\n"
- "}\n";
-
typedef struct
{
PuglTestOptions opts;
@@ -263,6 +220,27 @@ makeRects(const size_t numRects)
return rects;
}
+static char*
+loadShader(const char* const path)
+{
+ FILE* const file = fopen(path, "r");
+ if (!file) {
+ logError("Failed to open '%s'\n", path);
+ return NULL;
+ }
+
+ fseek(file, 0, SEEK_END);
+ const long fileSize = ftell(file);
+
+ fseek(file, 0, SEEK_SET);
+ char* source = (char*)calloc(1, fileSize + 1);
+
+ fread(source, 1, fileSize, file);
+ fclose(file);
+
+ return source;
+}
+
int
main(int argc, char** argv)
{
@@ -328,8 +306,20 @@ main(int argc, char** argv)
return 1;
}
+ // Load shader sources
+ char* const vertexSource = loadShader("shaders/rect.vert");
+ char* const fragmentSource = loadShader("shaders/rect.frag");
+ if (!vertexSource || !fragmentSource) {
+ logError("Failed to load shader sources\n");
+ puglFreeView(app.view);
+ puglFreeWorld(app.world);
+ return 1;
+ }
+
// Compile rectangle shaders and program
app.drawRect = compileProgram(vertexSource, fragmentSource);
+ free(fragmentSource);
+ free(vertexSource);
if (!app.drawRect.program) {
puglFreeView(app.view);
puglFreeWorld(app.world);
diff --git a/wscript b/wscript
index 5ea944d..9a3d5ea 100644
--- a/wscript
+++ b/wscript
@@ -284,6 +284,13 @@ def build(bld):
**kwargs)
if bld.env.BUILD_TESTS:
+ for s in ('rect.vert', 'rect.frag'):
+ # Copy shaders to build directory for test programs
+ bld(features = 'subst',
+ is_copy = True,
+ source = 'shaders/%s' % s,
+ target = 'shaders/%s' % s)
+
if bld.env.HAVE_GL:
build_test('pugl_test', ['test/pugl_test.c'],
platform, 'gl', uselib=['GL', 'M'])