2017-12-10 20:40:37 +00:00
|
|
|
#include "api.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
|
|
|
|
2017-10-21 20:39:50 +00:00
|
|
|
struct TempData {
|
|
|
|
void* data;
|
|
|
|
size_t size;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct TempData tempData;
|
|
|
|
|
2017-10-22 22:58:56 +00:00
|
|
|
int l_lovrShaderHasUniform(lua_State* L) {
|
|
|
|
Shader* shader = luax_checktype(L, 1, Shader);
|
|
|
|
const char* name = luaL_checkstring(L, 2);
|
2018-07-09 09:05:30 +00:00
|
|
|
lua_pushboolean(L, lovrShaderHasUniform(shader, name));
|
2017-10-22 22:58:56 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2018-07-09 09:05:30 +00:00
|
|
|
int count;
|
|
|
|
int components;
|
|
|
|
size_t size;
|
|
|
|
UniformType type;
|
|
|
|
bool present = lovrShaderGetUniform(shader, name, &count, &components, &size, &type);
|
2017-10-21 20:39:50 +00:00
|
|
|
|
2018-07-09 09:05:30 +00:00
|
|
|
if (!present) {
|
2016-08-28 20:36:54 +00:00
|
|
|
return luaL_error(L, "Unknown shader variable '%s'", name);
|
|
|
|
}
|
|
|
|
|
2018-07-09 09:05:30 +00:00
|
|
|
if (tempData.size < size) {
|
|
|
|
tempData.size = size;
|
2017-10-21 20:39:50 +00:00
|
|
|
tempData.data = realloc(tempData.data, tempData.size);
|
|
|
|
}
|
2016-11-27 02:58:58 +00:00
|
|
|
|
2017-10-21 20:39:50 +00:00
|
|
|
int* ints = (int*) tempData.data;
|
|
|
|
float* floats = (float*) tempData.data;
|
|
|
|
Texture** textures = (Texture**) tempData.data;
|
|
|
|
int n = 1;
|
|
|
|
|
2018-03-12 18:25:28 +00:00
|
|
|
if (components > 1 && lua_istable(L, 3)) {
|
2017-10-21 20:39:50 +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);
|
2018-07-09 09:05:30 +00:00
|
|
|
if (n != count) {
|
|
|
|
return luaL_error(L, "Expected %d element%s for array '%s', got %d", count, count == 1 ? "" : "s", name, n);
|
2017-10-21 20:39:50 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-28 20:36:54 +00:00
|
|
|
|
2018-07-25 04:15:07 +00:00
|
|
|
Blob* blob = luax_totype(L, 3, Blob);
|
2018-03-12 18:25:28 +00:00
|
|
|
|
2018-07-09 09:05:30 +00:00
|
|
|
switch (type) {
|
2017-10-21 20:39:50 +00:00
|
|
|
case UNIFORM_FLOAT:
|
2018-03-12 18:25:28 +00:00
|
|
|
if (blob) {
|
2018-07-09 09:05:30 +00:00
|
|
|
n = count;
|
2018-07-25 04:15:07 +00:00
|
|
|
floats = (float*) blob->data;
|
2018-03-12 20:27:14 +00:00
|
|
|
size_t count = n * components;
|
2018-07-25 04:15:07 +00:00
|
|
|
size_t capacity = blob->size / sizeof(float);
|
2018-03-12 20:27:14 +00:00
|
|
|
const char* s = capacity == 1 ? "" : "s";
|
|
|
|
lovrAssert(capacity >= count, "Blob can only hold %d float%s, at least %d needed", capacity, s, count);
|
2018-03-12 18:25:28 +00:00
|
|
|
} else if (components == 1) {
|
2018-01-10 04:54:55 +00:00
|
|
|
floats[0] = luaL_checknumber(L, 3);
|
2016-12-30 19:57:15 +00:00
|
|
|
} else {
|
2017-10-21 20:39:50 +00:00
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
|
|
|
if (lua_type(L, -1) != LUA_TTABLE || (int) lua_objlen(L, -1) != components) {
|
2018-07-09 09:05:30 +00:00
|
|
|
return luaL_error(L, "Expected %d components for uniform '%s' #%d, got %d", components, name, lua_objlen(L, -1));
|
2017-10-21 20:39:50 +00:00
|
|
|
}
|
|
|
|
for (int j = 0; j < components; j++) {
|
|
|
|
lua_rawgeti(L, -1, j + 1);
|
|
|
|
floats[i * components + j] = luaL_checknumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-12-30 19:57:15 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-08-28 20:36:54 +00:00
|
|
|
}
|
2017-12-08 21:04:43 +00:00
|
|
|
lovrShaderSetFloat(shader, name, floats, n * components);
|
2016-08-28 20:36:54 +00:00
|
|
|
break;
|
|
|
|
|
2017-10-21 20:39:50 +00:00
|
|
|
case UNIFORM_INT:
|
2018-03-12 18:25:28 +00:00
|
|
|
if (blob) {
|
2018-07-09 09:05:30 +00:00
|
|
|
n = count;
|
2018-07-25 04:15:07 +00:00
|
|
|
ints = (int*) blob->data;
|
2018-03-12 20:27:14 +00:00
|
|
|
size_t count = n * components;
|
2018-07-25 04:15:07 +00:00
|
|
|
size_t capacity = blob->size / sizeof(int);
|
2018-03-12 20:27:14 +00:00
|
|
|
const char* s = capacity == 1 ? "" : "s";
|
|
|
|
lovrAssert(capacity >= count, "Blob can only hold %d int%s, at least %d needed", capacity, s, count);
|
2018-03-12 18:25:28 +00:00
|
|
|
} else if (components == 1) {
|
2017-10-21 20:39:50 +00:00
|
|
|
ints[0] = luaL_checkinteger(L, 3);
|
2016-12-30 19:57:15 +00:00
|
|
|
} else {
|
2017-10-21 20:39:50 +00:00
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
|
|
|
if (lua_type(L, -1) != LUA_TTABLE || (int) lua_objlen(L, -1) != components) {
|
2018-07-09 09:05:30 +00:00
|
|
|
return luaL_error(L, "Expected %d components for uniform '%s' #%d, got %d", components, name, lua_objlen(L, -1));
|
2017-10-21 20:39:50 +00:00
|
|
|
}
|
|
|
|
for (int j = 0; j < components; j++) {
|
|
|
|
lua_rawgeti(L, -1, j + 1);
|
|
|
|
ints[i * components + j] = luaL_checkinteger(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-12-30 19:57:15 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-08-28 20:36:54 +00:00
|
|
|
}
|
2017-12-08 21:04:43 +00:00
|
|
|
lovrShaderSetInt(shader, name, ints, n * components);
|
2016-08-28 20:36:54 +00:00
|
|
|
break;
|
|
|
|
|
2017-10-21 20:39:50 +00:00
|
|
|
case UNIFORM_MATRIX:
|
2018-03-12 18:25:28 +00:00
|
|
|
if (blob) {
|
2018-07-09 09:05:30 +00:00
|
|
|
n = count;
|
2018-07-25 04:15:07 +00:00
|
|
|
floats = (float*) blob->data;
|
2018-03-12 20:27:14 +00:00
|
|
|
size_t count = n * components * components;
|
2018-07-25 04:15:07 +00:00
|
|
|
size_t capacity = blob->size / sizeof(float);
|
2018-03-12 20:27:14 +00:00
|
|
|
const char* s = capacity == 1 ? "x" : "ces";
|
|
|
|
lovrAssert(capacity >= count, "Blob can only hold %d matri%s, at least %d needed", capacity, s, count);
|
2018-03-12 18:25:28 +00:00
|
|
|
} else if (components == 4 && lua_isuserdata(L, 3)) {
|
2017-10-21 20:39:50 +00:00
|
|
|
Transform* transform = luax_checktype(L, 3, Transform);
|
|
|
|
memcpy(floats, transform->matrix, 16 * sizeof(float));
|
2016-12-30 19:57:15 +00:00
|
|
|
} else {
|
2017-10-21 20:39:50 +00:00
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
|
|
|
for (int j = 0; j < components * components; j++) {
|
|
|
|
lua_rawgeti(L, -1, j + 1);
|
|
|
|
floats[i * components * components + j] = luaL_checknumber(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-12-30 19:57:15 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
}
|
2017-12-08 21:04:43 +00:00
|
|
|
lovrShaderSetMatrix(shader, name, floats, n * components * components);
|
2016-08-28 20:36:54 +00:00
|
|
|
break;
|
|
|
|
|
2017-10-21 20:39:50 +00:00
|
|
|
case UNIFORM_SAMPLER:
|
|
|
|
if (components == 1) {
|
2018-07-25 04:15:07 +00:00
|
|
|
textures[0] = luax_checktype(L, 3, Texture);
|
2017-02-18 23:18:30 +00:00
|
|
|
} else {
|
|
|
|
luaL_checktype(L, 3, LUA_TTABLE);
|
2017-10-21 20:39:50 +00:00
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
lua_rawgeti(L, -1, i + 1);
|
2018-07-25 04:15:07 +00:00
|
|
|
textures[i] = luax_checktype(L, -1, Texture);
|
2017-02-18 23:18:30 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2016-08-28 20:36:54 +00:00
|
|
|
}
|
2017-10-21 20:39:50 +00:00
|
|
|
lovrShaderSetTexture(shader, name, textures, n);
|
2016-08-28 20:36:54 +00:00
|
|
|
break;
|
|
|
|
|
2017-10-21 20:39:50 +00:00
|
|
|
default: break;
|
2016-08-28 20:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-03-11 11:08:07 +00:00
|
|
|
|
|
|
|
const luaL_Reg lovrShader[] = {
|
2017-10-22 22:58:56 +00:00
|
|
|
{ "hasUniform", l_lovrShaderHasUniform },
|
2017-03-11 11:08:07 +00:00
|
|
|
{ "send", l_lovrShaderSend },
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|