mirror of https://github.com/bjornbytes/lovr.git
ShaderBlock:send; Helper function for reading uniforms;
This commit is contained in:
parent
18ee139341
commit
2b093b5828
|
@ -56,6 +56,7 @@ extern const luaL_Reg lovrModelData[];
|
||||||
extern const luaL_Reg lovrRandomGenerator[];
|
extern const luaL_Reg lovrRandomGenerator[];
|
||||||
extern const luaL_Reg lovrRasterizer[];
|
extern const luaL_Reg lovrRasterizer[];
|
||||||
extern const luaL_Reg lovrShader[];
|
extern const luaL_Reg lovrShader[];
|
||||||
|
extern const luaL_Reg lovrShaderBlock[];
|
||||||
extern const luaL_Reg lovrShape[];
|
extern const luaL_Reg lovrShape[];
|
||||||
extern const luaL_Reg lovrSliderJoint[];
|
extern const luaL_Reg lovrSliderJoint[];
|
||||||
extern const luaL_Reg lovrSoundData[];
|
extern const luaL_Reg lovrSoundData[];
|
||||||
|
@ -114,3 +115,4 @@ Blob* luax_readblob(lua_State* L, int index, const char* debug);
|
||||||
Seed luax_checkrandomseed(lua_State* L, int index);
|
Seed luax_checkrandomseed(lua_State* L, int index);
|
||||||
void luax_checkvariant(lua_State* L, int index, Variant* variant);
|
void luax_checkvariant(lua_State* L, int index, Variant* variant);
|
||||||
int luax_pushvariant(lua_State* L, Variant* variant);
|
int luax_pushvariant(lua_State* L, Variant* variant);
|
||||||
|
int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* dest, const char* debug);
|
||||||
|
|
|
@ -241,6 +241,7 @@ int l_lovrGraphicsInit(lua_State* L) {
|
||||||
luax_registertype(L, "Mesh", lovrMesh);
|
luax_registertype(L, "Mesh", lovrMesh);
|
||||||
luax_registertype(L, "Model", lovrModel);
|
luax_registertype(L, "Model", lovrModel);
|
||||||
luax_registertype(L, "Shader", lovrShader);
|
luax_registertype(L, "Shader", lovrShader);
|
||||||
|
luax_registertype(L, "ShaderBlock", lovrShaderBlock);
|
||||||
luax_registertype(L, "Texture", lovrTexture);
|
luax_registertype(L, "Texture", lovrTexture);
|
||||||
luax_extendtype(L, "Texture", "Canvas", lovrTexture, lovrCanvas);
|
luax_extendtype(L, "Texture", "Canvas", lovrTexture, lovrCanvas);
|
||||||
lovrGraphicsInit();
|
lovrGraphicsInit();
|
||||||
|
@ -885,9 +886,9 @@ int l_lovrGraphicsNewShaderBlock(lua_State* L) {
|
||||||
lua_getfield(L, -1, "type");
|
lua_getfield(L, -1, "type");
|
||||||
const char* type = lua_tolstring(L, -1, &length);
|
const char* type = lua_tolstring(L, -1, &length);
|
||||||
uniform.components = 1;
|
uniform.components = 1;
|
||||||
if (strcmp(type, "float")) {
|
if (!strcmp(type, "float")) {
|
||||||
uniform.type = UNIFORM_FLOAT;
|
uniform.type = UNIFORM_FLOAT;
|
||||||
} else if (strcmp(type, "int")) {
|
} else if (!strcmp(type, "int")) {
|
||||||
uniform.type = UNIFORM_INT;
|
uniform.type = UNIFORM_INT;
|
||||||
} else {
|
} else {
|
||||||
uniform.components = type[length - 1] - '0';
|
uniform.components = type[length - 1] - '0';
|
||||||
|
|
|
@ -9,6 +9,132 @@ struct TempData {
|
||||||
|
|
||||||
static struct TempData tempData;
|
static struct TempData tempData;
|
||||||
|
|
||||||
|
int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* dest, const char* debug) {
|
||||||
|
Blob* blob = luax_totype(L, index, Blob);
|
||||||
|
int components = uniform->components;
|
||||||
|
int count = uniform->count;
|
||||||
|
|
||||||
|
if (uniform->type == UNIFORM_MATRIX) {
|
||||||
|
components *= components;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO samplers/textures
|
||||||
|
|
||||||
|
if (blob) {
|
||||||
|
size_t elements = count * components;
|
||||||
|
const char* s = elements == 1 ? "" : "s";
|
||||||
|
size_t capacity;
|
||||||
|
|
||||||
|
switch (uniform->type) {
|
||||||
|
case UNIFORM_FLOAT:
|
||||||
|
case UNIFORM_MATRIX:
|
||||||
|
capacity = blob->size / sizeof(float);
|
||||||
|
lovrAssert(capacity >= elements, "Blob can only hold %d float%s, at least %d needed", capacity, s, elements);
|
||||||
|
memcpy(dest, blob->data, elements * sizeof(float));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNIFORM_INT:
|
||||||
|
capacity = blob->size / sizeof(int);
|
||||||
|
lovrAssert(capacity >= elements, "Blob can only hold %d int%s, at least %d needed", capacity, s, elements);
|
||||||
|
memcpy(dest, blob->data, elements * sizeof(int));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: lovrThrow(""); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (components == 1) {
|
||||||
|
bool isTable = lua_istable(L, index);
|
||||||
|
if (isTable) {
|
||||||
|
int length = lua_objlen(L, index);
|
||||||
|
lovrAssert(length == count, ""); // TODO
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
lua_rawgeti(L, index, i + 1);
|
||||||
|
switch (uniform->type) {
|
||||||
|
case UNIFORM_FLOAT: *((float*) dest + i) = luaL_checknumber(L, -1); break;
|
||||||
|
case UNIFORM_INT: *((int*) dest + i) = luaL_checkinteger(L, -1); break;
|
||||||
|
default: lovrThrow(""); // TODO
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
switch (uniform->type) {
|
||||||
|
case UNIFORM_FLOAT: *((float*) dest + i) = luaL_checknumber(L, index + i); break;
|
||||||
|
case UNIFORM_INT: *((int*) dest + i) = luaL_checkinteger(L, index + i); break;
|
||||||
|
default: lovrThrow(""); // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
luaL_checktype(L, index, LUA_TTABLE);
|
||||||
|
lua_rawgeti(L, index, 1);
|
||||||
|
bool wrappedTable = lua_istable(L, -1) || luax_totype(L, -1, Transform);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
if (wrappedTable) {
|
||||||
|
int length = lua_objlen(L, index);
|
||||||
|
lovrAssert(length == count, ""); // TODO
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
lua_rawgeti(L, index, i + 1);
|
||||||
|
|
||||||
|
if (uniform->type == UNIFORM_MATRIX && lua_isuserdata(L, -1)) {
|
||||||
|
Transform* transform = luax_checktype(L, -1, Transform);
|
||||||
|
memcpy((float*) dest + i * components, transform->matrix, 16 * sizeof(float));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < components; j++) {
|
||||||
|
lua_rawgeti(L, -1, j + 1);
|
||||||
|
switch (uniform->type) {
|
||||||
|
case UNIFORM_FLOAT:
|
||||||
|
case UNIFORM_MATRIX:
|
||||||
|
*((float*) dest + i * components + j) = luaL_checknumber(L, -1);
|
||||||
|
|
||||||
|
case UNIFORM_INT:
|
||||||
|
*((int*) dest + i * components + j) = luaL_checkinteger(L, -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
lovrThrow(""); // TODO
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (uniform->type == UNIFORM_MATRIX && lua_isuserdata(L, index + i)) {
|
||||||
|
Transform* transform = luax_checktype(L, index + i, Transform);
|
||||||
|
memcpy((float*) dest + i * components, transform->matrix, 16 * sizeof(float));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaL_checktype(L, index + i, LUA_TTABLE);
|
||||||
|
for (int j = 0; j < components; j++) {
|
||||||
|
lua_rawgeti(L, index + i, j + 1);
|
||||||
|
switch (uniform->type) {
|
||||||
|
case UNIFORM_FLOAT:
|
||||||
|
case UNIFORM_MATRIX:
|
||||||
|
*((float*) dest + i * components + j) = luaL_checknumber(L, -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNIFORM_INT:
|
||||||
|
*((float*) dest + i * components + j) = luaL_checknumber(L, -1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: lovrThrow(""); // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int l_lovrShaderHasUniform(lua_State* L) {
|
int l_lovrShaderHasUniform(lua_State* L) {
|
||||||
Shader* shader = luax_checktype(L, 1, Shader);
|
Shader* shader = luax_checktype(L, 1, Shader);
|
||||||
const char* name = luaL_checkstring(L, 2);
|
const char* name = luaL_checkstring(L, 2);
|
||||||
|
@ -19,146 +145,15 @@ int l_lovrShaderHasUniform(lua_State* L) {
|
||||||
int l_lovrShaderSend(lua_State* L) {
|
int l_lovrShaderSend(lua_State* L) {
|
||||||
Shader* shader = luax_checktype(L, 1, Shader);
|
Shader* shader = luax_checktype(L, 1, Shader);
|
||||||
const char* name = luaL_checkstring(L, 2);
|
const char* name = luaL_checkstring(L, 2);
|
||||||
lua_settop(L, 3);
|
const Uniform* uniform = lovrShaderGetUniform(shader, name);
|
||||||
|
lovrAssert(uniform, "Unknown shader variable '%s'", name);
|
||||||
|
|
||||||
int count;
|
if (tempData.size < uniform->size) {
|
||||||
int components;
|
tempData.size = uniform->size;
|
||||||
int size;
|
|
||||||
UniformType type;
|
|
||||||
bool present = lovrShaderGetUniform(shader, name, &count, &components, &size, &type);
|
|
||||||
|
|
||||||
if (!present) {
|
|
||||||
return luaL_error(L, "Unknown shader variable '%s'", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tempData.size < size) {
|
|
||||||
tempData.size = size;
|
|
||||||
tempData.data = realloc(tempData.data, tempData.size);
|
tempData.data = realloc(tempData.data, tempData.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int* ints = (int*) tempData.data;
|
luax_checkuniform(L, 3, uniform, tempData.data, name);
|
||||||
float* floats = (float*) tempData.data;
|
|
||||||
Texture** textures = (Texture**) tempData.data;
|
|
||||||
int n = 1;
|
|
||||||
|
|
||||||
if (components > 1 && lua_istable(L, 3)) {
|
|
||||||
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 != count) {
|
|
||||||
return luaL_error(L, "Expected %d element%s for array '%s', got %d", count, count == 1 ? "" : "s", name, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Blob* blob = luax_totype(L, 3, Blob);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case UNIFORM_FLOAT:
|
|
||||||
if (blob) {
|
|
||||||
n = count;
|
|
||||||
floats = (float*) blob->data;
|
|
||||||
size_t count = n * components;
|
|
||||||
size_t capacity = blob->size / sizeof(float);
|
|
||||||
const char* s = capacity == 1 ? "" : "s";
|
|
||||||
lovrAssert(capacity >= count, "Blob can only hold %d float%s, at least %d needed", capacity, s, count);
|
|
||||||
} else if (components == 1) {
|
|
||||||
floats[0] = luaL_checknumber(L, 3);
|
|
||||||
} else {
|
|
||||||
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) {
|
|
||||||
return luaL_error(L, "Expected %d components for uniform '%s' #%d, got %d", components, name, lua_objlen(L, -1));
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lovrShaderSetFloat(shader, name, floats, n * components);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNIFORM_INT:
|
|
||||||
if (blob) {
|
|
||||||
n = count;
|
|
||||||
ints = (int*) blob->data;
|
|
||||||
size_t count = n * components;
|
|
||||||
size_t capacity = blob->size / sizeof(int);
|
|
||||||
const char* s = capacity == 1 ? "" : "s";
|
|
||||||
lovrAssert(capacity >= count, "Blob can only hold %d int%s, at least %d needed", capacity, s, count);
|
|
||||||
} else if (components == 1) {
|
|
||||||
ints[0] = luaL_checkinteger(L, 3);
|
|
||||||
} else {
|
|
||||||
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) {
|
|
||||||
return luaL_error(L, "Expected %d components for uniform '%s' #%d, got %d", components, name, lua_objlen(L, -1));
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lovrShaderSetInt(shader, name, ints, n * components);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNIFORM_MATRIX:
|
|
||||||
if (blob) {
|
|
||||||
n = count;
|
|
||||||
floats = (float*) blob->data;
|
|
||||||
size_t count = n * components * components;
|
|
||||||
size_t capacity = blob->size / sizeof(float);
|
|
||||||
const char* s = capacity == 1 ? "x" : "ces";
|
|
||||||
lovrAssert(capacity >= count, "Blob can only hold %d matri%s, at least %d needed", capacity, s, count);
|
|
||||||
} else if (components == 4 && lua_isuserdata(L, 3)) {
|
|
||||||
Transform* transform = luax_checktype(L, 3, Transform);
|
|
||||||
memcpy(floats, transform->matrix, 16 * sizeof(float));
|
|
||||||
} else {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lovrShaderSetMatrix(shader, name, floats, n * components * components);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNIFORM_SAMPLER:
|
|
||||||
if (components == 1) {
|
|
||||||
textures[0] = luax_checktype(L, 3, Texture);
|
|
||||||
} else {
|
|
||||||
luaL_checktype(L, 3, LUA_TTABLE);
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
lua_rawgeti(L, -1, i + 1);
|
|
||||||
textures[i] = luax_checktype(L, -1, Texture);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lovrShaderSetTexture(shader, name, textures, n);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "api.h"
|
||||||
|
#include "graphics/shader.h"
|
||||||
|
#include "math/transform.h"
|
||||||
|
|
||||||
|
int l_lovrShaderBlockGetSize(lua_State* L) {
|
||||||
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
||||||
|
lua_pushinteger(L, lovrShaderBlockGetSize(block));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_lovrShaderBlockSend(lua_State* L) {
|
||||||
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
||||||
|
const char* name = luaL_checkstring(L, 2);
|
||||||
|
const Uniform* uniform = lovrShaderBlockGetUniform(block, name);
|
||||||
|
lovrAssert(uniform, "Unknown uniform for ShaderBlock '%s'", name);
|
||||||
|
uint8_t* data = ((uint8_t*) lovrShaderBlockMap(block)) + uniform->offset;
|
||||||
|
|
||||||
|
luax_checkuniform(L, 3, uniform, data, name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const luaL_Reg lovrShaderBlock[] = {
|
||||||
|
{ "getSize", l_lovrShaderBlockGetSize },
|
||||||
|
{ "send", l_lovrShaderBlockSend },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
|
@ -67,7 +67,11 @@ static struct {
|
||||||
struct ShaderBlock {
|
struct ShaderBlock {
|
||||||
Ref ref;
|
Ref ref;
|
||||||
vec_uniform_t uniforms;
|
vec_uniform_t uniforms;
|
||||||
|
map_int_t uniformMap;
|
||||||
uint32_t buffer;
|
uint32_t buffer;
|
||||||
|
size_t size;
|
||||||
|
void* data;
|
||||||
|
bool mapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -1442,7 +1446,12 @@ void lovrShaderBind(Shader* shader) {
|
||||||
|
|
||||||
UniformBlock* block;
|
UniformBlock* block;
|
||||||
vec_foreach_ptr(&shader->blocks, block, i) {
|
vec_foreach_ptr(&shader->blocks, block, i) {
|
||||||
lovrGpuBindUniformBuffer(block->source ? block->source->buffer : 0, block->binding);
|
if (block->source) {
|
||||||
|
lovrShaderBlockUnmap(block->source);
|
||||||
|
lovrGpuBindUniformBuffer(block->source->buffer, block->binding);
|
||||||
|
} else {
|
||||||
|
lovrGpuBindUniformBuffer(0, block->binding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1455,19 +1464,13 @@ bool lovrShaderHasUniform(Shader* shader, const char* name) {
|
||||||
return map_get(&shader->uniformMap, name) != NULL;
|
return map_get(&shader->uniformMap, name) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrShaderGetUniform(Shader* shader, const char* name, int* count, int* components, int* size, UniformType* type) {
|
const Uniform* lovrShaderGetUniform(Shader* shader, const char* name) {
|
||||||
int* index = map_get(&shader->uniformMap, name);
|
int* index = map_get(&shader->uniformMap, name);
|
||||||
if (!index) {
|
if (!index) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uniform* uniform = &shader->uniforms.data[*index];
|
return &shader->uniforms.data[*index];
|
||||||
|
|
||||||
*count = uniform->count;
|
|
||||||
*components = uniform->components;
|
|
||||||
*size = uniform->size;
|
|
||||||
*type = uniform->type;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lovrShaderSetUniform(Shader* shader, const char* name, UniformType type, void* data, int count, int size, const char* debug) {
|
static void lovrShaderSetUniform(Shader* shader, const char* name, UniformType type, void* data, int count, int size, const char* debug) {
|
||||||
|
@ -1529,32 +1532,70 @@ ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms) {
|
||||||
|
|
||||||
vec_init(&block->uniforms);
|
vec_init(&block->uniforms);
|
||||||
vec_extend(&block->uniforms, uniforms);
|
vec_extend(&block->uniforms, uniforms);
|
||||||
|
map_init(&block->uniformMap);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
Uniform* uniform;
|
Uniform* uniform;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
vec_foreach_ptr(&block->uniforms, uniform, i) {
|
vec_foreach_ptr(&block->uniforms, uniform, i) {
|
||||||
|
|
||||||
|
// Calculate size and offset
|
||||||
uniform->offset = size;
|
uniform->offset = size;
|
||||||
if (uniform->type == UNIFORM_MATRIX) {
|
if (uniform->type == UNIFORM_MATRIX) {
|
||||||
size += uniform->components * uniform->components * 4;
|
size += uniform->components * uniform->components * 4;
|
||||||
} else {
|
} else {
|
||||||
size += uniform->count == 1 ? 4 : (uniform->count * 16);
|
size += uniform->count == 1 ? 4 : (uniform->count * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write index to uniform lookup
|
||||||
|
map_set(&block->uniformMap, uniform->name, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenBuffers(1, &block->buffer);
|
glGenBuffers(1, &block->buffer);
|
||||||
lovrGpuBindUniformBuffer(block->buffer, 0);
|
lovrGpuBindUniformBuffer(block->buffer, 0);
|
||||||
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
|
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
block->size = size;
|
||||||
|
block->data = calloc(1, size);
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrShaderBlockDestroy(void* ref) {
|
void lovrShaderBlockDestroy(void* ref) {
|
||||||
UniformBlock* block = ref;
|
ShaderBlock* block = ref;
|
||||||
vec_deinit(&block->uniforms);
|
vec_deinit(&block->uniforms);
|
||||||
|
map_deinit(&block->uniformMap);
|
||||||
|
free(block->data);
|
||||||
free(block);
|
free(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t lovrShaderBlockGetSize(ShaderBlock* block) {
|
||||||
|
return block->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Uniform* lovrShaderBlockGetUniform(ShaderBlock* block, const char* name) {
|
||||||
|
int* index = map_get(&block->uniformMap, name);
|
||||||
|
if (!index) return NULL;
|
||||||
|
|
||||||
|
return &block->uniforms.data[*index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void* lovrShaderBlockMap(ShaderBlock* block) {
|
||||||
|
block->mapped = true;
|
||||||
|
return block->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrShaderBlockUnmap(ShaderBlock* block) {
|
||||||
|
if (!block->mapped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lovrGpuBindUniformBuffer(block->buffer, 0);
|
||||||
|
glBufferData(GL_UNIFORM_BUFFER, block->size, NULL, GL_STATIC_DRAW);
|
||||||
|
glBufferSubData(GL_UNIFORM_BUFFER, 0, block->size, block->data);
|
||||||
|
block->mapped = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Mesh
|
// Mesh
|
||||||
|
|
||||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, MeshUsage usage) {
|
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, MeshUsage usage) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ void lovrShaderDestroy(void* ref);
|
||||||
void lovrShaderBind(Shader* shader);
|
void lovrShaderBind(Shader* shader);
|
||||||
int lovrShaderGetAttributeId(Shader* shader, const char* name);
|
int lovrShaderGetAttributeId(Shader* shader, const char* name);
|
||||||
bool lovrShaderHasUniform(Shader* shader, const char* name);
|
bool lovrShaderHasUniform(Shader* shader, const char* name);
|
||||||
bool lovrShaderGetUniform(Shader* shader, const char* name, int* count, int* components, int* size, UniformType* type);
|
const Uniform* lovrShaderGetUniform(Shader* shader, const char* name);
|
||||||
void lovrShaderSetFloat(Shader* shader, const char* name, float* data, int count);
|
void lovrShaderSetFloat(Shader* shader, const char* name, float* data, int count);
|
||||||
void lovrShaderSetInt(Shader* shader, const char* name, int* data, int count);
|
void lovrShaderSetInt(Shader* shader, const char* name, int* data, int count);
|
||||||
void lovrShaderSetMatrix(Shader* shader, const char* name, float* data, int count);
|
void lovrShaderSetMatrix(Shader* shader, const char* name, float* data, int count);
|
||||||
|
@ -64,3 +64,7 @@ void lovrShaderSetBlock(Shader* shader, const char* name, ShaderBlock* block);
|
||||||
|
|
||||||
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms);
|
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms);
|
||||||
void lovrShaderBlockDestroy(void* ref);
|
void lovrShaderBlockDestroy(void* ref);
|
||||||
|
size_t lovrShaderBlockGetSize(ShaderBlock* block);
|
||||||
|
const Uniform* lovrShaderBlockGetUniform(ShaderBlock* block, const char* name);
|
||||||
|
void* lovrShaderBlockMap(ShaderBlock* block);
|
||||||
|
void lovrShaderBlockUnmap(ShaderBlock* block);
|
||||||
|
|
Loading…
Reference in New Issue