polyadvent

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

commit 15dd96fbee3c7ec13c2acb65980051034235a6f4
parent c8d002fcf2b5529e1933a9526eee15dee2a2c711
Author: William Casarin <bill@casarin.me>
Date:   Sat, 27 Jun 2015 23:43:06 -0700

rendering a teapot!

Diffstat:
MMakefile | 3++-
Metc/slab/test.slab | 0
Msrc/buffer.c | 13+++++++++----
Msrc/buffer.h | 2+-
Asrc/buffer_geometry.c | 0
Asrc/buffer_geometry.h | 1+
Msrc/game.c | 2+-
Msrc/game.h | 5+++--
Msrc/geometry.c | 36++++++++++++++++++++++++++++++++++++
Msrc/geometry.h | 18++++++++++++++----
Msrc/main.c | 13+++++++++++--
Msrc/render.c | 76+++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/render.h | 2+-
Msrc/slab.c | 36++++++++++++++++++++++++++----------
Msrc/slab.h | 8+++++---
Msrc/slab_geom.c | 41+++++++++++++++++++++++++++++------------
Msrc/slab_geom.h | 12++++++------
Asrc/util.c | 10++++++++++
Msrc/util.h | 5+++++
19 files changed, 205 insertions(+), 78 deletions(-)

diff --git a/Makefile b/Makefile @@ -26,7 +26,8 @@ OBJS += $(SRC)/shader.o OBJS += $(SRC)/update.o OBJS += $(SRC)/slab.o OBJS += $(SRC)/slab_geom.o -#OBJS += $(SRC)/geometry.o +OBJS += $(SRC)/geometry.o +OBJS += $(SRC)/util.o all: $(BIN) diff --git a/etc/slab/test.slab b/etc/slab/test.slab Binary files differ. diff --git a/src/buffer.c b/src/buffer.c @@ -1,16 +1,21 @@ #include "buffer.h" - -/* - * Functions for creating OpenGL objects: - */ +#include "util.h" +#include <assert.h> gpu_addr make_buffer(GLenum target, const void *buffer_data, GLsizei buffer_size) { gpu_addr buffer; + check_gl(); glGenBuffers(1, &buffer); + check_gl(); + glBindBuffer(target, buffer); + check_gl(); + glBufferData(target, buffer_size, buffer_data, GL_STATIC_DRAW); + check_gl(); + return buffer; } diff --git a/src/buffer.h b/src/buffer.h @@ -15,7 +15,7 @@ struct vbo { #define NUM_VBO_SLOTS 1 gpu_addr make_buffer(GLenum target, const void *buffer_data, - GLsizei buffer_size); + GLsizei buffer_size); struct vbo * make_vertex_buffer(GLenum target, const void *buffer_data, diff --git a/src/buffer_geometry.c b/src/buffer_geometry.c diff --git a/src/buffer_geometry.h b/src/buffer_geometry.h @@ -0,0 +1 @@ + diff --git a/src/game.c b/src/game.c @@ -9,5 +9,5 @@ void init_game(struct game_state *game) { mat4_id(normal); // move the camera a bit - mat4_translate(mvp, 0.0f, 0.0f, -10.0f, mvp); + mat4_translate(mvp, -10.0f, -10.0f, -20.0f, mvp); } diff --git a/src/game.h b/src/game.h @@ -6,19 +6,20 @@ /* * Global data used by our render callback: + * NOTE: just for testing right now */ struct resources { struct vbo vertex_buffer, element_buffer, normal_buffer; GLuint vertex_shader, fragment_shader, program; - struct { + struct uniforms { GLint fade_factor; GLint light_dir; GLint mvp; GLint normal_matrix; } uniforms; - struct { + struct attributes { gpu_addr position; gpu_addr normal; } attributes; diff --git a/src/geometry.c b/src/geometry.c @@ -1,2 +1,38 @@ +#include "geometry.h" +#include <assert.h> +void +make_buffer_geometry(struct geometry *geom) { + // VBOs + + assert(geom->vertices); + assert(geom->normals); + assert(geom->indices); + + printf("making vertex buffer\n"); + make_vertex_buffer( + GL_ARRAY_BUFFER, + geom->vertices, + geom->num_verts * 3 * (int)sizeof(float), + &geom->buffer.vertex_buffer + ); + + printf("making normal buffer\n"); + // cube normals + make_vertex_buffer( + GL_ARRAY_BUFFER, + geom->normals, + geom->num_verts * 3 * (int)sizeof(float), + &geom->buffer.normal_buffer + ); + + printf("making index buffer\n"); + // cube indices + make_index_buffer( + GL_ELEMENT_ARRAY_BUFFER, + geom->indices, + geom->num_elements * (int)sizeof(u32), + &geom->buffer.index_buffer + ); +} diff --git a/src/geometry.h b/src/geometry.h @@ -1,15 +1,25 @@ -#include "common.h" - #ifndef GEOMETRY_H #define GEOMETRY_H +#include "common.h" +#include "buffer.h" + +struct buffer_geometry { + struct vbo vertex_buffer; + struct vbo index_buffer; + struct vbo normal_buffer; +}; -struct geom { +struct geometry { + struct buffer_geometry buffer; int num_elements; + int num_verts; float *vertices; float *normals; - u16 *indices; + u32 *indices; }; +void make_buffer_geometry(struct geometry *geom); + #endif /* GEOMETRY_H */ diff --git a/src/main.c b/src/main.c @@ -6,15 +6,18 @@ #include "update.h" #include "window.h" #include "slab_geom.h" +#include "slab.h" #include "geometry.h" #include "event.h" #include "render.h" +#include <assert.h> + int main(void) { struct game_state game; struct slab slab; - struct geom slab_geom; + struct geometry slab_geom; size_t length; void *slab_buffer; @@ -32,8 +35,14 @@ int main(void) // parse to a slab_t slab_parse(&slab, slab_buffer); slab_show(&slab); + slab_alloc_arrays(&slab, &slab_geom, NULL); + slab_arrays(&slab, + slab_geom.vertices, + slab_geom.normals, + slab_geom.indices, + &slab_geom.num_elements); + make_buffer_geometry(&slab_geom); // mesh it -> load into vbo - alloc_slab_geom(&slab, &slab_geom, NULL); /* Loop until the user closes the window */ while (1) { diff --git a/src/render.c b/src/render.c @@ -7,6 +7,7 @@ #include "game.h" #include "mat4/mat4.h" #include "buffer.h" +#include "buffer_geometry.h" #include "shader.h" #include "geometry.h" #include "debug.h" @@ -56,10 +57,7 @@ void init_gl(struct resources *resources) { glEnable(GL_DEPTH_TEST); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - - - /* wireframe_mode_on(); */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); // VBOs make_vertex_buffer( @@ -99,7 +97,7 @@ init_gl(struct resources *resources) { assert(resources->fragment_shader != 0); // camera - mat4_perspective(45 /* fov */, 1080 / 720, 1, 100, resources->camera); + mat4_perspective(90 /* fov */, 1080 / 720, 1, 100, resources->camera); // Shader program resources->program = make_program(resources->vertex_shader, @@ -129,43 +127,27 @@ init_gl(struct resources *resources) { assert(resources->program != 0); } -static mat4 -*calc_normals(mat4 *mvp, mat4 *normal) { + +static mat4 * +calc_normals(mat4 *mvp, mat4 *normal) { mat4_inverse(mvp, normal); mat4_transpose(normal, normal); return normal; } + static void recalc_normals(GLint norm_uniform, mat4 *mvp, mat4 *normal) { mat4 *calc = calc_normals(mvp, normal); glUniformMatrix4fv(norm_uniform, 1, 0, calc); } + static float tmp_matrix[MAT4_ELEMS] = { 0 }; + static void render_cube (struct resources * resources) { - static float id[MAT4_ELEMS] = { 0 }; - mat4_id(id); - - float *mvp = resources->test_mvp; - float *normal = resources->normal_matrix; - float *camera = resources->camera; - float fade_factor = resources->fade_factor; - - static float v3[] = { 1, 1, 0 }; - v3[1] = fade_factor * 1.4f; - mat4_rotate(mvp, 0.004f, v3, mvp); - mat4_multiply(camera, mvp, tmp_matrix); - recalc_normals(resources->uniforms.normal_matrix, tmp_matrix, normal); - - glUseProgram(resources->program); - - glUniform3f(resources->uniforms.light_dir, -1, 1, -0.099f); - //glUniform1f(resources->uniforms.fade_factor, fade_factor); - glUniformMatrix4fv(resources->uniforms.mvp, 1, 0, tmp_matrix); - bind_vbo(&resources->vertex_buffer, resources->attributes.position); @@ -187,16 +169,48 @@ render_cube (struct resources * resources) { //glDisableVertexAttribArray(resources->attributes.position); } -static void render_geom (struct resources *res, struct geom_t *slab) { + +static void render_geom (struct resources *res, + struct geometry *geom) { + struct attributes *attrs = &res->attributes; + + bind_vbo(&geom->buffer.vertex_buffer, attrs->position); + bind_vbo(&geom->buffer.normal_buffer, attrs->normal); + bind_ibo(&geom->buffer.index_buffer); + + glDrawElements( + GL_TRIANGLES, + geom->num_elements, /* count */ + GL_UNSIGNED_INT, /* type */ + (void*)0 /* element array buffer offset */ + ); } + void -render (struct resources * resources, struct geom_t *geom) { +render (struct resources * resources, struct geometry *geom) { glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); //clear background screen to black glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - render_cube(resources); -} + static float id[MAT4_ELEMS] = { 0 }; + mat4_id(id); + + float *mvp = resources->test_mvp; + float *normal = resources->normal_matrix; + float *camera = resources->camera; + float fade_factor = resources->fade_factor; + static float v3[] = { 1, 1, 0 }; + v3[1] = fade_factor * 1.4f; + mat4_rotate(mvp, 0.004f, v3, mvp); + mat4_multiply(camera, mvp, tmp_matrix); + recalc_normals(resources->uniforms.normal_matrix, tmp_matrix, normal); + glUseProgram(resources->program); + glUniform3f(resources->uniforms.light_dir, -1, 1, -0.099f); + //glUniform1f(resources->uniforms.fade_factor, fade_factor); + glUniformMatrix4fv(resources->uniforms.mvp, 1, 0, tmp_matrix); + //render_cube(resources); + render_geom(resources, geom); +} diff --git a/src/render.h b/src/render.h @@ -4,7 +4,7 @@ #include "geometry.h" void init_gl(struct resources *resources); -void render (struct resources *resources, struct geom *geom); +void render (struct resources *resources, struct geometry *geom); void wireframe_mode_on(); void wireframe_mode_off(); diff --git a/src/slab.c b/src/slab.c @@ -76,7 +76,7 @@ static const float cube_normals[] = { }; -static const u16 cube_indices[] = { +static const u32 cube_indices[] = { 0, 1, 2, 0, 2, 3, // front 4, 5, 6, 4, 6, 7, // right 8, 9,10, 8,10,11, // top @@ -88,25 +88,35 @@ static const u16 cube_indices[] = { void slab_arrays(const struct slab *slab, float *verts, - u16 *indices, - float *normals) { + float *normals, + u32 *indices, + int *num_elements) { int x, y, z, i, j; - u16 start_index = 0; + u32 start_index = 0; int verts_ind, normals_ind, index_ind; verts_ind = 0; normals_ind = 0; index_ind = 0; - float xs = slab->x; - float ys = slab->y; - float zs = slab->z; + int xs = slab->x; + int ys = slab->y; + int zs = slab->z; int cube_verts_size = ARRAY_SIZE(cube_verts); int cube_indices_size = ARRAY_SIZE(cube_indices); float n = 0.5f; u8 color = 0; - for (y = 0; y < ys; ++y) + printf("got here cvs(%d) %d %d %d\n", cube_verts_size, xs, ys, zs); + for (x = 0; x < xs; ++x) + for (y = 0; y < ys; ++y) for (z = 0; z < zs; ++z) { - for (i = 0; i < cube_verts_size; i += 12) - for (j = 0; j < 12; j += 3) { + int yind = y * zs; + int xind = x * zs * ys; + color = slab->voxels[z + yind + xind]; + + /* printf("building color(0x%x) %d %d %d vi(%d) ni(%d) ii(%d)\n", */ + /* color, x, y, z, verts_ind, normals_ind, index_ind); */ + + for (i = 0; i < cube_verts_size; i += 12) // for each face + for (j = 0; j < 12; j += 3) { // for each vert int k = i + j; verts[verts_ind++] = cube_verts[k] * n + x; verts[verts_ind++] = cube_verts[k+1] * n + y; @@ -126,4 +136,10 @@ slab_arrays(const struct slab *slab, start_index += 24; } + + + //assert(index_ind < 65535); + printf("ind %d pos(%d) norm(%d)\n", index_ind, verts_ind, normals_ind); + printf("ret slab_arrays %d\n", index_ind); + *num_elements = index_ind; } diff --git a/src/slab.h b/src/slab.h @@ -8,7 +8,7 @@ struct slab { int x; int y; int z; - char *voxels; + u8 *voxels; }; struct slab * @@ -22,7 +22,9 @@ int slab_size(const struct slab *slab); void slab_arrays(const struct slab *slab, float *verts, - u16 *indices, - float *normals); + float *normals, + u32 *indices, + int *num_elements + ); #endif /* SLAB_H */ diff --git a/src/slab_geom.c b/src/slab_geom.c @@ -1,32 +1,49 @@ #include "slab_geom.h" #include <stdlib.h> +#include <assert.h> -struct geom* -alloc_slab_geom(const struct slab *slab, - struct geom *geom, - void* (*_realloc)(void*, size_t)) { +struct geometry* +slab_alloc_arrays(const struct slab *slab, + struct geometry *geom, + void* (*_realloc)(void*, size_t)) { _realloc = _realloc ? _realloc : realloc; float *verts, *normals; - u16 *indices; + u32 *indices; const int num_cubes = slab_size(slab); const int num_sides = 6; const int vert_per_side = 4; - const int num_verts = num_cubes * num_sides * vert_per_side; - verts = _realloc(NULL, (size_t)num_verts * 3 * sizeof(float)); - normals = _realloc(NULL, (size_t)num_verts * 3 * sizeof(float)); - indices = _realloc(NULL, (size_t)num_verts * sizeof(u16)); + const int wut_factor = 0; + const int num_verts = (num_cubes * num_sides * vert_per_side) + wut_factor; + const size_t verts_allocd = (size_t)num_verts * 3 * sizeof(float); + printf("stuff ncubes(%d) num_verts(%d) num_sides(%d) vert_per_side(%d) allocd(%zu)\n", + num_cubes, + num_verts, + num_sides, + vert_per_side, + verts_allocd + ); + verts = malloc(verts_allocd * 2); + normals = malloc(verts_allocd * 2); + indices = malloc((size_t)num_verts * sizeof(u32) * 2); + + assert(verts); + assert(normals); + assert(indices); + geom->vertices = verts; geom->indices = indices; geom->normals = normals; - geom->num_elements = num_verts; + + geom->num_verts = num_verts - wut_factor; + return geom; } void -free_slab_geom(struct geom *geom, - void (*_free)(void*)) { +slab_free_arrays(struct geometry *geom, + void (*_free)(void*)) { _free = _free ? _free : free; _free(geom->vertices); _free(geom->indices); diff --git a/src/slab_geom.h b/src/slab_geom.h @@ -6,13 +6,13 @@ #include "slab.h" #include <stddef.h> -struct geom* -alloc_slab_geom(const struct slab *slab, - struct geom *geom, - void* (*_realloc)(void*, size_t)); +struct geometry* +slab_alloc_arrays(const struct slab *slab, + struct geometry *geom, + void* (*_realloc)(void*, size_t)); void -free_slab_geom(struct geom *geom, - void (*_free)(void*)); +slab_free_arrays(struct geometry *geom, + void (*_free)(void*)); #endif // SLAB_GEOM diff --git a/src/util.c b/src/util.c @@ -0,0 +1,10 @@ + +#include "util.h" + +void check_gl() { + unsigned int e = glGetError(); + if (e != GL_NO_ERROR) { + printf("Got error from OpenGL: %d\n", e); + assert(0); + } +} diff --git a/src/util.h b/src/util.h @@ -2,6 +2,11 @@ #ifndef PA_UTIL_H #define PA_UTIL_H +#include "gl.h" +#include <assert.h> + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +void check_gl(void); + #endif /* PA_UTIL_H */