FBO working as expected, render background on menu state

This commit is contained in:
Eduardo Bart 2010-11-23 19:56:28 -02:00
parent 4b2886ebec
commit 4102ae093c
9 changed files with 131 additions and 57 deletions

View File

@ -68,6 +68,8 @@ void Engine::init()
void Engine::terminate() void Engine::terminate()
{ {
changeState(NULL);
// save configs // save configs
g_config.setValue("width", Platform::getWindowWidth()); g_config.setValue("width", Platform::getWindowWidth());
g_config.setValue("height", Platform::getWindowHeight()); g_config.setValue("height", Platform::getWindowHeight());

View File

@ -24,25 +24,31 @@
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include "framebuffer.h" #include "framebuffer.h"
#include "platform.h"
#include "graphics.h"
#include "logger.h"
#include <GL/glext.h> #include <GL/glext.h>
#include <GL/glu.h> #include <GL/glu.h>
#include "platform.h"
#include "graphics.h"
FrameBuffer::FrameBuffer(int width, int height) : FrameBuffer::FrameBuffer(int width, int height)
m_fbo(0)
{ {
m_fbo = 0;
m_width = width; m_width = width;
m_height = height; m_height = height;
// texture where the framebuffer will be store // create FBO texture
m_frameTexture = TexturePtr(new Texture(width, height, 4)); 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 // we want bilinear filtering (for a smooth framebuffer)
m_frameTexture->enableBilinearFilter(); 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")) { if(Platform::isExtensionSupported("EXT_framebuffer_object")) {
m_fallbackOldImp = false; m_fallbackOldImp = false;
@ -51,18 +57,14 @@ FrameBuffer::FrameBuffer(int width, int height) :
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
// attach 2D texture to this FBO // attach 2D texture to this FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_frameTexture->getTextureId(), 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_fboTexture, 0);
// must be called before checking
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status) { switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT: case GL_FRAMEBUFFER_COMPLETE_EXT:
//ok //ok
break; break;
default: default: // fallback to old implementation
m_fallbackOldImp = true; m_fallbackOldImp = true;
break; break;
} }
@ -74,6 +76,7 @@ FrameBuffer::FrameBuffer(int width, int height) :
FrameBuffer::~FrameBuffer() FrameBuffer::~FrameBuffer()
{ {
glDeleteTextures(1, &m_fboTexture);
if(m_fbo) if(m_fbo)
glDeleteFramebuffersEXT(1, &m_fbo); glDeleteFramebuffersEXT(1, &m_fbo);
} }
@ -83,18 +86,21 @@ void FrameBuffer::bind()
if(!m_fallbackOldImp) { if(!m_fallbackOldImp) {
// bind framebuffer // bind framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); 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 // clear framebuffer
glClearColor(0.0, 0.0, 0.0, 0.0); glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
// setup framebuffer viewport
g_graphics.setViewport(m_width, m_height);
} }
void FrameBuffer::unbind() void FrameBuffer::unbind()
@ -102,19 +108,32 @@ void FrameBuffer::unbind()
if(!m_fallbackOldImp) { if(!m_fallbackOldImp) {
// bind back buffer again // bind back buffer again
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// must be called to render to back buffer again
glDrawBuffer(GL_BACK); glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
} else {
// copy screen to texture
m_frameTexture->copyFromScreen(0, 0, 0, 0, m_width, m_height);
// clear screen
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
// restore graphics viewport // restore graphics viewport
g_graphics.restoreViewport(); g_graphics.restoreViewport();
} else {
// copy screen to texture
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, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
}
}
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();
} }

View File

@ -25,24 +25,25 @@
#ifndef FRAMEBUFFER_H #ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H #define FRAMEBUFFER_H
#include "texture.h" #include <GL/gl.h>
class FrameBuffer class FrameBuffer
{ {
public:
FrameBuffer(int width, int height); FrameBuffer(int width, int height);
virtual ~FrameBuffer(); virtual ~FrameBuffer();
/// Return the texture where everything was drawn
TexturePtr getFramebufferTexture();
/// Bind the framebuffer, everything rendered will be draw on it /// Bind the framebuffer, everything rendered will be draw on it
void bind(); void bind();
/// Unbind the framebuffer, render on back buffer again /// Unbind the framebuffer, render on back buffer again
void unbind(); void unbind();
/// Draw framebuffer
void draw(int x, int y, int width, int height);
private: private:
TexturePtr m_frameTexture; GLuint m_fboTexture;
GLuint m_fbo; GLuint m_fbo;
bool m_fallbackOldImp; bool m_fallbackOldImp;
int m_width; int m_width;

View File

@ -27,6 +27,7 @@
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>
#include "texture.h"
Graphics g_graphics; Graphics g_graphics;
@ -43,10 +44,10 @@ Graphics::~Graphics()
void Graphics::init() void Graphics::init()
{ {
// setup opengl // setup opengl
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // black background glEnable(GL_ALPHA_TEST); // enable alpha by default
glEnable(GL_ALPHA_TEST); // enable alpha
glAlphaFunc(GL_GREATER, 0.0f); // default alpha mode glAlphaFunc(GL_GREATER, 0.0f); // default alpha mode
glDisable(GL_DEPTH_TEST); // we are rendering 2D only, we don't need it 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("GPU %s", (const char*)glGetString(GL_RENDERER));
notice("OpenGL %s", (const char*)glGetString(GL_VERSION)); notice("OpenGL %s", (const char*)glGetString(GL_VERSION));
@ -64,13 +65,13 @@ void Graphics::resize(int width, int height)
restoreViewport(); restoreViewport();
} }
void Graphics::setViewport(int width, int height) void Graphics::restoreViewport()
{ {
// resize gl viewport // 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 // setup view region like above
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
gluOrtho2D(0.0f, width, height, 0.0f); gluOrtho2D(0.0f, m_width, m_height, 0.0f);
// back to model view // back to model view
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
@ -88,6 +89,7 @@ void Graphics::setViewport(int width, int height)
void Graphics::beginRender() void Graphics::beginRender()
{ {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity(); glLoadIdentity();
} }

View File

@ -25,6 +25,8 @@
#ifndef GRAPHICS_H #ifndef GRAPHICS_H
#define GRAPHICS_H #define GRAPHICS_H
class Texture;
class Graphics class Graphics
{ {
public: public:
@ -37,18 +39,15 @@ public:
/// Called after every window resize /// Called after every window resize
void resize(int width, int height); void resize(int width, int height);
/// Restore original viewport
void restoreViewport();
/// Called before every render /// Called before every render
void beginRender(); void beginRender();
/// Called after every render /// Called after every render
void endRender(); 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 getWidth() { return m_width; }
int getHeight() { return m_height; } int getHeight() { return m_height; }

View File

@ -70,6 +70,7 @@ int main(int argc, const char *argv[])
g_resources.init(argv[0]); g_resources.init(argv[0]);
if(g_resources.setWriteDir(Platform::getAppUserDir())) if(g_resources.setWriteDir(Platform::getAppUserDir()))
g_resources.addToSearchPath(Platform::getAppUserDir()); g_resources.addToSearchPath(Platform::getAppUserDir());
g_resources.addToSearchPath("data");
// before loading configurations set the default ones // before loading configurations set the default ones
setDefaultConfigs(); setDefaultConfigs();

View File

@ -26,9 +26,15 @@
#include "framebuffer.h" #include "framebuffer.h"
#include "graphics.h" #include "graphics.h"
#include "texturemanager.h" #include "texturemanager.h"
#include "logger.h"
#include "engine.h"
FrameBuffer *fbo;
TexturePtr background;
MenuState::MenuState() MenuState::MenuState()
{ {
} }
MenuState::~MenuState() MenuState::~MenuState()
@ -38,7 +44,8 @@ MenuState::~MenuState()
void MenuState::onEnter() void MenuState::onEnter()
{ {
background = g_textures.get("background.png");
background->enableBilinearFilter();
} }
void MenuState::onLeave() void MenuState::onLeave()
@ -48,17 +55,52 @@ void MenuState::onLeave()
void MenuState::onClose() void MenuState::onClose()
{ {
g_engine.stop();
} }
void MenuState::onInputEvent(InputEvent* event) void MenuState::onInputEvent(InputEvent* event)
{ {
} }
void MenuState::render() 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) void MenuState::update(int elapsedTicks)

View File

@ -62,7 +62,7 @@ Texture::Texture(int width, int height, int components, unsigned char *pixels)
Texture::~Texture() Texture::~Texture()
{ {
if(m_textureId > 0) if(m_textureId)
glDeleteTextures(1, &m_textureId); glDeleteTextures(1, &m_textureId);
} }
@ -73,14 +73,23 @@ void Texture::bind()
void Texture::enableBilinearFilter() 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_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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(); draw(x, y, m_width, m_height);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, 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();
}

View File

@ -43,12 +43,11 @@ public:
/// Enable texture bilinear filter (smooth scaled textures) /// Enable texture bilinear filter (smooth scaled textures)
void enableBilinearFilter(); void enableBilinearFilter();
/// Copy screen pixels to texture void draw(int x, int y);
void copyFromScreen(int xoffset, int yoffset, int x, int y, int width, int height); void draw(int x, int y, int width, int height);
int getWidth() const { return m_width; } int getWidth() const { return m_width; }
int getHeight() const { return m_height; } int getHeight() const { return m_height; }
GLuint getTextureId() const { return m_textureId; }
private: private:
GLuint m_textureId; GLuint m_textureId;