From 8362e866271d69420de73990ff5b76405579c9ca Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Tue, 10 Aug 2010 16:23:11 +0200 Subject: [PATCH] First import and review of vrld's patch --- src/common/types.h | 2 + src/modules/graphics/opengl/Fbo.cpp | 103 ++++++++++++++++++ src/modules/graphics/opengl/Fbo.h | 46 ++++++++ src/modules/graphics/opengl/Graphics.cpp | 7 +- src/modules/graphics/opengl/Graphics.h | 53 ++++----- src/modules/graphics/opengl/wrap_Fbo.cpp | 58 ++++++++++ src/modules/graphics/opengl/wrap_Fbo.h | 25 +++++ src/modules/graphics/opengl/wrap_Graphics.cpp | 21 +++- src/modules/graphics/opengl/wrap_Graphics.h | 8 +- 9 files changed, 292 insertions(+), 31 deletions(-) create mode 100644 src/modules/graphics/opengl/Fbo.cpp create mode 100644 src/modules/graphics/opengl/Fbo.h create mode 100644 src/modules/graphics/opengl/wrap_Fbo.cpp create mode 100644 src/modules/graphics/opengl/wrap_Fbo.h diff --git a/src/common/types.h b/src/common/types.h index 063135094..ecbe1a773 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -52,6 +52,7 @@ namespace love GRAPHICS_PARTICLE_SYSTEM_ID, GRAPHICS_SPRITE_BATCH_ID, GRAPHICS_VERTEX_BUFFER_ID, + GRAPHICS_FBO_ID, // Image IMAGE_IMAGE_DATA_ID, @@ -116,6 +117,7 @@ namespace love const bits GRAPHICS_PARTICLE_SYSTEM_T = (bits(1) << GRAPHICS_PARTICLE_SYSTEM_ID) | GRAPHICS_DRAWABLE_T; const bits GRAPHICS_SPRITE_BATCH_T = (bits(1) << GRAPHICS_SPRITE_BATCH_ID) | GRAPHICS_DRAWABLE_T; const bits GRAPHICS_VERTEX_BUFFER_T = (bits(1) << GRAPHICS_VERTEX_BUFFER_ID) | GRAPHICS_DRAWABLE_T; + const bits GRAPHICS_FBO_T = (bits(1) << GRAPHICS_FBO_ID) | GRAPHICS_DRAWABLE_T; // Image. const bits IMAGE_IMAGE_DATA_T = (bits(1) << IMAGE_IMAGE_DATA_ID) | DATA_T; diff --git a/src/modules/graphics/opengl/Fbo.cpp b/src/modules/graphics/opengl/Fbo.cpp new file mode 100644 index 000000000..5ec3a4ce6 --- /dev/null +++ b/src/modules/graphics/opengl/Fbo.cpp @@ -0,0 +1,103 @@ +#include "Fbo.h" +#include + +namespace love +{ +namespace graphics +{ +namespace opengl +{ + + Fbo::Fbo(int width, int height) : + width(width), height(height) + { + // world coordinates + vertices[0].x = 0; vertices[0].y = 0; + vertices[1].x = 0; vertices[1].y = height; + vertices[2].x = width; vertices[2].y = height; + vertices[3].x = width; vertices[3].y = 0; + + // texture coordinates + vertices[0].s = 0; vertices[0].t = 1; + vertices[1].s = 0; vertices[1].t = 0; + vertices[2].s = 1; vertices[2].t = 0; + vertices[3].s = 1; vertices[3].t = 1; + + // generate depth buffer + glGenRenderbuffers(1, &depthbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + // generate texture save target + glGenTextures(1, &img); + glBindTexture(GL_TEXTURE_2D, img); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + // create framebuffer + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, img, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, depthbuffer); + status_ = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + // unbind buffers and texture + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + Fbo::~Fbo() + { + glDeleteTextures(1, &fbo); + glDeleteRenderbuffers(1, &depthbuffer); + glDeleteFramebuffers(1, &img); + } + + GLenum Fbo::status() const + { + return status_; + } + + void Fbo::bind() + { + glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, width, height); + } + + void Fbo::unbind() + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glPopAttrib(); + } + + void Fbo::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const + { + static Matrix t; + t.setTransformation(x, y, angle, sx, sy, ox, oy); + + glPushMatrix(); + glMultMatrixf((const GLfloat*)t.getElements()); + + glBindTexture(GL_TEXTURE_2D, img); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&vertices[0].x); + glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&vertices[0].s); + glDrawArrays(GL_QUADS, 0, 4); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glPopMatrix(); + } + +} // opengl +} // graphics +} // love diff --git a/src/modules/graphics/opengl/Fbo.h b/src/modules/graphics/opengl/Fbo.h new file mode 100644 index 000000000..0fa6a9900 --- /dev/null +++ b/src/modules/graphics/opengl/Fbo.h @@ -0,0 +1,46 @@ +#ifndef LOVE_GRAPHICS_FBO_H +#define LOVE_GRAPHICS_FBO_H + +#include +#include +#include +#include "GLee.h" + +namespace love +{ +namespace graphics +{ +namespace opengl +{ + + class Fbo : public Drawable // Fbo vs. FBO? + { + public: + Fbo(int width, int height); + virtual ~Fbo(); + + GLenum status() const; //SERIOUS DISLIKE HERE + + void bind(); //DOUBTFUL ABOUT NAME + void unbind(); //Maybe start/stop? + //And what about clearing, clear() isn't entirely what I want either + //maybe make bind/start autoclear? + + virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const; + + private: + GLsizei width; + GLsizei height; + GLuint fbo; + GLuint depthbuffer; + GLuint img; + GLenum status_; + + vertex vertices[4]; + }; + +} // opengl +} // graphics +} // love + +#endif // LOVE_GRAPHICS_FBO_H diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 4a958a7f1..b8216a2fa 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -306,7 +306,7 @@ namespace opengl { SDL_GL_SwapBuffers(); } - + void Graphics::setIcon(Image * image) { Uint32 rmask, gmask, bmask, amask; @@ -470,6 +470,11 @@ namespace opengl return new ParticleSystem(image, size); } + Fbo * Graphics::newFbo(int width, int height) + { + return new Fbo(width, height); + } + void Graphics::setColor(Color c) { glColor4ubv(&c.r); diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 2eaeb80fd..04163475e 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -1,14 +1,14 @@ /** * Copyright (c) 2006-2010 LOVE Development Team -* +* * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. -* +* * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: -* +* * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be @@ -43,6 +43,7 @@ #include "Quad.h" #include "SpriteBatch.h" #include "ParticleSystem.h" +#include "Fbo.h" namespace love { @@ -95,13 +96,13 @@ namespace opengl // Default values. DisplayState() { - color.r = 255; - color.g = 255; - color.b = 255; + color.r = 255; + color.g = 255; + color.b = 255; color.a = 255; - backgroundColor.r = 0; - backgroundColor.g = 0; - backgroundColor.b = 0; + backgroundColor.r = 0; + backgroundColor.g = 0; + backgroundColor.b = 0; backgroundColor.a = 255; blendMode = Graphics::BLEND_ALPHA; colorMode = Graphics::COLOR_MODULATE; @@ -126,7 +127,7 @@ namespace opengl Graphics(); virtual ~Graphics(); - + // Implements Module. const char * getName() const; @@ -165,18 +166,18 @@ namespace opengl * when the game reloads. **/ void reset(); - + /** * Clears the screen. **/ void clear(); /** - * Flips buffers. (Rendered geometry is + * Flips buffers. (Rendered geometry is * presented on screen). **/ void present(); - + /** * Sets the window's icon. **/ @@ -207,13 +208,13 @@ namespace opengl /** * This native Lua function gets available modes * from SDL and returns them as a table on the following format: - * - * { - * { width = 800, height = 600 }, + * + * { + * { width = 800, height = 600 }, * { width = 1024, height = 768 }, * ... * } - * + * * Only fullscreen modes are returned here, as all * window sizes are supported (normally). **/ @@ -245,7 +246,7 @@ namespace opengl **/ Image * newImage(love::filesystem::File * file); Image * newImage(love::image::ImageData * data); - + /** * Creates a Frame **/ @@ -255,11 +256,13 @@ namespace opengl * Creates a Font object. **/ Font * newFont(love::font::FontData * data); - + SpriteBatch * newSpriteBatch(Image * image, int size, int usage); ParticleSystem * newParticleSystem(Image * image, int size); - + + Fbo * newFbo(int width, int height); + /** * Sets the foreground color. **/ @@ -271,7 +274,7 @@ namespace opengl Color getColor(); /** - * Sets the background Color. + * Sets the background Color. **/ void setBackgroundColor(Color c); @@ -383,7 +386,7 @@ namespace opengl PointStyle getPointStyle(); /** - * Gets the maximum point size supported. + * Gets the maximum point size supported. * This may vary from computer to computer. **/ int getMaxPointSize(); @@ -406,7 +409,7 @@ namespace opengl void print(const char * str, float x, float y , float angle); /** - * Draws text at the specified coordinates, with rotation and + * Draws text at the specified coordinates, with rotation and * scaling. * @param x The x-coordinate. * @param y The y-coordinate. @@ -416,7 +419,7 @@ namespace opengl void print(const char * str, float x, float y , float angle, float s); /** - * Draws text at the specified coordinates, with rotation and + * Draws text at the specified coordinates, with rotation and * scaling along both axes. * @param x The x-coordinate. * @param y The y-coordinate. @@ -452,7 +455,7 @@ namespace opengl * @param y2 Second y-coordinate. **/ void line(float x1, float y1, float x2, float y2); - + /** * Draws a series of lines connecting the given vertices. * @param ... Vertex components (x1, y1, x2, y2, etc.) diff --git a/src/modules/graphics/opengl/wrap_Fbo.cpp b/src/modules/graphics/opengl/wrap_Fbo.cpp new file mode 100644 index 000000000..3af9e6be9 --- /dev/null +++ b/src/modules/graphics/opengl/wrap_Fbo.cpp @@ -0,0 +1,58 @@ +#include "wrap_Fbo.h" + +namespace love +{ +namespace graphics +{ +namespace opengl +{ + Fbo * luax_checkfbo(lua_State * L, int idx) + { + return luax_checktype(L, idx, "Fbo", GRAPHICS_FBO_T); + } + + int w_Fbo_render(lua_State * L) + { + Fbo * fbo = luax_checkfbo(L, 1); + if (!lua_isfunction(L, 2)) + return luaL_error(L, "Need a function to render to fbo"); + + fbo->bind(); + + lua_settop(L, 2); // make sure the function is on top of the stack + lua_pcall(L, 0, 0, 0); + + fbo->unbind(); + + return 0; + } + + int w_Fbo_bind(lua_State * L) + { + Fbo * fbo = luax_checkfbo(L, 1); + fbo->bind(); + return 0; + } + + int w_Fbo_unbind(lua_State * L) + { + Fbo * fbo = luax_checkfbo(L, 1); + fbo->unbind(); + return 0; + } + + static const luaL_Reg functions[] = { + { "render", w_Fbo_render }, + { "bind", w_Fbo_bind }, + { "unbind", w_Fbo_unbind }, + { 0, 0 } + }; + + int luaopen_fbo(lua_State * L) + { + return luax_register_type(L, "Fbo", functions); + } + +} // opengl +} // graphics +} // love diff --git a/src/modules/graphics/opengl/wrap_Fbo.h b/src/modules/graphics/opengl/wrap_Fbo.h new file mode 100644 index 000000000..03454a74e --- /dev/null +++ b/src/modules/graphics/opengl/wrap_Fbo.h @@ -0,0 +1,25 @@ +#ifndef LOVE_GRAPHICS_OPENGL_WRAP_FBO_H +#define LOVE_GRAPHICS_OPENGL_WRAP_FBO_H + +// LOVE +#include +#include "Fbo.h" + +namespace love +{ +namespace graphics +{ +namespace opengl +{ + //see Fbo.h + Fbo * luax_checkfbo(lua_State * L, int idx); + int w_Fbo_render(lua_State * L); + int w_Fbo_bind(lua_State * L); + int w_Fbo_unbind(lua_State * L); + int luaopen_fbo(lua_State * L); + +} // opengl +} // graphics +} // love + +#endif // LOVE_GRAPHICS_OPENGL_WRAP_FBO_H diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 8b146f04b..f6b198f1d 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -84,7 +84,7 @@ namespace opengl instance->setIcon(image); return 0; } - + int w_setCaption(lua_State * L) { const char * str = luaL_checkstring(L, 1); @@ -292,6 +292,21 @@ namespace opengl return 1; } + int w_newFbo(lua_State * L) + { + int width, height; + width = luaL_checkint(L, 1); + height = luaL_checkint(L, 2); + Fbo * fbo = instance->newFbo(width, height); + + //and there we go with the status... still disliked + GLenum status = fbo->status(); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) + return luaL_error(L, "Cannot create FBO: %d", status); + luax_newtype(L, "Fbo", GRAPHICS_FBO_T, (void*)fbo); + return 1; + } + int w_setColor(lua_State * L) { Color c; @@ -829,6 +844,7 @@ namespace opengl { "newImageFont", w_newImageFont }, { "newSpriteBatch", w_newSpriteBatch }, { "newParticleSystem", w_newParticleSystem }, + { "newFbo", w_newFbo }, { "setColor", w_setColor }, { "getColor", w_getColor }, @@ -866,7 +882,7 @@ namespace opengl { "setCaption", w_setCaption }, { "getCaption", w_getCaption }, - + { "setIcon", w_setIcon }, { "getWidth", w_getWidth }, @@ -906,6 +922,7 @@ namespace opengl luaopen_frame, luaopen_spritebatch, luaopen_particlesystem, + luaopen_fbo, 0 }; diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index 2ad3a95f7..5dc7c6e47 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -1,14 +1,14 @@ /** * Copyright (c) 2006-2010 LOVE Development Team -* +* * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. -* +* * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: -* +* * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be @@ -28,6 +28,7 @@ #include "wrap_Quad.h" #include "wrap_SpriteBatch.h" #include "wrap_ParticleSystem.h" +#include "wrap_Fbo.h" #include "Graphics.h" namespace love @@ -58,6 +59,7 @@ namespace opengl int w_newImageFont(lua_State * L); int w_newSpriteBatch(lua_State * L); int w_newParticleSystem(lua_State * L); + int w_newFbo(lua_State * L); // commetns in function int w_setColor(lua_State * L); int w_getColor(lua_State * L); int w_setBackgroundColor(lua_State * L);