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()
{
changeState(NULL);
// save configs
g_config.setValue("width", Platform::getWindowWidth());
g_config.setValue("height", Platform::getWindowHeight());

View File

@ -24,25 +24,31 @@
#define GL_GLEXT_PROTOTYPES
#include "framebuffer.h"
#include "platform.h"
#include "graphics.h"
#include "logger.h"
#include <GL/glext.h>
#include <GL/glu.h>
#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();
}

View File

@ -25,24 +25,25 @@
#ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H
#include "texture.h"
#include <GL/gl.h>
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;

View File

@ -27,6 +27,7 @@
#include <GL/gl.h>
#include <GL/glu.h>
#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();
}

View File

@ -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; }

View File

@ -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();

View File

@ -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)

View File

@ -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();
}

View File

@ -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;