commit f5d7f7b36c7347e764353b1b7dc1d7356eed4716
parent 144f64a31905cc8a536b0d244a8aeda1b8aae29a
Author: Brian Swetland <swetland@frotz.net>
Date: Thu, 20 Jun 2013 20:16:56 -0700
improve shader management a bit
Allow multiple shaders to be combined in one file using a syntax similar
to Philip Rideout's GLSW (http://prideout.net/blog/?p=11)
Diffstat:
16 files changed, 590 insertions(+), 376 deletions(-)
diff --git a/common/assets/TextPS.glsl b/common/assets/TextPS.glsl
@@ -1,9 +0,0 @@
-#version 150
-
-uniform sampler2D uTexture0;
-
-in vec2 vTEXCOORD;
-
-void main() {
- gl_FragColor = texture2D(uTexture0, vTEXCOORD);
-}
diff --git a/common/assets/TextVS.glsl b/common/assets/TextVS.glsl
@@ -1,41 +0,0 @@
-#version 150
-#extension GL_ARB_explicit_attrib_location : enable
-
-layout(std140) uniform cb0 {
- mat4 MVP;
- int cw;
- int ch;
-};
-
-layout (location = 0) in vec4 POSITION;
-layout (location = 1) in vec2 TEXCOORD;
-layout (location = 2) in uint CHARACTER;
-
-out vec2 vTEXCOORD;
-
-void main() {
- vec4 pos = POSITION;
- int id = gl_InstanceID;
-
- // shift unit rectangle to character cell rectangle
- pos.xy += vec2(id % cw, (ch-1) - id / ch);
-
- // adjust unit texture coord to font cell rectangle
- float tx = (CHARACTER % uint(16));
- float ty = (CHARACTER / uint(16));
-
- vTEXCOORD =
- // scale to size of character in fonttexture
- TEXCOORD * vec2(1.0/16.0,1.0/16.0)
- // move to correct character
- + vec2(tx/16.0,ty/16.0)
- // offset to avoid cruft
- + vec2(1.0/256.0,1.0/256.0);
-
-
- pos = MVP * pos;
- // discard via clipping
- if (CHARACTER == uint(0)) pos.z = -1.1;
-
- gl_Position = pos;
-}
diff --git a/common/assets/textgrid.glsl b/common/assets/textgrid.glsl
@@ -0,0 +1,53 @@
+#version 150
+#extension GL_ARB_explicit_attrib_location : enable
+
+-- vertex
+
+layout(std140) uniform cb0 {
+ mat4 MVP;
+ int cw;
+ int ch;
+};
+
+layout (location = 0) in vec4 POSITION;
+layout (location = 1) in vec2 TEXCOORD;
+layout (location = 2) in uint CHARACTER;
+
+out vec2 vTEXCOORD;
+
+void main() {
+ vec4 pos = POSITION;
+ int id = gl_InstanceID;
+
+ // shift unit rectangle to character cell rectangle
+ pos.xy += vec2(id % cw, (ch-1) - id / ch);
+
+ // adjust unit texture coord to font cell rectangle
+ float tx = (CHARACTER % uint(16));
+ float ty = (CHARACTER / uint(16));
+
+ vTEXCOORD =
+ // scale to size of character in fonttexture
+ TEXCOORD * vec2(1.0/16.0,1.0/16.0)
+ // move to correct character
+ + vec2(tx/16.0,ty/16.0)
+ // offset to avoid cruft
+ + vec2(1.0/256.0,1.0/256.0);
+
+
+ pos = MVP * pos;
+ // discard via clipping
+ if (CHARACTER == uint(0)) pos.z = -1.1;
+
+ gl_Position = pos;
+}
+
+-- fragment
+
+uniform sampler2D uTexture0;
+
+in vec2 vTEXCOORD;
+
+void main() {
+ gl_FragColor = texture2D(uTexture0, vTEXCOORD);
+}
diff --git a/common/buffers.cc b/common/buffers.cc
@@ -0,0 +1,154 @@
+/* Copyright 2013 Brian Swetland <swetland@frotz.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#define GLUE_DEFINE_EXTENSIONS 1
+#endif
+
+#include "app.h"
+#include "util.h"
+
+#if 1
+#define CHECK() do {} while (0)
+#else
+const char *__gl_error_string(unsigned e) {
+ static char buf[16];
+ switch (e) {
+ case GL_INVALID_ENUM: return "INVALID ENUM";
+ case GL_INVALID_VALUE: return "INVALID VALUE";
+ case GL_INVALID_OPERATION: return "INVALID OPERATION";
+ case GL_INVALID_FRAMEBUFFER_OPERATION: return "INVALID FRAMEBUFFER OPERATION";
+ case GL_OUT_OF_MEMORY: return "OUT OF MEMORY";
+ default:
+ sprintf(buf,"0x%08x", e);
+ return buf;
+ }
+}
+
+void __check_gl_error(const char *fn, int line) {
+ unsigned e;
+ while ((e = glGetError()) != GL_NO_ERROR)
+ printx("%s:%d: GL ERROR %s\n", fn, line, __gl_error_string(e));
+}
+#define CHECK() __check_gl_error(__func__, __LINE__)
+#endif
+
+static unsigned vattr_type(unsigned type) {
+ switch (type) {
+ case SRC_INT8: return GL_BYTE;
+ case SRC_UINT8: return GL_UNSIGNED_BYTE;
+ case SRC_INT16: return GL_SHORT;
+ case SRC_UINT16: return GL_UNSIGNED_SHORT;
+ case SRC_INT32: return GL_INT;
+ case SRC_UINT32: return GL_UNSIGNED_INT;
+ case SRC_FLOAT: return GL_FLOAT;
+ default: return GL_FLOAT;
+ }
+}
+
+#define OFF2PTR(off) (((char*) NULL) + off)
+
+void VertexAttributes::init(VertexAttrDesc *desc, VertexBuffer **data, unsigned count) {
+ unsigned id = 0, n;
+ glGenVertexArrays(1, &vao);
+ CHECK();
+ glBindVertexArray(vao);
+ CHECK();
+ for (n = 0; n < count; n++) {
+ if (data && (data[n]->id != id)) {
+ id = data[n]->id;
+ glBindBuffer(GL_ARRAY_BUFFER, id);
+ CHECK();
+ }
+ switch (desc->dst_type) {
+ case DST_FLOAT:
+ glVertexAttribPointer(desc->index, desc->count,
+ vattr_type(desc->src_type), GL_FALSE, desc->stride,
+ OFF2PTR(desc->offset));
+ CHECK();
+ break;
+ case DST_NORMALIZED:
+ glVertexAttribPointer(desc->index, desc->count,
+ vattr_type(desc->src_type), GL_TRUE, desc->stride,
+ OFF2PTR(desc->offset));
+ CHECK();
+ break;
+ case DST_INTEGER:
+ glVertexAttribIPointer(desc->index, desc->count,
+ vattr_type(desc->src_type), desc->stride,
+ OFF2PTR(desc->offset));
+ CHECK();
+ break;
+ }
+ glVertexAttribDivisor(desc->index, desc->divisor);
+ CHECK();
+ glEnableVertexAttribArray(desc->index);
+ CHECK();
+ desc++;
+ }
+}
+
+
+void VertexBuffer::load(void *data, unsigned size) {
+ if (id == 0)
+ glGenBuffers(1, &id);
+ glBindBuffer(GL_ARRAY_BUFFER, id);
+ glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
+ sz = size;
+}
+
+void IndexBuffer::load(void *data, unsigned size) {
+ if (id == 0)
+ glGenBuffers(1, &id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
+ sz = size;
+}
+
+void UniformBuffer::load(void *data, unsigned size) {
+ if (id == 0)
+ glGenBuffers(1, &id);
+ glBindBuffer(GL_UNIFORM_BUFFER, id);
+ glBufferData(GL_UNIFORM_BUFFER, size, data, GL_STATIC_DRAW);
+ sz = size;
+}
+
+int Texture2D::load(const char *fn, int genmips) {
+ void *data;
+ unsigned dw, dh;
+ int r;
+ if (!(data = load_png_rgba(fn, &dw, &dh, 0)))
+ return error("cannot load '%s'", fn);
+ r = load(data, dw, dh, genmips);
+ free(data);
+ return r;
+}
+
+int Texture2D::load(void *data, unsigned w, unsigned h, int genmips) {
+ if (id == 0)
+ glGenTextures(1, &id);
+ glBindTexture(GL_TEXTURE_2D, id);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, data);
+ if (genmips)
+ glGenerateMipmap(GL_TEXTURE_2D);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ return 0;
+}
+
diff --git a/common/glapp.cc b/common/glapp.cc
@@ -23,31 +23,6 @@
#include "app.h"
#include "util.h"
-#if 1
-#define CHECK() do {} while (0)
-#else
-const char *__gl_error_string(unsigned e) {
- static char buf[16];
- switch (e) {
- case GL_INVALID_ENUM: return "INVALID ENUM";
- case GL_INVALID_VALUE: return "INVALID VALUE";
- case GL_INVALID_OPERATION: return "INVALID OPERATION";
- case GL_INVALID_FRAMEBUFFER_OPERATION: return "INVALID FRAMEBUFFER OPERATION";
- case GL_OUT_OF_MEMORY: return "OUT OF MEMORY";
- default:
- sprintf(buf,"0x%08x", e);
- return buf;
- }
-}
-
-void __check_gl_error(const char *fn, int line) {
- unsigned e;
- while ((e = glGetError()) != GL_NO_ERROR)
- printx("%s:%d: GL ERROR %s\n", fn, line, __gl_error_string(e));
-}
-#define CHECK() __check_gl_error(__func__, __LINE__)
-#endif
-
#ifdef _WIN32
static void gl_map_functions(void) {
int n;
@@ -190,217 +165,3 @@ int main(int argc, char **argv) {
return 0;
}
-static unsigned vattr_type(unsigned type) {
- switch (type) {
- case SRC_INT8: return GL_BYTE;
- case SRC_UINT8: return GL_UNSIGNED_BYTE;
- case SRC_INT16: return GL_SHORT;
- case SRC_UINT16: return GL_UNSIGNED_SHORT;
- case SRC_INT32: return GL_INT;
- case SRC_UINT32: return GL_UNSIGNED_INT;
- case SRC_FLOAT: return GL_FLOAT;
- default: return GL_FLOAT;
- }
-}
-
-#define OFF2PTR(off) (((char*) NULL) + off)
-
-void VertexAttributes::init(VertexAttrDesc *desc, VertexBuffer **data, unsigned count) {
- unsigned id = 0, n;
- glGenVertexArrays(1, &vao);
- CHECK();
- glBindVertexArray(vao);
- CHECK();
- for (n = 0; n < count; n++) {
- if (data && (data[n]->id != id)) {
- id = data[n]->id;
- glBindBuffer(GL_ARRAY_BUFFER, id);
- CHECK();
- }
- switch (desc->dst_type) {
- case DST_FLOAT:
- glVertexAttribPointer(desc->index, desc->count,
- vattr_type(desc->src_type), GL_FALSE, desc->stride,
- OFF2PTR(desc->offset));
- CHECK();
- break;
- case DST_NORMALIZED:
- glVertexAttribPointer(desc->index, desc->count,
- vattr_type(desc->src_type), GL_TRUE, desc->stride,
- OFF2PTR(desc->offset));
- CHECK();
- break;
- case DST_INTEGER:
- glVertexAttribIPointer(desc->index, desc->count,
- vattr_type(desc->src_type), desc->stride,
- OFF2PTR(desc->offset));
- CHECK();
- break;
- }
- glVertexAttribDivisor(desc->index, desc->divisor);
- CHECK();
- glEnableVertexAttribArray(desc->index);
- CHECK();
- desc++;
- }
-}
-
-
-void VertexBuffer::load(void *data, unsigned size) {
- if (id == 0)
- glGenBuffers(1, &id);
- glBindBuffer(GL_ARRAY_BUFFER, id);
- glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
- sz = size;
-}
-
-void IndexBuffer::load(void *data, unsigned size) {
- if (id == 0)
- glGenBuffers(1, &id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
- sz = size;
-}
-
-void UniformBuffer::load(void *data, unsigned size) {
- if (id == 0)
- glGenBuffers(1, &id);
- glBindBuffer(GL_UNIFORM_BUFFER, id);
- glBufferData(GL_UNIFORM_BUFFER, size, data, GL_STATIC_DRAW);
- sz = size;
-}
-
-static void dump_compile_error(unsigned id) {
- int len;
- char *buf;
- glGetShaderiv(id, GL_INFO_LOG_LENGTH, &len);
- buf = (char*) malloc(len + 1);
- if (buf != 0) {
- memset(buf, 0, len);
- glGetShaderInfoLog(id, len, &len, buf);
- buf[len] = 0;
- fprintf(stderr,"-- shader compiler error --\n%s\n", buf);
- free(buf);
- }
-}
-
-static void dump_link_error(unsigned id) {
- int len;
- char *buf;
- glGetProgramiv(id, GL_INFO_LOG_LENGTH, &len);
- buf = (char*) malloc(len + 1);
- if (buf != 0) {
- memset(buf, 0, len);
- glGetProgramInfoLog(id, len, &len, buf);
- buf[len] = 0;
- fprintf(stderr,"-- shader link error --\n%s\n", buf);
- free(buf);
- }
-}
-
-int Program::link(VertexShader *vs, PixelShader *ps) {
- return link(vs, NULL, ps);
-}
-
-int Program::link(VertexShader *vs, GeometryShader *gs, PixelShader *ps) {
- unsigned n;
- int r;
- n = glCreateProgram();
- glAttachShader(n, vs->id);
- if (gs)
- glAttachShader(n, gs->id);
- glAttachShader(n, ps->id);
- glLinkProgram(n);
- glGetProgramiv(n, GL_LINK_STATUS, &r);
- if (!r) {
- dump_link_error(n);
- glDeleteProgram(n);
- return error("shader program link error");
- }
- if (id)
- glDeleteProgram(id);
- id = n;
- return 0;
-}
-
-int Program::load(const char *vsfn, const char *gsfn, const char *psfn) {
- VertexShader vs;
- GeometryShader gs;
- PixelShader ps;
- if (vs.load(vsfn))
- return -1;
- if (gs.load(gsfn))
- return -1;
- if (ps.load(psfn))
- return -1;
- return link(&vs, &gs, &ps);
-}
-
-int Program::load(const char *vsfn, const char *psfn) {
- VertexShader vs;
- PixelShader ps;
- if (vs.load(vsfn))
- return -1;
- if (ps.load(psfn))
- return -1;
- return link(&vs, &ps);
-}
-
-static int _load_shader(unsigned *out, const char *fn, unsigned type) {
- void *data;
- unsigned sz;
- unsigned id;
- int r;
- if (!(data = load_file(fn, &sz)))
- return error("cannot load shader source '%s'", fn);
- id = glCreateShader(type);
- glShaderSource(id, 1, (const char **) &data, NULL);
- glCompileShader(id);
- glGetShaderiv(id, GL_COMPILE_STATUS, &r);
- if (!r) {
- dump_compile_error(id);
- glDeleteShader(id);
- return error("shader '%s' compile error", fn);
- }
- if (*out)
- glDeleteShader(*out);
- *out = id;
- return 0;
-}
-
-int VertexShader::load(const char *fn) {
- return _load_shader(&id, fn, GL_VERTEX_SHADER);
-}
-
-int PixelShader::load(const char *fn) {
- return _load_shader(&id, fn, GL_FRAGMENT_SHADER);
-}
-
-int GeometryShader::load(const char *fn) {
- return _load_shader(&id, fn, GL_GEOMETRY_SHADER);
-}
-
-int Texture2D::load(const char *fn, int genmips) {
- void *data;
- unsigned dw, dh;
- int r;
- if (!(data = load_png_rgba(fn, &dw, &dh, 0)))
- return error("cannot load '%s'", fn);
- r = load(data, dw, dh, genmips);
- free(data);
- return r;
-}
-
-int Texture2D::load(void *data, unsigned w, unsigned h, int genmips) {
- if (id == 0)
- glGenTextures(1, &id);
- glBindTexture(GL_TEXTURE_2D, id);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, data);
- if (genmips)
- glGenerateMipmap(GL_TEXTURE_2D);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- return 0;
-}
-
diff --git a/common/module.mk b/common/module.mk
@@ -1,6 +1,8 @@
M_NAME := common
M_OBJS := glapp.o
+M_OBJS += shaders.o
+M_OBJS += buffers.o
M_OBJS += io.o
M_OBJS += loadfile.o
M_OBJS += loadpng.o
diff --git a/common/shaders.cc b/common/shaders.cc
@@ -0,0 +1,288 @@
+/* Copyright 2013 Brian Swetland <swetland@frotz.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#define GLUE_DEFINE_EXTENSIONS 1
+#endif
+
+#include "app.h"
+#include "util.h"
+
+static void dump_compile_error(unsigned id) {
+ int len;
+ char *buf;
+ glGetShaderiv(id, GL_INFO_LOG_LENGTH, &len);
+ buf = (char*) malloc(len + 1);
+ if (buf != 0) {
+ memset(buf, 0, len);
+ glGetShaderInfoLog(id, len, &len, buf);
+ buf[len] = 0;
+ fprintf(stderr,"-- shader compiler error --\n%s\n", buf);
+ free(buf);
+ }
+}
+
+static void dump_link_error(unsigned id) {
+ int len;
+ char *buf;
+ glGetProgramiv(id, GL_INFO_LOG_LENGTH, &len);
+ buf = (char*) malloc(len + 1);
+ if (buf != 0) {
+ memset(buf, 0, len);
+ glGetProgramInfoLog(id, len, &len, buf);
+ buf[len] = 0;
+ fprintf(stderr,"-- shader link error --\n%s\n", buf);
+ free(buf);
+ }
+}
+
+int Program::link(VertexShader *vs, PixelShader *ps) {
+ return link(vs, NULL, ps);
+}
+
+int Program::link(VertexShader *vs, GeometryShader *gs, PixelShader *ps) {
+ unsigned n;
+ int r;
+ n = glCreateProgram();
+ glAttachShader(n, vs->id);
+ if (gs)
+ glAttachShader(n, gs->id);
+ glAttachShader(n, ps->id);
+ glLinkProgram(n);
+ glGetProgramiv(n, GL_LINK_STATUS, &r);
+ if (!r) {
+ dump_link_error(n);
+ glDeleteProgram(n);
+ return error("shader program link error");
+ }
+ if (id)
+ glDeleteProgram(id);
+ id = n;
+ return 0;
+}
+
+int Program::load(const char *vsfn, const char *gsfn, const char *psfn) {
+ VertexShader vs;
+ GeometryShader gs;
+ PixelShader ps;
+ if (vs.load(vsfn))
+ return -1;
+ if (gs.load(gsfn))
+ return -1;
+ if (ps.load(psfn))
+ return -1;
+ return link(&vs, &gs, &ps);
+}
+
+int Program::load(const char *vsfn, const char *psfn) {
+ VertexShader vs;
+ PixelShader ps;
+ if (vs.load(vsfn))
+ return -1;
+ if (ps.load(psfn))
+ return -1;
+ return link(&vs, &ps);
+}
+
+struct section {
+ section *next;
+ unsigned lineno;
+ const char *name;
+ const char *str;
+ unsigned len;
+};
+
+struct source {
+ source *next;
+ const char *name;
+ section *sections;
+ section common;
+ const char *str;
+ unsigned len;
+};
+
+static source *source_cache = NULL;
+
+static struct source *load_shader_source(const char *fn) {
+ source *src;
+ section *part;
+ unsigned lineno = 1;
+ unsigned len;
+ char *x, *end, *tmp;
+ char buf[1024];
+
+ x = (char*) strchr(fn, '.');
+ if (x) {
+ memcpy(buf, fn, x-fn);
+ strcpy(buf + (x - fn), ".glsl");
+ } else {
+ sprintf(buf, "%s.glsl", fn);
+ }
+
+ for (src = source_cache; src; src = src->next)
+ if (!strcmp(buf, src->name))
+ return src;
+
+ src = new source;
+ src->sections = NULL;
+ part = &src->common;
+ part->name = "$common$";
+
+ x = (char*) load_file(buf, &len);
+ if (!x) {
+ delete src;
+ return NULL;
+ }
+ src->str = x;
+ src->len = len;
+
+ part->str = x;
+ part->lineno = lineno;
+
+ end = x + len;
+ while (x < end) {
+ if (*x++ != '\n')
+ continue;
+ lineno++;
+ if ((end - x) < 3)
+ continue;
+ if ((x[0] != '-') || (x[1] != '-'))
+ continue;
+ part->len = x - part->str;
+ part->next = src->sections;
+ src->sections = part;
+ *x = 0;
+ x += 2;
+
+ part = new section;
+ part->next = NULL;
+ part->name = "";
+
+ tmp = x;
+ while (x < end) {
+ if (*x == '\n') {
+ *x = 0;
+ while ((tmp < x) && (*tmp <= ' '))
+ tmp++;
+ part->name = tmp;
+ while (tmp < x) {
+ if (*tmp <= ' ')
+ *tmp = 0;
+ tmp++;
+ }
+ x++;
+ break;
+ }
+ x++;
+ }
+
+ lineno++;
+ part->str = x;
+ part->lineno = lineno;
+ }
+
+ part->len = x - part->str;
+ part->next = src->sections;
+ src->sections = part;
+
+#if 0
+ printx("[ source '%s' %d lines ]\n", buf, lineno);
+ for (part = src->sections; part; part = part->next)
+ printx(" [ section '%s' %d bytes @ %d]\n",
+ part->name, part->len, part->lineno);
+#endif
+
+ src->name = strdup(buf);
+ src->next = source_cache;
+ source_cache = src;
+ return src;
+}
+
+static int compile_shader_source(source *src, const char *name, unsigned id) {
+ char misc[128];
+ const char *data[3];
+ int size[3];
+ section *part;
+
+ for (part = src->sections; part; part = part->next) {
+ if (!strcmp(name, part->name)) {
+ printx("Loaded shader section '%s' from '%s'\n",
+ part->name, src->name);
+ sprintf(misc, "#line %d\n", part->lineno - 1);
+ data[0] = src->common.str;
+ size[0] = src->common.len;
+ data[1] = misc;
+ size[1] = strlen(misc);
+ data[2] = part->str;
+ size[2] = part->len;
+#if 0
+ printf("----------------\n%s%s%s\n-------------\n",
+ data[0], data[1], data[2]);
+#endif
+ glShaderSource(id, 3, data, size);
+ return 0;
+ }
+ }
+ return error("cannot find section '%s'", name);
+}
+
+static int _load_shader(unsigned *out, const char *fn, unsigned type) {
+ unsigned id;
+ source *src;
+ const char *x;
+ int r;
+
+ x = strchr(fn, '.');
+ if (x == 0)
+ return error("shader source '%s' has no section", fn);
+ x++;
+
+ src = load_shader_source(fn);
+ if (src == NULL)
+ return error("cannot load shader source '%s'", fn);
+
+ id = glCreateShader(type);
+ if (compile_shader_source(src, x, id)) {
+ glDeleteShader(id);
+ return -1;
+ }
+ glCompileShader(id);
+ glGetShaderiv(id, GL_COMPILE_STATUS, &r);
+ if (!r) {
+ dump_compile_error(id);
+ glDeleteShader(id);
+ return error("shader '%s' compile error", fn);
+ }
+ if (*out)
+ glDeleteShader(*out);
+ *out = id;
+ return 0;
+}
+
+int VertexShader::load(const char *fn) {
+ return _load_shader(&id, fn, GL_VERTEX_SHADER);
+}
+
+int PixelShader::load(const char *fn) {
+ return _load_shader(&id, fn, GL_FRAGMENT_SHADER);
+}
+
+int GeometryShader::load(const char *fn) {
+ return _load_shader(&id, fn, GL_GEOMETRY_SHADER);
+}
+
diff --git a/common/textgrid.cc b/common/textgrid.cc
@@ -76,9 +76,9 @@ int TextGrid::init(App *a, int w, int h) {
if (texture.load("font-vincent-8x8.png", 0))
return -1;
- if (ps.load("TextPS.glsl"))
+ if (ps.load("textgrid.fragment"))
return -1;
- if (vs.load("TextVS.glsl"))
+ if (vs.load("textgrid.vertex"))
return -1;
if (pgm.link(&vs, &ps))
return -1;
diff --git a/hello/assets/SimplePS.glsl b/hello/assets/SimplePS.glsl
@@ -1,9 +0,0 @@
-#version 150
-
-varying vec2 vTEXCOORD;
-varying float vDIFFUSE;
-
-void main() {
- vec4 c = vec4(1.0, 0.0, 0.0, 1.0);
- gl_FragColor = c * 0.25 + c * vDIFFUSE;
-}
diff --git a/hello/assets/SimpleVS.glsl b/hello/assets/SimpleVS.glsl
@@ -1,32 +0,0 @@
-#version 150
-#extension GL_ARB_explicit_attrib_location : enable
-
-layout(std140) uniform cb0 {
- mat4 MVP;
- mat4 MV;
-};
-
-layout(location = 0) in vec4 POSITION;
-layout(location = 1) in vec4 NORMAL;
-layout(location = 2) in vec2 TEXCOORD;
-
-in vec4 LOCATION;
-
-out vec2 vTEXCOORD;
-out float vDIFFUSE;
-
-void main() {
- vec4 pos = POSITION;
-
- pos.xyz += LOCATION.xyz * vec3(127,127,127);
-
- vec3 mvPosition = (MV * pos).xyz;
- vec3 mvNormal = (MV * vec4(NORMAL.xyz,0.0)).xyz;
-
- vec3 lightVec = normalize(vec3(10,20,25) - mvPosition);
- float diffuse = max(dot(mvNormal, lightVec), 0.0);
-
- gl_Position = MVP * pos; //POSITION;
- vTEXCOORD = TEXCOORD;
- vDIFFUSE = diffuse;
-}
diff --git a/hello/assets/simple.glsl b/hello/assets/simple.glsl
@@ -0,0 +1,44 @@
+#version 150
+#extension GL_ARB_explicit_attrib_location : enable
+
+-- vertex
+
+layout(std140) uniform cb0 {
+ mat4 MVP;
+ mat4 MV;
+};
+
+layout(location = 0) in vec4 POSITION;
+layout(location = 1) in vec4 NORMAL;
+layout(location = 2) in vec2 TEXCOORD;
+
+in vec4 LOCATION;
+
+out vec2 vTEXCOORD;
+out float vDIFFUSE;
+
+void main() {
+ vec4 pos = POSITION;
+
+ pos.xyz += LOCATION.xyz * vec3(127,127,127);
+
+ vec3 mvPosition = (MV * pos).xyz;
+ vec3 mvNormal = (MV * vec4(NORMAL.xyz,0.0)).xyz;
+
+ vec3 lightVec = normalize(vec3(10,20,25) - mvPosition);
+ float diffuse = max(dot(mvNormal, lightVec), 0.0);
+
+ gl_Position = MVP * pos; //POSITION;
+ vTEXCOORD = TEXCOORD;
+ vDIFFUSE = diffuse;
+}
+
+-- fragment
+
+varying vec2 vTEXCOORD;
+varying float vDIFFUSE;
+
+void main() {
+ vec4 c = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = c * 0.25 + c * vDIFFUSE;
+}
diff --git a/hello/hello.cc b/hello/hello.cc
@@ -119,9 +119,9 @@ int TestApp::init(void) {
VertexBuffer *data[] = {
&vbuf, &vbuf, &vbuf, &lbuf,
};
- if (ps.load("SimplePS.glsl"))
+ if (ps.load("simple.fragment"))
return -1;
- if (vs.load("SimpleVS.glsl"))
+ if (vs.load("simple.vertex"))
return -1;
if (pgm.link(&vs, &ps))
return -1;
diff --git a/test/assets/TestPS.glsl b/test/assets/TestPS.glsl
@@ -1,9 +0,0 @@
-#version 150
-
-in vec2 vTEXCOORD;
-in float vDIFFUSE;
-
-void main() {
- vec4 c = vec4(1.0, 0.0, 0.0, 1.0);
- gl_FragColor = c * 0.25 + c * vDIFFUSE;
-}
diff --git a/test/assets/TestVS.glsl b/test/assets/TestVS.glsl
@@ -1,30 +0,0 @@
-#version 150
-#extension GL_ARB_explicit_attrib_location : enable
-
-//uniform mat4 MVP0;
-
-layout(std140) uniform cb0 {
- mat4 MVP;
- mat4 MV;
-};
-
-layout (location = 0) in vec4 POSITION;
-layout (location = 1) in vec4 NORMAL;
-layout (location = 2) in vec2 TEXCOORD;
-
-out vec2 vTEXCOORD;
-out float vDIFFUSE;
-
-void main() {
- vec4 pos = POSITION;
-
- vec3 mvPosition = (MV * pos).xyz;
- vec3 mvNormal = (MV * vec4(NORMAL.xyz,0.0)).xyz;
-
- vec3 lightVec = normalize(vec3(10,20,25) - mvPosition);
- float diffuse = max(dot(mvNormal, lightVec), 0.0);
-
- gl_Position = MVP * POSITION;
- vTEXCOORD = TEXCOORD;
- vDIFFUSE = diffuse;
-}
diff --git a/test/assets/simple.glsl b/test/assets/simple.glsl
@@ -0,0 +1,41 @@
+#version 150
+#extension GL_ARB_explicit_attrib_location : enable
+
+-- vertex
+
+layout(std140) uniform cb0 {
+ mat4 MVP;
+ mat4 MV;
+};
+
+layout (location = 0) in vec4 POSITION;
+layout (location = 1) in vec4 NORMAL;
+layout (location = 2) in vec2 TEXCOORD;
+
+out vec2 vTEXCOORD;
+out float vDIFFUSE;
+
+void main() {
+ vec4 pos = POSITION;
+
+ vec3 mvPosition = (MV * pos).xyz;
+ vec3 mvNormal = (MV * vec4(NORMAL.xyz,0.0)).xyz;
+
+ vec3 lightVec = normalize(vec3(10,20,25) - mvPosition);
+ float diffuse = max(dot(mvNormal, lightVec), 0.0);
+
+ gl_Position = MVP * POSITION;
+ vTEXCOORD = TEXCOORD;
+ vDIFFUSE = diffuse;
+}
+
+-- fragment
+
+in vec2 vTEXCOORD;
+in float vDIFFUSE;
+
+void main() {
+ vec4 c = vec4(1.0, 0.0, 0.0, 1.0);
+ gl_FragColor = c * 0.25 + c * vDIFFUSE;
+}
+
diff --git a/test/test.cc b/test/test.cc
@@ -54,8 +54,8 @@ private:
int vs_mtime;
};
-static const char *psfn = "TestPS.glsl";
-static const char *vsfn = "TestVS.glsl";
+static const char *psfn = "simple.fragment";
+static const char *vsfn = "simple.vertex";
TestApp::TestApp() : App(), r(0.0) {
}
@@ -96,6 +96,7 @@ void TestApp::render(void) {
unsigned stride, offset;
int t;
+#if 0
t = file_get_mtime(psfn);
if (t != ps_mtime) {
printx("ps change!\n");
@@ -110,7 +111,7 @@ void TestApp::render(void) {
vs_mtime = t;
pgm.link(&vs, &ps);
}
-
+#endif
struct {
mat4 mvp;
mat4 mv;