From 6c316c75871d6abf0bf4342b83bd63b9b41c0cba Mon Sep 17 00:00:00 2001 From: bjorn Date: Wed, 9 Aug 2017 00:56:13 -0700 Subject: [PATCH] Fix Shader bugs; --- src/api/graphics.c | 2 +- src/graphics/graphics.c | 57 ++++++++++++++++++++++------------------- src/graphics/graphics.h | 14 ++++------ src/graphics/mesh.c | 4 +-- src/graphics/shader.c | 39 +++++++++++++++++----------- src/graphics/shader.h | 24 +++++++---------- 6 files changed, 71 insertions(+), 69 deletions(-) diff --git a/src/api/graphics.c b/src/api/graphics.c index c753c316..490ea4b7 100644 --- a/src/api/graphics.c +++ b/src/api/graphics.c @@ -673,7 +673,7 @@ int l_lovrGraphicsNewShader(lua_State* L) { const char* vertexSource = lua_tostring(L, 1); const char* fragmentSource = lua_tostring(L, 2); - Shader* shader = lovrShaderCreate(vertexSource, fragmentSource, 0); + Shader* shader = lovrShaderCreate(vertexSource, fragmentSource); luax_pushtype(L, Shader, shader); lovrRelease(&shader->ref); return 1; diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index 33b90c65..18bf7857 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -122,9 +122,16 @@ void lovrGraphicsPresent() { } void lovrGraphicsPrepare() { + Shader* shader = lovrGraphicsGetActiveShader(); + + if (!shader) { + shader = state.defaultShaders[state.defaultShader] = lovrShaderCreateDefault(state.defaultShader); + } + mat4 transform = state.transforms[state.transform]; mat4 projection = state.canvases[state.canvas].projection; - lovrShaderBind(state.shader, transform, projection, state.color, 0); + lovrGraphicsBindProgram(shader->id); + lovrShaderBind(shader, transform, projection, state.color, 0); } // State @@ -310,10 +317,7 @@ void lovrGraphicsSetShader(Shader* shader) { state.shader = shader; if (shader) { - glUseProgram(shader->id); lovrRetain(&state.shader->ref); - } else { - glUseProgram(0); } } } @@ -470,7 +474,6 @@ void lovrGraphicsTriangle(DrawMode mode, float* points) { } void lovrGraphicsPlane(DrawMode mode, Texture* texture, mat4 transform) { - lovrGraphicsSetDefaultShader(SHADER_DEFAULT); lovrGraphicsPush(); lovrGraphicsMatrixTransform(transform); @@ -483,6 +486,7 @@ void lovrGraphicsPlane(DrawMode mode, Texture* texture, mat4 transform) { }; lovrGraphicsBindTexture(NULL); + lovrGraphicsSetDefaultShader(SHADER_DEFAULT); lovrGraphicsSetShapeData(points, 12); lovrGraphicsDrawPrimitive(GL_LINE_LOOP, 0, 0, 0); } else if (mode == DRAW_MODE_FILL) { @@ -494,6 +498,7 @@ void lovrGraphicsPlane(DrawMode mode, Texture* texture, mat4 transform) { }; lovrGraphicsBindTexture(texture); + lovrGraphicsSetDefaultShader(SHADER_DEFAULT); lovrGraphicsSetShapeData(data, 32); lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, 1, 1, 0); } @@ -542,6 +547,7 @@ void lovrGraphicsBox(DrawMode mode, Texture* texture, mat4 transform) { }; lovrGraphicsBindTexture(NULL); + lovrGraphicsSetDefaultShader(SHADER_DEFAULT); lovrGraphicsSetShapeData(points, 24); lovrGraphicsSetIndexData(indices, 24); lovrGraphicsDrawPrimitive(GL_LINES, 0, 0, 1); @@ -589,6 +595,7 @@ void lovrGraphicsBox(DrawMode mode, Texture* texture, mat4 transform) { }; lovrGraphicsBindTexture(texture); + lovrGraphicsSetDefaultShader(SHADER_DEFAULT); lovrGraphicsSetShapeData(data, 208); lovrGraphicsDrawPrimitive(GL_TRIANGLE_STRIP, 1, 1, 0); } @@ -597,7 +604,6 @@ void lovrGraphicsBox(DrawMode mode, Texture* texture, mat4 transform) { } void lovrGraphicsCylinder(float x1, float y1, float z1, float x2, float y2, float z2, float r1, float r2, int capped, int segments) { - lovrGraphicsSetDefaultShader(SHADER_DEFAULT); float axis[3] = { x1 - x2, y1 - y2, z1 - z2 }; float n[3] = { x1 - x2, y1 - y2, z1 - z2 }; float p[3]; @@ -697,13 +703,13 @@ void lovrGraphicsCylinder(float x1, float y1, float z1, float x2, float y2, floa } lovrGraphicsBindTexture(NULL); + lovrGraphicsSetDefaultShader(SHADER_DEFAULT); lovrGraphicsDrawPrimitive(GL_TRIANGLES, 1, 0, 1); #undef PUSH_CYLINDER_VERTEX #undef PUSH_CYLINDER_TRIANGLE } void lovrGraphicsSphere(Texture* texture, mat4 transform, int segments, Skybox* skybox) { - lovrGraphicsSetDefaultShader(SHADER_DEFAULT); vec_clear(&state.streamData); vec_clear(&state.streamIndices); @@ -746,6 +752,8 @@ void lovrGraphicsSphere(Texture* texture, mat4 transform, int segments, Skybox* } } + lovrGraphicsSetDefaultShader(SHADER_DEFAULT); + if (skybox) { Texture* oldTexture = lovrGraphicsGetTexture(); glBindTexture(GL_TEXTURE_2D, skybox->texture); @@ -885,26 +893,6 @@ void lovrGraphicsBindFramebuffer(int framebuffer) { } } -void lovrGraphicsSetDefaultShader(DefaultShader defaultShader) { - if (state.defaultShader == defaultShader || (state.shader && !state.shader->isDefault)) { - return; - } - - if (!state.defaultShaders[defaultShader]) { - Shader* shader; - switch (defaultShader) { - case SHADER_DEFAULT: shader = lovrShaderCreate(lovrDefaultVertexShader, lovrDefaultFragmentShader, 1); break; - case SHADER_SKYBOX: shader = lovrShaderCreate(lovrSkyboxVertexShader, lovrSkyboxFragmentShader, 1); break; - case SHADER_FONT: shader = lovrShaderCreate(lovrDefaultVertexShader, lovrFontFragmentShader, 1); break; - case SHADER_FULLSCREEN: shader = lovrShaderCreate(lovrNoopVertexShader, lovrDefaultFragmentShader, 1); break; - } - state.defaultShaders[defaultShader] = shader; - } - - state.defaultShader = defaultShader; - lovrGraphicsSetShader(state.defaultShaders[defaultShader]); -} - Texture* lovrGraphicsGetTexture() { return state.texture; } @@ -924,6 +912,21 @@ void lovrGraphicsBindTexture(Texture* texture) { } } +void lovrGraphicsSetDefaultShader(DefaultShader shader) { + state.defaultShader = shader; +} + +Shader* lovrGraphicsGetActiveShader() { + return state.shader ? state.shader : state.defaultShaders[state.defaultShader]; +} + +void lovrGraphicsBindProgram(uint32_t program) { + if (state.program != program) { + state.program = program; + glUseProgram(program); + } +} + void lovrGraphicsBindVertexArray(uint32_t vertexArray) { if (state.vertexArray != vertexArray) { state.vertexArray = vertexArray; diff --git a/src/graphics/graphics.h b/src/graphics/graphics.h index 070b6845..08428d4b 100644 --- a/src/graphics/graphics.h +++ b/src/graphics/graphics.h @@ -62,16 +62,10 @@ typedef struct { int viewport[4]; } CanvasState; -typedef enum { - SHADER_DEFAULT, - SHADER_SKYBOX, - SHADER_FONT, - SHADER_FULLSCREEN -} DefaultShader; - typedef struct { GLFWwindow* window; Shader* defaultShaders[DEFAULT_SHADER_COUNT]; + DefaultShader defaultShader; Font* defaultFont; Texture* defaultTexture; float transforms[MAX_TRANSFORMS + INTERNAL_TRANSFORMS][16]; @@ -97,8 +91,8 @@ typedef struct { vec_uint_t streamIndices; CanvasState canvases[MAX_CANVASES]; int canvas; - DefaultShader defaultShader; Texture* texture; + uint32_t program; uint32_t vertexArray; uint32_t vertexBuffer; uint32_t indexBuffer; @@ -171,7 +165,9 @@ void lovrGraphicsSetViewport(int x, int y, int w, int h); void lovrGraphicsBindFramebuffer(int framebuffer); Texture* lovrGraphicsGetTexture(); void lovrGraphicsBindTexture(Texture* texture); +void lovrGraphicsSetDefaultShader(DefaultShader defaultShader); +Shader* lovrGraphicsGetActiveShader(); +void lovrGraphicsBindProgram(uint32_t program); void lovrGraphicsBindVertexArray(uint32_t vao); void lovrGraphicsBindVertexBuffer(uint32_t vbo); void lovrGraphicsBindIndexBuffer(uint32_t ibo); -void lovrGraphicsSetDefaultShader(DefaultShader defaultShader); diff --git a/src/graphics/mesh.c b/src/graphics/mesh.c index 37ab8f77..93e88b39 100644 --- a/src/graphics/mesh.c +++ b/src/graphics/mesh.c @@ -4,8 +4,8 @@ #include static void lovrMeshBindAttributes(Mesh* mesh) { - Shader* shader = lovrGraphicsGetShader(); - if (!shader || (shader == mesh->lastShader && !mesh->attributesDirty)) { + Shader* shader = lovrGraphicsGetActiveShader(); + if (shader == mesh->lastShader && !mesh->attributesDirty) { return; } diff --git a/src/graphics/shader.c b/src/graphics/shader.c index 0326668e..c74617da 100644 --- a/src/graphics/shader.c +++ b/src/graphics/shader.c @@ -4,7 +4,7 @@ #include #include -const char* lovrShaderVertexPrefix = "" +static const char* lovrShaderVertexPrefix = "" #ifdef EMSCRIPTEN "#version 300 es \n" "precision mediump float; \n" @@ -19,7 +19,7 @@ const char* lovrShaderVertexPrefix = "" "uniform mat3 lovrNormalMatrix; \n" "uniform mat4 lovrProjection; \n"; -const char* lovrShaderFragmentPrefix = "" +static const char* lovrShaderFragmentPrefix = "" #ifdef EMSCRIPTEN "#version 300 es \n" "precision mediump float; \n" @@ -32,42 +32,42 @@ const char* lovrShaderFragmentPrefix = "" "uniform vec4 lovrColor; \n" "uniform sampler2D lovrTexture; \n"; -const char* lovrShaderVertexSuffix = "" +static const char* lovrShaderVertexSuffix = "" "void main() { \n" " texCoord = lovrTexCoord; \n" " gl_Position = position(lovrProjection, lovrTransform, vec4(lovrPosition, 1.0)); \n" "}"; -const char* lovrShaderFragmentSuffix = "" +static const char* lovrShaderFragmentSuffix = "" "void main() { \n" " lovrFragColor = color(lovrColor, lovrTexture, texCoord); \n" "}"; -const char* lovrDefaultVertexShader = "" +static const char* lovrDefaultVertexShader = "" "vec4 position(mat4 projection, mat4 transform, vec4 vertex) { \n" " return projection * transform * vertex; \n" "}"; -const char* lovrDefaultFragmentShader = "" +static const char* lovrDefaultFragmentShader = "" "vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n" " return graphicsColor * texture(image, uv); \n" "}"; -const char* lovrSkyboxVertexShader = "" +static const char* lovrSkyboxVertexShader = "" "out vec3 texturePosition; \n" "vec4 position(mat4 projection, mat4 transform, vec4 vertex) { \n" " texturePosition = vertex.xyz; \n" " return projection * transform * vertex; \n" "}"; -const char* lovrSkyboxFragmentShader = "" +static const char* lovrSkyboxFragmentShader = "" "in vec3 texturePosition; \n" "uniform samplerCube cube = 1; \n" "vec4 color(vec4 graphicsColor, sampler2D image, vec2 uv) { \n" " return graphicsColor * texture(cube, texturePosition); \n" "}"; -const char* lovrFontFragmentShader = "" +static const char* lovrFontFragmentShader = "" "float median(float r, float g, float b) { \n" " return max(min(r, g), min(max(r, g), b)); \n" "} \n" @@ -79,12 +79,12 @@ const char* lovrFontFragmentShader = "" " return vec4(graphicsColor.rgb, graphicsColor.a * alpha); \n" "}"; -const char* lovrNoopVertexShader = "" +static const char* lovrNoopVertexShader = "" "vec4 position(mat4 projection, mat4 transform, vec4 vertex) { \n" " return vertex; \n" "}"; -GLuint compileShader(GLenum type, const char* source) { +static GLuint compileShader(GLenum type, const char* source) { GLuint shader = glCreateShader(type); glShaderSource(shader, 1, (const GLchar**)&source, NULL); @@ -104,7 +104,7 @@ GLuint compileShader(GLenum type, const char* source) { return shader; } -GLuint linkShaders(GLuint vertexShader, GLuint fragmentShader) { +static GLuint linkShaders(GLuint vertexShader, GLuint fragmentShader) { GLuint shader = glCreateProgram(); if (vertexShader) { @@ -140,7 +140,7 @@ GLuint linkShaders(GLuint vertexShader, GLuint fragmentShader) { return shader; } -Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource, int isDefault) { +Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) { Shader* shader = lovrAlloc(sizeof(Shader), lovrShaderDestroy); if (!shader) return NULL; @@ -181,15 +181,24 @@ Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource, i mat4_identity(shader->transform); mat4_identity(shader->projection); shader->color = (Color) { 0, 0, 0, 0 }; - shader->isDefault = isDefault; // Send initial uniform values to shader - lovrGraphicsSetShader(shader); + lovrGraphicsBindProgram(id); lovrShaderBind(shader, shader->transform, shader->projection, shader->color, 1); return shader; } +Shader* lovrShaderCreateDefault(DefaultShader type) { + switch (type) { + case SHADER_DEFAULT: return lovrShaderCreate(NULL, NULL); + case SHADER_SKYBOX: return lovrShaderCreate(lovrSkyboxVertexShader, lovrSkyboxFragmentShader); + case SHADER_FONT: return lovrShaderCreate(NULL, lovrFontFragmentShader); + case SHADER_FULLSCREEN: return lovrShaderCreate(lovrNoopVertexShader, NULL); + default: error("Unknown default shader type"); + } +} + void lovrShaderDestroy(const Ref* ref) { Shader* shader = containerof(ref, Shader); glDeleteProgram(shader->id); diff --git a/src/graphics/shader.h b/src/graphics/shader.h index a949ec32..b5346e2b 100644 --- a/src/graphics/shader.h +++ b/src/graphics/shader.h @@ -8,9 +8,15 @@ #define LOVR_SHADER_POSITION 0 #define LOVR_SHADER_NORMAL 1 #define LOVR_SHADER_TEX_COORD 2 - #define LOVR_MAX_UNIFORM_LENGTH 256 +typedef enum { + SHADER_DEFAULT, + SHADER_SKYBOX, + SHADER_FONT, + SHADER_FULLSCREEN +} DefaultShader; + typedef struct { GLchar name[LOVR_MAX_UNIFORM_LENGTH]; int index; @@ -28,22 +34,10 @@ typedef struct { float transform[16]; float projection[16]; Color color; - int isDefault; } Shader; -extern const char* lovrShaderVertexPrefix; -extern const char* lovrShaderFragmentPrefix; -extern const char* lovrDefaultVertexShader; -extern const char* lovrDefaultFragmentShader; -extern const char* lovrSkyboxVertexShader; -extern const char* lovrSkyboxFragmentShader; -extern const char* lovrFontFragmentShader; -extern const char* lovrNoopVertexShader; - -GLuint compileShader(GLuint type, const char* source); -GLuint linkShaders(GLuint vertexShader, GLuint fragmentShader); - -Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource, int isDefault); +Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource); +Shader* lovrShaderCreateDefault(DefaultShader type); void lovrShaderDestroy(const Ref* ref); void lovrShaderBind(Shader* shader, mat4 transform, mat4 projection, Color color, int force); int lovrShaderGetAttributeId(Shader* shader, const char* name);