mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
Add support for non-square matrix uniforms in desktop GLSL. The notation is columns x rows, e.g. a mat4x2 has 4 columns and 2 rows.
Fixed the memory layout of matrices sent to shaders via Shader:send. Note that this is a breaking fix and will probably cause matrices designed to work with older versions of LÖVE to be transposed in shaders compared to what they were previously, if Shader:send or sendMatrix was used to put them in the shader. --HG-- branch : minor
This commit is contained in:
@@ -200,7 +200,11 @@ void Shader::mapActiveUniforms()
|
||||
u.name = std::string(cname, (size_t) namelen);
|
||||
u.location = glGetUniformLocation(program, u.name.c_str());
|
||||
u.baseType = getUniformBaseType(gltype);
|
||||
u.components = getUniformTypeSize(gltype);
|
||||
|
||||
if (u.baseType == UNIFORM_MATRIX)
|
||||
u.matrix = getMatrixSize(gltype);
|
||||
else
|
||||
u.components = getUniformTypeComponents(gltype);
|
||||
|
||||
// Initialize all samplers to 0. Both GLSL and GLSL ES are supposed to
|
||||
// do this themselves, but some Android devices (galaxy tab 3 and 4)
|
||||
@@ -517,19 +521,27 @@ void Shader::sendMatrices(const UniformInfo *info, const float *m, int count)
|
||||
|
||||
int location = info->location;
|
||||
|
||||
switch (info->components)
|
||||
{
|
||||
case 4:
|
||||
glUniformMatrix4fv(location, count, GL_FALSE, m);
|
||||
break;
|
||||
case 3:
|
||||
glUniformMatrix3fv(location, count, GL_FALSE, m);
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
int columns = info->matrix.columns;
|
||||
int rows = info->matrix.rows;
|
||||
|
||||
if (columns == 2 && rows == 2)
|
||||
glUniformMatrix2fv(location, count, GL_FALSE, m);
|
||||
break;
|
||||
}
|
||||
else if (columns == 3 && rows == 3)
|
||||
glUniformMatrix3fv(location, count, GL_FALSE, m);
|
||||
else if (columns == 4 && rows == 4)
|
||||
glUniformMatrix4fv(location, count, GL_FALSE, m);
|
||||
else if (columns == 2 && rows == 3)
|
||||
glUniformMatrix2x3fv(location, count, GL_FALSE, m);
|
||||
else if (columns == 2 && rows == 4)
|
||||
glUniformMatrix2x4fv(location, count, GL_FALSE, m);
|
||||
else if (columns == 3 && rows == 2)
|
||||
glUniformMatrix3x2fv(location, count, GL_FALSE, m);
|
||||
else if (columns == 3 && rows == 4)
|
||||
glUniformMatrix3x4fv(location, count, GL_FALSE, m);
|
||||
else if (columns == 4 && rows == 2)
|
||||
glUniformMatrix4x2fv(location, count, GL_FALSE, m);
|
||||
else if (columns == 4 && rows == 3)
|
||||
glUniformMatrix4x3fv(location, count, GL_FALSE, m);
|
||||
}
|
||||
|
||||
void Shader::sendTexture(const UniformInfo *info, Texture *texture)
|
||||
@@ -819,7 +831,7 @@ bool Shader::isSupported()
|
||||
return GLAD_ES_VERSION_2_0 || (getGLSLVersion() >= "1.2");
|
||||
}
|
||||
|
||||
int Shader::getUniformTypeSize(GLenum type) const
|
||||
int Shader::getUniformTypeComponents(GLenum type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
@@ -850,6 +862,50 @@ int Shader::getUniformTypeSize(GLenum type) const
|
||||
}
|
||||
}
|
||||
|
||||
Shader::MatrixSize Shader::getMatrixSize(GLenum type) const
|
||||
{
|
||||
MatrixSize m;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GL_FLOAT_MAT2:
|
||||
m.columns = m.rows = 2;
|
||||
break;
|
||||
case GL_FLOAT_MAT3:
|
||||
m.columns = m.rows = 3;
|
||||
break;
|
||||
case GL_FLOAT_MAT4:
|
||||
m.columns = m.rows = 4;
|
||||
break;
|
||||
case GL_FLOAT_MAT2x3:
|
||||
m.columns = 2;
|
||||
m.rows = 3;
|
||||
break;
|
||||
case GL_FLOAT_MAT2x4:
|
||||
m.columns = 2;
|
||||
m.rows = 4;
|
||||
break;
|
||||
case GL_FLOAT_MAT3x2:
|
||||
m.columns = 3;
|
||||
m.rows = 2;
|
||||
break;
|
||||
case GL_FLOAT_MAT3x4:
|
||||
m.columns = 3;
|
||||
m.rows = 4;
|
||||
break;
|
||||
case GL_FLOAT_MAT4x2:
|
||||
m.columns = 4;
|
||||
m.rows = 2;
|
||||
break;
|
||||
case GL_FLOAT_MAT4x3:
|
||||
m.columns = 4;
|
||||
m.rows = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
Shader::UniformType Shader::getUniformBaseType(GLenum type) const
|
||||
{
|
||||
switch (type)
|
||||
|
||||
@@ -88,11 +88,21 @@ public:
|
||||
std::string pixel;
|
||||
};
|
||||
|
||||
struct MatrixSize
|
||||
{
|
||||
short columns;
|
||||
short rows;
|
||||
};
|
||||
|
||||
struct UniformInfo
|
||||
{
|
||||
int location;
|
||||
int count;
|
||||
int components;
|
||||
union
|
||||
{
|
||||
int components;
|
||||
MatrixSize matrix;
|
||||
};
|
||||
UniformType baseType;
|
||||
std::string name;
|
||||
};
|
||||
@@ -195,7 +205,8 @@ private:
|
||||
// Map active uniform names to their locations.
|
||||
void mapActiveUniforms();
|
||||
|
||||
int getUniformTypeSize(GLenum type) const;
|
||||
int getUniformTypeComponents(GLenum type) const;
|
||||
MatrixSize getMatrixSize(GLenum type) const;
|
||||
UniformType getUniformBaseType(GLenum type) const;
|
||||
|
||||
GLuint compileCode(ShaderStage stage, const std::string &code);
|
||||
|
||||
@@ -151,8 +151,9 @@ int w_Shader_sendBooleans(lua_State *L, int startidx, Shader *shader, const Shad
|
||||
int w_Shader_sendMatrices(lua_State *L, int startidx, Shader *shader, const Shader::UniformInfo *info)
|
||||
{
|
||||
int count = _getCount(L, startidx, info);
|
||||
int dimension = info->components;
|
||||
int elements = dimension * dimension;
|
||||
int columns = info->matrix.columns;
|
||||
int rows = info->matrix.rows;
|
||||
int elements = columns * rows;
|
||||
|
||||
float *values = shader->getScratchBuffer<float>(elements * count);
|
||||
|
||||
@@ -166,28 +167,36 @@ int w_Shader_sendMatrices(lua_State *L, int startidx, Shader *shader, const Shad
|
||||
|
||||
if (table_of_tables)
|
||||
{
|
||||
int n = 0;
|
||||
int n = i * elements;
|
||||
|
||||
for (int j = 1; j <= dimension; j++)
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
lua_rawgeti(L, startidx + i, j);
|
||||
lua_rawgeti(L, startidx + i, row + 1);
|
||||
|
||||
for (int k = 1; k <= dimension; k++)
|
||||
for (int column = 0; column < columns; column++)
|
||||
{
|
||||
lua_rawgeti(L, -k, k);
|
||||
values[i * elements + n] = (float) luaL_checknumber(L, -1);
|
||||
n++;
|
||||
// The table has the matrix elements laid out in row-major
|
||||
// order, but we need to store them column-major in memory.
|
||||
lua_rawgeti(L, -(column + 1), column + 1);
|
||||
values[n + (column * rows + row)] = (float) luaL_checknumber(L, -1);
|
||||
}
|
||||
|
||||
lua_pop(L, dimension + 1);
|
||||
lua_pop(L, columns + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int k = 1; k <= elements; k++)
|
||||
int n = i * elements;
|
||||
|
||||
for (int column = 0; column < columns; column++)
|
||||
{
|
||||
lua_rawgeti(L, startidx + i, k);
|
||||
values[i * elements + (k - 1)] = (float) luaL_checknumber(L, -1);
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
// The table has the matrix elements laid out in row-major
|
||||
// order, but we need to store them column-major in memory.
|
||||
lua_rawgeti(L, startidx + i, row * columns + column + 1);
|
||||
values[n + (column * rows + row)] = (float) luaL_checknumber(L, -1);
|
||||
}
|
||||
}
|
||||
|
||||
lua_pop(L, elements);
|
||||
|
||||
Reference in New Issue
Block a user