polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

commit eefb282c5d136f8638984151591800290f547d42
parent 90c4b692bc865eeb92e8f2d92010ed80419d0b2b
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 27 Oct 2018 21:17:32 -0700

fbos working

Diffstat:
Metc/shaders/ui.f.glsl | 6+++++-
Metc/shaders/ui.v.glsl | 10+++++-----
Msrc/buffer.c | 12++++++++++--
Msrc/buffer.h | 2++
Msrc/event.c | 7+++----
Msrc/event.h | 4++--
Msrc/fbo.c | 10++++++++++
Msrc/fbo.h | 1+
Msrc/game.c | 32++++++++++++++++++++++++++------
Msrc/game.h | 6+++++-
Msrc/geometry.c | 23++++++++++++++++++++++-
Msrc/geometry.h | 2++
Msrc/gl.h | 4++--
Msrc/main.c | 26++++++++++++++++++++++++--
Msrc/model.c | 2++
Msrc/render.c | 21+++++++++++----------
Msrc/render.h | 8+++++++-
Msrc/ui.c | 43+++++++++++++++++++++++++++++--------------
Msrc/ui.h | 11++++++++---
Msrc/update.c | 16++++++++++++++++
Msrc/update.h | 1+
Msrc/window.c | 9+++++++--
Msrc/window.h | 3++-
23 files changed, 202 insertions(+), 57 deletions(-)

diff --git a/etc/shaders/ui.f.glsl b/etc/shaders/ui.f.glsl @@ -3,9 +3,13 @@ precision mediump float; in vec3 v_color; +in vec2 v_tex_coords; + out vec4 fragmentColor; +uniform sampler2D screen_texture; + void main() { // fragmentColor = vec4(color + diffuse, 1.0); - fragmentColor = vec4(v_color, 1.0); + fragmentColor = texture(screen_texture, v_tex_coords) + vec4(v_color, 1.0) * 0.00001; } diff --git a/etc/shaders/ui.v.glsl b/etc/shaders/ui.v.glsl @@ -2,21 +2,21 @@ in vec3 position; in vec3 color; +in vec2 tex_coords; out vec3 v_color; +out vec2 v_tex_coords; uniform mat4 mvp; uniform vec2 uipos; uniform vec2 uisize; -uniform sampler2D texture1; - void main() { - vec2 v2_pos = uipos + uisize * (position.xy - vec2(0.5, 0.5)) - (1.0 - uisize); + vec2 v2_pos = uipos + uisize * (position.xy - vec2(0.5, 0.5)); vec4 v4_pos = vec4(v2_pos, 0.0, 1.0) ; gl_Position = mvp * v4_pos; - - v_color = color + position; + v_tex_coords = tex_coords; + v_color = color + v4_pos.xyz; } diff --git a/src/buffer.c b/src/buffer.c @@ -43,14 +43,22 @@ void bind_ibo(struct vbo *vbo) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->handle); } -void bind_vbo(struct vbo *vbo, gpu_addr slot) { +static void bind_vbo_internal(struct vbo *vbo, gpu_addr slot, int size) { glEnableVertexAttribArray(slot); glBindBuffer(vbo->type, vbo->handle); glVertexAttribPointer(slot, // attribute - 3, // size + size, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); } + +void bind_uv_vbo(struct vbo *vbo, gpu_addr slot) { + bind_vbo_internal(vbo, slot, 2); +} + +void bind_vbo(struct vbo *vbo, gpu_addr slot) { + bind_vbo_internal(vbo, slot, 3); +} diff --git a/src/buffer.h b/src/buffer.h @@ -10,6 +10,7 @@ struct attributes { gpu_addr position; gpu_addr normal; gpu_addr color; + gpu_addr tex_coord; }; struct vbo { @@ -31,6 +32,7 @@ struct vbo * make_index_buffer(GLenum target, const void *buffer_data, GLsizei buffer_size, struct vbo *vbo); +void bind_uv_vbo(struct vbo *vbo, gpu_addr slot); void bind_vbo(struct vbo *vbo, gpu_addr slot); void bind_ibo(struct vbo *vbo); diff --git a/src/event.c b/src/event.c @@ -4,20 +4,19 @@ #include "input.h" #include "game.h" -void process_events(struct ui *ui, float *camera, struct input *input) { +void process_events(struct game *game, float *camera) { SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: case SDL_KEYUP: - handle_key(input, event.key); + handle_key(&game->input, event.key); break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: - handle_resize(camera, event.window.data1, event.window.data2); - resize_ui(ui, event.window.data1, event.window.data2); + handle_resize(game, event.window.data1, event.window.data2); break; } break; diff --git a/src/event.h b/src/event.h @@ -4,8 +4,8 @@ #include "gl.h" #include "input.h" -#include "ui.h" +#include "game.h" -void process_events(struct ui *ui, float *camera, struct input *input); +void process_events(struct game *game, float *camera); #endif /* PA_EVENT_H */ diff --git a/src/fbo.c b/src/fbo.c @@ -8,6 +8,7 @@ void create_fbo(struct fbo *fbo, int width, int height) { glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); check_gl(); + fbo->n_attachments = 0; fbo->width = width; fbo->height = height; } @@ -35,6 +36,13 @@ int fbo_attach_renderbuffer(struct fbo *fbo, return *rbo; } +void init_fbo(struct fbo *fbo) { + fbo->n_attachments = 0; + fbo->handle = 0; + fbo->width = 0; + fbo->height = 0; +} + int fbo_attach_texture(struct fbo *fbo, GLenum attachment) { assert(fbo->n_attachments < MAX_FBO_ATTACHMENTS); GLuint *texture = &fbo->attachments[fbo->n_attachments++]; @@ -71,6 +79,8 @@ void fbo_check(struct fbo *fbo) { } void delete_fbo(struct fbo *fbo) { + // TODO: delete attachments + glDeleteFramebuffers(1, &fbo->handle); check_gl(); } diff --git a/src/fbo.h b/src/fbo.h @@ -13,6 +13,7 @@ struct fbo { int width, height; }; +void init_fbo(struct fbo *fbo); void bind_fbo(struct fbo *fbo); void create_fbo(struct fbo *fbo, int width, int height); int fbo_attach_texture(struct fbo *, GLenum attachment); diff --git a/src/game.c b/src/game.c @@ -6,6 +6,7 @@ #include "terrain.h" #include "render.h" #include "util.h" +#include "update.h" #include <assert.h> mat4 *cam_init = (float[16]){ @@ -31,6 +32,7 @@ void game_init(struct game *game, int width, int height) { mat4 *mvp = res->test_mvp; struct node *root = &res->root; struct node *camera = &res->camera; + struct node *alt_camera = &res->alt_camera; struct entity *player = &res->player; struct terrain *terrain = &game->terrain; mat4 *light_dir = res->light_dir; @@ -51,6 +53,16 @@ void game_init(struct game *game, int width, int height) { .scale = 1.0 }; + // default ortho screenspace projection + mat4_ortho(0.0, // left + width, // right + 0.0, // bottom + height, // top + 0.0, // near + 100000.0, // far + res->proj_ortho + ); + create_ui(&game->ui, width, height); check_gl(); @@ -68,12 +80,21 @@ void game_init(struct game *game, int width, int height) { light_dir[1] = 0.8; light_dir[2] = 0.8; + // BRB: shadow mapping next! + + // FBO STUFF + init_fbo(&res->shadow_buffer); + resize_fbos(game, width, height); + + // FBO STUFF END + game->test_resources.fog_on = 1; game->test_resources.diffuse_on = 0; node_init(root); node_init(&player->node); node_init(camera); + node_init(alt_camera); node_init(&terrain->entity.node); // player init @@ -88,18 +109,17 @@ void game_init(struct game *game, int width, int height) { node_attach(&player->node, root); node_attach(camera, &player->node); + node_attach(alt_camera, camera); quat_axis_angle(V3(1,0,0), -45, camera->orientation); - - /* camera->custom_update = camera_update; */ - /* camera->custom_update_data = (void*)game->test_resources.camera_persp; */ - - /* vec3_all(camera->scale, -1); */ - /* camera->mirrored = 1; */ + /* quat_axis_angle(V3(1,0,0), -45, alt_camera->orientation); */ node_translate(&player->node, V3(terrain->size/2.,terrain->size/2.,0.0)); /* vec3_scale(player->node.scale, 10.0, player->node.scale); */ + node_rotate(alt_camera, V3(0, 0, 0)); + /* node_translate(alt_camera, V3(0,60,-100)); */ + node_rotate(camera, V3(100, 0, 0)); node_translate(camera, V3(0,-40,20)); /* node_recalc(camera); */ diff --git a/src/game.h b/src/game.h @@ -10,6 +10,7 @@ #include "entity.h" #include "terrain.h" #include "ui.h" +#include "fbo.h" #define PLAYER_HEIGHT 1.73 @@ -19,6 +20,7 @@ */ struct resources { struct vbo vertex_buffer, element_buffer, normal_buffer; + struct fbo shadow_buffer; struct gpu_program program; struct gpu_program smooth_program; @@ -43,13 +45,15 @@ struct resources { struct node root; struct entity player; struct node camera; + struct node alt_camera; bool fog_on, diffuse_on; float test_mvp[MAT4_ELEMS]; float light_dir[3]; float light_intensity[3]; - float camera_persp[MAT4_ELEMS]; + float proj_persp[MAT4_ELEMS]; + float proj_ortho[MAT4_ELEMS]; }; struct game { diff --git a/src/geometry.c b/src/geometry.c @@ -9,7 +9,8 @@ destroy_buffer_geometry(struct geometry *geom) { geom->vbos.vertex.handle, geom->vbos.normal.handle, geom->vbos.color.handle, - geom->vbos.index.handle + geom->vbos.index.handle, + geom->vbos.tex_coord.handle }; /* void glDeleteVertexArrays(GLsizei n, const GLuint *arrays); */ /* glDisableVertexAttribArray(geom->buffer.vertex_buffer.handle); */ @@ -35,6 +36,10 @@ void render_geometry(struct geometry *geom, struct attributes *attrs) bind_vbo(&geom->vbos.color, attrs->color); check_gl(); } + if (geom->vbos.tex_coord.handle) { + bind_uv_vbo(&geom->vbos.tex_coord, attrs->tex_coord); + check_gl(); + } bind_ibo(&geom->vbos.index); check_gl(); @@ -51,7 +56,9 @@ void init_geometry(struct geometry *geom) { geom->colors = NULL; geom->vbos.color.handle = 0; geom->normals = NULL; + geom->tex_coords = NULL; geom->vbos.normal.handle = 0; + geom->vbos.tex_coord.handle = 0; } void @@ -90,6 +97,20 @@ make_buffer_geometry(struct geometry *geom) { &geom->vbos.color ); + if (geom->tex_coords != NULL) { + printf("%f %f %f %f\n", + geom->tex_coords[0], + geom->tex_coords[1], + geom->tex_coords[2], + geom->tex_coords[3] + ); + + make_vertex_buffer(GL_ARRAY_BUFFER, + geom->tex_coords, + geom->num_verts * 2 * (int)sizeof(*geom->tex_coords), + &geom->vbos.tex_coord); + } + /* printf("making index buffer\n"); */ // cube indices make_index_buffer( diff --git a/src/geometry.h b/src/geometry.h @@ -10,6 +10,7 @@ struct buffer_geometry { struct vbo index; struct vbo normal; struct vbo color; + struct vbo tex_coord; }; struct geometry { @@ -20,6 +21,7 @@ struct geometry { float *normals; u32 *indices; float *colors; + float *tex_coords; }; void render_geometry(struct geometry *geom, struct attributes *); diff --git a/src/gl.h b/src/gl.h @@ -88,7 +88,7 @@ void glFramebufferRenderbuffer( GLenum target, GLuint renderbuffer); - - +void glDeleteRenderbuffers( GLsizei n, + GLuint *renderbuffers); #endif /* POLYADVENT_GL_H */ diff --git a/src/main.c b/src/main.c @@ -17,6 +17,7 @@ #include "poisson.h" #include "uniform.h" #include "ply.h" +#include "fbo.h" int main(void) @@ -43,13 +44,34 @@ int main(void) check_gl(); u32 last = SDL_GetTicks(); + struct render_config fbo_render_config = { + .draw_ui = 0, + .camera = game.test_resources.camera.mat, + .projection = game.test_resources.proj_persp + }; + + struct render_config default_config = { + .draw_ui = 1, + .camera = game.test_resources.camera.mat, + .projection = game.test_resources.proj_persp + }; + while (1) { - process_events(&game.ui, game.test_resources.camera_persp, &game.input); + process_events(&game, game.test_resources.proj_persp); u32 ticks = SDL_GetTicks(); update(&game, ticks-last); last = ticks; - render(&game); + + GLuint texture = game.test_resources.shadow_buffer.attachments[0]; + struct fbo *fbo = &game.test_resources.shadow_buffer; + bind_fbo(fbo); + + /* glViewport( 0, 0, width, height ); */ + + render(&game, &fbo_render_config); + unbind_fbo(&game.test_resources.shadow_buffer); + render(&game, &default_config); /* Swap front and back buffers */ SDL_GL_SwapWindow(window); diff --git a/src/model.c b/src/model.c @@ -8,6 +8,8 @@ int load_model(struct model *model, const char *name) { int ok = 0; + init_geometry(&model->geom); + // Load mesh snprintf(path, 128, "data/models/%s.ply", name); ok = parse_ply(path, &model->geom); diff --git a/src/render.c b/src/render.c @@ -78,7 +78,7 @@ init_gl(struct resources *resources, int width, int height) { (float)width / height, 1, 5000, - resources->camera_persp); + resources->proj_persp); // Shader program ok = make_program(&terrain_vertex, &fragment, &resources->terrain_program); @@ -152,7 +152,7 @@ recalc_normals(GLint nm_uniform, mat4 *model_view, mat4 *normal) { -void render (struct game *game) { +void render (struct game *game, struct render_config *config) { float adjust = game->test_resources.light_intensity[0]; glEnable(GL_DEPTH_TEST); glClearColor( 0.5294f * adjust, 0.8078f * adjust, 0.9216f * adjust, 1.0f ); //clear background screen to black @@ -169,11 +169,11 @@ void render (struct game *game) { struct resources *res = &game->test_resources; mat4 *mvp = res->test_mvp; - mat4 *persp = res->camera_persp; + mat4 *projection = config->projection; mat4 *light = res->light_dir; mat4 *light_intensity = res->light_intensity; - struct node *camera = &res->camera; + float *camera = config->camera; struct entity *entities[] = { &game->terrain.entity @@ -189,13 +189,13 @@ void render (struct game *game) { glUseProgram(game->test_resources.program.handle); check_gl(); - mat4_inverse(camera->mat, view); - mat4_multiply(persp, view, view_proj); + mat4_inverse(camera, view); + mat4_multiply(projection, view, view_proj); glUniform3f(res->uniforms.camera_position, - camera->mat[M_X], - camera->mat[M_Y], - camera->mat[M_Z]); + camera[M_X], + camera[M_Y], + camera[M_Z]); glUniform1i(res->uniforms.fog_on, res->fog_on); glUniform1i(res->uniforms.diffuse_on, res->diffuse_on); @@ -217,7 +217,8 @@ void render (struct game *game) { check_gl(); } - render_ui(&game->ui, view); + if (config->draw_ui) + render_ui(&game->ui, view); //player // y tho diff --git a/src/render.h b/src/render.h @@ -5,8 +5,14 @@ struct game; +struct render_config { + int draw_ui; + float *camera; + float *projection; +}; + void init_gl(struct resources *resources, int width, int height); -void render (struct game *game); +void render (struct game *game, struct render_config *config); void wireframe_mode_on(); void wireframe_mode_off(); diff --git a/src/ui.c b/src/ui.c @@ -25,12 +25,22 @@ static GLfloat quad_normals[] = { static GLuint quad_indices[] = {0, 1, 2, 0, 2, 3}; +static GLfloat quad_uvs[] = +{ + 1.0, 1.0, // v0 + 0.0, 1.0, // v1 + 0.0, 0.0, // v2 + 1.0, 0.0, // v3 +}; + + static void create_quad(struct geometry *geom) { init_geometry(geom); geom->indices = quad_indices; geom->vertices = quad_vertices; geom->colors = quad_normals; + geom->tex_coords = quad_uvs; geom->num_indices = ARRAY_SIZE(quad_indices); geom->num_verts = ARRAY_SIZE(quad_vertices); make_buffer_geometry(geom); @@ -44,16 +54,17 @@ void render_ui(struct ui *ui, float *view) { check_gl(); float uipos[2] = {0.01, 0.01}; - float uisize[2] = {0.2, 0.2}; + float uisize[2] = {0.4, 0.4}; mat4_multiply(ui->ortho, view, mvp); // setup camera for shader /* glUniform2f(ui->uipos_uniform, uipos[0] * uisize[0], uipos[1] * uisize[1]); */ - glUniform2f(ui->uipos_uniform, uipos[0], uipos[1]); - glUniform2f(ui->uisize_uniform, uisize[0], uisize[1]); + glUniform2f(ui->uniforms.uipos, uipos[0], uipos[1]); + glUniform2f(ui->uniforms.uisize, uisize[0], uisize[1]); + glUniform1i(ui->uniforms.texture, 0); - glUniformMatrix4fv(ui->mvp_uniform, 1, 0, ui->ortho); + glUniformMatrix4fv(ui->uniforms.mvp, 1, 0, ui->ortho); check_gl(); // render quad @@ -63,12 +74,12 @@ void render_ui(struct ui *ui, float *view) { void resize_ui(struct ui *ui, int width, int height) { - float left = 0; + float left = 0.0; float right = 1.0; - float bottom = 1.0; - float top = 0; - float near = 0.0; - float far = 1.0; + float bottom = 0.0; + float top = 1.0; + float near = -1.0; + float far = 2.0; mat4_ortho(left, right, bottom, top, near, far, ui->ortho); } @@ -93,13 +104,17 @@ void create_ui(struct ui *ui, int width, int height) { GLuint program = ui->shader.handle; - ui->mvp_uniform = glGetUniformLocation(program, "mvp"); - ui->uipos_uniform = glGetUniformLocation(program, "uipos"); - ui->uisize_uniform = glGetUniformLocation(program, "uisize"); + ui->uniforms.mvp = glGetUniformLocation(program, "mvp"); + ui->uniforms.uipos = glGetUniformLocation(program, "uipos"); + ui->uniforms.uisize = glGetUniformLocation(program, "uisize"); + + ui->uniforms.texture = + glGetUniformLocation(program, "screen_texture"); /* ui->attrs.normal = (gpu_addr)glGetAttribLocation(program, "normal"); */ - ui->attrs.position = (gpu_addr)glGetAttribLocation(program, "position"); - ui->attrs.color = (gpu_addr)glGetAttribLocation(program, "color"); + ui->attrs.position = (gpu_addr)glGetAttribLocation(program, "position"); + ui->attrs.color = (gpu_addr)glGetAttribLocation(program, "color"); + ui->attrs.tex_coord = (gpu_addr)glGetAttribLocation(program, "tex_coords"); check_gl(); resize_ui(ui, width, height); diff --git a/src/ui.h b/src/ui.h @@ -10,9 +10,14 @@ struct ui { struct gpu_program shader; struct geometry quad; struct attributes attrs; - GLint mvp_uniform; - GLint uipos_uniform; - GLint uisize_uniform; + + struct ui_uniforms { + GLint mvp; + GLint uipos; + GLint uisize; + GLint texture; + } uniforms; + float ortho[MAT4_ELEMS]; }; diff --git a/src/update.c b/src/update.c @@ -200,6 +200,22 @@ static int try_reload_shaders(struct resources *res) { } #endif +void resize_fbos(struct game *game, int width, int height) { + struct resources *res = &game->test_resources; + + if (res->shadow_buffer.handle) { + // TODO: remove once delete_fbo deletes attachments + glDeleteTextures(1, &res->shadow_buffer.attachments[1]); + glDeleteRenderbuffers(1, &res->shadow_buffer.attachments[0]); + delete_fbo(&res->shadow_buffer); + } + + create_fbo(&res->shadow_buffer, width, height); + fbo_attach_renderbuffer(&res->shadow_buffer, GL_DEPTH24_STENCIL8, + GL_DEPTH_STENCIL_ATTACHMENT); + fbo_attach_texture(&res->shadow_buffer, GL_COLOR_ATTACHMENT0); +} + // TODO: match based on some real concept of time static void day_night_cycle(float n, struct resources *res) { float darkest = 0.25; diff --git a/src/update.h b/src/update.h @@ -5,5 +5,6 @@ #include "game.h" void update(struct game * game, u32 dt); +void resize_fbos(struct game * game, int width, int height); #endif /* PA_UPDATE_H */ diff --git a/src/window.c b/src/window.c @@ -3,13 +3,18 @@ #include "gl.h" #include "mat4.h" #include "window.h" +#include "game.h" +#include "update.h" void -handle_resize(float *camera, int width, int height) { +handle_resize(struct game *game, int width, int height) { /* printf("resizing %d %d\n", width, height); */ glViewport( 0, 0, width, height ); - mat4_perspective(75 /* fov */, (float)width / height, 1, 20000, camera); + mat4_perspective(75 /* fov */, (float)width / height, 1, 20000, + game->test_resources.proj_persp); + + resize_fbos(game, width, height); /* glMatrixMode( GL_PROJECTION ); //Switch to setting the camera perspective */ /* Set the camera perspective */ diff --git a/src/window.h b/src/window.h @@ -3,9 +3,10 @@ #define POLYADVENT_WINDOW_H #include "gl.h" +#include "game.h" void -handle_resize(float *camera, int width, int height); +handle_resize(struct game *game, int width, int height); #endif /* POLYADVENT_WINDOW_H */