2017-03-11 11:08:07 +00:00
|
|
|
#include "api/lovr.h"
|
2017-08-11 05:23:19 +00:00
|
|
|
#include "graphics/graphics.h"
|
2017-03-11 11:08:07 +00:00
|
|
|
#include "graphics/shader.h"
|
2017-02-18 23:18:30 +00:00
|
|
|
#include "math/transform.h"
|
2016-08-10 06:28:17 +00:00
|
|
|
|
2016-08-28 20:36:54 +00:00
|
|
|
int l_lovrShaderSend(lua_State* L) {
|
2016-11-19 08:57:18 +00:00
|
|
|
Shader* shader = luax_checktype(L, 1, Shader);
|
2016-08-28 20:36:54 +00:00
|
|
|
const char* name = luaL_checkstring(L, 2);
|
2016-12-30 19:57:15 +00:00
|
|
|
lua_settop(L, 3);
|
2016-08-28 20:36:54 +00:00
|
|
|
|
|
|
|
int id = lovrShaderGetUniformId(shader, name);
|
|
|
|
if (id == -1) {
|
|
|
|
return luaL_error(L, "Unknown shader variable '%s'", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
GLenum type;
|
|
|
|
int size;
|
2016-10-18 22:29:26 +00:00
|
|
|
lovrShaderGetUniformType(shader, name, &type, &size);
|
2017-08-11 05:23:19 +00:00
|
|
|
lovrGraphicsBindProgram(shader->id);
|
2016-08-28 20:36:54 +00:00
|
|
|
float data[16];
|
2016-12-30 19:57:15 +00:00
|
|
|
int n;
|
|
|
|
vec_float_t values;
|
|
|
|
vec_init(&values);
|
2016-08-28 20:36:54 +00:00
|
|
|
|
|
|
|
switch (type) {
|
2017-03-31 01:54:39 +00:00
|
|
|
case GL_SAMPLER_2D:
|
|
|
|
case GL_SAMPLER_CUBE:
|
2016-11-27 02:58:58 +00:00
|
|
|
case GL_INT:
|
|
|
|
lovrShaderSendInt(shader, id, luaL_checkinteger(L, 3));
|
|
|
|
break;
|
|
|
|
|
2016-08-28 20:36:54 +00:00
|
|
|
case GL_FLOAT:
|
|
|
|
lovrShaderSendFloat(shader, id, luaL_checknumber(L, 3));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GL_FLOAT_VEC2:
|
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
2016-12-30 19:57:15 +00:00
|
|
|
lua_rawgeti(L, 3, 1);
|
|
|
|
if (!lua_istable(L, -1)) {
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushvalue(L, 3);
|
|
|
|
lua_rawseti(L, -2, 1);
|
|
|
|
} else {
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
n = lua_objlen(L, -1);
|
|
|
|
if (n < size) {
|
|
|
|
return luaL_error(L, "Expected %d vec3s, got %d", size, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
|
|
|
for (int j = 0; j < 2; j++) {
|
|
|
|
lua_rawgeti(L, -1, j + 1);
|
|
|
|
vec_push(&values, lua_tonumber(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-08-28 20:36:54 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-12-30 19:57:15 +00:00
|
|
|
|
|
|
|
lovrShaderSendFloatVec2(shader, id, size, values.data);
|
2016-08-28 20:36:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GL_FLOAT_VEC3:
|
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
2016-12-30 19:57:15 +00:00
|
|
|
lua_rawgeti(L, 3, 1);
|
|
|
|
if (!lua_istable(L, -1)) {
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushvalue(L, 3);
|
|
|
|
lua_rawseti(L, -2, 1);
|
|
|
|
} else {
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
n = lua_objlen(L, -1);
|
|
|
|
if (n < size) {
|
|
|
|
return luaL_error(L, "Expected %d vec3s, got %d", size, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
|
|
|
for (int j = 0; j < 3; j++) {
|
|
|
|
lua_rawgeti(L, -1, j + 1);
|
|
|
|
vec_push(&values, lua_tonumber(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-08-28 20:36:54 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-12-30 19:57:15 +00:00
|
|
|
|
|
|
|
lovrShaderSendFloatVec3(shader, id, size, values.data);
|
2016-08-28 20:36:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GL_FLOAT_VEC4:
|
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
2016-12-30 19:57:15 +00:00
|
|
|
lua_rawgeti(L, 3, 1);
|
|
|
|
if (!lua_istable(L, -1)) {
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushvalue(L, 3);
|
|
|
|
lua_rawseti(L, -2, 1);
|
|
|
|
} else {
|
2016-08-28 20:36:54 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-12-30 19:57:15 +00:00
|
|
|
|
|
|
|
n = lua_objlen(L, -1);
|
|
|
|
if (n < size) {
|
|
|
|
return luaL_error(L, "Expected %d vec3s, got %d", size, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
|
|
|
for (int j = 0; j < 4; j++) {
|
|
|
|
lua_rawgeti(L, -1, j + 1);
|
|
|
|
vec_push(&values, lua_tonumber(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
lovrShaderSendFloatVec4(shader, id, size, values.data);
|
2016-08-28 20:36:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GL_FLOAT_MAT2:
|
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
lua_rawgeti(L, 3, i + 1);
|
|
|
|
data[i] = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
lovrShaderSendFloatMat2(shader, id, data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GL_FLOAT_MAT3:
|
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
|
|
lua_rawgeti(L, 3, i + 1);
|
|
|
|
data[i] = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
lovrShaderSendFloatMat3(shader, id, data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GL_FLOAT_MAT4:
|
2017-02-18 23:18:30 +00:00
|
|
|
if (lua_isuserdata(L, 3)) {
|
|
|
|
Transform* transform = luax_checktype(L, 3, Transform);
|
|
|
|
memcpy(data, transform->matrix, 16 * sizeof(float));
|
|
|
|
} else {
|
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
|
|
lua_rawgeti(L, 3, i + 1);
|
|
|
|
data[i] = lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-08-28 20:36:54 +00:00
|
|
|
}
|
|
|
|
lovrShaderSendFloatMat4(shader, id, data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return luaL_error(L, "Unknown uniform type %d", type);
|
|
|
|
}
|
|
|
|
|
2016-12-30 19:57:15 +00:00
|
|
|
vec_deinit(&values);
|
|
|
|
|
2016-08-28 20:36:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-03-11 11:08:07 +00:00
|
|
|
|
|
|
|
const luaL_Reg lovrShader[] = {
|
|
|
|
{ "send", l_lovrShaderSend },
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|