aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2018-10-19 23:22:07 +0300
committerTomasz Kramkowski <tk@the-tk.com>2018-10-19 23:30:23 +0300
commit7c1edef3ac501d40e3de495b9434df71f535e9bc (patch)
treefd7f4264bdf5c30f7182a147ed9e6c7935c69bf2
parent91b543a29cb8852251908a49cd120a6f7d9f2f11 (diff)
downloadfaqe-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--.gitignore2
-rw-r--r--Makefile5
-rw-r--r--README.md1
-rw-r--r--assets.c10
-rw-r--r--assets.h19
-rw-r--r--assets.mk10
-rw-r--r--faqe.c38
-rw-r--r--glprog.c113
-rw-r--r--glprog.h26
-rw-r--r--shaders/data.h33
-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
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 <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) $<
diff --git a/faqe.c b/faqe.c
index 7f4803c..afb8bb4 100644
--- a/faqe.c
+++ b/faqe.c
@@ -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);
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 <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"
}
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 <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));
}