polyadvent

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

commit c0f7412b3f672b0de814096613e92ea089792b5c
parent 11266b439f4ef1dfd32039ae406ed7464a5812b0
Author: William Casarin <bill@casarin.me>
Date:   Sun, 21 Jun 2015 20:43:09 -0700

normals almost working

Diffstat:
MMakefile | 4++--
Metc/shaders/test.f.glsl | 7++++---
Metc/shaders/test.v.glsl | 10+++++++---
Msrc/common.h | 3+++
Msrc/game.c | 2++
Msrc/game.h | 5++++-
Msrc/mat4/mat4.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/mat4/mat4.h | 2++
Msrc/render.c | 58+++++++++++++++++++++++++++++++++++++++++-----------------
9 files changed, 152 insertions(+), 26 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ NAME ?= polyadvent BIN ?= $(NAME) PREFIX ?= /usr/local -CFLAGS = -ggdb -Wall -Wextra -Weverything -Werror +CFLAGS = -ggdb -Wall -Wextra -Weverything -Werror -std=c99 -Wno-unused-function LDFLAGS = -lSDL2 -lGL DEFS= -DGLFW_INCLUDE_NONE SRC=src @@ -36,7 +36,7 @@ install: $(BIN) install $(BIN) $(PREFIX)/bin nixbuild: - nix-shell shell.nix --pure --command 'make -j4' + nix-shell shell.nix --command 'make -j4' clean: rm -f main.o $(OBJS) $(SHLIB) $(BIN) diff --git a/etc/shaders/test.f.glsl b/etc/shaders/test.f.glsl @@ -1,5 +1,7 @@ uniform float fade_factor; +varying float v_dot; void main() { - gl_FragColor = vec4(0.4, 0.4, 0.8, 1.0); -}- \ No newline at end of file + vec4 color = vec4(0.4, 0.4, 0.8, 1.0); + gl_FragColor = vec4(color.xyz * v_dot, color.a); +} diff --git a/etc/shaders/test.v.glsl b/etc/shaders/test.v.glsl @@ -1,9 +1,14 @@ #version 110 attribute vec3 position; +attribute vec3 normal; uniform mat4 mvp; +varying float v_dot; +uniform vec3 light_dir; void main() { - gl_Position = mvp * vec4(position.xyz * 0.5, 1.0); -}- \ No newline at end of file + vec4 trans_normal = vec4(normal, 1); + gl_Position = mvp * vec4(position.xyz * 0.2, 1.0); + v_dot = max(dot(trans_normal.xyz, light_dir), 0.4); +} diff --git a/src/common.h b/src/common.h @@ -2,6 +2,9 @@ #ifndef POLYADVENT_COMMON_H #define POLYADVENT_COMMON_H +#define MAT3_ELEMS 9 +#define MAT4_ELEMS 16 + typedef unsigned short u16; typedef signed short s16; diff --git a/src/game.c b/src/game.c @@ -4,5 +4,7 @@ void init_game(struct game_state *game) { float *mvp = &game->test_resources.test_mvp[0]; + float *normal = &game->test_resources.normal_matrix[0]; mat4_id(mvp); + mat4_id(normal); } diff --git a/src/game.h b/src/game.h @@ -13,7 +13,9 @@ struct test_resources { struct { GLint fade_factor; + GLint light_dir; GLint mvp; + GLint normal_matrix; } uniforms; struct { @@ -21,7 +23,8 @@ struct test_resources { gpu_addr normal; } attributes; - float test_mvp[16]; + float normal_matrix[MAT4_ELEMS]; + float test_mvp[MAT4_ELEMS]; GLfloat fade_factor; }; diff --git a/src/mat4/mat4.c b/src/mat4/mat4.c @@ -18,6 +18,93 @@ mat4 *mat4_id(mat4 *dst) { return dst; } +mat4 *mat4_transpose(mat4 *src, mat4 *dest) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if(dest == NULL || src == dest) { + float a01 = src[1], a02 = src[2], a03 = src[3]; + float a12 = src[6], a13 = src[7]; + float a23 = src[11]; + + src[1] = src[4]; + src[2] = src[8]; + src[3] = src[12]; + src[4] = a01; + src[6] = src[9]; + src[7] = src[13]; + src[8] = a02; + src[9] = a12; + src[11] = src[14]; + src[12] = a03; + src[13] = a13; + src[14] = a23; + return src; + } + + dest[0] = src[0]; + dest[1] = src[4]; + dest[2] = src[8]; + dest[3] = src[12]; + dest[4] = src[1]; + dest[5] = src[5]; + dest[6] = src[9]; + dest[7] = src[13]; + dest[8] = src[2]; + dest[9] = src[6]; + dest[10] = src[10]; + dest[11] = src[14]; + dest[12] = src[3]; + dest[13] = src[7]; + dest[14] = src[11]; + dest[15] = src[15]; + return dest; + +} + +mat4 *mat4_inverse(mat4 *src, mat4 *dest) { + if(dest == NULL) { dest = src; } + + // Cache the srcrix values (makes for huge speed increases!) + float a00 = src[0], a01 = src[1], a02 = src[2], a03 = src[3]; + float a10 = src[4], a11 = src[5], a12 = src[6], a13 = src[7]; + float a20 = src[8], a21 = src[9], a22 = src[10], a23 = src[11]; + float a30 = src[12], a31 = src[13], a32 = src[14], a33 = src[15]; + + float b00 = a00*a11 - a01*a10; + float b01 = a00*a12 - a02*a10; + float b02 = a00*a13 - a03*a10; + float b03 = a01*a12 - a02*a11; + float b04 = a01*a13 - a03*a11; + float b05 = a02*a13 - a03*a12; + float b06 = a20*a31 - a21*a30; + float b07 = a20*a32 - a22*a30; + float b08 = a20*a33 - a23*a30; + float b09 = a21*a32 - a22*a31; + float b10 = a21*a33 - a23*a31; + float b11 = a22*a33 - a23*a32; + + // Calculate the determinant (inlined to avoid double-caching) + float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); + + dest[0] = (a11*b11 - a12*b10 + a13*b09)*invDet; + dest[1] = (-a01*b11 + a02*b10 - a03*b09)*invDet; + dest[2] = (a31*b05 - a32*b04 + a33*b03)*invDet; + dest[3] = (-a21*b05 + a22*b04 - a23*b03)*invDet; + dest[4] = (-a10*b11 + a12*b08 - a13*b07)*invDet; + dest[5] = (a00*b11 - a02*b08 + a03*b07)*invDet; + dest[6] = (-a30*b05 + a32*b02 - a33*b01)*invDet; + dest[7] = (a20*b05 - a22*b02 + a23*b01)*invDet; + dest[8] = (a10*b10 - a11*b08 + a13*b06)*invDet; + dest[9] = (-a00*b10 + a01*b08 - a03*b06)*invDet; + dest[10] = (a30*b04 - a31*b02 + a33*b00)*invDet; + dest[11] = (-a20*b04 + a21*b02 - a23*b00)*invDet; + dest[12] = (-a10*b09 + a11*b07 - a12*b06)*invDet; + dest[13] = (a00*b09 - a01*b07 + a02*b06)*invDet; + dest[14] = (-a30*b03 + a31*b01 - a32*b00)*invDet; + dest[15] = (a20*b03 - a21*b01 + a22*b00)*invDet; + + return dest; +} + mat4 *mat4_multiply(const mat4 *a, const mat4 *b, mat4 *dst) { float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3]; diff --git a/src/mat4/mat4.h b/src/mat4/mat4.h @@ -1,6 +1,8 @@ typedef float mat4; +mat4 *mat4_transpose(mat4 *src, mat4 *dest); +mat4 *mat4_inverse(mat4 *src, mat4 *dest); mat4 *mat4_copy(const mat4 *src, mat4 *dst); mat4 *mat4_id(mat4 *dest); mat4 *mat4_multiply(const mat4 *a, const mat4 *b, mat4 *dest); diff --git a/src/render.c b/src/render.c @@ -32,14 +32,14 @@ static const GLfloat cube_vertices[] = { }; -/* static const GLfloat cube_normals[] = { */ -/* 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // front */ -/* 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // right */ -/* 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // top */ -/* -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // left */ -/* 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // bottom */ -/* 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 // back */ -/* }; */ +static const GLfloat cube_normals[] = { + 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // front + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // right + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // top + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // left + 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // bottom + 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 // back +}; static const GLushort cube_indices[] = { @@ -57,6 +57,7 @@ init_gl(struct test_resources * resources) { 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(); */ // VBOs @@ -68,12 +69,12 @@ init_gl(struct test_resources * resources) { ); // cube normals - /* make_vertex_buffer( */ - /* GL_ARRAY_BUFFER, */ - /* cube_normals, */ - /* sizeof(cube_normals), */ - /* &resources->normal_buffer */ - /* ); */ + make_vertex_buffer( + GL_ARRAY_BUFFER, + cube_normals, + sizeof(cube_normals), + &resources->normal_buffer + ); // cube indices make_index_buffer( @@ -106,6 +107,12 @@ init_gl(struct test_resources * resources) { resources->uniforms.fade_factor = glGetUniformLocation(resources->program, "fade_factor"); + resources->uniforms.light_dir + = glGetUniformLocation(resources->program, "light_dir"); + + resources->uniforms.normal_matrix + = glGetUniformLocation(resources->program, "normal_matrix"); + resources->uniforms.mvp = glGetUniformLocation(resources->program, "mvp"); @@ -118,6 +125,18 @@ init_gl(struct test_resources * resources) { assert(resources->program != 0); } +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); +} void render (struct test_resources * resources) { @@ -128,18 +147,23 @@ void render (struct test_resources * resources) { glClear( GL_COLOR_BUFFER_BIT ); static float v3[] = { 1, 1, 0 }; - v3[1] = (float)(fade_factor * 0.4); + //v3[1] = (float)(fade_factor * 0.4); mat4_rotate(mvp, (float)0.004, v3, mvp); + recalc_normals(resources->uniforms.normal_matrix, mvp, + &resources->normal_matrix[0]); + glUseProgram(resources->program); + + glUniform3f(resources->uniforms.light_dir, -1, 1, (float)-0.09); glUniform1f(resources->uniforms.fade_factor, fade_factor); glUniformMatrix4fv(resources->uniforms.mvp, 1, 0, resources->test_mvp); bind_vbo(&resources->vertex_buffer, resources->attributes.position); - /* bind_vbo(&resources->normal_buffer, */ - /* resources->attributes.normal) */; + bind_vbo(&resources->normal_buffer, + resources->attributes.normal); bind_ibo(&resources->element_buffer);