mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
Merged in fbos
This commit is contained in:
@@ -0,0 +1,324 @@
|
||||
#include "Framebuffer.h"
|
||||
#include <common/Matrix.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
// functions to get opengl capabilities at runtime
|
||||
vector<string> tokenize(const string& str)
|
||||
{
|
||||
vector<string> tokens;
|
||||
|
||||
istringstream iss( str );
|
||||
copy(istream_iterator<string>(iss), istream_iterator<string>(),
|
||||
back_inserter< vector<string> >(tokens));
|
||||
return tokens;
|
||||
}
|
||||
|
||||
float getOpenGLVersionNumber()
|
||||
{
|
||||
vector<string> tokens = tokenize( (const char*)glGetString(GL_VERSION) );
|
||||
stringstream toNumber( tokens.at(0) );
|
||||
|
||||
double version;
|
||||
toNumber >> version;
|
||||
return version;
|
||||
}
|
||||
|
||||
bool hasFramebufferExtension()
|
||||
{
|
||||
vector<string> ext = tokenize( (const char*)glGetString(GL_EXTENSIONS) );
|
||||
return find(ext.begin(), ext.end(), "GL_EXT_framebuffer_object") != ext.end();
|
||||
}
|
||||
|
||||
|
||||
// strategy for fbo creation, interchangable at runtime:
|
||||
// none, opengl >= 3.0, extensions
|
||||
struct FramebufferStrategy {
|
||||
/// create a new framebuffer, depthbuffer and texture
|
||||
/**
|
||||
* @param[out] framebuffer Framebuffer name
|
||||
* @param[out] depthbuffer Depthbuffer name
|
||||
* @param[out] img Texture name
|
||||
* @param[in] width Width of framebuffer
|
||||
* @param[in] height Height of framebuffer
|
||||
* @return Creation status
|
||||
*/
|
||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
||||
{ return GL_FRAMEBUFFER_UNSUPPORTED; }
|
||||
/// remove objects
|
||||
/**
|
||||
* @param[in] framebuffer Framebuffer name
|
||||
* @param[in] depthbuffer Depthbuffer name
|
||||
* @param[in] img Texture name
|
||||
*/
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img) {}
|
||||
virtual void bindFBO(GLuint framebuffer) {}
|
||||
};
|
||||
|
||||
#ifdef GL_VERSION_3_0
|
||||
struct FramebufferStrategyGL3 : public FramebufferStrategy {
|
||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
||||
{
|
||||
// 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, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, img, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_RENDERBUFFER, depthbuffer);
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
// unbind buffers and texture
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
return status;
|
||||
}
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
||||
{
|
||||
glDeleteTextures(1, &img);
|
||||
glDeleteRenderbuffers(1, &depthbuffer);
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
}
|
||||
|
||||
virtual void bindFBO(GLuint framebuffer)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct FramebufferStrategyEXT : public FramebufferStrategy {
|
||||
|
||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
||||
{
|
||||
// generate depth buffer
|
||||
glGenRenderbuffersEXT(1, &depthbuffer);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 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
|
||||
glGenFramebuffersEXT(1, &framebuffer);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D, img, 0);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, depthbuffer);
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
|
||||
// unbind buffers and texture
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
||||
{
|
||||
glDeleteTextures(1, &img);
|
||||
glDeleteRenderbuffersEXT(1, &depthbuffer);
|
||||
glDeleteFramebuffersEXT(1, &framebuffer);
|
||||
}
|
||||
|
||||
virtual void bindFBO(GLuint framebuffer)
|
||||
{
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||
}
|
||||
};
|
||||
|
||||
FramebufferStrategy* strategy = NULL;
|
||||
|
||||
FramebufferStrategy strategyNone;
|
||||
#ifdef GL_VERSION_3_0
|
||||
FramebufferStrategyGL3 strategyGL3;
|
||||
#endif
|
||||
FramebufferStrategyEXT strategyEXT;
|
||||
|
||||
};
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace opengl
|
||||
{
|
||||
Framebuffer* Framebuffer::current = NULL;
|
||||
|
||||
Framebuffer::Framebuffer(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;
|
||||
|
||||
if (!strategy) {
|
||||
#ifdef GL_VERSION_3_0
|
||||
if (getOpenGLVersionNumber() >= 3.0)
|
||||
strategy = &strategyGL3;
|
||||
else if (hasFramebufferExtension())
|
||||
#else
|
||||
if (hasFramebufferExtension())
|
||||
#endif
|
||||
strategy = &strategyEXT;
|
||||
else
|
||||
strategy = &strategyNone;
|
||||
|
||||
}
|
||||
|
||||
loadVolatile();
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer()
|
||||
{
|
||||
// reset framebuffer if still using this one
|
||||
if (current == this)
|
||||
stopGrab();
|
||||
|
||||
unloadVolatile();
|
||||
}
|
||||
|
||||
void Framebuffer::bindDefaultBuffer()
|
||||
{
|
||||
if (current != NULL)
|
||||
current->stopGrab();
|
||||
}
|
||||
|
||||
void Framebuffer::startGrab()
|
||||
{
|
||||
// already grabbing
|
||||
if (current == this)
|
||||
return;
|
||||
|
||||
// cleanup after previous fbo
|
||||
if (current != NULL)
|
||||
glPopAttrib();
|
||||
|
||||
// bind buffer and clear screen
|
||||
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
strategy->bindFBO(fbo);
|
||||
glClearColor(.0f, .0f, .0f, .0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
// indicate we are using this fbo
|
||||
current = this;
|
||||
}
|
||||
|
||||
void Framebuffer::stopGrab()
|
||||
{
|
||||
// i am not grabbing. leave me alone
|
||||
if (current != this)
|
||||
return;
|
||||
|
||||
// bind default
|
||||
strategy->bindFBO( 0 );
|
||||
glPopAttrib();
|
||||
current = NULL;
|
||||
}
|
||||
|
||||
void Framebuffer::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();
|
||||
}
|
||||
|
||||
love::image::ImageData * Framebuffer::getImageData(love::image::Image * image)
|
||||
{
|
||||
int row = 4 * width;
|
||||
int size = row * height;
|
||||
|
||||
// see Graphics::newScreenshot. OpenGL reads from lower-left,
|
||||
// but we need the pixels from upper-left.
|
||||
GLubyte* pixels = new GLubyte[size];
|
||||
GLubyte* screenshot = new GLubyte[size];
|
||||
|
||||
strategy->bindFBO( fbo );
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
if (current)
|
||||
strategy->bindFBO( current->fbo );
|
||||
else
|
||||
strategy->bindFBO( 0 );
|
||||
|
||||
GLubyte* src = pixels - row; // second line of buffer
|
||||
GLubyte* dst = screenshot + size; // end of buffer
|
||||
|
||||
for (int i = 0; i < height; ++i)
|
||||
memcpy(dst -= row, src += row, row);
|
||||
|
||||
love::image::ImageData * img = image->newImageData(width, height, (void*)screenshot);
|
||||
|
||||
delete[] screenshot;
|
||||
delete[] pixels;
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
bool Framebuffer::loadVolatile()
|
||||
{
|
||||
status = strategy->createFBO(fbo, depthbuffer, img, width, height);
|
||||
return (status == GL_FRAMEBUFFER_COMPLETE);
|
||||
}
|
||||
|
||||
void Framebuffer::unloadVolatile()
|
||||
{
|
||||
strategy->deleteFBO(fbo, depthbuffer, img);
|
||||
}
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef LOVE_GRAPHICS_FRAMEBUFFER_H
|
||||
#define LOVE_GRAPHICS_FRAMEBUFFER_H
|
||||
|
||||
#include <graphics/Drawable.h>
|
||||
#include <graphics/Volatile.h>
|
||||
#include <image/Image.h>
|
||||
#include <image/ImageData.h>
|
||||
#include <common/math.h>
|
||||
#include <map>
|
||||
#include "GLee.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
class Framebuffer : public Drawable, public Volatile
|
||||
{
|
||||
public:
|
||||
Framebuffer(int width, int height);
|
||||
virtual ~Framebuffer();
|
||||
|
||||
unsigned int getStatus() const { return status; }
|
||||
|
||||
static Framebuffer* current;
|
||||
static void bindDefaultBuffer();
|
||||
|
||||
void startGrab();
|
||||
void stopGrab();
|
||||
|
||||
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
|
||||
love::image::ImageData * getImageData(love::image::Image * image);
|
||||
|
||||
bool loadVolatile();
|
||||
void unloadVolatile();
|
||||
|
||||
private:
|
||||
GLsizei width;
|
||||
GLsizei height;
|
||||
GLuint fbo;
|
||||
GLuint depthbuffer;
|
||||
GLuint img;
|
||||
|
||||
vertex vertices[4];
|
||||
|
||||
GLenum status;
|
||||
};
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
#endif // LOVE_GRAPHICS_FRAMEBUFFER_H
|
||||
@@ -477,6 +477,11 @@ namespace opengl
|
||||
return new ParticleSystem(image, size);
|
||||
}
|
||||
|
||||
Framebuffer * Graphics::newFramebuffer(int width, int height)
|
||||
{
|
||||
return new Framebuffer(width, height);
|
||||
}
|
||||
|
||||
void Graphics::setColor(Color c)
|
||||
{
|
||||
glColor4ubv(&c.r);
|
||||
|
||||
@@ -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 "Framebuffer.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);
|
||||
|
||||
|
||||
Framebuffer * newFramebuffer(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.)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "wrap_Framebuffer.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace opengl
|
||||
{
|
||||
Framebuffer * luax_checkfbo(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<Framebuffer>(L, idx, "Framebuffer", GRAPHICS_FRAMEBUFFER_T);
|
||||
}
|
||||
|
||||
int w_Framebuffer_renderTo(lua_State * L)
|
||||
{
|
||||
// As startGrab() clears the framebuffer, better not allow
|
||||
// grabbing inside another grabbing
|
||||
if (Framebuffer::current != NULL) {
|
||||
Framebuffer::bindDefaultBuffer();
|
||||
return luaL_error(L, "Current render target not the default framebuffer!");
|
||||
}
|
||||
|
||||
Framebuffer * fbo = luax_checkfbo(L, 1);
|
||||
if (!lua_isfunction(L, 2))
|
||||
return luaL_error(L, "Need a function to render to fbo");
|
||||
|
||||
fbo->startGrab();
|
||||
lua_settop(L, 2); // make sure the function is on top of the stack
|
||||
lua_call(L, 0, 0);
|
||||
fbo->stopGrab();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Framebuffer_getImageData(lua_State * L)
|
||||
{
|
||||
Framebuffer * fbo = luax_checkfbo(L, 1);
|
||||
love::image::Image * image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
|
||||
love::image::ImageData * img = fbo->getImageData( image );
|
||||
luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)img);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] = {
|
||||
{ "renderTo", w_Framebuffer_renderTo },
|
||||
{ "getImageData", w_Framebuffer_getImageData },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
int luaopen_framebuffer(lua_State * L)
|
||||
{
|
||||
return luax_register_type(L, "Framebuffer", functions);
|
||||
}
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_FBO_H
|
||||
#define LOVE_GRAPHICS_OPENGL_WRAP_FBO_H
|
||||
|
||||
// LOVE
|
||||
#include <common/runtime.h>
|
||||
#include "Framebuffer.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace opengl
|
||||
{
|
||||
//see Framebuffer.h
|
||||
Framebuffer * luax_checkfbo(lua_State * L, int idx);
|
||||
int w_Framebuffer_renderTo(lua_State * L);
|
||||
int w_Framebuffer_getImageData(lua_State * L);
|
||||
int luaopen_framebuffer(lua_State * L);
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
#endif // LOVE_GRAPHICS_OPENGL_WRAP_FBO_H
|
||||
@@ -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,46 @@ namespace opengl
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newFramebuffer(lua_State * L)
|
||||
{
|
||||
// check if width and height are given. else default to screen dimensions.
|
||||
int width = luaL_optint(L, 1, instance->getWidth());
|
||||
int height = luaL_optint(L, 2, instance->getHeight());
|
||||
glGetError(); // clear opengl error flag
|
||||
Framebuffer * framebuffer = instance->newFramebuffer(width, height);
|
||||
|
||||
//and there we go with the status... still disliked
|
||||
if (framebuffer->getStatus() != GL_FRAMEBUFFER_COMPLETE) {
|
||||
switch (framebuffer->getStatus()) {
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED:
|
||||
return luaL_error(L, "Cannot create Framebuffer: "
|
||||
"Not supported by your OpenGL implementation");
|
||||
// remaining error codes are highly unlikely:
|
||||
case GL_FRAMEBUFFER_UNDEFINED:
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
|
||||
return luaL_error(L, "Cannot create Framebuffer: "
|
||||
"Error in implementation (please inform the love devs)");
|
||||
default:
|
||||
// my intel hda card wrongly returns 0 to glCheckFramebufferStatus() but sets
|
||||
// no error flag. I think it meant to return GL_FRAMEBUFFER_UNSUPPORTED, but who
|
||||
// knows.
|
||||
if (glGetError() == GL_NO_ERROR)
|
||||
return luaL_error(L, "Cannot create Framebuffer: "
|
||||
"May not be supported by your OpenGL implementation.");
|
||||
// the remaining error is an indication of a serious fuckup since it should
|
||||
// only be returned if glCheckFramebufferStatus() was called with the wrong
|
||||
// arguments.
|
||||
return luaL_error(L, "Cannot create Framebuffer: Aliens did it (OpenGL error code: %d)", glGetError());
|
||||
}
|
||||
}
|
||||
luax_newtype(L, "Framebuffer", GRAPHICS_FRAMEBUFFER_T, (void*)framebuffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_setColor(lua_State * L)
|
||||
{
|
||||
Color c;
|
||||
@@ -567,6 +607,21 @@ namespace opengl
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_setRenderTarget(lua_State * L)
|
||||
{
|
||||
// called with nil or none -> reset to default buffer
|
||||
if (lua_isnoneornil(L,1)) {
|
||||
Framebuffer::bindDefaultBuffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Framebuffer * fbo = luax_checkfbo(L, 1);
|
||||
// this unbinds the previous fbo
|
||||
fbo->startGrab();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws an Image at the specified coordinates, with rotation and
|
||||
* scaling along both axes.
|
||||
@@ -829,6 +884,7 @@ namespace opengl
|
||||
{ "newImageFont", w_newImageFont },
|
||||
{ "newSpriteBatch", w_newSpriteBatch },
|
||||
{ "newParticleSystem", w_newParticleSystem },
|
||||
{ "newFramebuffer", w_newFramebuffer },
|
||||
|
||||
{ "setColor", w_setColor },
|
||||
{ "getColor", w_getColor },
|
||||
@@ -856,6 +912,7 @@ namespace opengl
|
||||
{ "getPointStyle", w_getPointStyle },
|
||||
{ "getMaxPointSize", w_getMaxPointSize },
|
||||
{ "newScreenshot", w_newScreenshot },
|
||||
{ "setRenderTarget", w_setRenderTarget },
|
||||
|
||||
{ "draw", w_draw },
|
||||
{ "drawq", w_drawq },
|
||||
@@ -866,7 +923,7 @@ namespace opengl
|
||||
|
||||
{ "setCaption", w_setCaption },
|
||||
{ "getCaption", w_getCaption },
|
||||
|
||||
|
||||
{ "setIcon", w_setIcon },
|
||||
|
||||
{ "getWidth", w_getWidth },
|
||||
@@ -906,6 +963,7 @@ namespace opengl
|
||||
luaopen_frame,
|
||||
luaopen_spritebatch,
|
||||
luaopen_particlesystem,
|
||||
luaopen_framebuffer,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
@@ -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_Framebuffer.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_newFramebuffer(lua_State * L); // commetns in function
|
||||
int w_setColor(lua_State * L);
|
||||
int w_getColor(lua_State * L);
|
||||
int w_setBackgroundColor(lua_State * L);
|
||||
@@ -82,6 +84,7 @@ namespace opengl
|
||||
int w_getPointStyle(lua_State * L);
|
||||
int w_getMaxPointSize(lua_State * L);
|
||||
int w_newScreenshot(lua_State * L);
|
||||
int w_setRenderTarget(lua_State * L);
|
||||
int w_draw(lua_State * L);
|
||||
int w_drawq(lua_State * L);
|
||||
int w_drawTest(lua_State * L);
|
||||
|
||||
Reference in New Issue
Block a user