From 4102ae093c62399e39c67720e390c758e4766653 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 23 Nov 2010 19:56:28 -0200 Subject: [PATCH] FBO working as expected, render background on menu state --- src/engine.cpp | 2 ++ src/framebuffer.cpp | 75 ++++++++++++++++++++++++++++----------------- src/framebuffer.h | 11 ++++--- src/graphics.cpp | 14 +++++---- src/graphics.h | 11 +++---- src/main.cpp | 1 + src/menustate.cpp | 50 +++++++++++++++++++++++++++--- src/texture.cpp | 19 +++++++++--- src/texture.h | 5 ++- 9 files changed, 131 insertions(+), 57 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index cb7a838a..cb91aaac 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -68,6 +68,8 @@ void Engine::init() void Engine::terminate() { + changeState(NULL); + // save configs g_config.setValue("width", Platform::getWindowWidth()); g_config.setValue("height", Platform::getWindowHeight()); diff --git a/src/framebuffer.cpp b/src/framebuffer.cpp index 9e4762f9..5e3f1e53 100644 --- a/src/framebuffer.cpp +++ b/src/framebuffer.cpp @@ -24,25 +24,31 @@ #define GL_GLEXT_PROTOTYPES #include "framebuffer.h" +#include "platform.h" +#include "graphics.h" +#include "logger.h" #include #include -#include "platform.h" -#include "graphics.h" -FrameBuffer::FrameBuffer(int width, int height) : - m_fbo(0) +FrameBuffer::FrameBuffer(int width, int height) { + m_fbo = 0; m_width = width; m_height = height; - // texture where the framebuffer will be store - m_frameTexture = TexturePtr(new Texture(width, height, 4)); + // create FBO texture + glGenTextures(1, &m_fboTexture); + glBindTexture(GL_TEXTURE_2D, m_fboTexture); + glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // we want a smooth framebuffer - m_frameTexture->enableBilinearFilter(); + // we want bilinear filtering (for a smooth framebuffer) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // use FBO only if supported + // use FBO ext only if supported if(Platform::isExtensionSupported("EXT_framebuffer_object")) { m_fallbackOldImp = false; @@ -51,18 +57,14 @@ FrameBuffer::FrameBuffer(int width, int height) : glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); // attach 2D texture to this FBO - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_frameTexture->getTextureId(), 0); - - // must be called before checking - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_fboTexture, 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: //ok break; - default: + default: // fallback to old implementation m_fallbackOldImp = true; break; } @@ -74,6 +76,7 @@ FrameBuffer::FrameBuffer(int width, int height) : FrameBuffer::~FrameBuffer() { + glDeleteTextures(1, &m_fboTexture); if(m_fbo) glDeleteFramebuffersEXT(1, &m_fbo); } @@ -83,18 +86,21 @@ void FrameBuffer::bind() if(!m_fallbackOldImp) { // bind framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - - // must be called before rendering to framebuffer - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); } + // setup framebuffer viewport + glViewport(0, 0, m_width, m_height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0.0f, m_width, 0, m_height); + + // back to model view + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + // clear framebuffer glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); - - // setup framebuffer viewport - g_graphics.setViewport(m_width, m_height); } void FrameBuffer::unbind() @@ -102,19 +108,32 @@ void FrameBuffer::unbind() if(!m_fallbackOldImp) { // bind back buffer again glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - - // must be called to render to back buffer again glDrawBuffer(GL_BACK); glReadBuffer(GL_BACK); + + // restore graphics viewport + g_graphics.restoreViewport(); } else { // copy screen to texture - m_frameTexture->copyFromScreen(0, 0, 0, 0, m_width, m_height); + glBindTexture(GL_TEXTURE_2D, m_fboTexture); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_width, m_height); + + // restore graphics viewport + g_graphics.restoreViewport(); // clear screen - glClearColor(0.0, 0.0, 0.0, 0.0); + glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); } +} - // restore graphics viewport - g_graphics.restoreViewport(); +void FrameBuffer::draw(int x, int y, int width, int height) +{ + glBindTexture(GL_TEXTURE_2D, m_fboTexture); + glBegin(GL_QUADS); + glTexCoord2i(0, 0); glVertex2i(x, y); + glTexCoord2i(0, 1); glVertex2i(x, y+height); + glTexCoord2i(1, 1); glVertex2i(x+width, y+height); + glTexCoord2i(1, 0); glVertex2i(x+width, y); + glEnd(); } diff --git a/src/framebuffer.h b/src/framebuffer.h index 32ebfca3..ed4fe509 100644 --- a/src/framebuffer.h +++ b/src/framebuffer.h @@ -25,24 +25,25 @@ #ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H -#include "texture.h" +#include class FrameBuffer { +public: FrameBuffer(int width, int height); virtual ~FrameBuffer(); - /// Return the texture where everything was drawn - TexturePtr getFramebufferTexture(); - /// Bind the framebuffer, everything rendered will be draw on it void bind(); /// Unbind the framebuffer, render on back buffer again void unbind(); + /// Draw framebuffer + void draw(int x, int y, int width, int height); + private: - TexturePtr m_frameTexture; + GLuint m_fboTexture; GLuint m_fbo; bool m_fallbackOldImp; int m_width; diff --git a/src/graphics.cpp b/src/graphics.cpp index ee967661..34a47a58 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -27,6 +27,7 @@ #include #include +#include "texture.h" Graphics g_graphics; @@ -43,10 +44,10 @@ Graphics::~Graphics() void Graphics::init() { // setup opengl - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // black background - glEnable(GL_ALPHA_TEST); // enable alpha + glEnable(GL_ALPHA_TEST); // enable alpha by default glAlphaFunc(GL_GREATER, 0.0f); // default alpha mode glDisable(GL_DEPTH_TEST); // we are rendering 2D only, we don't need it + glEnable(GL_TEXTURE_2D); // enable textures by default notice("GPU %s", (const char*)glGetString(GL_RENDERER)); notice("OpenGL %s", (const char*)glGetString(GL_VERSION)); @@ -64,13 +65,13 @@ void Graphics::resize(int width, int height) restoreViewport(); } -void Graphics::setViewport(int width, int height) +void Graphics::restoreViewport() { // resize gl viewport - glViewport(0, 0, width, height); + glViewport(0, 0, m_width, m_height); /* - 0 ,0---------0,w** + 0,0---------0,w | | | | | | @@ -79,7 +80,7 @@ void Graphics::setViewport(int width, int height) // setup view region like above glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluOrtho2D(0.0f, width, height, 0.0f); + gluOrtho2D(0.0f, m_width, m_height, 0.0f); // back to model view glMatrixMode(GL_MODELVIEW); @@ -88,6 +89,7 @@ void Graphics::setViewport(int width, int height) void Graphics::beginRender() { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); } diff --git a/src/graphics.h b/src/graphics.h index 57f772e2..1f885490 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -25,6 +25,8 @@ #ifndef GRAPHICS_H #define GRAPHICS_H +class Texture; + class Graphics { public: @@ -37,18 +39,15 @@ public: /// Called after every window resize void resize(int width, int height); + /// Restore original viewport + void restoreViewport(); + /// Called before every render void beginRender(); /// Called after every render void endRender(); - /// Restore original viewport - void restoreViewport() { setViewport(m_width, m_height); } - - /// Set viewport, used by FrameBuffer - void setViewport(int width, int height); - int getWidth() { return m_width; } int getHeight() { return m_height; } diff --git a/src/main.cpp b/src/main.cpp index 5ec5b984..b4b19708 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,6 +70,7 @@ int main(int argc, const char *argv[]) g_resources.init(argv[0]); if(g_resources.setWriteDir(Platform::getAppUserDir())) g_resources.addToSearchPath(Platform::getAppUserDir()); + g_resources.addToSearchPath("data"); // before loading configurations set the default ones setDefaultConfigs(); diff --git a/src/menustate.cpp b/src/menustate.cpp index 8b8d258c..d7edbbb1 100644 --- a/src/menustate.cpp +++ b/src/menustate.cpp @@ -26,9 +26,15 @@ #include "framebuffer.h" #include "graphics.h" #include "texturemanager.h" +#include "logger.h" +#include "engine.h" + +FrameBuffer *fbo; +TexturePtr background; MenuState::MenuState() { + } MenuState::~MenuState() @@ -38,7 +44,8 @@ MenuState::~MenuState() void MenuState::onEnter() { - + background = g_textures.get("background.png"); + background->enableBilinearFilter(); } void MenuState::onLeave() @@ -48,17 +55,52 @@ void MenuState::onLeave() void MenuState::onClose() { - + g_engine.stop(); } void MenuState::onInputEvent(InputEvent* event) { - } void MenuState::render() { - + // draw background + background->bind(); + + int x = 0; + int y = 0; + int screenWidth = g_graphics.getWidth(); + int screenHeight = g_graphics.getHeight(); + int textureWidth = background->getWidth(); + int textureHeight = background->getHeight(); + + int texCoordX; + int texCoordY; + int texCoordWidth; + int texCoordHeight; + + int wantedWidth = 1240; + int wantedHeight = 880; + + float originalRatio = (float)wantedWidth/wantedHeight; + float screenRatio = (float)screenWidth/screenHeight; + if(screenRatio >= originalRatio) { + texCoordHeight = wantedHeight; + texCoordWidth = std::min((int)(wantedHeight*screenRatio), textureWidth); + } else { + texCoordWidth = wantedWidth; + texCoordHeight = std::min((int)(wantedWidth/screenRatio), textureHeight); + } + texCoordX = textureWidth - texCoordWidth; + texCoordY = textureHeight - texCoordHeight; + + + glBegin(GL_QUADS); + glTexCoord2f((float)texCoordX/textureWidth, (float)texCoordY/textureHeight); glVertex2i(x, y); + glTexCoord2f((float)texCoordX/textureWidth, (float)(texCoordY+texCoordHeight)/textureHeight); glVertex2i(x, y+screenHeight); + glTexCoord2f((float)(texCoordX+texCoordWidth)/textureWidth, (float)(texCoordY+texCoordHeight)/textureHeight); glVertex2i(x+screenWidth, y+screenHeight); + glTexCoord2f((float)(texCoordX+texCoordWidth)/textureWidth, (float)texCoordY/textureHeight); glVertex2i(x+screenWidth, y); + glEnd(); } void MenuState::update(int elapsedTicks) diff --git a/src/texture.cpp b/src/texture.cpp index baac399a..a47f3aee 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -62,7 +62,7 @@ Texture::Texture(int width, int height, int components, unsigned char *pixels) Texture::~Texture() { - if(m_textureId > 0) + if(m_textureId) glDeleteTextures(1, &m_textureId); } @@ -73,14 +73,23 @@ void Texture::bind() void Texture::enableBilinearFilter() { - bind(); + glBindTexture(GL_TEXTURE_2D, m_textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } -void Texture::copyFromScreen(int xoffset, int yoffset, int x, int y, int width, int height) +void Texture::draw(int x, int y) { - bind(); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height); + draw(x, y, m_width, m_height); } +void Texture::draw(int x, int y, int width, int height) +{ + glBindTexture(GL_TEXTURE_2D, m_textureId); + glBegin(GL_QUADS); + glTexCoord2i(0, 0); glVertex2i(x, y); + glTexCoord2i(0, 1); glVertex2i(x, y+height); + glTexCoord2i(1, 1); glVertex2i(x+width, y+height); + glTexCoord2i(1, 0); glVertex2i(x+width, y); + glEnd(); +} diff --git a/src/texture.h b/src/texture.h index 5c105782..096a7658 100644 --- a/src/texture.h +++ b/src/texture.h @@ -43,12 +43,11 @@ public: /// Enable texture bilinear filter (smooth scaled textures) void enableBilinearFilter(); - /// Copy screen pixels to texture - void copyFromScreen(int xoffset, int yoffset, int x, int y, int width, int height); + void draw(int x, int y); + void draw(int x, int y, int width, int height); int getWidth() const { return m_width; } int getHeight() const { return m_height; } - GLuint getTextureId() const { return m_textureId; } private: GLuint m_textureId;