polyadvent

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

commit dc809dd3b27dd35c37e5edde3ac3d43d09bd8ab8
parent 0ab43ad67334d1984eb5178b6887197e68a4ee26
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 26 Oct 2018 23:57:02 -0700

progress on UI/FBOS/geometry refactor

Diffstat:
MMakefile | 8+++++---
Metc/shaders/terrain.glsl | 20+++++++++-----------
Metc/shaders/vertex-color.glsl | 2++
Msrc/buffer.c | 1-
Msrc/buffer.h | 6++++++
Asrc/fbo.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fbo.h | 26++++++++++++++++++++++++++
Msrc/game.c | 5++---
Msrc/game.h | 16+++++++---------
Msrc/geometry.c | 31+++++++++++++++++++++++--------
Msrc/geometry.h | 11++++++-----
Msrc/gl.h | 39+++++++++++++++++++++++++++++++++++++++
Msrc/main.c | 1+
Msrc/model.h | 8+++++++-
Msrc/render.c | 2+-
Asrc/ui.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ui.h | 19+++++++++++++++++++
Msrc/window.c | 2+-
18 files changed, 298 insertions(+), 43 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,7 +8,7 @@ CFLAGS = $(DEFS) -ggdb -Ofast -I src -Wall -Werror -Wextra -std=c99 \ -Wno-unused-variable \ -Wno-cast-align \ -Wno-padded -LDFLAGS = -lSDL2 -lGL +LDFLAGS = -lSDL2 -lGL -lm SRC=src OBJS = $(SRC)/window.o @@ -17,6 +17,7 @@ OBJS += $(SRC)/camera.o OBJS += $(SRC)/debug.o OBJS += $(SRC)/delaunay.o OBJS += $(SRC)/event.o +OBJS += $(SRC)/fbo.o OBJS += $(SRC)/file.o OBJS += $(SRC)/game.o OBJS += $(SRC)/geometry.o @@ -24,8 +25,10 @@ OBJS += $(SRC)/input.o OBJS += $(SRC)/main.o OBJS += $(SRC)/mat4.o OBJS += $(SRC)/mat_util.o +OBJS += $(SRC)/model.o OBJS += $(SRC)/node.o OBJS += $(SRC)/perlin.o +OBJS += $(SRC)/ply.o OBJS += $(SRC)/poisson.o OBJS += $(SRC)/quat.o OBJS += $(SRC)/render.o @@ -35,8 +38,7 @@ OBJS += $(SRC)/uniform.o OBJS += $(SRC)/update.o OBJS += $(SRC)/util.o OBJS += $(SRC)/vec3.o -OBJS += $(SRC)/ply.o -OBJS += $(SRC)/model.o +OBJS += $(SRC)/ui.o SRCS=$(OBJS:.o=.c) diff --git a/etc/shaders/terrain.glsl b/etc/shaders/terrain.glsl @@ -19,15 +19,6 @@ out vec3 v_ray; const int nlands = 6; -const vec4 land[nlands] = vec4[]( - vec4(0.0, 0.5, 0.79, 0.0), // 0 - water - vec4(0.9176, 0.8156, 0.6588, 1.0), // 1 - sand - vec4(0.6274, 0.749, 0.156, 2.0), // 2 - grass - vec4(0.4627, 0.3333, 0.1686, 20.0), // 3 - dirt - vec4(0.5, 0.5, 0.5, 80.0), // 4 - stone - vec4(1.0, 1.0, 1.0, 380.0) // 5 - snow -); - vec3 standard_light(vec3 color) { vec4 v4_normal = vec4(normal , 1); vec4 trans_normal = normal_matrix * v4_normal; @@ -54,11 +45,19 @@ vec3 gamma_correct(vec3 color) { return pow(color, vec3(1.0/2.2)); } +const vec4 land[nlands] = vec4[]( + vec4(0.0, 0.5, 0.79, 0.0), // 0 - water + vec4(0.9176, 0.8156, 0.6588, 1.0), // 1 - sand + vec4(0.6274, 0.749, 0.156, 2.0), // 2 - grass + vec4(0.4627, 0.3333, 0.1686, 20.0), // 3 - dirt + vec4(0.5, 0.5, 0.5, 80.0), // 4 - stone + vec4(1.0, 1.0, 1.0, 380.0) // 5 - snow +); + void main() { vec4 v4_pos = vec4(position, 1.0); gl_Position = mvp * v4_pos; - // float light = dot(trans_normal.xyz, normalize(light_dir)) ; vec3 color = land[0].xyz; @@ -70,7 +69,6 @@ void main() } // v_color = vec3(0.2 + position.z*0.05, position.z*0.0095, position.z*0.0001) * 0.5; - // v_color = vec3(position.z, position.z, position.z) * 0.005; v_color = hemispherical(color); diff --git a/etc/shaders/vertex-color.glsl b/etc/shaders/vertex-color.glsl @@ -20,6 +20,8 @@ flat out vec3 v_color; flat out vec3 v_normal; out vec3 v_ray; +// TODO: includes +// #include "lighting.glsl" vec3 standard_light(vec3 color) { vec4 v4_normal = vec4(normal, 1); diff --git a/src/buffer.c b/src/buffer.c @@ -20,7 +20,6 @@ make_buffer(GLenum target, const void *buffer_data, GLsizei buffer_size) { return buffer; } - struct vbo* make_index_buffer(GLenum target, const void *data, GLsizei buffer_size, struct vbo *vbo) { diff --git a/src/buffer.h b/src/buffer.h @@ -6,6 +6,12 @@ typedef GLuint gpu_addr; +struct attributes { + gpu_addr position; + gpu_addr normal; + gpu_addr color; +}; + struct vbo { u32 type; int components; diff --git a/src/fbo.c b/src/fbo.c @@ -0,0 +1,65 @@ + +#include <assert.h> +#include "fbo.h" + +void create_fbo(struct fbo *fbo, int width, int height) { + glGenFramebuffers(1, &fbo->handle); + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + + fbo->width = width; + fbo->height = height; +} + +int fbo_attach_renderbuffer(struct fbo *fbo, + GLenum internalformat, GLenum attachment) { + assert(fbo->n_attachments < MAX_FBO_ATTACHMENTS); + GLuint *rbo = &fbo->attachments[fbo->n_attachments++]; + + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glGenRenderbuffers(1, rbo); + glBindRenderbuffer(GL_RENDERBUFFER, *rbo); + glRenderbufferStorage(GL_RENDERBUFFER, internalformat, fbo->width, fbo->height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, *rbo); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return *rbo; +} + +int fbo_attach_texture(struct fbo *fbo, GLenum attachment) { + assert(fbo->n_attachments < MAX_FBO_ATTACHMENTS); + GLuint *texture = &fbo->attachments[fbo->n_attachments++]; + + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo->width, fbo->height, 0, GL_RGB, + GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, *texture, + 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return *texture; +} + +void fbo_check(struct fbo *fbo) { + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void delete_fbo(struct fbo *fbo) { + glDeleteFramebuffers(1, &fbo->handle); +} + + +void bind_fbo(struct fbo *fbo) { + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); +} + +void unbind_fbo(struct fbo *fbo) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} diff --git a/src/fbo.h b/src/fbo.h @@ -0,0 +1,26 @@ +#ifndef POLYADVENT_FBO_H +#define POLYADVENT_FBO_H + +#include "common.h" +#include "gl.h" + +#define MAX_FBO_ATTACHMENTS 3 + +struct fbo { + GLuint handle; + GLuint attachments[MAX_FBO_ATTACHMENTS]; + int n_attachments; + int width, height; +}; + +void bind_fbo(struct fbo *fbo); +void create_fbo(struct fbo *fbo, int width, int height); +int fbo_attach_texture(struct fbo *, GLenum attachment); +void fbo_check(struct fbo *fbo); +int fbo_attach_renderbuffer(struct fbo *fbo, GLenum internalformat, GLenum attachment); +void delete_fbo(struct fbo *); +void unbind_fbo(struct fbo *fbo); + + + +#endif /* POLYADVENT_FBO_H */ diff --git a/src/game.c b/src/game.c @@ -33,7 +33,6 @@ void game_init(struct game *game) { int ok = 0; const double size = 10000; - const double pdist = 1.7; terrain->settings = (struct perlin_settings){ .depth = 1, @@ -48,7 +47,7 @@ void game_init(struct game *game) { }; terrain_init(terrain); - terrain->entity.model.program = res->terrain_program.handle; + terrain->entity.model.shading = SHADING_TERRAIN; terrain->size = size; mat4_id(mvp); @@ -72,7 +71,7 @@ void game_init(struct game *game) { // player init ok = load_model(&player->model, "pirate-officer"); assert(ok); - player->model.program = res->program.handle; + player->model.shading = SHADING_VERT_COLOR; player->node.label = "player"; root->label = "root"; diff --git a/src/game.h b/src/game.h @@ -22,6 +22,7 @@ struct resources { struct gpu_program program; struct gpu_program smooth_program; struct gpu_program terrain_program; + struct gpu_program ui_program; struct uniforms { GLint camera_position; @@ -36,11 +37,7 @@ struct resources { GLint world; } uniforms; - struct attributes { - gpu_addr position; - gpu_addr normal; - gpu_addr color; - } attributes; + struct attributes attributes; struct node root; struct entity player; @@ -55,10 +52,11 @@ struct resources { }; struct game { - int counter; - struct resources test_resources; - struct input input; - struct terrain terrain; + int counter; + int seed; + struct resources test_resources; + struct input input; + struct terrain terrain; }; void game_init(struct game *game); diff --git a/src/geometry.c b/src/geometry.c @@ -6,10 +6,10 @@ void destroy_buffer_geometry(struct geometry *geom) { gpu_addr buffers[] = { - geom->buffer.vertex_buffer.handle, - geom->buffer.normal_buffer.handle, - geom->buffer.color_buffer.handle, - geom->buffer.index_buffer.handle + geom->vbos.vertex.handle, + geom->vbos.normal.handle, + geom->vbos.color.handle, + geom->vbos.index.handle }; /* void glDeleteVertexArrays(GLsizei n, const GLuint *arrays); */ /* glDisableVertexAttribArray(geom->buffer.vertex_buffer.handle); */ @@ -23,6 +23,21 @@ destroy_buffer_geometry(struct geometry *geom) { check_gl(); } +void render_geometry(struct geometry *geom, struct attributes *attrs) +{ + bind_vbo(&geom->vbos.vertex, attrs->position); + bind_vbo(&geom->vbos.normal, attrs->normal); + if (geom->vbos.color.handle) + bind_vbo(&geom->vbos.color, attrs->color); + bind_ibo(&geom->vbos.index); + + glDrawElements(GL_TRIANGLES, + geom->num_indices, /* count */ + GL_UNSIGNED_INT, /* type */ + (void*)0 /* element array buffer offset */ + ); +} + void init_geometry(struct geometry *geom) { geom->colors = NULL; @@ -42,7 +57,7 @@ make_buffer_geometry(struct geometry *geom) { GL_ARRAY_BUFFER, geom->vertices, geom->num_verts * 3 * (int)sizeof(*geom->vertices), - &geom->buffer.vertex_buffer + &geom->vbos.vertex ); /* printf("making normal buffer\n"); */ @@ -51,7 +66,7 @@ make_buffer_geometry(struct geometry *geom) { GL_ARRAY_BUFFER, geom->normals, geom->num_verts * 3 * (int)sizeof(*geom->normals), - &geom->buffer.normal_buffer + &geom->vbos.normal ); // vertex colors @@ -60,7 +75,7 @@ make_buffer_geometry(struct geometry *geom) { GL_ARRAY_BUFFER, geom->colors, geom->num_verts * 3 * (int)sizeof(*geom->colors), - &geom->buffer.color_buffer + &geom->vbos.color ); /* printf("making index buffer\n"); */ @@ -69,6 +84,6 @@ make_buffer_geometry(struct geometry *geom) { GL_ELEMENT_ARRAY_BUFFER, geom->indices, geom->num_indices * (int)sizeof(*geom->indices), - &geom->buffer.index_buffer + &geom->vbos.index ); } diff --git a/src/geometry.h b/src/geometry.h @@ -6,14 +6,14 @@ #include "buffer.h" struct buffer_geometry { - struct vbo vertex_buffer; - struct vbo index_buffer; - struct vbo normal_buffer; - struct vbo color_buffer; + struct vbo vertex; + struct vbo index; + struct vbo normal; + struct vbo color; }; struct geometry { - struct buffer_geometry buffer; + struct buffer_geometry vbos; int num_indices; int num_verts; float *vertices; @@ -22,6 +22,7 @@ struct geometry { float *colors; }; +void render_geometry(struct geometry *geom, struct attributes *); void init_geometry(struct geometry *geom); void make_buffer_geometry(struct geometry *geom); void destroy_buffer_geometry(struct geometry *geom); diff --git a/src/gl.h b/src/gl.h @@ -43,9 +43,48 @@ void glUniform1f(GLint location, GLfloat v0); void glGetProgramiv(GLuint program, GLenum pname, GLint *params); void glDeleteProgram( GLuint program); +void glGenFramebuffers(GLsizei handle, GLuint *ids); +void glBindFramebuffer( GLenum target, GLuint framebuffer); +GLenum glCheckFramebufferStatus(GLenum target); +void glDeleteFramebuffers(GLsizei n, const GLuint * framebuffers); + void glDisableVertexAttribArray(GLuint index); void glDeleteVertexArrays(GLsizei n, const GLuint *arrays); GLboolean glIsBuffer( GLuint buffer); + +void glTexImage2D( GLenum target, + GLint level, + GLint internalformat, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const GLvoid * data); + +void glFramebufferTexture2D( GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level); + +void glGenRenderbuffers( GLsizei n, + GLuint * renderbuffers); + +void glBindRenderbuffer( GLenum target, + GLuint renderbuffer); + +void glRenderbufferStorage( GLenum target, + GLenum internalformat, + GLsizei width, + GLsizei height); + +void glFramebufferRenderbuffer( GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); + + #endif /* POLYADVENT_GL_H */ diff --git a/src/main.c b/src/main.c @@ -27,6 +27,7 @@ int main(void) srand(seed); struct game game; + game.seed = seed; /* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */ int width = 640; diff --git a/src/model.h b/src/model.h @@ -8,9 +8,15 @@ #include "geometry.h" #include "common.h" +enum shading { + SHADING_TERRAIN, + SHADING_VERT_COLOR, + SHADING_UI, +}; + struct model { struct geometry geom; - u32 program; + enum shading shading; }; diff --git a/src/render.c b/src/render.c @@ -211,7 +211,7 @@ void render (struct game *game) { recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix); - render_geom(res, &entity->model.geom, GL_TRIANGLES); + render_geometry(&entity->model.geom, &res->attributes); check_gl(); } diff --git a/src/ui.c b/src/ui.c @@ -0,0 +1,79 @@ + +#include "ui.h" +#include "mat4.h" +#include "buffer.h" +#include "geometry.h" +#include "util.h" + + +// v1------v0 +// | | +// | | +// | | +// v2------v3 + +static const GLfloat quad_vertices[] = { + 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5,-0.5, 0.5, 0.5,-0.5, 0.5, // v0-v1-v2-v3 front +}; + + +static const GLfloat quad_normals[] = { + 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // front +}; + +static const GLushort quad_indices[] = {0, 1, 2, 0, 2, 3}; + +static void +render_quad(struct geometry *geom, struct attributes *attrs) { + bind_vbo(&geom->vbos.vertex, attrs->position); + bind_vbo(&geom->vbos.normal, attrs->normal); + + bind_ibo(&geom->vbos.index); + + glDrawElements( + GL_TRIANGLES, + ARRAY_SIZE(quad_indices), /* count */ + GL_UNSIGNED_SHORT, /* type */ + (void*)0 /* element array buffer offset */ + ); + + //glDisableVertexAttribArray(resources->attributes.position); +} + + +static void create_quad(struct geometry *geom) +{ + +} + +void render_ui(struct ui *ui) { + glUseProgram(ui->shader.handle); + + // render quad + + // setup camera for shader +} + + +void resize_ui(struct ui *ui, int width, int height) { + float left = 0; + float right = width; + float top = 0; + float bottom = height; + float near = 0; + float far = 2; + + mat4_ortho(left, right, bottom, top, near, far, ui->camera); +} + + +void create_ui(struct ui *ui, int width, int height) { + struct shader vertex; + struct shader fragment; + + make_shader(GL_VERTEX_SHADER, "ui.v.glsl", &vertex); + make_shader(GL_FRAGMENT_SHADER, "ui.f.glsl", &vertex); + make_program(&vertex, &fragment, &ui->shader); + + resize_ui(ui, width, height); +} diff --git a/src/ui.h b/src/ui.h @@ -0,0 +1,19 @@ + +#ifndef POLYADVENT_UI_H +#define POLYADVENT_UI_H + +#include "common.h" +#include "shader.h" +#include "geometry.h" + +struct ui { + struct gpu_program shader; + struct geometry quad; + float camera[MAT4_ELEMS]; +}; + +void create_ui(struct ui *ui, int width, int height); +void resize_ui(struct ui *ui, int width, int height); +void render_ui(struct ui *); + +#endif /* POLYADVENT_UI_H */ diff --git a/src/window.c b/src/window.c @@ -7,7 +7,7 @@ void handle_resize(float *camera, int width, int height) { - printf("resizing %d %d\n", width, height); + /* printf("resizing %d %d\n", width, height); */ glViewport( 0, 0, width, height ); mat4_perspective(75 /* fov */, (float)width / height, 1, 20000, camera);