changed PixelEffect name to ShaderEffect, added lua-side support for vert/frag shader combinations with love.graphics.newShaderEffect, added tentative support for single-file vertex+fragment shaders

This commit is contained in:
Alexander Szpakowski
2012-12-20 21:51:31 -04:00
parent 28e3b105e9
commit 0611234067
18 changed files with 434 additions and 233 deletions
+1 -1
View File
@@ -157,7 +157,7 @@ StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::suppor
{
{ "canvas", Graphics::SUPPORT_CANVAS },
{ "hdrcanvas", Graphics::SUPPORT_HDR_CANVAS },
{ "pixeleffect", Graphics::SUPPORT_PIXELEFFECT },
{ "shadereffect", Graphics::SUPPORT_SHADEREFFECT },
{ "npot", Graphics::SUPPORT_NPOT },
{ "subtractive", Graphics::SUPPORT_SUBTRACTIVE },
};
+1 -1
View File
@@ -86,7 +86,7 @@ public:
{
SUPPORT_CANVAS = 1,
SUPPORT_HDR_CANVAS,
SUPPORT_PIXELEFFECT,
SUPPORT_SHADEREFFECT,
SUPPORT_NPOT,
SUPPORT_SUBTRACTIVE,
SUPPORT_MAX_ENUM
+1 -1
View File
@@ -96,7 +96,7 @@ public:
static void bindDefaultCanvas();
private:
friend class PixelEffect;
friend class ShaderEffect;
GLuint getTextureName() const
{
return img;
+4 -4
View File
@@ -190,7 +190,7 @@ void Graphics::reset()
DisplayState s;
discardStencil();
Canvas::bindDefaultCanvas();
PixelEffect::detach();
ShaderEffect::detach();
restoreState(s);
}
@@ -450,12 +450,12 @@ Canvas *Graphics::newCanvas(int width, int height, Canvas::TextureType texture_t
return NULL; // never reached
}
PixelEffect *Graphics::newPixelEffect(const std::string &code)
ShaderEffect *Graphics::newShaderEffect(const std::string &vertcode, const std::string &fragcode)
{
PixelEffect *effect = NULL;
ShaderEffect *effect = NULL;
try
{
effect = new PixelEffect("", code);
effect = new ShaderEffect(vertcode, fragcode);
}
catch(love::Exception &e)
{
+2 -2
View File
@@ -44,7 +44,7 @@
#include "SpriteBatch.h"
#include "ParticleSystem.h"
#include "Canvas.h"
#include "PixelEffect.h"
#include "ShaderEffect.h"
namespace love
{
@@ -271,7 +271,7 @@ public:
Canvas *newCanvas(int width, int height, Canvas::TextureType texture_type = Canvas::TYPE_NORMAL);
PixelEffect *newPixelEffect(const std::string &code);
ShaderEffect *newShaderEffect(const std::string &vertcode, const std::string &fragcode);
/**
* Sets the foreground color.
+1 -1
View File
@@ -126,7 +126,7 @@ private:
void drawv(const Matrix &t, const vertex *v) const;
friend class PixelEffect;
friend class ShaderEffect;
GLuint getTextureName() const
{
return texture;
@@ -18,7 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "PixelEffect.h"
#include "ShaderEffect.h"
#include "GLee.h"
#include "Graphics.h"
@@ -28,7 +28,7 @@ namespace
// reattaches the originally active program when destroyed
struct TemporaryAttacher
{
TemporaryAttacher(love::graphics::opengl::PixelEffect *sp) : s(sp)
TemporaryAttacher(love::graphics::opengl::ShaderEffect *sp) : s(sp)
{
glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
s->attach();
@@ -37,7 +37,7 @@ struct TemporaryAttacher
{
glUseProgram(activeProgram);
}
love::graphics::opengl::PixelEffect *s;
love::graphics::opengl::ShaderEffect *s;
GLint activeProgram;
};
} // anonymous namespace
@@ -49,13 +49,13 @@ namespace graphics
namespace opengl
{
PixelEffect *PixelEffect::current = NULL;
ShaderEffect *ShaderEffect::current = NULL;
std::map<std::string, GLint> PixelEffect::_texture_unit_pool;
GLint PixelEffect::_current_texture_unit = 0;
GLint PixelEffect::_max_texture_units = 0;
std::map<std::string, GLint> ShaderEffect::_texture_unit_pool;
GLint ShaderEffect::_current_texture_unit = 0;
GLint ShaderEffect::_max_texture_units = 0;
GLint PixelEffect::getTextureUnit(const std::string &name)
GLint ShaderEffect::getTextureUnit(const std::string &name)
{
std::map<std::string, GLint>::const_iterator it = _texture_unit_pool.find(name);
@@ -69,7 +69,7 @@ GLint PixelEffect::getTextureUnit(const std::string &name)
return _current_texture_unit;
}
PixelEffect::PixelEffect(const std::string &vertcode, const std::string &fragcode)
ShaderEffect::ShaderEffect(const std::string &vertcode, const std::string &fragcode)
: _program(0)
, _vertcode(vertcode)
, _fragcode(fragcode)
@@ -78,7 +78,7 @@ GLint PixelEffect::getTextureUnit(const std::string &name)
loadVolatile();
}
GLuint PixelEffect::createShader(GLenum type, const std::string &code)
GLuint ShaderEffect::createShader(GLenum type, const std::string &code)
{
const char *shadertypename = NULL;
switch (type)
@@ -125,46 +125,33 @@ GLuint PixelEffect::createShader(GLenum type, const std::string &code)
return shader;
}
GLuint PixelEffect::createProgram(const std::vector<GLuint> &shaders)
void ShaderEffect::createProgram(const std::vector<GLuint> &shaders)
{
GLuint program = glCreateProgram();
if (program == 0) // should only fail when called between glBegin() and glEnd()
_program = glCreateProgram();
if (_program == 0) // should only fail when called between glBegin() and glEnd()
throw love::Exception("Cannot create shader program object.");
std::vector<GLuint>::const_iterator it;
for (it = shaders.begin(); it != shaders.end(); ++it)
glAttachShader(program, *it);
glAttachShader(_program, *it);
glLinkProgram(program);
glLinkProgram(_program);
for (it = shaders.begin(); it != shaders.end(); ++it)
glDetachShader(program, *it);
glDetachShader(_program, *it);
GLint link_ok;
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
glGetProgramiv(_program, GL_LINK_STATUS, &link_ok);
if (link_ok == GL_FALSE)
{
GLint strlen, nullpos;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &strlen);
char *temp_str = new char[strlen+1];
// be extra sure that the error string will be 0-terminated
memset(temp_str, '\0', strlen+1);
glGetProgramInfoLog(program, strlen, &nullpos, temp_str);
temp_str[nullpos] = '\0';
std::string warnings(temp_str);
delete[] temp_str;
glDeleteProgram(program);
const std::string warnings = getWarnings();
glDeleteProgram(_program);
throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str());
}
return program;
}
bool PixelEffect::loadVolatile()
bool ShaderEffect::loadVolatile()
{
std::vector<GLuint> shaders;
@@ -175,11 +162,11 @@ bool PixelEffect::loadVolatile()
shaders.push_back(createShader(GL_FRAGMENT_SHADER, _fragcode));
if (shaders.size() == 0)
throw love::Exception("Cannot create PixelEffect: no source code!");
throw love::Exception("Cannot create ShaderEffect: no source code!");
try
{
_program = createProgram(shaders);
createProgram(shaders);
}
catch (love::Exception &e)
{
@@ -197,18 +184,18 @@ bool PixelEffect::loadVolatile()
return true;
}
PixelEffect::~PixelEffect()
ShaderEffect::~ShaderEffect()
{
unloadVolatile();
}
void PixelEffect::unloadVolatile()
void ShaderEffect::unloadVolatile()
{
if (_program != 0)
glDeleteProgram(_program);
}
std::string PixelEffect::getGLSLVersion()
std::string ShaderEffect::getGLSLVersion()
{
// GL_SHADING_LANGUAGE_VERSION may not be available in OpenGL < 2.0.
const char *tmp = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
@@ -226,12 +213,12 @@ std::string PixelEffect::getGLSLVersion()
}
bool PixelEffect::isSupported()
bool ShaderEffect::isSupported()
{
return GLEE_VERSION_2_0 && getGLSLVersion() >= "1.2";
}
std::string PixelEffect::getWarnings() const
std::string ShaderEffect::getWarnings() const
{
GLint strlen, nullpos;
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &strlen);
@@ -246,19 +233,19 @@ std::string PixelEffect::getWarnings() const
return warnings;
}
void PixelEffect::attach()
void ShaderEffect::attach()
{
glUseProgram(_program);
current = this;
}
void PixelEffect::detach()
void ShaderEffect::detach()
{
glUseProgram(0);
current = NULL;
}
void PixelEffect::sendFloat(const std::string &name, int size, const GLfloat *vec, int count)
void ShaderEffect::sendFloat(const std::string &name, int size, const GLfloat *vec, int count)
{
TemporaryAttacher attacher(this);
GLint location = getUniformLocation(name);
@@ -289,7 +276,7 @@ void PixelEffect::sendFloat(const std::string &name, int size, const GLfloat *ve
checkSetUniformError();
}
void PixelEffect::sendMatrix(const std::string &name, int size, const GLfloat *m, int count)
void ShaderEffect::sendMatrix(const std::string &name, int size, const GLfloat *m, int count)
{
TemporaryAttacher attacher(this);
GLint location = getUniformLocation(name);
@@ -318,7 +305,7 @@ void PixelEffect::sendMatrix(const std::string &name, int size, const GLfloat *m
checkSetUniformError();
}
void PixelEffect::sendImage(const std::string &name, const Image &image)
void ShaderEffect::sendImage(const std::string &name, const Image &image)
{
GLint texture_unit = getTextureUnit(name);
@@ -336,7 +323,7 @@ void PixelEffect::sendImage(const std::string &name, const Image &image)
checkSetUniformError();
}
void PixelEffect::sendCanvas(const std::string &name, const Canvas &canvas)
void ShaderEffect::sendCanvas(const std::string &name, const Canvas &canvas)
{
GLint texture_unit = getTextureUnit(name);
@@ -354,7 +341,7 @@ void PixelEffect::sendCanvas(const std::string &name, const Canvas &canvas)
checkSetUniformError();
}
GLint PixelEffect::getUniformLocation(const std::string &name)
GLint ShaderEffect::getUniformLocation(const std::string &name)
{
std::map<std::string, GLint>::const_iterator it = _uniforms.find(name);
if (it != _uniforms.end())
@@ -372,7 +359,7 @@ GLint PixelEffect::getUniformLocation(const std::string &name)
return location;
}
void PixelEffect::checkSetUniformError()
void ShaderEffect::checkSetUniformError()
{
GLenum error_code = glGetError();
if (GL_INVALID_OPERATION == error_code)
@@ -36,11 +36,11 @@ namespace graphics
namespace opengl
{
// A fragment shader
class PixelEffect : public Object, public Volatile
class ShaderEffect : public Object, public Volatile
{
public:
PixelEffect(const std::string &vertcode, const std::string &fragcode);
virtual ~PixelEffect();
ShaderEffect(const std::string &vertcode, const std::string &fragcode);
virtual ~ShaderEffect();
std::string getWarnings() const;
virtual bool loadVolatile();
@@ -51,7 +51,7 @@ public:
static std::string getGLSLVersion();
static bool isSupported();
static PixelEffect *current;
static ShaderEffect *current;
void sendFloat(const std::string &name, int size, const GLfloat *vec, int count);
void sendMatrix(const std::string &name, int size, const GLfloat *m, int count);
@@ -62,7 +62,7 @@ private:
GLint getUniformLocation(const std::string &name);
void checkSetUniformError();
GLuint createShader(GLenum type, const std::string &code);
GLuint createProgram(const std::vector<GLuint> &shaders);
void createProgram(const std::vector<GLuint> &shaders);
GLuint _program;
std::string _vertcode;
+31 -22
View File
@@ -433,29 +433,38 @@ int w_newCanvas(lua_State *L)
return 1;
}
int w_newPixelEffect(lua_State *L)
int w_newShaderEffect(lua_State *L)
{
if (!PixelEffect::isSupported())
if (!ShaderEffect::isSupported())
return luaL_error(L, "Sorry, your graphics card does not support pixel effects.");
try
{
luaL_checkstring(L, 1);
// clamp stack to 2 elements
lua_settop(L, 2);
luax_getfunction(L, "graphics", "_effectCodeToGLSL");
// push vertcode and fragcode strings to the top of the stack so they become arguments for the function
lua_pushvalue(L, 1);
lua_pcall(L, 1, 1, 0);
const char *code = lua_tostring(L, -1);
PixelEffect *effect = instance->newPixelEffect(code);
luax_newtype(L, "PixelEffect", GRAPHICS_PIXELEFFECT_T, (void *)effect);
lua_pushvalue(L, 2);
// call effectCodeToGLSL
lua_pcall(L, 2, 2, 0);
// get returned values from the top of the stack
const char *vertcode = luaL_optstring(L, -2, "");
const char *fragcode = luaL_optstring(L, -1, "");
ShaderEffect *effect = instance->newShaderEffect(vertcode, fragcode);
luax_newtype(L, "ShaderEffect", GRAPHICS_SHADEREFFECT_T, (void *)effect);
}
catch(const love::Exception &e)
{
// memory is freed in Graphics::newPixelEffect
// memory is freed in Graphics::newShaderEffect
luax_getfunction(L, "graphics", "_transformGLSLErrorMessages");
lua_pushstring(L, e.what());
lua_pcall(L, 1,1, 0);
lua_pcall(L, 1, 1, 0);
const char *err = lua_tostring(L, -1);
return luaL_error(L, "%s", err);
}
@@ -794,26 +803,26 @@ int w_getCanvas(lua_State *L)
return 1;
}
int w_setPixelEffect(lua_State *L)
int w_setShaderEffect(lua_State *L)
{
if (lua_isnoneornil(L,1))
{
PixelEffect::detach();
ShaderEffect::detach();
return 0;
}
PixelEffect *effect = luax_checkpixeleffect(L, 1);
ShaderEffect *effect = luax_checkshadereffect(L, 1);
effect->attach();
return 0;
}
int w_getPixelEffect(lua_State *L)
int w_getShaderEffect(lua_State *L)
{
PixelEffect *effect = PixelEffect::current;
ShaderEffect *effect = ShaderEffect::current;
if (effect)
{
effect->retain();
luax_newtype(L, "PixelEffect", GRAPHICS_PIXELEFFECT_T, (void *) effect);
luax_newtype(L, "ShaderEffect", GRAPHICS_SHADEREFFECT_T, (void *) effect);
}
else
lua_pushnil(L);
@@ -841,8 +850,8 @@ int w_isSupported(lua_State *L)
if (!Canvas::isHdrSupported())
supported = false;
break;
case Graphics::SUPPORT_PIXELEFFECT:
if (!PixelEffect::isSupported())
case Graphics::SUPPORT_SHADEREFFECT:
if (!ShaderEffect::isSupported())
supported = false;
break;
case Graphics::SUPPORT_NPOT:
@@ -1256,7 +1265,7 @@ static const luaL_Reg functions[] =
{ "newSpriteBatch", w_newSpriteBatch },
{ "newParticleSystem", w_newParticleSystem },
{ "newCanvas", w_newCanvas },
{ "newPixelEffect", w_newPixelEffect },
{ "newShaderEffect", w_newShaderEffect },
{ "setColor", w_setColor },
{ "getColor", w_getColor },
@@ -1287,8 +1296,8 @@ static const luaL_Reg functions[] =
{ "setCanvas", w_setCanvas },
{ "getCanvas", w_getCanvas },
{ "setPixelEffect", w_setPixelEffect },
{ "getPixelEffect", w_getPixelEffect },
{ "setShaderEffect", w_setShaderEffect },
{ "getShaderEffect", w_getShaderEffect },
{ "isSupported", w_isSupported },
@@ -1349,7 +1358,7 @@ static const lua_CFunction types[] =
luaopen_spritebatch,
luaopen_particlesystem,
luaopen_canvas,
luaopen_pixeleffect,
luaopen_shadereffect,
0
};
+4 -3
View File
@@ -28,7 +28,7 @@
#include "wrap_SpriteBatch.h"
#include "wrap_ParticleSystem.h"
#include "wrap_Canvas.h"
#include "wrap_PixelEffect.h"
#include "wrap_ShaderEffect.h"
#include "Graphics.h"
namespace love
@@ -63,7 +63,7 @@ int w_newImageFont(lua_State *L);
int w_newSpriteBatch(lua_State *L);
int w_newParticleSystem(lua_State *L);
int w_newCanvas(lua_State *L); // comments in function
int w_newPixelEffect(lua_State *L);
int w_newShaderEffect(lua_State *L);
int w_setColor(lua_State *L);
int w_getColor(lua_State *L);
int w_setBackgroundColor(lua_State *L);
@@ -90,7 +90,8 @@ int w_getMaxPointSize(lua_State *L);
int w_newScreenshot(lua_State *L);
int w_setCanvas(lua_State *L);
int w_getCanvas(lua_State *L);
int w_setPixelEffect(lua_State *L);
int w_setShaderEffect(lua_State *L);
int w_getShaderEffect(lua_State *L);
int w_isSupported(lua_State *L);
int w_draw(lua_State *L);
int w_drawq(lua_State *L);
@@ -18,7 +18,7 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_PixelEffect.h"
#include "wrap_ShaderEffect.h"
#include "wrap_Image.h"
#include "wrap_Canvas.h"
#include <string>
@@ -32,19 +32,19 @@ namespace graphics
namespace opengl
{
PixelEffect *luax_checkpixeleffect(lua_State *L, int idx)
ShaderEffect *luax_checkshadereffect(lua_State *L, int idx)
{
return luax_checktype<PixelEffect>(L, idx, "PixelEffect", GRAPHICS_PIXELEFFECT_T);
return luax_checktype<ShaderEffect>(L, idx, "ShaderEffect", GRAPHICS_SHADEREFFECT_T);
}
int w_PixelEffect_getWarnings(lua_State *L)
int w_ShaderEffect_getWarnings(lua_State *L)
{
PixelEffect *effect = luax_checkpixeleffect(L, 1);
ShaderEffect *effect = luax_checkshadereffect(L, 1);
lua_pushstring(L, effect->getWarnings().c_str());
return 1;
}
static int _sendScalars(lua_State *L, PixelEffect *effect, const char *name, int count)
static int _sendScalars(lua_State *L, ShaderEffect *effect, const char *name, int count)
{
float *values = new float[count];
for (int i = 0; i < count; ++i)
@@ -71,7 +71,7 @@ static int _sendScalars(lua_State *L, PixelEffect *effect, const char *name, int
return 0;
}
static int _sendVectors(lua_State *L, PixelEffect *effect, const char *name, int count)
static int _sendVectors(lua_State *L, ShaderEffect *effect, const char *name, int count)
{
size_t dimension = lua_objlen(L, 3);
float *values = new float[count * dimension];
@@ -112,9 +112,9 @@ static int _sendVectors(lua_State *L, PixelEffect *effect, const char *name, int
return 0;
}
int w_PixelEffect_sendFloat(lua_State *L)
int w_ShaderEffect_sendFloat(lua_State *L)
{
PixelEffect *effect = luax_checkpixeleffect(L, 1);
ShaderEffect *effect = luax_checkshadereffect(L, 1);
const char *name = luaL_checkstring(L, 2);
int count = lua_gettop(L) - 2;
@@ -129,10 +129,10 @@ int w_PixelEffect_sendFloat(lua_State *L)
return luaL_typerror(L, 3, "number or table");
}
int w_PixelEffect_sendMatrix(lua_State *L)
int w_ShaderEffect_sendMatrix(lua_State *L)
{
int count = lua_gettop(L) - 2;
PixelEffect *effect = luax_checkpixeleffect(L, 1);
ShaderEffect *effect = luax_checkshadereffect(L, 1);
const char *name = luaL_checkstring(L, 2);
if (!lua_istable(L, 3))
@@ -186,9 +186,9 @@ int w_PixelEffect_sendMatrix(lua_State *L)
return 0;
}
int w_PixelEffect_sendImage(lua_State *L)
int w_ShaderEffect_sendImage(lua_State *L)
{
PixelEffect *effect = luax_checkpixeleffect(L, 1);
ShaderEffect *effect = luax_checkshadereffect(L, 1);
const char *name = luaL_checkstring(L, 2);
Image *img = luax_checkimage(L, 3);
@@ -204,9 +204,9 @@ int w_PixelEffect_sendImage(lua_State *L)
return 0;
}
int w_PixelEffect_sendCanvas(lua_State *L)
int w_ShaderEffect_sendCanvas(lua_State *L)
{
PixelEffect *effect = luax_checkpixeleffect(L, 1);
ShaderEffect *effect = luax_checkshadereffect(L, 1);
const char *name = luaL_checkstring(L, 2);
Canvas *canvas = luax_checkcanvas(L, 3);
@@ -225,17 +225,17 @@ int w_PixelEffect_sendCanvas(lua_State *L)
static const luaL_Reg functions[] =
{
{ "getWarnings", w_PixelEffect_getWarnings },
{ "sendFloat", w_PixelEffect_sendFloat },
{ "sendMatrix", w_PixelEffect_sendMatrix },
{ "sendImage", w_PixelEffect_sendImage },
{ "sendCanvas", w_PixelEffect_sendCanvas },
{ "getWarnings", w_ShaderEffect_getWarnings },
{ "sendFloat", w_ShaderEffect_sendFloat },
{ "sendMatrix", w_ShaderEffect_sendMatrix },
{ "sendImage", w_ShaderEffect_sendImage },
{ "sendCanvas", w_ShaderEffect_sendCanvas },
{ 0, 0 }
};
extern "C" int luaopen_pixeleffect(lua_State *L)
extern "C" int luaopen_shadereffect(lua_State *L)
{
return luax_register_type(L, "PixelEffect", functions);
return luax_register_type(L, "ShaderEffect", functions);
}
} // opengl
@@ -22,7 +22,7 @@
#define LOVE_GRAPHICS_OPENGL_WRAP_PROGRAM_H
#include "common/runtime.h"
#include "PixelEffect.h"
#include "ShaderEffect.h"
namespace love
{
@@ -31,12 +31,12 @@ namespace graphics
namespace opengl
{
PixelEffect *luax_checkpixeleffect(lua_State *L, int idx);
int w_PixelEffect_getWarnings(lua_State *L);
int w_PixelEffect_sendFloat(lua_State *L);
int w_PixelEffect_sendMatrix(lua_State *L);
int w_PixelEffect_sendImage(lua_State *L);
extern "C" int luaopen_pixeleffect(lua_State *L);
ShaderEffect *luax_checkshadereffect(lua_State *L, int idx);
int w_ShaderEffect_getWarnings(lua_State *L);
int w_ShaderEffect_sendFloat(lua_State *L);
int w_ShaderEffect_sendMatrix(lua_State *L);
int w_ShaderEffect_sendImage(lua_State *L);
extern "C" int luaopen_shadereffect(lua_State *L);
} // opengl
} // graphics