From 387a8ab2dc61db8ec215375516f225b8684fe26e Mon Sep 17 00:00:00 2001 From: rude Date: Sat, 23 Jul 2011 17:12:29 +0200 Subject: [PATCH] Issue #262: Add per-sprite colors. --- src/modules/graphics/opengl/SpriteBatch.cpp | 40 ++++++++++++++++++- src/modules/graphics/opengl/SpriteBatch.h | 29 ++++++++++++++ .../graphics/opengl/wrap_SpriteBatch.cpp | 20 ++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index 51cb9b4db..83ed4e2f8 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/src/modules/graphics/opengl/SpriteBatch.cpp @@ -34,7 +34,7 @@ namespace graphics namespace opengl { SpriteBatch::SpriteBatch(Image * image, int size, int usage) - : image(image), size(size), next(0), usage(usage), lockp(0) + : image(image), size(size), next(0), usage(usage), lockp(0), color(0) { if (!(GLEE_ARB_vertex_buffer_object || GLEE_VERSION_1_5)) throw love::Exception("Your OpenGL version does not support SpriteBatches. Go upgrade!"); @@ -67,6 +67,7 @@ namespace opengl delete [] vertices; delete [] indices; + delete color; } bool SpriteBatch::loadVolatile() @@ -120,6 +121,9 @@ namespace opengl t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky); t.transform(v, v, 4); + if (color) + setColorv(v, *color); + addv(v); // Increment counter. @@ -143,6 +147,9 @@ namespace opengl t.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky); t.transform(v, v, 4); + if (color) + setColorv(v, *color); + addv(v); // Increment counter. @@ -183,6 +190,20 @@ namespace opengl image->retain(); } + void SpriteBatch::setColor(const Color & color) + { + if(!this->color) + this->color = new Color(color); + else + *(this->color) = color; + } + + void SpriteBatch::setColor() + { + delete color; + color = 0; + } + void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const { static Matrix t; @@ -201,12 +222,21 @@ namespace opengl // Bind the VBO buffer. glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo[0]); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo[1]); + + // Apply per-sprite color, if a color is set. + if (color) + { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), 0); + } + glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4)); glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)(sizeof(unsigned char)*4+sizeof(float)*2)); glDrawElements(GL_TRIANGLES, next*6, GL_UNSIGNED_SHORT, 0); // Disable vertex arrays. + glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); @@ -232,6 +262,14 @@ namespace opengl } } + void SpriteBatch::setColorv(vertex * v, const Color & color) + { + v[0].r = color.r; v[0].g = color.g; v[0].b = color.b; v[0].a = color.a; + v[1].r = color.r; v[1].g = color.g; v[1].b = color.b; v[1].a = color.a; + v[2].r = color.r; v[2].g = color.g; v[2].b = color.b; v[2].a = color.a; + v[3].r = color.r; v[3].g = color.g; v[3].b = color.b; v[3].a = color.a; + } + } // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/SpriteBatch.h b/src/modules/graphics/opengl/SpriteBatch.h index be620e20c..fdc868e82 100644 --- a/src/modules/graphics/opengl/SpriteBatch.h +++ b/src/modules/graphics/opengl/SpriteBatch.h @@ -31,6 +31,7 @@ #include #include #include +#include // OpenGL #include "GLee.h" @@ -73,6 +74,10 @@ namespace opengl // If the buffer is locked, this pointer is nonzero. vertex * lockp; + // Current color. This color, if present, will be applied to the next + // added quad. + Color * color; + public: enum UsageHint @@ -98,6 +103,21 @@ namespace opengl void setImage(Image * newimage); + /** + * Set the current color for this SpriteBatch. The geometry added + * after this call will use this color. Note that global color + * will not longer apply to the SpriteBatch if this is used. + * + * @param color The color to use for the following geometry. + */ + void setColor(const Color & color); + + /** + * Disable per-quad colors for this SpriteBatch. The next call to + * draw will use the global color for all sprites. + */ + void setColor(); + // Implements Drawable. void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const; @@ -105,6 +125,15 @@ namespace opengl void addv(const vertex * v); + /** + * Set the color for vertices. + * + * @param v The vertices to set the color for. Must be an array of + * of size 4. + * @param color The color to assign to each vertex. + */ + void setColorv(vertex * v, const Color & color); + }; // SpriteBatch } // opengl diff --git a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp b/src/modules/graphics/opengl/wrap_SpriteBatch.cpp index a84e5772a..ac22ad18d 100644 --- a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp +++ b/src/modules/graphics/opengl/wrap_SpriteBatch.cpp @@ -93,6 +93,25 @@ namespace opengl return 0; } + int w_SpriteBatch_setColor(lua_State * L) + { + SpriteBatch * t = luax_checkspritebatch(L, 1); + + if (lua_gettop(L) <= 1) + t->setColor(); + else + { + Color c; + c.r = (unsigned char)luaL_checkint(L, 2); + c.g = (unsigned char)luaL_checkint(L, 3); + c.b = (unsigned char)luaL_checkint(L, 4); + c.a = (unsigned char)luaL_optint(L, 5, 255); + t->setColor(c); + } + + return 0; + } + static const luaL_Reg functions[] = { { "add", w_SpriteBatch_add }, { "addq", w_SpriteBatch_addq }, @@ -100,6 +119,7 @@ namespace opengl { "bind", w_SpriteBatch_bind }, { "unbind", w_SpriteBatch_unbind }, { "setImage", w_SpriteBatch_setImage }, + { "setColor", w_SpriteBatch_setColor }, { 0, 0 } };