From 135d8d8a02341719302158e7beade95fae2daf95 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 20 May 2023 06:50:10 +0300 Subject: [PATCH] distance function generation from level data, first pass --- Makefile | 8 ++-- sdr/raydungeon.p.glsl | 116 ++++++++++++++++++++++++++++++++++++++++++++++++- src/darray.h | 12 ++--- src/game.c | 7 ++- src/game.h | 1 + src/level.c | 67 +++++++++++++++++++++++++--- src/level.h | 2 + src/options.c | 3 ++ src/scr_game.c | 28 +++++++----- src/scr_lvled.c | 8 ++++ 10 files changed, 221 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index 9c0f1ce..0af9e1a 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ -src = $(wildcard src/*.c) +src = $(wildcard src/*.c) libs/glew/glew.c obj = $(src:.c=.o) dep = $(src:.c=.d) bin = game warn = -pedantic -Wall dbg = -g -def = -DMINIGLUT_USE_LIBC +def = -DMINIGLUT_USE_LIBC -DGLEW_STATIC -inc = -Ilibs -Ilibs/assfile -Ilibs/treestor/include +inc = -Ilibs -Ilibs/assfile -Ilibs/treestor/include -Ilibs/glew libs = -lassfile -ldrawtext -lgoat3d -limago -ltreestor CFLAGS = $(warn) $(opt) $(dbg) $(inc) $(def) -MMD @@ -24,7 +24,7 @@ ifeq ($(sys), mingw) libdir = -Llibs/w32 else - libgl = -lGL -lGLU -lX11 + libgl = -lGL -lX11 libdir = -Llibs/unix endif diff --git a/sdr/raydungeon.p.glsl b/sdr/raydungeon.p.glsl index 8a66df7..c10be18 100644 --- a/sdr/raydungeon.p.glsl +++ b/sdr/raydungeon.p.glsl @@ -1,5 +1,117 @@ +uniform float aspect; +uniform mat4 matrix; +uniform mat3 dirmatrix; + +#define DIST_THRES 1e-3 +#define MAX_ITER 250 +#define MAX_STEP 1.0 + +vec3 raymarch(inout vec3 p, in vec3 dir, out float depth); +vec3 shade(in vec3 p, in vec3 dir, in float dist, in float total_dist); +vec3 backdrop(in vec3 dir); +float eval_sdf(in vec3 p); +vec3 eval_grad(in vec3 p, float dist); +vec3 primray(in vec2 uv, out vec3 org); + +float boxdist(in vec3 p, in vec3 b); +float sphdist(in vec3 p, in vec3 sp, in float srad); + void main() { - vec3 col = vec3(gl_TexCoord[0].st, 1.0); - gl_FragColor = vec4(col, 1.0); + vec2 uv = gl_TexCoord[0].st; + vec3 rorg; + vec3 rdir = primray(uv, rorg); + float depth; + + gl_FragColor.rgb = raymarch(rorg, rdir, depth); + gl_FragColor.a = 1.0; + + vec4 projp = gl_ProjectionMatrix * vec4(0.0, 0.0, -depth, 1.0); + float zval = projp.z / projp.w; + + gl_FragDepth = zval; +} + +vec3 raymarch(inout vec3 p, in vec3 dir, out float depth) +{ + float d, total_d = 0.0; + + for(int i=0; iinit() == -1) { diff --git a/src/game.h b/src/game.h index 36e5854..7984996 100644 --- a/src/game.h +++ b/src/game.h @@ -45,6 +45,7 @@ extern int fullscr; extern long time_msec; extern struct game_screen *cur_scr; +extern char *start_scr_name; int game_init(int argc, char **argv); diff --git a/src/level.c b/src/level.c index 4120867..dd0e3a1 100644 --- a/src/level.c +++ b/src/level.c @@ -180,6 +180,29 @@ int save_level(const struct level *lvl, const char *fname) rect++; } fprintf(fp, "RECTEND\n\n"); + + + fprintf(fp, "SDRSTART\n"); + fprintf(fp, "float eval_sdf(in vec3 p)\n"); + fprintf(fp, "{\n"); + rect = lvl->rects; + for(i=0; ix - 0.5f + rect->w * 0.5f) * lvl->scale; + float cy = (rect->y - 0.5f + rect->h * 0.5f) * lvl->scale; + float rx = (rect->w + 0.1f) * lvl->scale * 0.5f; + float ry = (rect->h + 0.1f) * lvl->scale * 0.5f; + + if(i == 0) { + fprintf(fp, "\tfloat d = boxdist(p - vec3(%f, 0.0, %f), vec3(%f, 1.0, %f));\n", + cx, cy, rx, ry); + } else { + fprintf(fp, "\td = min(d, boxdist(p - vec3(%f, 0.0, %f), vec3(%f, 1.0, %f)));\n", + cx, cy, rx, ry); + } + rect++; + } + fprintf(fp, "\treturn d;\n}\n"); + fprintf(fp, "SDREND\n\n"); } fclose(fp); @@ -200,6 +223,13 @@ static char *clean_line(char *s) return *s ? s : 0; } +enum { + ST_HEADER, + ST_ASSIGN, + ST_MAP, + ST_SDR +}; + int load_level(struct level *lvl, const char *fname) { ass_file *fp; @@ -209,6 +239,7 @@ int load_level(struct level *lvl, const char *fname) int state = 0; int i, nrow; struct level_rect rect; + char *sdr = 0; if(!(fp = ass_fopen(fname, "rb"))) { fprintf(stderr, "load_level: failed to open: %s\n", fname); @@ -217,16 +248,16 @@ int load_level(struct level *lvl, const char *fname) while(ass_fgets(buf, sizeof buf, fp)) { switch(state) { - case 0: + case ST_HEADER: if(memcmp(buf, "RDLEVEL", 7) != 0) { fprintf(stderr, "load_level: invalid level file: %s\n", fname); ass_fclose(fp); return -1; } - state++; + state = ST_ASSIGN; break; - case 1: + case ST_ASSIGN: if(!(line = clean_line(buf)) || *line == '#') { continue; } @@ -267,7 +298,15 @@ int load_level(struct level *lvl, const char *fname) lvl->cells = calloc_nf(lvl->xsz * lvl->ysz, sizeof *lvl->cells); nrow = 0; - state++; + state = ST_MAP; + + } else if(strcmp(line, "SDRSTART") == 0) { + if(sdr) { + darr_clear(sdr); + } else { + sdr = darr_alloc(0, 1); + } + state = ST_SDR; } else if(sscanf(line, "rect %d %d %d %d", &rect.x, &rect.y, &rect.w, &rect.h) == 4) { rect.dbgcol[0] = (rand() & 0x7f) + 0x7f; @@ -278,9 +317,9 @@ int load_level(struct level *lvl, const char *fname) } break; - case 2: + case ST_MAP: if(memcmp(buf, "MAPEND", 6) == 0) { - state = 1; + state = ST_ASSIGN; break; } for(i=0; ixsz; i++) { @@ -288,13 +327,27 @@ int load_level(struct level *lvl, const char *fname) parse_cell(lvl, i, nrow, buf[i]); } if(++nrow >= lvl->ysz) { - state = 1; + state = ST_ASSIGN; break; } break; + + case ST_SDR: + if(memcmp(buf, "SDREND", 6) == 0) { + state = ST_ASSIGN; + break; + } + for(i=0; buf[i]; i++) { + darr_strpush(sdr, buf[i]); + } + break; } } + if(sdr) { + lvl->sdf_src = darr_finalize(sdr); + } + ass_fclose(fp); return 0; } diff --git a/src/level.h b/src/level.h index 0a1a605..e3b53fe 100644 --- a/src/level.h +++ b/src/level.h @@ -24,6 +24,8 @@ struct level { int sx, sy; struct level_rect *rects; /* darr, empty spaces */ + + char *sdf_src; }; void init_level(struct level *lvl); diff --git a/src/options.c b/src/options.c index 34dee8f..b4964f9 100644 --- a/src/options.c +++ b/src/options.c @@ -3,6 +3,7 @@ #include #include #include "options.h" +#include "game.h" #include "treestor.h" #define DEF_XRES 1280 @@ -40,6 +41,8 @@ int parse_options(int argc, char **argv) fprintf(stderr, "%s must be followed by a screen name\n", argv[i - 1]); return -1; } + start_scr_name = argv[i]; + } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) { printf(usage_fmt, argv[0]); exit(0); diff --git a/src/scr_game.c b/src/scr_game.c index 2f1f31b..d19ff70 100644 --- a/src/scr_game.c +++ b/src/scr_game.c @@ -35,18 +35,13 @@ static cgm_vec3 cam_pan; static unsigned int sdr; - static int ginit(void) { - if(!(sdr = create_program_load("sdr/raydungeon.v.glsl", "sdr/raydungeon.p.glsl"))) { - return -1; - } return 0; } static void gdestroy(void) { - free_program(sdr); } static int gstart(void) @@ -59,6 +54,19 @@ static int gstart(void) cam_pan.x = -(lvl->xsz / 2.0f) * lvl->scale; cam_pan.y = 0; cam_pan.z = -(lvl->ysz / 2.0f) * lvl->scale; + + glEnable(GL_DEPTH_TEST); + + if(lvl->sdf_src) { + add_shader_footer(GL_FRAGMENT_SHADER, lvl->sdf_src); + } else { + add_shader_footer(GL_FRAGMENT_SHADER, "float eval_sdf(in vec3 p) { return 10000.0; }\n"); + } + if(!(sdr = create_program_load("sdr/raydungeon.v.glsl", "sdr/raydungeon.p.glsl"))) { + return -1; + } + clear_shader_footer(GL_FRAGMENT_SHADER); + glUseProgram(sdr); return 0; } @@ -66,6 +74,8 @@ static void gstop(void) { destroy_level(lvl); free(lvl); + + free_program(sdr); } static void gdisplay(void) @@ -85,13 +95,11 @@ static void gdisplay(void) glUseProgram(sdr); - glDepthMask(0); glBegin(GL_TRIANGLES); glTexCoord2f(0, 0); glVertex2f(-1, -1); - glTexCoord2f(2, 0); glVertex2f(4, -1); - glTexCoord2f(0, 2); glVertex2f(-1, 4); + glTexCoord2f(2, 0); glVertex2f(3, -1); + glTexCoord2f(0, 2); glVertex2f(-1, 3); glEnd(); - glDepthMask(1); glUseProgram(0); @@ -118,7 +126,7 @@ static void gdisplay(void) static void greshape(int x, int y) { - cgm_mperspective(proj_mat, cgm_deg_to_rad(60), win_aspect, 0.5, 500.0); + cgm_mperspective(proj_mat, cgm_deg_to_rad(60), win_aspect, 0.5, 40.0); glMatrixMode(GL_PROJECTION); glLoadMatrixf(proj_mat); } diff --git a/src/scr_lvled.c b/src/scr_lvled.c index e06cd32..3b5eda3 100644 --- a/src/scr_lvled.c +++ b/src/scr_lvled.c @@ -2,6 +2,7 @@ #include #include #include +#include "cgmath/cgmath.h" #include "game.h" #include "level.h" #include "util.h" @@ -64,6 +65,8 @@ static void display(void) struct level_cell *cell; struct level_rect *rect; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, -cam_dist); @@ -113,6 +116,11 @@ static void display(void) static void reshape(int x, int y) { + float proj_mat[16]; + + cgm_mperspective(proj_mat, cgm_deg_to_rad(60), win_aspect, 0.5, 40.0); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj_mat); } static void keyb(int key, int press) -- 1.7.10.4