diff --git a/src/engine.cpp b/src/engine.cpp index d58b0cc..e8f2b79 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -33,6 +33,7 @@ Engine::init(void) engine->currentCamera = nil; engine->currentWorld = nil; engine->currentTexDictionary = nil; + engine->imtexture = nil; engine->loadTextures = 1; engine->makeDummies = 1; @@ -41,6 +42,7 @@ Engine::init(void) engine->clearCamera = null::clearCamera; engine->setRenderState = null::setRenderState; engine->getRenderState = null::getRenderState; + engine->im2DRenderIndexedPrimitive = null::im2DRenderIndexedPrimitive; engine->zNear = 0.0f; // random values engine->zFar = 1.0f; @@ -71,6 +73,7 @@ Driver::open(void) driver[i]->rasterFromImage = null::rasterFromImage; driver[i]->rasterToImage = null::rasterToImage; + s_plglist[i].construct(rw::driver[i]); } } @@ -84,6 +87,8 @@ void clearCamera(Camera*,RGBA*,uint32) { } void setRenderState(int32, uint32) { } uint32 getRenderState(int32) { return 0; } +void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32) { } + void rasterCreate(Raster*) { diff --git a/src/gl/gl3driver.cpp b/src/gl/gl3driver.cpp index 50c62e3..b16d462 100644 --- a/src/gl/gl3driver.cpp +++ b/src/gl/gl3driver.cpp @@ -12,6 +12,7 @@ #include #include "rwgl3.h" #include "rwgl3shader.h" +#include "rwgl3impl.h" namespace rw { namespace gl3 { @@ -417,6 +418,7 @@ initializeRender(void) engine->clearCamera = clearCamera; engine->setRenderState = setRenderState; engine->getRenderState = getRenderState; + engine->im2DRenderIndexedPrimitive = im2DRenderIndexedPrimitive; engine->zNear = -1.0f; engine->zFar = 1.0f; @@ -461,6 +463,8 @@ initializeRender(void) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel); + + im2DInit(); } } } diff --git a/src/gl/gl3im2d.cpp b/src/gl/gl3im2d.cpp new file mode 100644 index 0000000..699fdc7 --- /dev/null +++ b/src/gl/gl3im2d.cpp @@ -0,0 +1,90 @@ +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#ifdef RW_OPENGL +#include +#include "rwgl3.h" +#include "rwgl3shader.h" + +namespace rw { +namespace gl3 { + +uint32 im2DVbo, im2DIbo; + +#define STARTINDICES 1024 +#define STARTVERTICES 1024 + +static Shader *im2dShader; +static AttribDesc attribDesc[3] = { + { ATTRIB_POS, GL_FLOAT, GL_FALSE, 3, + sizeof(Im2DVertex), 0 }, + { ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4, + sizeof(Im2DVertex), offsetof(Im2DVertex, r) }, + { ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2, + sizeof(Im2DVertex), offsetof(Im2DVertex, r) }, +}; + +static int primTypeMap[] = { + GL_POINTS, // invalid + GL_LINES, + GL_LINE_STRIP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + GL_POINTS +}; + +void +im2DInit(void) +{ +#include "shaders/im2d_gl3.inc" + im2dShader = Shader::fromStrings(im2d_vert_src, im2d_frag_src); + + glGenBuffers(1, &im2DIbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, STARTINDICES*2, + nil, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glGenBuffers(1, &im2DVbo); + glBindBuffer(GL_ARRAY_BUFFER, im2DVbo); + glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im2DVertex), + nil, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void +im2DRenderIndexedPrimitive(PrimitiveType primType, + void *vertices, int32 numVertices, + void *indices, int32 numIndices) +{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, + indices, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, im2DVbo); + glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), + vertices, GL_DYNAMIC_DRAW); + + setAttribPointers(attribDesc, 3); + im2dShader->use(); + + setTexture(0, engine->imtexture); + + flushCache(); + glDrawElements(primTypeMap[primType], numIndices, + GL_UNSIGNED_SHORT, nil); + disableAttribPointers(attribDesc, 3); +} + +} +} + +#endif diff --git a/src/gl/gl3pipe.cpp b/src/gl/gl3pipe.cpp index e23eafb..2fbb3e4 100644 --- a/src/gl/gl3pipe.cpp +++ b/src/gl/gl3pipe.cpp @@ -68,10 +68,10 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) header->vbo = 0; glGenBuffers(1, &header->ibo); - glBindBuffer(GL_ARRAY_BUFFER, header->ibo); - glBufferData(GL_ARRAY_BUFFER, header->totalNumIndex*2, + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, header->totalNumIndex*2, header->indexBuffer, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); pipe->instanceCB(geo, header); } diff --git a/src/gl/gl3plugins.cpp b/src/gl/gl3plugins.cpp index f549741..b58bae5 100644 --- a/src/gl/gl3plugins.cpp +++ b/src/gl/gl3plugins.cpp @@ -195,7 +195,7 @@ matfxRenderCB(Atomic *atomic, InstanceDataHeader *header) glBindBuffer(GL_ARRAY_BUFFER, header->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); - setAttribPointers(header); + setAttribPointers(header->attribDesc, header->numAttribs); InstanceData *inst = header->inst; int32 n = header->numMeshes; @@ -215,6 +215,7 @@ matfxRenderCB(Atomic *atomic, InstanceDataHeader *header) } inst++; } + disableAttribPointers(header->attribDesc, header->numAttribs); } ObjPipeline* @@ -454,7 +455,7 @@ skinRenderCB(Atomic *atomic, InstanceDataHeader *header) glBindBuffer(GL_ARRAY_BUFFER, header->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); - setAttribPointers(header); + setAttribPointers(header->attribDesc, header->numAttribs); InstanceData *inst = header->inst; int32 n = header->numMeshes; @@ -489,6 +490,7 @@ skinRenderCB(Atomic *atomic, InstanceDataHeader *header) GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); inst++; } + disableAttribPointers(header->attribDesc, header->numAttribs); } ObjPipeline* diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp index bb3b2c6..143f6de 100644 --- a/src/gl/gl3render.cpp +++ b/src/gl/gl3render.cpp @@ -21,18 +21,24 @@ namespace gl3 { #define MAX_LIGHTS 8 void -setAttribPointers(InstanceDataHeader *header) +setAttribPointers(AttribDesc *attribDescs, int32 numAttribs) { AttribDesc *a; - for(a = header->attribDesc; - a != &header->attribDesc[header->numAttribs]; - a++){ + for(a = attribDescs; a != &attribDescs[numAttribs]; a++){ glEnableVertexAttribArray(a->index); glVertexAttribPointer(a->index, a->size, a->type, a->normalized, a->stride, (void*)(uint64)a->offset); } } +void +disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs) +{ + AttribDesc *a; + for(a = attribDescs; a != &attribDescs[numAttribs]; a++) + glDisableVertexAttribArray(a->index); +} + void lightingCB(void) { @@ -73,7 +79,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) glBindBuffer(GL_ARRAY_BUFFER, header->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); - setAttribPointers(header); + setAttribPointers(header->attribDesc, header->numAttribs); InstanceData *inst = header->inst; int32 n = header->numMeshes; @@ -104,6 +110,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); inst++; } + disableAttribPointers(header->attribDesc, header->numAttribs); } diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 8fc702c..0a51e9a 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -58,7 +58,15 @@ struct InstanceDataHeader : rw::InstanceDataHeader InstanceData *inst; }; -void setAttribPointers(InstanceDataHeader *header); +struct Im2DVertex +{ + float32 x, y, z; + uint8 r, g, b, a; + float32 u, v; +}; + +void setAttribPointers(AttribDesc *attribDescs, int32 numAttribs); +void disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs); // Render state diff --git a/src/gl/rwgl3impl.h b/src/gl/rwgl3impl.h index 0263c67..7a83321 100644 --- a/src/gl/rwgl3impl.h +++ b/src/gl/rwgl3impl.h @@ -4,6 +4,10 @@ namespace gl3 { #ifdef RW_OPENGL extern Shader *simpleShader; +extern uint32 im2DVbo, im2DIbo; +void im2DInit(void); +void im2DRenderIndexedPrimitive(PrimitiveType primType, + void *vertices, int32 numVertices, void *indices, int32 numIndices); #endif diff --git a/src/gl/shaders/Makefile b/src/gl/shaders/Makefile index 5d6fe06..e7be584 100644 --- a/src/gl/shaders/Makefile +++ b/src/gl/shaders/Makefile @@ -1,4 +1,12 @@ -all: simple_gl3.inc matfx_gl3.inc skin_gl3.inc +all: im2d_gl3.inc simple_gl3.inc matfx_gl3.inc skin_gl3.inc + +im2d_gl3.inc: im2d.frag im2d.vert + (echo 'const char *im2d_vert_src =';\ + sed 's/..*/"&\\n"/' im2d.vert;\ + echo ';';\ + echo 'const char *im2d_frag_src =';\ + sed 's/..*/"&\\n"/' im2d.frag;\ + echo ';') >im2d_gl3.inc simple_gl3.inc: simple.frag simple.vert (echo 'const char *simple_vert_src =';\ diff --git a/src/gl/shaders/im2d.frag b/src/gl/shaders/im2d.frag new file mode 100644 index 0000000..b40c2f9 --- /dev/null +++ b/src/gl/shaders/im2d.frag @@ -0,0 +1,15 @@ +#version 330 + +uniform sampler2D tex; + +in vec4 v_color; +in vec2 v_tex0; + +out vec4 color; + +void +main(void) +{ + color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); +} + diff --git a/src/gl/shaders/im2d.vert b/src/gl/shaders/im2d.vert new file mode 100644 index 0000000..2e776c9 --- /dev/null +++ b/src/gl/shaders/im2d.vert @@ -0,0 +1,23 @@ +#version 330 + +layout(std140) uniform Im2DState +{ + int u_alphaTest; + float u_alphaRef; + mat4 u_xform; +}; + +layout(location = 0) in vec3 in_pos; +layout(location = 2) in vec4 in_color; +layout(location = 3) in vec2 in_tex0; + +out vec4 v_color; +out vec2 v_tex0; + +void +main(void) +{ + gl_Position = vec4(in_pos, 1.0); + v_color = in_color; + v_tex0 = in_tex0; +} diff --git a/src/gl/shaders/im2d_gl3.inc b/src/gl/shaders/im2d_gl3.inc new file mode 100644 index 0000000..23af07c --- /dev/null +++ b/src/gl/shaders/im2d_gl3.inc @@ -0,0 +1,42 @@ +const char *im2d_vert_src = +"#version 330\n" + +"layout(std140) uniform Im2DState\n" +"{\n" +" int u_alphaTest;\n" +" float u_alphaRef;\n" +" mat4 u_xform;\n" +"};\n" + +"layout(location = 0) in vec3 in_pos;\n" +"layout(location = 2) in vec4 in_color;\n" +"layout(location = 3) in vec2 in_tex0;\n" + +"out vec4 v_color;\n" +"out vec2 v_tex0;\n" + +"void\n" +"main(void)\n" +"{\n" +" gl_Position = vec4(in_pos, 1.0);\n" +" v_color = in_color;\n" +" v_tex0 = in_tex0;\n" +"}\n" +; +const char *im2d_frag_src = +"#version 330\n" + +"uniform sampler2D tex;\n" + +"in vec4 v_color;\n" +"in vec2 v_tex0;\n" + +"out vec4 color;\n" + +"void\n" +"main(void)\n" +"{\n" +" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +"}\n" + +; diff --git a/src/rwbase.h b/src/rwbase.h index 42daa95..e3c10c8 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -124,7 +124,7 @@ struct Quat float32 x, y, z, w; Quat(void) : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {} Quat(float32 w, float32 x, float32 y, float32 z) : x(x), y(y), z(z), w(w) {} - Quat(float32 w, V3d vec) : x(vec.x), y(vec.y), z(vec.z), w(w) {} + Quat(float32 w, const V3d &vec) : x(vec.x), y(vec.y), z(vec.z), w(w) {} Quat(V3d vec) : x(vec.x), y(vec.y), z(vec.z), w(0.0f) {} static Quat rotation(float32 angle, const V3d &axis){ return Quat(cos(angle/2.0f), scale(axis, sin(angle/2.0f))); } @@ -204,6 +204,17 @@ struct Sphere float32 radius; }; +enum PrimitiveType +{ + PRIMTYPENONE = 0, + PRIMTYPELINELIST, + PRIMTYPEPOLYLINE, + PRIMTYPETRILIST, + PRIMTYPETRISTRIP, + PRIMTYPETRIFAN, + PRIMTYPEPOINTLIST, +}; + /* * Streams */ diff --git a/src/rwengine.h b/src/rwengine.h index c3c40c6..de4d9d4 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -50,6 +50,7 @@ struct Engine { void *currentCamera; void *currentWorld; + Texture *imtexture; TexDictionary *currentTexDictionary; bool32 loadTextures; // load textures from files @@ -63,6 +64,8 @@ struct Engine void (*clearCamera)(Camera*, RGBA *col, uint32 mode); void (*setRenderState)(int32 state, uint32 value); uint32 (*getRenderState)(int32 state); + void (*im2DRenderIndexedPrimitive)(PrimitiveType, + void*, int32, void*, int32); static void init(void); }; @@ -115,6 +118,9 @@ namespace null { int32 rasterNumLevels(Raster*); void rasterFromImage(Raster*, Image*); Image *rasterToImage(Raster*); + + void im2DRenderIndexedPrimitive(PrimitiveType, + void*, int32, void*, int32); } }