From 7c1edef3ac501d40e3de495b9434df71f535e9bc Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Fri, 19 Oct 2018 23:22:07 +0300 Subject: 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. --- .gitignore | 2 - Makefile | 5 --- README.md | 1 - assets.c | 10 ----- assets.h | 19 --------- assets.mk | 10 ----- faqe.c | 38 +++++------------ frag.glsl | 32 -------------- glprog.c | 113 ++++++++++++++++++++++++++++++++++++++++++------- glprog.h | 26 ++++++++---- shaders/data.h | 33 +++++++++++++++ shaders/main/frag.glsl | 28 ++++++++++++ shaders/main/vert.glsl | 18 ++++++++ vert.glsl | 28 ------------ 14 files changed, 204 insertions(+), 159 deletions(-) delete mode 100644 assets.c delete mode 100644 assets.h delete mode 100644 assets.mk delete mode 100644 frag.glsl create mode 100644 shaders/data.h create mode 100644 shaders/main/frag.glsl create mode 100644 shaders/main/vert.glsl delete mode 100644 vert.glsl diff --git a/.gitignore b/.gitignore index 4c49610..34ee8c4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,6 @@ eprintf.h eprintf.c loadgl.h loadgl.c -assets.bie -assets.idx config.mk .dir-locals.el diff --git a/Makefile b/Makefile index 235ec3f..9f991d1 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/README.md b/README.md index 862ee33..8435225 100644 --- a/README.md +++ b/README.md @@ -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 - * 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 - * SPDX-License-Identifier: MIT - */ -#ifndef ASSETS_H -#define ASSETS_H - -#include - -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) $< diff --git a/faqe.c b/faqe.c index 7f4803c..afb8bb4 100644 --- a/faqe.c +++ b/faqe.c @@ -5,7 +5,6 @@ #include #include -#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); diff --git a/frag.glsl b/frag.glsl deleted file mode 100644 index 2f0a367..0000000 --- a/frag.glsl +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2018 Tomasz Kramkowski - * 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)); - vec3 lico = vec3(1.0, 1.0, 1.0); - - float amb = 0.1; - - vec3 norm = normalize(fnorm); - vec3 lidir = normalize(lipos - fpos); - float dif = max(dot(norm, lidir), 0.0); - - float speen = max(sign(dot(lidir, norm)), 0.0); - vec3 vwdir = normalize(-fpos); - vec3 mid = normalize(lidir + vwdir); - - float spe = pow(max(dot(norm, mid), 0.0), 256) * speen; - - color = vec4((amb + dif + spe) * lico * objco, 1.0); -} diff --git a/glprog.c b/glprog.c index 5019af2..2996889 100644 --- a/glprog.c +++ b/glprog.c @@ -3,23 +3,87 @@ * SPDX-License-Identifier: MIT */ #include +#include +#include +#include +#include #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" } diff --git a/glprog.h b/glprog.h index cd0ef83..74987b3 100644 --- a/glprog.h +++ b/glprog.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 + * 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/shaders/main/frag.glsl b/shaders/main/frag.glsl new file mode 100644 index 0000000..c57598c --- /dev/null +++ b/shaders/main/frag.glsl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Tomasz Kramkowski + * SPDX-License-Identifier: MIT + */ +in vec3 fnorm; +in vec3 fpos; +in vec2 fuv; +in vec3 lipos; + +void main() +{ + vec3 objco = vec3(texture(tex, fuv)); + vec3 lico = vec3(1.0, 1.0, 1.0); + + float amb = 0.1; + + vec3 norm = normalize(fnorm); + vec3 lidir = normalize(lipos - fpos); + float dif = max(dot(norm, lidir), 0.0); + + float speen = max(sign(dot(lidir, norm)), 0.0); + vec3 vwdir = normalize(-fpos); + vec3 mid = normalize(lidir + vwdir); + + float spe = pow(max(dot(norm, mid), 0.0), 256) * speen; + + color = vec4((amb + dif + spe) * lico * objco, 1.0); +} diff --git a/shaders/main/vert.glsl b/shaders/main/vert.glsl new file mode 100644 index 0000000..f710067 --- /dev/null +++ b/shaders/main/vert.glsl @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018 Tomasz Kramkowski + * SPDX-License-Identifier: MIT + */ +out vec3 fnorm; +out vec3 fpos; +out vec2 fuv; +out vec3 lipos; + +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; + lipos = vec3(view * vec4(light, 1.0)); +} diff --git a/vert.glsl b/vert.glsl deleted file mode 100644 index 19469a4..0000000 --- a/vert.glsl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2018 Tomasz Kramkowski - * 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; - lipos = vec3(view * vec4(light, 1.0)); -} -- cgit v1.2.3-54-g00ecf