diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2018-10-19 23:22:07 +0300 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2018-10-19 23:30:23 +0300 |
commit | 7c1edef3ac501d40e3de495b9434df71f535e9bc (patch) | |
tree | fd7f4264bdf5c30f7182a147ed9e6c7935c69bf2 | |
parent | 91b543a29cb8852251908a49cd120a6f7d9f2f11 (diff) | |
download | faqe-7c1edef3ac501d40e3de495b9434df71f535e9bc.tar.gz faqe-7c1edef3ac501d40e3de495b9434df71f535e9bc.tar.xz faqe-7c1edef3ac501d40e3de495b9434df71f535e9bc.zip |
Allow multiple shaders while reducing duplication
This change also stops using bie as eventually it will be replaced with
a more sophisticated asset handling system which will also allow custom
shaders.
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | assets.c | 10 | ||||
-rw-r--r-- | assets.h | 19 | ||||
-rw-r--r-- | assets.mk | 10 | ||||
-rw-r--r-- | faqe.c | 38 | ||||
-rw-r--r-- | glprog.c | 113 | ||||
-rw-r--r-- | glprog.h | 26 | ||||
-rw-r--r-- | shaders/data.h | 33 | ||||
-rw-r--r-- | shaders/main/frag.glsl (renamed from frag.glsl) | 4 | ||||
-rw-r--r-- | shaders/main/vert.glsl (renamed from vert.glsl) | 12 |
12 files changed, 159 insertions, 114 deletions
@@ -14,8 +14,6 @@ eprintf.h eprintf.c loadgl.h loadgl.c -assets.bie -assets.idx config.mk .dir-locals.el @@ -18,13 +18,8 @@ OBJ := faqe.o camera.o ensize.o eprintf.o fmd.o gl.o glprog.o ieee754.o model.o all: $(PROG) -include assets.mk -include $(EPRINTF_PATH)/module.mk -include $(LINMATH_PATH)/module.mk - $(PROG): $(OBJ) test_ieee754: ieee754.o -faqe.o: assets.h deplinks: $(EPRINTF_FILES) $(LINMATH_FILES) @@ -15,7 +15,6 @@ Dependencies - linmath (make) - GNU make (make) - pkg-config (make) -- bie (make) Compilation ----------- diff --git a/assets.c b/assets.c deleted file mode 100644 index f3254e2..0000000 --- a/assets.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> - * SPDX-License-Identifier: MIT - */ -#include "assets.h" - -extern char _binary_assets_bie_start[]; - -#define BIE_ENTRY(name, pos, size) struct asset name = { &_binary_assets_bie_start[pos], size }; -#include "assets.idx" diff --git a/assets.h b/assets.h deleted file mode 100644 index 1d18a0a..0000000 --- a/assets.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> - * SPDX-License-Identifier: MIT - */ -#ifndef ASSETS_H -#define ASSETS_H - -#include <stddef.h> - -struct asset { - void *data; - size_t size; -}; - -#define BIE_ENTRY(name, pos, size) extern struct asset name; -#include "assets.idx" -#undef BIE_ENTRY - -#endif // ASSETS_H diff --git a/assets.mk b/assets.mk deleted file mode 100644 index cdb2c8a..0000000 --- a/assets.mk +++ /dev/null @@ -1,10 +0,0 @@ -ASSETS := vert.glsl frag.glsl -OBJ += assets.o assets_data.o -CLEAN += assets.bie assets.idx - -assets.o: assets.h -assets.h assets.c: assets.idx -assets.bie assets.idx: $(ASSETS) - bie assets.bie assets.idx $^ -assets_data.o: assets.bie - $(LD) -r -b binary $(OUTPUT_OPTION) $< @@ -5,7 +5,6 @@ #include <SDL.h> #include <stdbool.h> -#include "assets.h" #include "camera.h" #include "eprintf.h" #include "gl.h" @@ -49,10 +48,6 @@ int main(int argc, char **argv) bool running = true; SDL_Window *win; SDL_GLContext *glc; - GLuint prog; - struct { - GLint model, view, proj, tex, light; - } uni; struct model mdl; struct camera cam = { .pos = { 0.0, 0.0, 3.0 }, .yaw = -PI/2 }; struct { @@ -88,24 +83,11 @@ int main(int argc, char **argv) loadmodel(&mdl, "assets/utah.fmd"); - prog = glprog_load((struct shdrdat []){ - { GL_VERTEX_SHADER, vert_glsl.data, vert_glsl.size }, - { GL_FRAGMENT_SHADER, frag_glsl.data, frag_glsl.size }, - { 0 }, - }, - (struct unidat []){ - { "model", &uni.model }, - { "view", &uni.view }, - { "proj", &uni.proj }, - { "tex", &uni.tex }, - { "light", &uni.light }, - { 0 }, - }); - - gl_uni_set1i(uni.tex, 0); - - gl_prog_use(prog); - viewport(uni.proj, WIDTH, HEIGHT); + glprog_init(); + + gl_prog_use(prog.main.prog); + viewport(prog.main.uni.proj, WIDTH, HEIGHT); + gl_uni_set1i(prog.main.tex.tex, 0); gl_enable(GL_DEPTH_TEST); gl_enable(GL_FRAMEBUFFER_SRGB); @@ -148,7 +130,7 @@ int main(int argc, char **argv) case SDL_WINDOWEVENT: switch (ev.window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: - viewport(uni.proj, + viewport(prog.main.uni.proj, ev.window.data1, ev.window.data2); } @@ -180,10 +162,10 @@ int main(int argc, char **argv) gl_clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); mat4x4_identity(model); - gl_prog_use(prog); - gl_uni_setm4fv(uni.view, 1, GL_FALSE, (GLfloat *)view); - gl_uni_setm4fv(uni.model, 1, GL_FALSE, (GLfloat *)model); - gl_uni_set3fv(uni.light, 1, lipos); + gl_prog_use(prog.main.prog); + gl_uni_setm4fv(prog.main.uni.view, 1, GL_FALSE, (GLfloat *)view); + gl_uni_setm4fv(prog.main.uni.model, 1, GL_FALSE, (GLfloat *)model); + gl_uni_set3fv(prog.main.uni.light, 1, lipos); model_render(&mdl); gl_va_bind(0); @@ -3,23 +3,87 @@ * SPDX-License-Identifier: MIT */ #include <assert.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include "eprintf.h" #include "gl.h" #include "glprog.h" +#include "nelem.h" enum { LOGSIZE = 1024, }; -static GLuint load_shader(const struct shdrdat *shdr) +struct glprog_progs prog; + +static const struct { + GLuint type; + const char *name; + bool reqd; + const char *pre; +} langs[] = { + { GL_VERTEX_SHADER, "vert", true, +#define SH_IN(type, name) "in " #type " " #name ";\n" +#include "shaders/data.h" + }, + { GL_TESS_CONTROL_SHADER, "tesc", false, "" }, + { GL_TESS_EVALUATION_SHADER, "tese", false, "" }, + { GL_GEOMETRY_SHADER, "geom", false, "" }, + { GL_FRAGMENT_SHADER, "frag", true, +#define SH_TEX(type, name) "uniform sampler" #type " " #name ";\n" +#define SH_OUT(type, name) "out " #type " " #name ";\n" +#include "shaders/data.h" + }, +}; + +static bool readfile(char **data, size_t *size, const char *name) +{ + FILE *f; + size_t len = 0; + + assert(data != NULL); + assert(size != NULL); + assert(name != NULL); + + f = fopen(name, "rb"); + if (f == NULL) return false; + if (*size < 1024) { + *size = 1024; + *data = erealloc(*data, *size); + } + + while (true) { + size_t read = fread(*data + len, 1, *size - len, f); + len += read; + if (*size - len > 0) break; + *size *= 2; + *data = erealloc(*data, *size); + } + + *size = len; + *data = erealloc(*data, *size); + + return true; +} + +static GLuint compile(const char *src, size_t len, const char *pre, GLuint type) { GLuint id; GLint success; char log[LOGSIZE]; + static const char *common_pre = +#define SH_VER(v) "#version " v "\n" +#define SH_UNI(type, name) "uniform " #type " " #name ";\n" +#include "shaders/data.h" + ; + const char *srcs[] = { common_pre, pre, src }; + GLint lens[] = { -1, -1, len }; - id = gl_shdr_create(shdr->type); - gl_shdr_source(id, 1, &shdr->src, &shdr->len); + id = gl_shdr_create(type); + gl_shdr_source(id, NELEM(srcs), srcs, lens); gl_shdr_compile(id); gl_shdr_param(id, GL_COMPILE_STATUS, &success); @@ -31,7 +95,7 @@ static GLuint load_shader(const struct shdrdat *shdr) return id; } -void detach_shaders(GLuint prog) +static void detach_shaders(GLuint prog) { GLsizei count; GLuint shdr; @@ -40,33 +104,52 @@ void detach_shaders(GLuint prog) gl_prog_detachshdr(prog, shdr); } -GLuint glprog_load(const struct shdrdat *shdrs, const struct unidat *unis) +static void load_shader(struct shader *s, const char *path) { GLuint prog; GLint success; - char log[LOGSIZE]; + char log[LOGSIZE], *full, *src = NULL; + size_t srclen = 0, fullsz; + + assert(s != NULL); + assert(path != NULL); - assert(shdrs != NULL); + fullsz = strlen(path) + strlen("/xxxx.glsl") + 1; + assert(fullsz > strlen(path)); + full = emalloc(fullsz); prog = gl_prog_create(); - for (const struct shdrdat *s = shdrs; s->type != 0; s++) { - GLuint shdr = load_shader(s); + for (size_t i = 0; i < NELEM(langs); i++) { + GLuint shdr; + + snprintf(full, fullsz, "%s/%s.glsl", path, langs[i].name); + if (!readfile(&src, &srclen, full)) { + if (!langs[i].reqd) continue; + eprintf("Could not load shader file %s:\n", full); + } + shdr = compile(src, srclen, langs[i].pre, langs[i].type); gl_prog_attachshdr(prog, shdr); gl_shdr_del(shdr); } + free(src); + free(full); gl_prog_link(prog); gl_prog_param(prog, GL_LINK_STATUS, &success); if (!success) { gl_prog_infolog(prog, sizeof log, NULL, log); - eprintf("Failed to link program:\n%s", log); + eprintf("Failed to link program\n%s", log); } detach_shaders(prog); - if (unis == NULL) return prog; - - for (const struct unidat *u = unis; u->name != NULL; u++) - *u->loc = gl_uni_loc(prog, u->name); +#define SH_UNI(_, name) s->uni.name = gl_uni_loc(prog, #name); +#define SH_TEX(_, name) s->tex.name = gl_uni_loc(prog, #name); +#include "shaders/data.h" + s->prog = prog; +} - return prog; +void glprog_init(void) +{ +#define SH_PROG(name) load_shader(&prog.name, "shaders/" #name); +#include "shaders/data.h" } @@ -7,17 +7,25 @@ #include "gl.h" -struct unidat { - const char *name; - GLint *loc; +struct shader { + GLuint prog; + struct { +#define SH_UNI(_, name) GLint name; +#include "shaders/data.h" + } uni; + struct { +#define SH_TEX(_, name) GLint name; +#include "shaders/data.h" + } tex; }; -struct shdrdat { - GLuint type; - const char *src; - GLint len; +struct glprog_progs { +#define SH_PROG(name) struct shader name; +#include "shaders/data.h" }; -GLuint glprog_load(const struct shdrdat *shdrs, const struct unidat *unis); +extern struct glprog_progs prog; -#endif // SHADER_H +void glprog_init(void); + +#endif // GLPROG_H diff --git a/shaders/data.h b/shaders/data.h new file mode 100644 index 0000000..e1a71c3 --- /dev/null +++ b/shaders/data.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> + * SPDX-License-Identifier: MIT + */ +#ifdef SH_PROG + SH_PROG(main) +#undef SH_PROG +#endif // SH_PROG +#ifdef SH_VER + SH_VER("330 core") +#undef SH_VER +#endif // SH_VER +#ifdef SH_IN + SH_IN(vec3, pos) + SH_IN(vec3, norm) + SH_IN(vec2, uv) +#undef SH_IN +#endif // SH_IN +#ifdef SH_UNI + SH_UNI(mat4, model) + SH_UNI(mat4, view) + SH_UNI(mat4, proj) + SH_UNI(vec3, light) +#undef SH_UNI +#endif // SH_UNI +#ifdef SH_TEX + SH_TEX(2D, tex) +#undef SH_TEX +#endif // SH_TEX +#ifdef SH_OUT + SH_OUT(vec4, color) +#undef SH_OUT +#endif // SH_OUT diff --git a/frag.glsl b/shaders/main/frag.glsl index 2f0a367..c57598c 100644 --- a/frag.glsl +++ b/shaders/main/frag.glsl @@ -2,15 +2,11 @@ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> * SPDX-License-Identifier: MIT */ -#version 330 core -out vec4 color; in vec3 fnorm; in vec3 fpos; in vec2 fuv; in vec3 lipos; -uniform sampler2D tex; - void main() { vec3 objco = vec3(texture(tex, fuv)); diff --git a/vert.glsl b/shaders/main/vert.glsl index 19469a4..f710067 100644 --- a/vert.glsl +++ b/shaders/main/vert.glsl @@ -2,27 +2,17 @@ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> * SPDX-License-Identifier: MIT */ -#version 330 core -layout (location = 0) in vec3 pos; -layout (location = 1) in vec3 norm; -layout (location = 2) in vec2 uv; - out vec3 fnorm; out vec3 fpos; out vec2 fuv; out vec3 lipos; -uniform mat4 model; -uniform mat4 view; -uniform mat4 proj; -uniform vec3 light; - void main() { gl_Position = proj * view * model * vec4(pos, 1.0); fpos = vec3(view * model * vec4(pos, 1.0)); fuv = uv; // TODO: Try to work out how to only do this ONCE in C or see if it matters - fnorm = mat3(transpose(inverse(view * model))) * norm; + fnorm = mat3(transpose(inverse(view * model))) *norm; lipos = vec3(view * vec4(light, 1.0)); } |