graphics

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
M.gitignore | 4++--
Mcommon/app.h | 156++++++++++++++++++++++++++++++--------------------------------------------------
Mcommon/assets/TextPS.glsl | 1+
Mcommon/assets/TextVS.glsl | 11+++++------
Mcommon/glapp.cc | 406+++++++++++++++++++------------------------------------------------------------
Mcommon/io.cc | 4++--
Mcommon/textgrid.cc | 54+++++++++++++++++++++++++++++++-----------------------
Mcommon/textgrid.h | 3++-
Mhello/assets/SimplePS.glsl | 1+
Mhello/assets/SimpleVS.glsl | 10++++++----
Mhello/hello.cc | 53+++++++++++++++++++++++++++--------------------------
Mtest/assets/TestPS.glsl | 2+-
Mtest/assets/TestVS.glsl | 9+++++----
Mtest/test.cc | 64++++++++++++++++++++++++++++++++++------------------------------
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) {