Fix issue #292: Can't send arrays to pixeleffects.

Arrays of numbers, vectors and matrices are supported.
This commit is contained in:
vrld
2011-09-07 23:32:54 +02:00
parent 2eb9ee20d5
commit eec0250545
5 changed files with 177 additions and 71 deletions
+15 -16
View File
@@ -2,7 +2,6 @@
#include "GLee.h"
#include <limits>
#include <sstream>
#include <iostream>
namespace
{
@@ -148,28 +147,28 @@ namespace opengl
glUseProgram(0);
}
void PixelEffect::sendFloat(const std::string& name, int count, const GLfloat* vec)
void PixelEffect::sendFloat(const std::string& name, int size, const GLfloat* vec, int count)
{
TemporaryAttacher attacher(this);
GLint location = getUniformLocation(name);
if (count < 1 || count > 4) {
throw love::Exception("Invalid variable count: %d (expected 1-4).", count);
if (size < 1 || size > 4) {
throw love::Exception("Invalid variable size: %d (expected 1-4).", size);
}
switch (count) {
switch (size) {
case 4:
glUniform4fv(location, 1, vec);
glUniform4fv(location, count, vec);
break;
case 3:
glUniform3fv(location, 1, vec);
glUniform3fv(location, count, vec);
break;
case 2:
glUniform2fv(location, 1, vec);
glUniform2fv(location, count, vec);
break;
case 1:
default:
glUniform1fv(location, 1, vec);
glUniform1fv(location, count, vec);
break;
}
@@ -177,7 +176,7 @@ namespace opengl
checkSetUniformError();
}
void PixelEffect::sendMatrix(const std::string& name, int size, const GLfloat* m)
void PixelEffect::sendMatrix(const std::string& name, int size, const GLfloat* m, int count)
{
TemporaryAttacher attacher(this);
GLint location = getUniformLocation(name);
@@ -189,14 +188,14 @@ namespace opengl
switch (size) {
case 4:
glUniformMatrix4fv(location, 1, GL_FALSE, m);
glUniformMatrix4fv(location, count, GL_FALSE, m);
break;
case 3:
glUniformMatrix3fv(location, 1, GL_FALSE, m);
glUniformMatrix3fv(location, count, GL_FALSE, m);
break;
case 2:
default:
glUniformMatrix2fv(location, 1, GL_FALSE, m);
glUniformMatrix2fv(location, count, GL_FALSE, m);
break;
}
@@ -257,9 +256,9 @@ namespace opengl
if (GL_INVALID_OPERATION == error_code) {
throw love::Exception(
"Invalid operation:\n"
"Trying to send more than one value to a float variable, or"
"Size of shader variable does not match indicated size, or"
"Invalid variable name.");
"- Trying to send the wrong value type to shader variable, or\n"
"- Trying to send array values with wrong dimension, or\n"
"- Invalid variable name.");
}
}
} // opengl
+2 -2
View File
@@ -28,8 +28,8 @@ namespace opengl
static void detach();
static bool isSupported();
void sendFloat(const std::string& name, int count, const GLfloat* vec);
void sendMatrix(const std::string& name, int size, const GLfloat* m);
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);
void sendImage(const std::string& name, const Image& image);
void sendCanvas(const std::string& name, const Canvas& canvas);
+109 -27
View File
@@ -2,6 +2,8 @@
#include "wrap_Image.h"
#include "wrap_Canvas.h"
#include <string>
#include <iostream>
using namespace std;
namespace love
{
@@ -21,48 +23,128 @@ namespace opengl
return 1;
}
int w_PixelEffect_sendFloat(lua_State * L)
static int _sendScalars(lua_State * L, PixelEffect * effect, const char * name, int count)
{
size_t count = lua_gettop(L) - 2;
PixelEffect * effect = luax_checkpixeleffect(L, 1);
const char* name = luaL_checkstring(L, 2);
if (count < 1 || count > 4)
return luaL_error(L, "Invalid variable count (expected 1-4, got %d).", count);
float values[4] = {0,0,0,0};
for (unsigned int i = 0; i < count; ++i)
values[i] = (float) luaL_checknumber(L, i+1 + 2);
try {
effect->sendFloat(name, count, values);
} catch(love::Exception& e) {
luaL_error(L, e.what());
float * values = new float[count];
for (int i = 0; i < count; ++i) {
if (!lua_isnumber(L, 3 + i)) {
delete[] values;
return luaL_typerror(L, 3 + i, "number");
}
values[i] = (float)lua_tonumber(L, 3 + i);
}
try {
effect->sendFloat(name, 1, values, count);
} catch(love::Exception& e) {
delete[] values;
return luaL_error(L, e.what());
}
delete[] values;
return 0;
}
static int _sendVectors(lua_State * L, PixelEffect * effect, const char * name, int count)
{
int dimension = lua_objlen(L, 3);
float * values = new float[count * dimension];
for (int i = 0; i < count; ++i) {
if (!lua_istable(L, 3 + i)) {
delete[] values;
return luaL_typerror(L, 3 + i, "table");
}
if (lua_objlen(L, 3 + i) != dimension) {
delete[] values;
return luaL_error(L, "Error in argument %d: Expected table size %d, got %d.",
3+i, dimension, lua_objlen(L, 3+i));
}
for (int k = 1; k <= dimension; ++k) {
lua_rawgeti(L, 3 + i, k);
values[i * dimension + k - 1] = (float)lua_tonumber(L, -1);
}
lua_pop(L, dimension);
}
try {
effect->sendFloat(name, dimension, values, count);
} catch(love::Exception& e) {
delete[] values;
return luaL_error(L, e.what());
}
delete[] values;
return 0;
}
int w_PixelEffect_sendFloat(lua_State * L)
{
PixelEffect * effect = luax_checkpixeleffect(L, 1);
const char* name = luaL_checkstring(L, 2);
int count = lua_gettop(L) - 2;
if (count < 1)
return luaL_error(L, "No variable to send.");
if (lua_isnumber(L, 3))
return _sendScalars(L, effect, name, count);
else if (lua_istable(L, 3))
return _sendVectors(L, effect, name, count);
return luaL_typerror(L, 3, "number or table");
}
int w_PixelEffect_sendMatrix(lua_State * L)
{
size_t count = lua_gettop(L) - 3;
int count = lua_gettop(L) - 2;
PixelEffect * effect = luax_checkpixeleffect(L, 1);
const char* name = luaL_checkstring(L, 2);
int size = luaL_checkinteger(L, 3);
if (size < 2 || size > 4)
return luaL_error(L, "Invalid matrix size: %dx%d (only 2x2, 3x3 and 4x4 matrices are supported).", count, count);
if (!lua_istable(L, 3))
return luaL_typerror(L, 3, "matrix table");
float values[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for (unsigned int i = 0; i < count; ++i)
values[i] = (float) luaL_checknumber(L, i+1 + 3);
lua_getfield(L, 3, "dimension");
int dimension = lua_tointeger(L, -1);
lua_pop(L, 1);
try {
effect->sendFloat(name, size, values);
} catch(love::Exception& e) {
luaL_error(L, e.what());
if (dimension < 2 || dimension > 4)
return luaL_error(L, "Invalid matrix size: %dx%d (only 2x2, 3x3 and 4x4 matrices are supported).",
count, count);
float * values = new float[dimension * dimension * count];
for (int i = 0; i < count; ++i) {
lua_getfield(L, 3+i, "dimension");
if (lua_tointeger(L, -1) != dimension) {
// You unlock this door with the key of imagination. Beyond it is
// another dimension: a dimension of sound, a dimension of sight,
// a dimension of mind. You're moving into a land of both shadow
// and substance, of things and ideas. You've just crossed over
// into... the Twilight Zone.
int other_dimension = lua_tointeger(L, -1);
delete[] values;
return luaL_error(L, "Invalid matrix size at argument %d: Expected size %dx%d, got %dx%d.",
3+i, dimension, dimension, other_dimension, other_dimension);
}
for (int k = 1; k <= dimension*dimension; ++k) {
lua_rawgeti(L, 3+i, k);
values[i * dimension * dimension + k - 1] = (float)lua_tonumber(L, -1);
cout << i << "." << k << " = " << (float)lua_tonumber(L, -1) << endl;
}
lua_pop(L, 1 + dimension);
}
try {
effect->sendMatrix(name, dimension, values, count);
} catch(love::Exception& e) {
delete[] values;
return luaL_error(L, e.what());
}
delete[] values;
return 0;
}
+20 -9
View File
@@ -1318,9 +1318,26 @@ do
return table.concat(lines, "\n")
end
-- helper to transform a matrix from {{a,b,c}, {d,e,f}, ...} to
-- {a, b, c, d, e, f, ...}
local function flattenMatrices(mat, ...)
if not mat then return end
local ret,l = {}, 1
ret.dimension = #mat
for i = 1,#mat do
for k = 1,#mat[i] do
ret[l], l = tonumber(mat[i][k]), l+1
end
end
return ret, flattenMatrices(...)
end
-- automagic uniform setter
local function pixeleffect_dispatch_send(self, name, value, ...)
if type(value) == "number" then -- scalar or vector
if type(value) == "number" then -- scalar
self:sendFloat(name, value, ...)
elseif type(value) == "userdata" and value:typeOf("Image") then
self:sendImage(name, value)
@@ -1328,15 +1345,9 @@ do
self:sendCanvas(name, value)
elseif type(value) == "table" then -- vector or matrix
if type(value[1]) == "number" then
self:sendFloat(name, unpack(value))
self:sendFloat(name, value, ...)
elseif type(value[1]) == "table" then
local m,l = {}, 0
for i = 1,#value do
for k = 1,#value[i] do
m[l], l = tonumber(value[i][k]), l+1
end
end
self:sendMatrix(name, #value, unpack(m))
self:sendMatrix(name, flattenMatrices(value, ...))
else
error("Cannot send value (unsupported type: {"..type(value[1]).."}).")
end
+31 -17
View File
@@ -6359,6 +6359,33 @@ const unsigned char graphics_lua[] =
0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6e,
0x63, 0x61, 0x74, 0x28, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x0a,
0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
0x09, 0x2d, 0x2d, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x66, 0x72, 0x6f,
0x6d, 0x20, 0x7b, 0x7b, 0x61, 0x2c, 0x62, 0x2c, 0x63, 0x7d, 0x2c, 0x20, 0x7b, 0x64, 0x2c, 0x65, 0x2c, 0x66,
0x7d, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x7d, 0x20, 0x74, 0x6f, 0x0a,
0x09, 0x2d, 0x2d, 0x20, 0x7b, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x2c, 0x20, 0x64, 0x2c, 0x20, 0x65,
0x2c, 0x20, 0x66, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x7d, 0x0a,
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6c,
0x61, 0x74, 0x74, 0x65, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x63, 0x65, 0x73, 0x28, 0x6d, 0x61, 0x74, 0x2c,
0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x64, 0x0a,0x0a,
0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x74, 0x2c, 0x6c, 0x20, 0x3d, 0x20, 0x7b, 0x7d,
0x2c, 0x20, 0x31, 0x0a,
0x09, 0x09, 0x72, 0x65, 0x74, 0x2e, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20,
0x23, 0x6d, 0x61, 0x74, 0x0a,0x0a,
0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x23, 0x6d, 0x61, 0x74, 0x20, 0x64,
0x6f, 0x0a,
0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x23, 0x6d, 0x61, 0x74, 0x5b,
0x69, 0x5d, 0x20, 0x64, 0x6f, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x5b, 0x6c, 0x5d, 0x2c, 0x20, 0x6c, 0x20, 0x3d, 0x20, 0x74, 0x6f,
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, 0x6d, 0x61, 0x74, 0x5b, 0x69, 0x5d, 0x5b, 0x6b, 0x5d, 0x29, 0x2c,
0x20, 0x6c, 0x2b, 0x31, 0x0a,
0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x2c, 0x20, 0x66, 0x6c, 0x61, 0x74,
0x74, 0x65, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x63, 0x65, 0x73, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
0x09, 0x65, 0x6e, 0x64, 0x0a,0x0a,
0x09, 0x2d, 0x2d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x20, 0x75, 0x6e, 0x69, 0x66,
0x6f, 0x72, 0x6d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x65, 0x72, 0x0a,
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x69,
@@ -6367,8 +6394,7 @@ const unsigned char graphics_lua[] =
0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
0x09, 0x09, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x3d,
0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x20, 0x6f, 0x72,
0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x61, 0x72, 0x0a,
0x09, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x28,
0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x61, 0x6c, 0x75,
@@ -6391,25 +6417,13 @@ const unsigned char graphics_lua[] =
0x5d, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x46, 0x6c, 0x6f, 0x61, 0x74,
0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x28, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x29, 0x29, 0x0a,
0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x5b, 0x31, 0x5d, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x2c, 0x6c, 0x20, 0x3d, 0x20, 0x7b, 0x7d,
0x2c, 0x20, 0x30, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x23, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x20, 0x64, 0x6f, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x23, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x5b, 0x69, 0x5d, 0x20, 0x64, 0x6f, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x5b, 0x6c, 0x5d, 0x2c, 0x20, 0x6c, 0x20, 0x3d, 0x20, 0x74, 0x6f,
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5b, 0x69, 0x5d, 0x5b, 0x6b, 0x5d,
0x29, 0x2c, 0x20, 0x6c, 0x2b, 0x31, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x3a, 0x73, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x74, 0x72, 0x69,
0x78, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x23, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x75, 0x6e,
0x70, 0x61, 0x63, 0x6b, 0x28, 0x6d, 0x29, 0x29, 0x0a,
0x78, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x4d, 0x61, 0x74,
0x72, 0x69, 0x63, 0x65, 0x73, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20,
0x73, 0x65, 0x6e, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x28, 0x75, 0x6e, 0x73, 0x75, 0x70, 0x70,