From 9b0712bb66cf9b5b560d0a414dc1f3672eeed90f Mon Sep 17 00:00:00 2001 From: bjorn Date: Sat, 26 Nov 2016 18:58:58 -0800 Subject: [PATCH] Add default texture; --- src/graphics/buffer.c | 8 +------ src/graphics/graphics.c | 50 ++++++++++++++++++++++++++++++++++++++--- src/graphics/graphics.h | 6 +++++ src/graphics/model.c | 5 ----- src/graphics/shader.c | 24 +++++++++++++------- src/graphics/shader.h | 1 + src/loaders/model.c | 3 +++ src/lovr/timer.c | 6 +++++ src/lovr/timer.h | 1 + src/lovr/types/shader.c | 4 ++++ src/timer/timer.c | 14 ++++++++++++ src/timer/timer.h | 4 ++++ 12 files changed, 103 insertions(+), 23 deletions(-) diff --git a/src/graphics/buffer.c b/src/graphics/buffer.c index 5f85125f..26d07a2b 100644 --- a/src/graphics/buffer.c +++ b/src/graphics/buffer.c @@ -68,6 +68,7 @@ void lovrBufferDestroy(const Ref* ref) { void lovrBufferDraw(Buffer* buffer) { int usingIbo = buffer->map.length > 0; + lovrGraphicsSetTexture(buffer->texture); lovrGraphicsPrepare(); glBindVertexArray(buffer->vao); @@ -101,13 +102,6 @@ void lovrBufferDraw(Buffer* buffer) { } } - // Set texture - if (buffer->texture) { - lovrTextureBind(buffer->texture); - } else { - glBindTexture(GL_TEXTURE_2D, 0); - } - // Determine range of vertices to be rendered and whether we're using an IBO or not int start, count; if (buffer->isRangeEnabled) { diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index 989c60ba..41e7b34c 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -17,23 +17,37 @@ void lovrGraphicsInit() { state.projection = mat4_init(); state.defaultShader = lovrShaderCreate(lovrDefaultVertexShader, lovrDefaultFragmentShader); state.skyboxShader = lovrShaderCreate(lovrSkyboxVertexShader, lovrSkyboxFragmentShader); + int uniformId = lovrShaderGetUniformId(state.skyboxShader, "cube"); + lovrShaderSendInt(state.skyboxShader, uniformId, 1); glGenBuffers(1, &state.shapeBuffer); glGenBuffers(1, &state.shapeIndexBuffer); glGenVertexArrays(1, &state.shapeArray); vec_init(&state.shapeData); vec_init(&state.shapeIndices); state.depthTest = -1; + + // Create default texture + TextureData* defaultTextureData = malloc(sizeof(TextureData)); + defaultTextureData->width = 1; + defaultTextureData->height = 1; + uint8_t* data = malloc(4 * sizeof(uint8_t)); + data[0] = data[1] = data[2] = data[3] = 0xff; + defaultTextureData->data = data; + state.defaultTexture = lovrTextureCreate(defaultTextureData); + state.lastTexture = NULL; + glActiveTexture(GL_TEXTURE0); + lovrGraphicsReset(); } void lovrGraphicsDestroy() { lovrGraphicsSetShader(NULL); glUseProgram(0); - lovrRelease(&state.defaultShader->ref); vec_deinit(&state.transforms); mat4_deinit(state.projection); lovrRelease(&state.defaultShader->ref); lovrRelease(&state.skyboxShader->ref); + lovrRelease(&state.defaultTexture->ref); glDeleteBuffers(1, &state.shapeBuffer); glDeleteBuffers(1, &state.shapeIndexBuffer); glDeleteVertexArrays(1, &state.shapeArray); @@ -54,6 +68,7 @@ void lovrGraphicsReset() { lovrGraphicsSetProjection(.1f, 100.f, 67 * M_PI / 180); // TODO customize via lovr.conf lovrGraphicsSetShader(state.defaultShader); + lovrGraphicsSetTexture(state.defaultTexture); lovrGraphicsSetBackgroundColor(0, 0, 0, 0); lovrGraphicsSetColor(255, 255, 255, 255); lovrGraphicsSetColorMask(1, 1, 1, 1); @@ -87,6 +102,16 @@ void lovrGraphicsPresent() { void lovrGraphicsPrepare() { Shader* shader = lovrGraphicsGetShader(); lovrShaderBind(shader, vec_last(&state.transforms), state.projection, state.color, 0); + Texture* texture = lovrGraphicsGetTexture(); + if (texture) { + if (texture != state.lastTexture) { + lovrTextureBind(texture); + state.lastTexture = texture; + } + } else { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + } } // State @@ -173,11 +198,29 @@ void lovrGraphicsSetShader(Shader* shader) { } state.activeShader = shader; - lovrRetain(&state.activeShader->ref); } } +Texture* lovrGraphicsGetTexture() { + return state.activeTexture; +} + +void lovrGraphicsSetTexture(Texture* texture) { + if (!texture) { + texture = state.defaultTexture; + } + + if (texture != state.activeTexture) { + if (state.activeTexture) { + lovrRelease(&state.activeTexture->ref); + } + + state.activeTexture = texture; + lovrRetain(&state.activeTexture->ref); + } +} + void lovrGraphicsSetProjection(float near, float far, float fov) { int width, height; glfwGetWindowSize(window, &width, &height); @@ -603,7 +646,7 @@ void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float a }; glDepthMask(GL_FALSE); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_CUBE_MAP, skybox->texture); lovrGraphicsSetShapeData(cube, 156, NULL, 0); @@ -612,6 +655,7 @@ void lovrGraphicsSkybox(Skybox* skybox, float angle, float ax, float ay, float a glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glDepthMask(GL_TRUE); + glActiveTexture(GL_TEXTURE0); lovrGraphicsSetShader(lastShader); lovrRelease(&lastShader->ref); lovrGraphicsPop(); diff --git a/src/graphics/graphics.h b/src/graphics/graphics.h index 0b5a0629..25701523 100644 --- a/src/graphics/graphics.h +++ b/src/graphics/graphics.h @@ -2,6 +2,7 @@ #include "graphics/model.h" #include "graphics/shader.h" #include "graphics/skybox.h" +#include "graphics/texture.h" #include "matrix.h" #ifndef LOVR_GRAPHICS_TYPES @@ -38,6 +39,9 @@ typedef struct { Shader* activeShader; Shader* defaultShader; Shader* skyboxShader; + Texture* activeTexture; + Texture* lastTexture; + Texture* defaultTexture; vec_mat4_t transforms; mat4 projection; unsigned int color; @@ -80,6 +84,8 @@ void lovrGraphicsGetScissor(int* x, int* y, int* width, int* height); void lovrGraphicsSetScissor(int x, int y, int width, int height); Shader* lovrGraphicsGetShader(); void lovrGraphicsSetShader(Shader* shader); +Texture* lovrGraphicsGetTexture(); +void lovrGraphicsSetTexture(Texture* texture); void lovrGraphicsSetProjection(float near, float far, float fov); void lovrGraphicsSetProjectionRaw(mat4 projection); float lovrGraphicsGetLineWidth(); diff --git a/src/graphics/model.c b/src/graphics/model.c index 1a0bf3a1..2f6da52a 100644 --- a/src/graphics/model.c +++ b/src/graphics/model.c @@ -151,11 +151,6 @@ void lovrModelDataDestroy(ModelData* modelData) { void lovrModelDraw(Model* model, float x, float y, float z, float size, float angle, float ax, float ay, float az) { lovrGraphicsPush(); lovrGraphicsTransform(x, y, z, size, size, size, angle, ax, ay, az); - if (model->texture) { - lovrTextureBind(model->texture); - } else { - glBindTexture(GL_TEXTURE_2D, 0); - } lovrBufferDraw(model->buffer); lovrGraphicsPop(); } diff --git a/src/graphics/shader.c b/src/graphics/shader.c index 4ac750a3..8a047f93 100644 --- a/src/graphics/shader.c +++ b/src/graphics/shader.c @@ -6,26 +6,30 @@ const char* lovrShaderVertexPrefix = "" "#version 150 \n" "uniform mat4 lovrTransform; \n" "uniform mat4 lovrProjection; \n" -"in vec3 lovrPosition;" -"in vec3 lovrNormal;" -"in vec2 lovrTexCoord;" +"in vec3 lovrPosition; \n" +"in vec3 lovrNormal; \n" +"in vec2 lovrTexCoord; \n" +"out vec2 texCoord; \n" ""; const char* lovrShaderFragmentPrefix = "" "#version 150 \n" "uniform vec4 lovrColor; \n" -"out vec4 lovrFragColor;" +"uniform sampler2D lovrTexture; \n" +"in vec2 texCoord; \n" +"out vec4 lovrFragColor; \n" ""; const char* lovrShaderVertexSuffix = "" "void main() { \n" +" texCoord = lovrTexCoord; \n" " gl_Position = position(lovrProjection, lovrTransform, vec4(lovrPosition, 1.0)); \n" "}" ""; const char* lovrShaderFragmentSuffix = "" "void main() { \n" -" lovrFragColor = color(lovrColor); \n" +" lovrFragColor = color(lovrColor, lovrTexture, texCoord); \n" "}" ""; @@ -36,8 +40,8 @@ const char* lovrDefaultVertexShader = "" ""; const char* lovrDefaultFragmentShader = "" -"vec4 color(vec4 graphicsColor) { \n" -" return graphicsColor; \n" +"vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n" +" return graphicsColor * texture(image, uv); \n" "}" ""; @@ -52,7 +56,7 @@ const char* lovrSkyboxVertexShader = "" const char* lovrSkyboxFragmentShader = "" "in vec3 texturePosition; \n" "uniform samplerCube cube; \n" -"vec4 color(vec4 graphicsColor) { \n" +"vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n" " return graphicsColor * texture(cube, texturePosition); \n" "}" ""; @@ -228,6 +232,10 @@ int lovrShaderGetUniformType(Shader* shader, const char* name, GLenum* type, int return 0; } +void lovrShaderSendInt(Shader* shader, int id, int value) { + glUniform1i(id, value); +} + void lovrShaderSendFloat(Shader* shader, int id, float value) { glUniform1f(id, value); } diff --git a/src/graphics/shader.h b/src/graphics/shader.h index d8347473..c76477e5 100644 --- a/src/graphics/shader.h +++ b/src/graphics/shader.h @@ -48,6 +48,7 @@ void lovrShaderBind(Shader* shader, mat4 transform, mat4 projection, unsigned in 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); +void lovrShaderSendInt(Shader* shader, int id, int value); void lovrShaderSendFloat(Shader* shader, int id, float value); void lovrShaderSendFloatVec2(Shader* shader, int id, float* vector); void lovrShaderSendFloatVec3(Shader* shader, int id, float* vector); diff --git a/src/loaders/model.c b/src/loaders/model.c index 0ff01077..471acf46 100644 --- a/src/loaders/model.c +++ b/src/loaders/model.c @@ -28,6 +28,9 @@ ModelData* lovrModelDataFromFile(void* data, int size) { ModelData* modelData = malloc(sizeof(ModelData)); if (!modelData) return NULL; + modelData->hasNormals = 0; + modelData->hasTexCoords = 0; + unsigned int flags = aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_OptimizeGraph | aiProcess_FlipUVs; const struct aiScene* scene = aiImportFileFromMemory(data, size, flags, NULL); diff --git a/src/lovr/timer.c b/src/lovr/timer.c index d2f710ab..8146015d 100644 --- a/src/lovr/timer.c +++ b/src/lovr/timer.c @@ -3,6 +3,7 @@ const luaL_Reg lovrTimer[] = { { "getDelta", l_lovrTimerGetDelta }, + { "getFPS", l_lovrTimerGetFPS }, { "getTime", l_lovrTimerGetTime }, { "step", l_lovrTimerStep }, { "sleep", l_lovrTimerSleep }, @@ -21,6 +22,11 @@ int l_lovrTimerGetDelta(lua_State* L) { return 1; } +int l_lovrTimerGetFPS(lua_State* L) { + lua_pushnumber(L, lovrTimerGetFPS()); + return 1; +} + int l_lovrTimerGetTime(lua_State* L) { lua_pushnumber(L, lovrTimerGetTime()); return 1; diff --git a/src/lovr/timer.h b/src/lovr/timer.h index 04639162..aebca464 100644 --- a/src/lovr/timer.h +++ b/src/lovr/timer.h @@ -5,6 +5,7 @@ extern const luaL_Reg lovrTimer[]; int l_lovrTimerInit(lua_State* L); int l_lovrTimerGetDelta(lua_State* L); +int l_lovrTimerGetFPS(lua_State* L); int l_lovrTimerGetTime(lua_State* L); int l_lovrTimerStep(lua_State* L); int l_lovrTimerSleep(lua_State* L); diff --git a/src/lovr/types/shader.c b/src/lovr/types/shader.c index da4d99c5..59a44942 100644 --- a/src/lovr/types/shader.c +++ b/src/lovr/types/shader.c @@ -21,6 +21,10 @@ int l_lovrShaderSend(lua_State* L) { float data[16]; switch (type) { + case GL_INT: + lovrShaderSendInt(shader, id, luaL_checkinteger(L, 3)); + break; + case GL_FLOAT: lovrShaderSendFloat(shader, id, luaL_checknumber(L, 3)); break; diff --git a/src/timer/timer.c b/src/timer/timer.c index a8233fa9..15d69cb6 100644 --- a/src/timer/timer.c +++ b/src/timer/timer.c @@ -5,6 +5,9 @@ static TimerState timerState; void lovrTimerInit() { + timerState.frames = 0; + timerState.lastFpsUpdate = 0; + timerState.fps = 0; lovrTimerStep(); } @@ -20,9 +23,20 @@ double lovrTimerStep() { timerState.lastTime = timerState.time; timerState.time = glfwGetTime(); timerState.dt = timerState.time - timerState.lastTime; + timerState.frames++; + double fpsTimer = timerState.time - timerState.lastFpsUpdate; + if (fpsTimer > 1) { + timerState.fps = (int) timerState.frames / fpsTimer + .5; + timerState.lastFpsUpdate = timerState.time; + timerState.frames = 0; + } return timerState.dt; } +int lovrTimerGetFPS() { + return timerState.fps; +} + void lovrTimerSleep(double seconds) { lovrSleep(seconds); } diff --git a/src/timer/timer.h b/src/timer/timer.h index e3ebf0e3..fc64087b 100644 --- a/src/timer/timer.h +++ b/src/timer/timer.h @@ -3,6 +3,9 @@ typedef struct { double lastTime; double time; double dt; + int frames; + int fps; + double lastFpsUpdate; } TimerState; #endif @@ -10,4 +13,5 @@ void lovrTimerInit(); double lovrTimerGetDelta(); double lovrTimerGetTime(); double lovrTimerStep(); +int lovrTimerGetFPS(); void lovrTimerSleep(double seconds);