mirror of https://github.com/bjornbytes/lovr.git
Refactor graphics state, especially shaders;
This should improve performance, if not then I have failed.
This commit is contained in:
parent
c2feb24118
commit
954592d8bd
|
@ -13,12 +13,8 @@ static GraphicsState state;
|
|||
void lovrGraphicsInit() {
|
||||
vec_init(&state.transforms);
|
||||
state.projection = mat4_init();
|
||||
state.lastTransform = mat4_init();
|
||||
state.lastProjection = mat4_init();
|
||||
state.defaultShader = lovrShaderCreate(lovrDefaultVertexShader, lovrDefaultFragmentShader);
|
||||
state.skyboxShader = lovrShaderCreate(lovrSkyboxVertexShader, lovrSkyboxFragmentShader);
|
||||
state.lastShader = NULL;
|
||||
state.lastColor = 0;
|
||||
glGenBuffers(1, &state.shapeBuffer);
|
||||
glGenBuffers(1, &state.shapeIndexBuffer);
|
||||
glGenVertexArrays(1, &state.shapeArray);
|
||||
|
@ -30,8 +26,6 @@ void lovrGraphicsInit() {
|
|||
void lovrGraphicsDestroy() {
|
||||
vec_deinit(&state.transforms);
|
||||
mat4_deinit(state.projection);
|
||||
mat4_deinit(state.lastTransform);
|
||||
mat4_deinit(state.lastProjection);
|
||||
lovrShaderDestroy(state.defaultShader);
|
||||
lovrShaderDestroy(state.skyboxShader);
|
||||
glDeleteBuffers(1, &state.shapeBuffer);
|
||||
|
@ -52,9 +46,6 @@ void lovrGraphicsReset() {
|
|||
vec_clear(&state.transforms);
|
||||
vec_push(&state.transforms, mat4_init());
|
||||
|
||||
memset(state.lastTransform, 0, 16);
|
||||
memset(state.lastProjection, 0, 16);
|
||||
|
||||
lovrGraphicsSetProjection(.1f, 100.f, 67 * M_PI / 180); // TODO customize via lovr.conf
|
||||
lovrGraphicsSetShader(state.defaultShader);
|
||||
lovrGraphicsSetBackgroundColor(0, 0, 0, 0);
|
||||
|
@ -87,43 +78,7 @@ void lovrGraphicsPresent() {
|
|||
|
||||
void lovrGraphicsPrepare() {
|
||||
Shader* shader = lovrGraphicsGetShader();
|
||||
|
||||
if (!shader) {
|
||||
return;
|
||||
}
|
||||
|
||||
int shaderChanged = shader != state.lastShader;
|
||||
state.lastShader = shader;
|
||||
|
||||
mat4 transform = vec_last(&state.transforms);
|
||||
mat4 lastTransform = state.lastTransform;
|
||||
|
||||
if (shaderChanged || memcmp(transform, lastTransform, 16 * sizeof(float))) {
|
||||
int uniformId = lovrShaderGetUniformId(shader, "lovrTransform");
|
||||
lovrShaderSendFloatMat4(shader, uniformId, transform);
|
||||
memcpy(lastTransform, transform, 16 * sizeof(float));
|
||||
}
|
||||
|
||||
mat4 projection = state.projection;
|
||||
mat4 lastProjection = state.lastProjection;
|
||||
|
||||
if (shaderChanged || memcmp(projection, lastProjection, 16 * sizeof(float))) {
|
||||
int uniformId = lovrShaderGetUniformId(shader, "lovrProjection");
|
||||
lovrShaderSendFloatMat4(shader, uniformId, projection);
|
||||
memcpy(lastProjection, projection, 16 * sizeof(float));
|
||||
}
|
||||
|
||||
if (shaderChanged || state.lastColor != state.color) {
|
||||
int uniformId = lovrShaderGetUniformId(shader, "lovrColor");
|
||||
float color[4] = {
|
||||
LOVR_COLOR_R(state.color) / 255.f,
|
||||
LOVR_COLOR_G(state.color) / 255.f,
|
||||
LOVR_COLOR_B(state.color) / 255.f,
|
||||
LOVR_COLOR_A(state.color) / 255.f
|
||||
};
|
||||
lovrShaderSendFloatVec4(shader, uniformId, color);
|
||||
state.lastColor = state.color;
|
||||
}
|
||||
lovrShaderBind(shader, vec_last(&state.transforms), state.projection, state.color, 0);
|
||||
}
|
||||
|
||||
void lovrGraphicsGetBackgroundColor(float* r, float* g, float* b, float* a) {
|
||||
|
@ -203,7 +158,6 @@ void lovrGraphicsSetShader(Shader* shader) {
|
|||
}
|
||||
|
||||
state.activeShader = shader;
|
||||
glUseProgram(shader->id);
|
||||
}
|
||||
|
||||
void lovrGraphicsSetProjection(float near, float far, float fov) {
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
#ifndef LOVR_GRAPHICS_TYPES
|
||||
#define LOVR_GRAPHICS_TYPES
|
||||
|
||||
#define LOVR_COLOR(r, g, b, a) ((a << 0) | (b << 8) | (g << 16) | (r << 24))
|
||||
#define LOVR_COLOR_R(c) (c >> 24 & 0xff)
|
||||
#define LOVR_COLOR_G(c) (c >> 16 & 0xff)
|
||||
#define LOVR_COLOR_B(c) (c >> 8 & 0xff)
|
||||
#define LOVR_COLOR_A(c) (c >> 0 & 0xff)
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
|
@ -32,15 +26,11 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
Shader* activeShader;
|
||||
Shader* lastShader;
|
||||
Shader* defaultShader;
|
||||
Shader* skyboxShader;
|
||||
vec_mat4_t transforms;
|
||||
mat4 lastTransform;
|
||||
mat4 projection;
|
||||
mat4 lastProjection;
|
||||
unsigned int color;
|
||||
unsigned int lastColor;
|
||||
char colorMask;
|
||||
char isScissorEnabled;
|
||||
ScissorRectangle scissor;
|
||||
|
|
|
@ -99,27 +99,29 @@ GLuint linkShaders(GLuint vertexShader, GLuint fragmentShader) {
|
|||
}
|
||||
|
||||
Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) {
|
||||
Shader* shader = (Shader*) malloc(sizeof(Shader));
|
||||
if (!shader) return NULL;
|
||||
|
||||
// Vertex
|
||||
vertexSource = vertexSource == NULL ? lovrDefaultVertexShader : vertexSource;
|
||||
char fullVertexSource[1024];
|
||||
snprintf(fullVertexSource, sizeof(fullVertexSource), "%s\n%s", lovrShaderVertexPrefix, vertexSource);
|
||||
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, fullVertexSource);
|
||||
|
||||
// Fragment
|
||||
fragmentSource = fragmentSource == NULL ? lovrDefaultFragmentShader : fragmentSource;
|
||||
char fullFragmentSource[1024];
|
||||
snprintf(fullFragmentSource, sizeof(fullFragmentSource), "%s\n%s", lovrShaderFragmentPrefix, fragmentSource);
|
||||
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fullFragmentSource);
|
||||
|
||||
// Link
|
||||
GLuint id = linkShaders(vertexShader, fragmentShader);
|
||||
Shader* shader = (Shader*) malloc(sizeof(Shader));
|
||||
if (!shader) return NULL;
|
||||
|
||||
shader->id = id;
|
||||
|
||||
// Compute information about uniforms
|
||||
GLint uniformCount;
|
||||
GLsizei bufferSize = LOVR_MAX_UNIFORM_LENGTH / sizeof(GLchar);
|
||||
map_init(&shader->uniforms);
|
||||
glGetProgramiv(id, GL_ACTIVE_UNIFORMS, &uniformCount);
|
||||
|
||||
for (int i = 0; i < uniformCount; i++) {
|
||||
Uniform uniform;
|
||||
glGetActiveUniform(id, i, bufferSize, NULL, &uniform.count, &uniform.type, uniform.name);
|
||||
|
@ -128,6 +130,15 @@ Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) {
|
|||
map_set(&shader->uniforms, uniform.name, uniform);
|
||||
}
|
||||
|
||||
// Initial state
|
||||
shader->id = id;
|
||||
shader->transform = mat4_init();
|
||||
shader->projection = mat4_init();
|
||||
shader->color = 0;
|
||||
|
||||
// Send initial uniform values to shader
|
||||
lovrShaderBind(shader, shader->transform, shader->projection, shader->color, 1);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
@ -136,6 +147,43 @@ void lovrShaderDestroy(Shader* shader) {
|
|||
free(shader);
|
||||
}
|
||||
|
||||
void lovrShaderBind(Shader* shader, mat4 transform, mat4 projection, unsigned int color, int force) {
|
||||
|
||||
// Bind shader if necessary
|
||||
int program;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
|
||||
if (program != shader->id) {
|
||||
glUseProgram(shader->id);
|
||||
}
|
||||
|
||||
// Update transform if necessary
|
||||
if (force || memcmp(shader->transform, transform, 16 * sizeof(float))) {
|
||||
int uniformId = lovrShaderGetUniformId(shader, "lovrTransform");
|
||||
lovrShaderSendFloatMat4(shader, uniformId, transform);
|
||||
memcpy(shader->transform, transform, 16 * sizeof(float));
|
||||
}
|
||||
|
||||
// Update projection if necessary
|
||||
if (force || memcmp(shader->projection, projection, 16 * sizeof(float))) {
|
||||
int uniformId = lovrShaderGetUniformId(shader, "lovrProjection");
|
||||
lovrShaderSendFloatMat4(shader, uniformId, projection);
|
||||
memcpy(shader->projection, projection, 16 * sizeof(float));
|
||||
}
|
||||
|
||||
// Update color if necessary
|
||||
if (force || shader->color != color) {
|
||||
int uniformId = lovrShaderGetUniformId(shader, "lovrColor");
|
||||
float c[4] = {
|
||||
LOVR_COLOR_R(color) / 255.f,
|
||||
LOVR_COLOR_G(color) / 255.f,
|
||||
LOVR_COLOR_B(color) / 255.f,
|
||||
LOVR_COLOR_A(color) / 255.f
|
||||
};
|
||||
lovrShaderSendFloatVec4(shader, uniformId, c);
|
||||
shader->color = color;
|
||||
}
|
||||
}
|
||||
|
||||
int lovrShaderGetAttributeId(Shader* shader, const char* name) {
|
||||
if (!shader) {
|
||||
return -1;
|
||||
|
@ -146,12 +194,7 @@ int lovrShaderGetAttributeId(Shader* shader, const char* name) {
|
|||
|
||||
int lovrShaderGetUniformId(Shader* shader, const char* name) {
|
||||
Uniform* uniform = map_get(&shader->uniforms, name);
|
||||
|
||||
if (!uniform) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uniform->location;
|
||||
return uniform ? uniform->location : -1;
|
||||
}
|
||||
|
||||
int lovrShaderGetUniformType(Shader* shader, const char* name, GLenum* type, int* count) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "../glfw.h"
|
||||
#include "../vendor/map/map.h"
|
||||
#include "../matrix.h"
|
||||
|
||||
#ifndef LOVR_SHADER_TYPES
|
||||
#define LOVR_SHADER_TYPES
|
||||
|
@ -20,8 +21,11 @@ typedef struct {
|
|||
typedef map_t(Uniform) map_uniform_t;
|
||||
|
||||
typedef struct {
|
||||
GLuint id;
|
||||
int id;
|
||||
map_uniform_t uniforms;
|
||||
mat4 transform;
|
||||
mat4 projection;
|
||||
unsigned int color;
|
||||
} Shader;
|
||||
#endif
|
||||
|
||||
|
@ -37,6 +41,7 @@ GLuint linkShaders(GLuint vertexShader, GLuint fragmentShader);
|
|||
|
||||
Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource);
|
||||
void lovrShaderDestroy(Shader* shader);
|
||||
void lovrShaderBind(Shader* shader, mat4 transform, mat4 projection, unsigned int color, int force);
|
||||
int lovrShaderGetAttributeId(Shader* shader, const char* name);
|
||||
int lovrShaderGetUniformId(Shader* shader, const char* name);
|
||||
int lovrShaderGetUniformType(Shader* shader, const char* name, GLenum* type, int* count);
|
||||
|
|
|
@ -39,7 +39,7 @@ int l_lovrShaderSend(lua_State* L) {
|
|||
GLenum type;
|
||||
int size;
|
||||
lovrShaderGetUniformType(shader, name, &type, &size);
|
||||
|
||||
lovrShaderBind(shader, shader->transform, shader->projection, shader->color, 0); // Hmm
|
||||
float data[16];
|
||||
|
||||
switch (type) {
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#define MAX(a, b) a > b ? a : b
|
||||
#define MIN(a, b) a < b ? a : b
|
||||
|
||||
#define LOVR_COLOR(r, g, b, a) ((a << 0) | (b << 8) | (g << 16) | (r << 24))
|
||||
#define LOVR_COLOR_R(c) (c >> 24 & 0xff)
|
||||
#define LOVR_COLOR_G(c) (c >> 16 & 0xff)
|
||||
#define LOVR_COLOR_B(c) (c >> 8 & 0xff)
|
||||
#define LOVR_COLOR_A(c) (c >> 0 & 0xff)
|
||||
|
||||
typedef vec_t(unsigned int) vec_uint_t;
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue