commit 5feed92ead4dbcecbe9eeeb78269c1bfda1d095d
parent 78477aee9aab58fd257c5ccbe5b381d3dfd59a03
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 16 Jun 2013 22:48:58 -0700
rework the helper code to be much more GL-centric
Diffstat:
14 files changed, 271 insertions(+), 507 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -8,4 +8,5 @@ x64
Debug
Release
OpenGL-Debug
-*.opensdf
-\ No newline at end of file
+*.opensdf
+out
diff --git a/common/app.h b/common/app.h
@@ -32,68 +32,52 @@
#include <math.h>
enum {
- FMT_32x4_FLOAT = 1,
- FMT_32x3_FLOAT = 2,
- FMT_32x2_FLOAT = 3,
- FMT_32x1_FLOAT = 4,
-
- FMT_8x4_SNORM = 5,
-
- FMT_8x4_UNORM = 6,
- FMT_8x2_UNORM = 7,
- FMT_8x1_UNORM = 8,
-
- FMT_8x4_UINT = 9,
- FMT_8x2_UINT = 10,
- FMT_8x1_UINT = 11,
+ SRC_INT8,
+ SRC_UINT8,
+ SRC_INT16,
+ SRC_UINT16,
+ SRC_INT32,
+ SRC_UINT32,
+ SRC_FLOAT,
};
enum {
- VERTEX_DATA = 1,
- INSTANCE_DATA = 2,
-};
-
-struct AttribInfo {
- const char *name;
- unsigned nidx;
- unsigned format;
- unsigned slot;
- unsigned offset;
- unsigned type;
- unsigned divisor;
+ DST_FLOAT,
+ DST_NORMALIZED,
+ DST_INTEGER,
};
-
-struct GLAttrInfo {
-#define KIND_ATTRIB_POINTER 0
-#define KIND_ATTRIB_IPOINTER 1
- int kind;
-
-/* which VBO {0...} to associate with */
- int vidx;
-
-/* arguments for VertexAttrib[I]Pointer() */
- int index;
- int size;
- int type;
- int normalized;
- int pointer;
- int divisor;
+struct VertexAttrDesc {
+ unsigned index;
+ unsigned src_type; // data type
+ unsigned dst_type; // data type
+ unsigned count; // number of components (1-4)
+ unsigned offset; // offset of first attr
+ unsigned stride; // offset from first attr to next
+ unsigned divisor; // how often to step forward
+ unsigned unused;
};
struct PixelShader {
- unsigned ps;
- PixelShader() : ps(0) {};
- ~PixelShader() { if (ps) glDeleteShader(ps); };
+ unsigned id;
+ PixelShader() : id(0) {};
+ ~PixelShader() { if (id) glDeleteShader(id); };
+ int load(const char *fn);
};
struct VertexShader {
- unsigned vs;
- GLAttrInfo *ai;
- AttribInfo *info;
- unsigned count;
- VertexShader() : vs(0), ai(NULL), info(NULL), count(0) {};
- ~VertexShader() { if (vs) { glDeleteShader(vs); free(ai); } };
+ unsigned id;
+ VertexShader() : id(0) {};
+ ~VertexShader() { if (id) { glDeleteShader(id); } };
+ int load(const char *fn);
+};
+
+struct Program {
+ unsigned id;
+ Program() : id(0) {};
+ ~Program() { if (id) { glDeleteProgram(id); } };
+ void use(void) { glUseProgram(id); }
+ int link(VertexShader *vs, PixelShader *ps);
};
struct Texture2D {
@@ -103,37 +87,40 @@ struct Texture2D {
};
struct UniformBuffer {
- unsigned buf;
+ unsigned id;
unsigned sz;
- UniformBuffer() : buf(0) {};
- ~UniformBuffer() { if (buf) glDeleteBuffers(1, &buf); };
+ UniformBuffer() : id(0) {};
+ ~UniformBuffer() { if (id) glDeleteBuffers(1, &id); };
+ void use(unsigned index) { glBindBufferBase(GL_UNIFORM_BUFFER, index, id); };
+ void load(void *data, unsigned size);
};
+// TODO: when do we glUniformBLockBinding() ?
+
struct VertexBuffer {
- unsigned buf;
+ unsigned id;
unsigned sz;
- VertexBuffer() : buf(0) {};
- ~VertexBuffer() { if (buf) glDeleteBuffers(1, &buf); };
+ VertexBuffer() : id(0) {};
+ ~VertexBuffer() { if (id) glDeleteBuffers(1, &id); };
+ void use(void) { glBindBuffer(GL_ARRAY_BUFFER, id); };
+ void load(void *data, unsigned size);
};
struct IndexBuffer {
- unsigned buf;
+ unsigned id;
unsigned sz;
- IndexBuffer() : buf(0) {};
- ~IndexBuffer() { if (buf) glDeleteBuffers(1, &buf); };
+ IndexBuffer() : id(0) {};
+ ~IndexBuffer() { if (id) glDeleteBuffers(1, &id); };
+ void use(void) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); };
+ void load(void *data, unsigned size);
};
-struct InputConfiguration {
- PixelShader *ps;
- VertexShader *vs;
+struct VertexAttributes {
unsigned vao;
- unsigned pgm;
- VertexBuffer *vbuf[16];
- UniformBuffer *ubuf[16];
- IndexBuffer *ibuf;
- InputConfiguration() : ps(NULL), vs(NULL), vao(0), pgm(0), ibuf(NULL) {
- memset(vbuf, 0, sizeof(vbuf)); memset(ubuf, 0, sizeof(ubuf)); };
- ~InputConfiguration() { if (vao) glDeleteVertexArrays(1, &vao); if (pgm) glDeleteProgram(pgm); };
+ VertexAttributes() : vao(0) {};
+ ~VertexAttributes() { /* todo */ };
+ void init(VertexAttrDesc *desc, VertexBuffer **data, unsigned count);
+ void use(void) { glBindVertexArray(vao); };
};
class App {
@@ -149,37 +136,12 @@ public:
int start(void);
void handleEvents(void);
- // TODO: move away from D3D10_INPUT...
- int compileShader(VertexShader *vs, const char *fn,
- void *data, unsigned len, int raw,
- AttribInfo *layout, unsigned lcount);
- int compileShader(PixelShader *ps, const char *fn,
- void *data, unsigned len, int raw);
- int loadShader(VertexShader *vs, const char *fn,
- AttribInfo *layout, unsigned lcount);
- int loadShader(PixelShader *ps, const char *fn);
-
int loadTextureRGBA(Texture2D *tex, const char *fn, int genmips);
int createTextureRGBA(Texture2D *tex, void *data, unsigned w, unsigned h, int genmips);
- int initConfig(InputConfiguration *ic, VertexShader *vs, PixelShader *ps);
- int initBuffer(VertexBuffer *vb, void *data, int sz);
- int initBuffer(IndexBuffer *ib, void *data, int sz);
- int initBuffer(UniformBuffer *ub, void *data, int sz);
-
- void updateBuffer(VertexBuffer *vb, void *data);
- void updateBuffer(IndexBuffer *ib, void *data);
- void updateBuffer(UniformBuffer *ub, void *data);
-
- void useConfig(InputConfiguration *ic);
- void useBuffer(VertexBuffer *vb, int slot, unsigned stride, unsigned offset);
- void useBuffer(IndexBuffer *ib);
- void useBuffer(UniformBuffer *ub, int slot);
void useTexture(Texture2D *tex, int slot);
- void drawIndexedInstanced(unsigned numindices, unsigned numinstances);
- void drawInstanced(unsigned numvertices, unsigned numinstances);
- void drawIndexed(unsigned numindices);
void setBlend(int enable);
+
protected:
int width;
int height;
@@ -193,8 +155,6 @@ protected:
/* keys down */
unsigned char keystate[256];
- InputConfiguration *ic;
-
private:
int _vsync;
SDL_Window *win;
diff --git a/common/assets/TextPS.glsl b/common/assets/TextPS.glsl
@@ -1,3 +1,4 @@
+#version 150
uniform sampler2D uTexture0;
diff --git a/common/assets/TextVS.glsl b/common/assets/TextVS.glsl
@@ -1,4 +1,5 @@
-#version 330
+#version 150
+#extension GL_ARB_explicit_attrib_location : enable
layout(std140) uniform cb0 {
mat4 MVP;
@@ -6,14 +7,12 @@ layout(std140) uniform cb0 {
int ch;
};
-
-in vec4 POSITION;
-in vec2 TEXCOORD;
-in uint CHARACTER;
+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;
diff --git a/common/glapp.cc b/common/glapp.cc
@@ -190,135 +190,87 @@ 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 config_attr_info(GLAttrInfo *ai, unsigned count, int vidx, unsigned stride) {
- unsigned n;
- for (n = 0; n < count; n++, ai++) {
- if (ai->vidx != vidx) continue;
- if (ai->index < 0)
- continue;
- if (ai->kind == KIND_ATTRIB_POINTER) {
- printf("VTX ATR idx=%d sz=%d type=%d norm=%d stride=%d off=%d\n",
- ai->index, ai->size, ai->type, ai->normalized, stride, ai->pointer);
- glVertexAttribPointer(ai->index, ai->size, ai->type,
- ai->normalized, stride, OFF2PTR(ai->pointer));
- CHECK();
- } else {
- printf("VTX ATR idx=%d sz=%d type=%d stride=%d off=%d\n",
- ai->index, ai->size, ai->type, stride, ai->pointer);
- glVertexAttribIPointer(ai->index, ai->size, ai->type,
- stride, OFF2PTR(ai->pointer));
+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();
}
- if (ai->divisor) {
- glVertexAttribDivisor(ai->index, ai->divisor);
+ 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;
}
- glEnableVertexAttribArray(ai->index);
+ glVertexAttribDivisor(desc->index, desc->divisor);
+ CHECK();
+ glEnableVertexAttribArray(desc->index);
+ CHECK();
+ desc++;
}
}
-void bind_attr_info(GLAttrInfo *ai, AttribInfo *in, unsigned count, unsigned pgm) {
- for (int n = 0; n < count; n++, ai++, in++) {
- ai->index = glGetAttribLocation(pgm, in->name);
- if (ai->index < 0)
- printx("WARNING: cannot find attribute '%s' (late)\n", in->name);
- }
+
+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;
}
-/* map attribute names to indices, and adapt layout parameters for GL */
-int setup_attr_info(GLAttrInfo **out, AttribInfo *in, unsigned count, unsigned pgm) {
- GLAttrInfo *ai = (GLAttrInfo*) malloc(sizeof(GLAttrInfo) * count);
- unsigned n;
- if (!ai)
- return error("Out of Memory");
- memset(ai, 0, sizeof(GLAttrInfo) * count);
- for (n = 0; n < count; n++, in++) {
- ai[n].vidx = in->slot;
- ai[n].index = glGetAttribLocation(pgm, in->name);
- if (ai[n].index < 0)
- printx("WARNING: cannot find attribute '%s' (early)\n", in->name);
- ai[n].pointer = in->offset;
- ai[n].divisor = in->divisor;
- switch (in->format) {
- case FMT_32x4_FLOAT:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 4;
- ai[n].type = GL_FLOAT;
- ai[n].normalized = GL_FALSE;
- break;
- case FMT_32x3_FLOAT:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 3;
- ai[n].type = GL_FLOAT;
- ai[n].normalized = GL_FALSE;
- break;
- case FMT_32x2_FLOAT:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 2;
- ai[n].type = GL_FLOAT;
- ai[n].normalized = GL_FALSE;
- break;
- case FMT_32x1_FLOAT:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 1;
- ai[n].type = GL_FLOAT;
- ai[n].normalized = GL_FALSE;
- break;
- case FMT_8x4_SNORM:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 4;
- ai[n].type = GL_BYTE;
- ai[n].normalized = GL_TRUE;
- break;
- case FMT_8x4_UNORM:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 4;
- ai[n].type = GL_UNSIGNED_BYTE;
- ai[n].normalized = GL_TRUE;
- break;
- case FMT_8x2_UNORM:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 2;
- ai[n].type = GL_UNSIGNED_BYTE;
- ai[n].normalized = GL_TRUE;
- break;
- case FMT_8x1_UNORM:
- ai[n].kind = KIND_ATTRIB_POINTER;
- ai[n].size = 1;
- ai[n].type = GL_UNSIGNED_BYTE;
- ai[n].normalized = GL_TRUE;
- break;
- case FMT_8x4_UINT:
- ai[n].kind = KIND_ATTRIB_IPOINTER;
- ai[n].size = 4;
- ai[n].type = GL_BYTE;
- ai[n].normalized = GL_FALSE;
- break;
- case FMT_8x2_UINT:
- ai[n].kind = KIND_ATTRIB_IPOINTER;
- ai[n].size = 2;
- ai[n].type = GL_BYTE;
- ai[n].normalized = GL_FALSE;
- break;
- case FMT_8x1_UINT:
- ai[n].kind = KIND_ATTRIB_IPOINTER;
- ai[n].size = 1;
- ai[n].type = GL_BYTE;
- ai[n].normalized = GL_FALSE;
- break;
- default:
- return error("unknown format %d\n", in->format);
- }
- }
- *out = ai;
- return 0;
-};
+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 dump_compile_error(unsigned id) {
+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);
@@ -332,7 +284,7 @@ void dump_compile_error(unsigned id) {
}
}
-void dump_link_error(unsigned id) {
+static void dump_link_error(unsigned id) {
int len;
char *buf;
glGetProgramiv(id, GL_INFO_LOG_LENGTH, &len);
@@ -346,123 +298,53 @@ void dump_link_error(unsigned id) {
}
}
-int App::compileShader(VertexShader *vs, const char *fn,
- void *data, unsigned len, int raw,
- AttribInfo *layout, unsigned lcount) {
-
- unsigned pgm, id;
+int Program::link(VertexShader *vs, PixelShader *ps) {
+ unsigned n;
int r;
-
- id = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(id, 1, (const char**) &data, NULL);
- glCompileShader(id);
- glGetShaderiv(id, GL_COMPILE_STATUS, &r);
+ n = glCreateProgram();
+ glAttachShader(n, vs->id);
+ glAttachShader(n, ps->id);
+ glLinkProgram(n);
+ glGetProgramiv(n, GL_LINK_STATUS, &r);
if (!r) {
- dump_compile_error(id);
- glDeleteShader(id);
- return error("vertex shader '%s' compile error" ,fn);
+ dump_link_error(n);
+ glDeleteProgram(n);
+ return error("shader program link error");
}
- fprintf(stderr,"COMPILE %d\n", r);
-
- /* we need to compile a program to lookup the indices... */
- pgm = glCreateProgram();
- glAttachShader(pgm, id);
- glLinkProgram(pgm);
- glGetProgramiv(pgm, GL_LINK_STATUS, &r);
- if (!r) {
- dump_link_error(id);
- glDeleteProgram(pgm);
- glDeleteShader(id);
- return error("vertex shader '%s' link error", fn);
- }
-
- r = setup_attr_info(&vs->ai, layout, lcount, pgm);
- glDeleteProgram(pgm);
- if (r < 0) {
- glDeleteShader(id);
- return error("vertex shader '%s' bind error", fn);
- }
- vs->info = layout;
- vs->count = lcount;
- vs->vs = id;
- printx("VertexShader %d compiled\n", id);
+ if (id)
+ glDeleteProgram(id);
+ id = n;
return 0;
}
-int App::compileShader(PixelShader *ps, const char *fn,
- void *data, unsigned len, int raw) {
+static int _load_shader(unsigned *out, const char *fn, unsigned type) {
+ void *data;
+ unsigned sz;
unsigned id;
int r;
- id = glCreateShader(GL_FRAGMENT_SHADER);
+ 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("pixel shader '%s' compile error", fn);
+ return error("shader '%s' compile error", fn);
}
- ps->ps = id;
- printx("PixelShader %d compiled\n", id);
+ if (*out)
+ glDeleteShader(*out);
+ *out = id;
return 0;
}
-int App::loadShader(VertexShader *vs, const char *fn,
- AttribInfo *layout, unsigned lcount) {
- void *data;
- unsigned sz;
- int r;
- if (!(data = load_file(fn, &sz)))
- return error("cannot load file '%s'", fn);
- r = compileShader(vs, fn, data, sz, 0, layout, lcount);
- free(data);
- return r;
-}
-
-int App::loadShader(PixelShader *ps, const char *fn) {
- void *data;
- unsigned sz;
- int r;
- if (!(data = load_file(fn, &sz)))
- return error("cannot load file '%s'", fn);
- r = compileShader(ps, fn, data, sz, 0);
- free(data);
- return r;
+int PixelShader::load(const char *fn) {
+ return _load_shader(&id, fn, GL_FRAGMENT_SHADER);
}
-int App::initConfig(InputConfiguration *ic, VertexShader *vs, PixelShader *ps) {
- unsigned pgm, vao;
- int r;
- // TODO program cache
- pgm = glCreateProgram();
- glAttachShader(pgm, vs->vs);
- glAttachShader(pgm, ps->ps);
- glLinkProgram(pgm);
- glGetProgramiv(pgm, GL_LINK_STATUS, &r);
- if (!r) {
- dump_link_error(pgm);
- glDeleteProgram(pgm);
- return error("program link error");
- }
- bind_attr_info(vs->ai, vs->info, vs->count, pgm);
- glGenVertexArrays(1, &vao);
- CHECK();
- glBindVertexArray(ic->vao);
- CHECK();
- ic->vao = vao;
- ic->pgm = pgm;
- ic->vs = vs;
- ic->ps = ps;
- printx("Program %d linked\n", pgm);
- return 0;
-}
-
-void App::useConfig(InputConfiguration *ic) {
- this->ic = ic;
- glBindVertexArray(ic->vao);
- CHECK();
- glUseProgram(ic->pgm);
- CHECK();
+int VertexShader::load(const char *fn) {
+ return _load_shader(&id, fn, GL_VERTEX_SHADER);
}
int App::loadTextureRGBA(Texture2D *tex, const char *fn, int genmips) {
@@ -488,107 +370,11 @@ int App::createTextureRGBA(Texture2D *tex, void *data, unsigned w, unsigned h, i
return 0;
}
-int App::initBuffer(VertexBuffer *vb, void *data, int sz) {
- if (vb->buf)
- glDeleteBuffers(1, &vb->buf);
- glGenBuffers(1, &vb->buf);
- vb->sz = sz;
- if (data) {
- glBindBuffer(GL_ARRAY_BUFFER, vb->buf);
- CHECK();
- glBufferData(GL_ARRAY_BUFFER, sz, data, GL_STATIC_DRAW);
- CHECK();
- }
- return 0;
-}
-int App::initBuffer(IndexBuffer *ib, void *data, int sz) {
- glGenBuffers(1, &ib->buf);
- ib->sz = sz;
- if (data) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->buf);
- CHECK();
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sz, data, GL_STATIC_DRAW);
- CHECK();
- }
- return 0;
-}
-int App::initBuffer(UniformBuffer *ub, void *data, int sz) {
- glGenBuffers(1, &ub->buf);
- ub->sz = sz;
- if (data) {
- glBindBuffer(GL_UNIFORM_BUFFER, ub->buf);
- CHECK();
- glBufferData(GL_UNIFORM_BUFFER, sz, data, GL_STATIC_DRAW);
- CHECK();
- }
- return 0;
-}
-
-void App::updateBuffer(VertexBuffer *vb, void *data) {
- glBindBuffer(GL_ARRAY_BUFFER, vb->buf);
- CHECK();
- glBufferData(GL_ARRAY_BUFFER, vb->sz, data, GL_STATIC_DRAW);
- CHECK();
-}
-void App::updateBuffer(IndexBuffer *ib, void *data) {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->buf);
- CHECK();
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, ib->sz, data, GL_STATIC_DRAW);
- CHECK();
-}
-void App::updateBuffer(UniformBuffer *ub, void *data) {
- glBindBuffer(GL_UNIFORM_BUFFER, ub->buf);
- CHECK();
- glBufferData(GL_UNIFORM_BUFFER, ub->sz, data, GL_STATIC_DRAW);
- CHECK();
-}
-
-void App::useBuffer(VertexBuffer *vb, int slot, unsigned stride, unsigned offset) {
- glBindBuffer(GL_ARRAY_BUFFER, vb->buf);
- CHECK();
- config_attr_info(ic->vs->ai, ic->vs->count, slot, stride);
- ic->vbuf[slot] = vb;
-}
-void App::useBuffer(IndexBuffer *ib) {
- ic->ibuf = ib;
-}
-void App::useBuffer(UniformBuffer *ub, int slot) {
- if (ic->ubuf[slot] != ub) {
- ic->ubuf[slot] = ub;
- /* simple 1:1 binding */
- // TODO: smarting binding, avoid having to glBindBufferBase() on every draw
- glUniformBlockBinding(ic->pgm, slot, slot);
- }
-}
void App::useTexture(Texture2D *tex, int slot) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex->tex);
}
-void _prepare(InputConfiguration *ic) {
- int n;
- if (ic->ibuf)
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ic->ibuf->buf);
- for (n = 0; n < 16; n++)
- if (ic->ubuf[n])
- glBindBufferBase(GL_UNIFORM_BUFFER, n, ic->ubuf[n]->buf);
-}
-void App::drawIndexedInstanced(unsigned numindices, unsigned numinstances) {
- _prepare(ic);
- glDrawElementsInstanced(GL_TRIANGLES, numindices, GL_UNSIGNED_SHORT, NULL, numinstances);
- CHECK();
-}
-void App::drawInstanced(unsigned numvertices, unsigned numinstances) {
- _prepare(ic);
- glDrawArraysInstanced(GL_TRIANGLES, 0, numvertices, numinstances);
- CHECK();
-}
-void App::drawIndexed(unsigned numindices) {
- _prepare(ic);
- glDrawElements(GL_TRIANGLES, numindices, GL_UNSIGNED_SHORT, NULL);
- CHECK();
-}
-
void App::setBlend(int enable) {
if (enable)
glEnable(GL_BLEND);
diff --git a/common/io.cc b/common/io.cc
@@ -81,8 +81,8 @@ void init_io(void) {
int file_get_mtime(const char *fn) {
struct stat s;
- char buf[1024];
- snprintf(buf, 1024, "%s%s", base_path, fn);
+ char buf[2048 + 64];
+ snprintf(buf, 1024, "%s%s%s", base_path, search[0], fn);
if (stat(buf, &s))
return -1;
return s.st_mtime;
diff --git a/common/textgrid.cc b/common/textgrid.cc
@@ -29,10 +29,17 @@
#include "TextPS.h"
#endif
-static AttribInfo text_layout_desc[] = {
- { "POSITION", 0, FMT_32x2_FLOAT, 0, 0, VERTEX_DATA, 0 },
- { "TEXCOORD", 0, FMT_32x2_FLOAT, 0, 8, VERTEX_DATA, 0 },
- { "CHARACTER", 0, FMT_8x1_UINT, 1, 0, INSTANCE_DATA, 1 },
+//static AttribInfo text_layout_desc[] = {
+// { "POSITION", 0, FMT_32x2_FLOAT, 0, 0, VERTEX_DATA, 0 },
+// { "TEXCOORD", 0, FMT_32x2_FLOAT, 0, 8, VERTEX_DATA, 0 },
+// { "CHARACTER", 0, FMT_8x1_UINT, 1, 0, INSTANCE_DATA, 1 },
+//};
+
+// idx, src, dst, count, offset, stride, divisor
+static VertexAttrDesc layout[] = {
+ { 0, SRC_FLOAT, DST_FLOAT, 2, 0, 16, 0 },
+ { 1, SRC_FLOAT, DST_FLOAT, 2, 8, 16, 0 },
+ { 2, SRC_UINT8, DST_INTEGER, 1, 0, 1, 1 },
};
static float unit_box_2d[] = {
@@ -52,7 +59,11 @@ int TextGrid::init(App *a, int w, int h) {
unsigned pad0;
unsigned pad1;
} cb;
-
+ VertexBuffer *data[] = {
+ &vtx,
+ &vtx,
+ &cbuf,
+ };
width = w;
height = h;
dirty = 0;
@@ -64,30 +75,24 @@ int TextGrid::init(App *a, int w, int h) {
if (a->loadTextureRGBA(&texture, "font-vincent-8x8.png", 0))
return -1;
- if (a->initBuffer(&vtx, unit_box_2d, sizeof(unit_box_2d)))
- return -1;
- if (a->initBuffer(&cbuf, grid, width * height))
- return -1;
- if (a->initBuffer(&ubuf, NULL, sizeof(cb)))
+
+ if (ps.load("TextPS.glsl"))
return -1;
- if (a->loadShader(&ps, "TextPS.glsl"))
+ if (vs.load("TextVS.glsl"))
return -1;
- if (a->loadShader(&vs, "TextVS.glsl",
- text_layout_desc, sizeof(text_layout_desc)/sizeof(text_layout_desc[0])))
+ if (pgm.link(&vs, &ps))
return -1;
+
cb.proj.setOrtho(0, w, 0, h, -1, 1);
cb.cw = width;
cb.ch = height;
- a->updateBuffer(&ubuf, &cb);
- a->initConfig(&cfg, &vs, &ps);
+ vtx.load(unit_box_2d, sizeof(unit_box_2d));
+ cbuf.load(grid, width * height);
+ ubuf.load(&cb, sizeof(cb));
- a->useConfig(&cfg);
- a->useBuffer(&ubuf, 0);
- a->useTexture(&texture, 0);
- a->useBuffer(&vtx, 0, 16, 0);
- a->useBuffer(&cbuf, 1, 1, 0);
+ attr.init(layout, data, sizeof(layout) / sizeof(layout[0]));
return 0;
}
@@ -95,10 +100,13 @@ int TextGrid::init(App *a, int w, int h) {
void TextGrid::render(App *a) {
if (dirty) {
dirty = 0;
- a->updateBuffer(&cbuf, grid);
+ cbuf.load(grid, width * height);
}
- a->useConfig(&cfg);
- a->drawInstanced(6, width * height);
+ pgm.use();
+ attr.use();
+ ubuf.use(0);
+ a->useTexture(&texture, 0);
+ glDrawArraysInstanced(GL_TRIANGLES, 0, 6, width * height);
}
void TextGrid::clear(void) {
diff --git a/common/textgrid.h b/common/textgrid.h
@@ -33,8 +33,9 @@ private:
VertexBuffer cbuf;
PixelShader ps;
VertexShader vs;
+ Program pgm;
Texture2D texture;
- InputConfiguration cfg;
+ VertexAttributes attr;
unsigned char *grid;
};
diff --git a/hello/assets/SimplePS.glsl b/hello/assets/SimplePS.glsl
@@ -1,3 +1,4 @@
+#version 150
varying vec2 vTEXCOORD;
varying float vDIFFUSE;
diff --git a/hello/assets/SimpleVS.glsl b/hello/assets/SimpleVS.glsl
@@ -1,13 +1,15 @@
-#version 330
+#version 150
+#extension GL_ARB_explicit_attrib_location : enable
layout(std140) uniform cb0 {
mat4 MVP;
mat4 MV;
};
-in vec4 POSITION;
-in vec4 NORMAL;
-in vec2 TEXCOORD;
+layout(location = 0) in vec4 POSITION;
+layout(location = 1) in vec4 NORMAL;
+layout(location = 2) in vec2 TEXCOORD;
+
in vec4 LOCATION;
out vec2 vTEXCOORD;
diff --git a/hello/hello.cc b/hello/hello.cc
@@ -21,11 +21,12 @@
#include <stdio.h>
#include <stdlib.h>
-static AttribInfo obj_layout[] = {
- { "POSITION", 0, FMT_32x3_FLOAT, 0, 0, VERTEX_DATA, 0 },
- { "NORMAL", 0, FMT_32x3_FLOAT, 0, 12, VERTEX_DATA, 0 },
- { "TEXCOORD", 0, FMT_32x2_FLOAT, 0, 24, VERTEX_DATA, 0 },
- { "LOCATION", 0, FMT_8x4_SNORM, 1, 0, INSTANCE_DATA, 1 },
+// idx, src, dst, count, offset, stride, divisor
+static VertexAttrDesc layout[] = {
+ { 0, SRC_FLOAT, DST_FLOAT, 3, 0, 32, 0 },
+ { 1, SRC_FLOAT, DST_FLOAT, 3, 12, 32, 0 },
+ { 2, SRC_FLOAT, DST_FLOAT, 2, 24, 32, 0 },
+ { 3, SRC_INT8, DST_NORMALIZED, 4, 0, 4, 1 },
};
static float locationx[] = {
@@ -57,11 +58,12 @@ private:
PixelShader ps;
VertexShader vs;
+ Program pgm;
IndexBuffer ibuf;
VertexBuffer vbuf;
UniformBuffer ubuf;
VertexBuffer lbuf;
- InputConfiguration cfg;
+ VertexAttributes attr;
TextGrid text;
float nx,ny;
@@ -110,38 +112,35 @@ void TestApp::build(void) {
lcount = n / 4;
printx("Wrote %d locations\n", lcount);
- initBuffer(&lbuf, location, lcount * 4);
+ lbuf.load(location, lcount * 4);
}
int TestApp::init(void) {
- if (loadShader(&ps, "SimplePS.glsl"))
+ VertexBuffer *data[] = {
+ &vbuf, &vbuf, &vbuf, &lbuf,
+ };
+ if (ps.load("SimplePS.glsl"))
return -1;
- if (loadShader(&vs, "SimpleVS.glsl", obj_layout, sizeof(obj_layout) / sizeof(obj_layout[0])))
+ if (vs.load("SimpleVS.glsl"))
+ return -1;
+ if (pgm.link(&vs, &ps))
return -1;
if (!(m = load_wavefront_obj("unitcubeoid.obj")))
return error("cannot load model");
printx("Object Loaded. %d vertices, %d indices.\n", m->vcount, m->icount);
- if (initBuffer(&vbuf, m->vdata, 32 * m->vcount))
- return -1;
- if (initBuffer(&ibuf, m->idx, 2 * m->icount))
- return -1;
- if (initBuffer(&ubuf, NULL, 32 * 4))
- return -1;
+ vbuf.load(m->vdata, 32 * m->vcount);
+ ibuf.load(m->idx, 2 * m->icount);
+ ubuf.load(NULL, 32 * 4);
- if (initConfig(&cfg, &vs, &ps))
- return -1;
proj.setPerspective(D2R(90.0), width / (float) height, 0.1f, 250.0f);
build();
zoom = SZ;
- useConfig(&cfg);
- useBuffer(&ubuf, 0);
- useBuffer(&vbuf, 0, 32, 0);
- useBuffer(&lbuf, 1, 4, 0);
- useBuffer(&ibuf);
+ attr.init(layout, data, sizeof(layout) / sizeof(layout[0]));
+ ibuf.use();
if (text.init(this, 64, 64))
return -1;
@@ -187,8 +186,6 @@ oops:
build();
#endif
- useConfig(&cfg);
-
struct {
mat4 mvp;
mat4 mv;
@@ -201,8 +198,12 @@ oops:
world.identity().translate(0.5, 0.5, 0.5);
cb0.mvp = world * view * proj;
cb0.mv = world * view;
- updateBuffer(&ubuf, &cb0);
- drawIndexedInstanced(m->icount, lcount);
+
+ pgm.use();
+ ubuf.load(&cb0, sizeof(cb0));
+ ubuf.use(0);
+ attr.use();
+ glDrawElementsInstanced(GL_TRIANGLES, m->icount, GL_UNSIGNED_SHORT, NULL, lcount);
text.clear();
text.printf(0, 0, "rx: %8.4f", rx);
diff --git a/test/assets/TestPS.glsl b/test/assets/TestPS.glsl
@@ -1,4 +1,4 @@
-#version 330
+#version 150
in vec2 vTEXCOORD;
in float vDIFFUSE;
diff --git a/test/assets/TestVS.glsl b/test/assets/TestVS.glsl
@@ -1,4 +1,5 @@
-#version 330
+#version 150
+#extension GL_ARB_explicit_attrib_location : enable
//uniform mat4 MVP0;
@@ -7,9 +8,9 @@ layout(std140) uniform cb0 {
mat4 MV;
};
-in vec4 POSITION;
-in vec4 NORMAL;
-in vec2 TEXCOORD;
+layout (location = 0) in vec4 POSITION;
+layout (location = 1) in vec4 NORMAL;
+layout (location = 2) in vec2 TEXCOORD;
out vec2 vTEXCOORD;
out float vDIFFUSE;
diff --git a/test/test.cc b/test/test.cc
@@ -21,10 +21,11 @@
#include <stdio.h>
#include <stdlib.h>
-static AttribInfo obj_layout[] = {
- { "POSITION", 0, FMT_32x3_FLOAT, 0, 0, VERTEX_DATA, 0 },
- { "NORMAL", 0, FMT_32x3_FLOAT, 0, 12, VERTEX_DATA, 0 },
- { "TEXCOORD", 0, FMT_32x2_FLOAT, 0, 24, VERTEX_DATA, 0 },
+// idx, src, dst, count, offset, stride, divisor
+static VertexAttrDesc layout[] = {
+ { 0, SRC_FLOAT, DST_FLOAT, 3, 0, 32, 0 },
+ { 1, SRC_FLOAT, DST_FLOAT, 3, 12, 32, 0 },
+ { 2, SRC_FLOAT, DST_FLOAT, 2, 24, 32, 0 },
};
class TestApp : public App {
@@ -40,11 +41,11 @@ private:
PixelShader ps;
VertexShader vs;
+ Program pgm;
IndexBuffer ibuf;
VertexBuffer vbuf;
UniformBuffer ubuf;
- VertexBuffer lbuf;
- InputConfiguration cfg;
+ VertexAttributes attr;
mat4 proj;
struct model *m;
@@ -63,11 +64,9 @@ void TestApp::release(void) {
}
int TestApp::init(void) {
- if (loadShader(&ps, psfn))
- return -1;
- if (loadShader(&vs, vsfn, obj_layout, sizeof(obj_layout) / sizeof(obj_layout[0])))
- return -1;
-
+ VertexBuffer *data[] = {
+ &vbuf, &vbuf, &vbuf,
+ };
ps_mtime = file_get_mtime(psfn);
vs_mtime = file_get_mtime(vsfn);
@@ -75,22 +74,20 @@ int TestApp::init(void) {
return error("cannot load model");
printx("Object Loaded. %d vertices, %d indices.\n", m->vcount, m->icount);
- if (initBuffer(&vbuf, m->vdata, 32 * m->vcount))
- return -1;
- if (initBuffer(&ibuf, m->idx, 2 * m->icount))
- return -1;
- if (initBuffer(&ubuf, NULL, 32 * 4))
- return -1;
-
- if (initConfig(&cfg, &vs, &ps))
- return -1;
proj.setPerspective(D2R(90.0), width / (float) height, 0.1f, 250.0f);
- useConfig(&cfg);
- useBuffer(&ubuf, 0);
- useBuffer(&vbuf, 0, 32, 0);
- useBuffer(&lbuf, 1, 4, 0);
- useBuffer(&ibuf);
+ ps.load(psfn);
+ vs.load(vsfn);
+ pgm.link(&vs, &ps);
+
+ vbuf.load(m->vdata, 32 * m->vcount);
+ ibuf.load(m->idx, 2 * m->icount);
+ ubuf.load(NULL, 32 * 4);
+
+ attr.init(layout, data, sizeof(layout)/sizeof(layout[0]));
+
+ /* this will persist because it is part of the VAO state */
+ ibuf.use();
return 0;
}
@@ -101,16 +98,19 @@ void TestApp::render(void) {
t = file_get_mtime(psfn);
if (t != ps_mtime) {
- loadShader(&ps, psfn);
+ printx("ps change!\n");
+ ps.load(psfn);
ps_mtime = t;
+ pgm.link(&vs, &ps);
}
t = file_get_mtime(vsfn);
if (t != vs_mtime) {
- loadShader(&vs, vsfn, obj_layout, sizeof(obj_layout) / sizeof(obj_layout[0]));
+ printx("vs change!\n");
+ vs.load(vsfn);
vs_mtime = t;
+ pgm.link(&vs, &ps);
}
- useConfig(&cfg);
struct {
mat4 mvp;
mat4 mv;
@@ -126,8 +126,12 @@ void TestApp::render(void) {
cb0.mvp = world * view * proj;
cb0.mv = world * view;
- updateBuffer(&ubuf, &cb0);
- drawIndexed(m->icount);
+ ubuf.load(&cb0, 32 * 4);
+
+ pgm.use();
+ ubuf.use(0);
+ attr.use();
+ glDrawElements(GL_TRIANGLES, m->icount, GL_UNSIGNED_SHORT, NULL);
}
App *createApp(void) {