polyadvent

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

commit a029a83bff3d9e9782b1788efc1c77204b6e3546
parent c0f7412b3f672b0de814096613e92ea089792b5c
Author: William Casarin <bill@casarin.me>
Date:   Tue, 23 Jun 2015 01:57:59 -0700

working perspective camera

Diffstat:
Metc/shaders/test.v.glsl | 7+++++--
Msrc/common.h | 2++
Msrc/game.c | 3+++
Msrc/game.h | 1+
Msrc/mat4/mat4.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/mat4/mat4.h | 7+++++++
Msrc/render.c | 27++++++++++++++++++---------
7 files changed, 127 insertions(+), 11 deletions(-)

diff --git a/etc/shaders/test.v.glsl b/etc/shaders/test.v.glsl @@ -2,13 +2,16 @@ attribute vec3 position; attribute vec3 normal; + uniform mat4 mvp; +uniform mat4 normal_matrix; + varying float v_dot; uniform vec3 light_dir; void main() { - vec4 trans_normal = vec4(normal, 1); - gl_Position = mvp * vec4(position.xyz * 0.2, 1.0); + vec4 trans_normal = normal_matrix * vec4(normal, 1); + gl_Position = mvp * vec4(position.xyz, 1.0); v_dot = max(dot(trans_normal.xyz, light_dir), 0.4); } diff --git a/src/common.h b/src/common.h @@ -5,6 +5,8 @@ #define MAT3_ELEMS 9 #define MAT4_ELEMS 16 +#define PI 3.14159265f; + typedef unsigned short u16; typedef signed short s16; diff --git a/src/game.c b/src/game.c @@ -7,4 +7,7 @@ void init_game(struct game_state *game) { float *normal = &game->test_resources.normal_matrix[0]; mat4_id(mvp); mat4_id(normal); + + // move the camera a bit + mat4_translate(mvp, 0.0f, 0.0f, -10.0f, mvp); } diff --git a/src/game.h b/src/game.h @@ -25,6 +25,7 @@ struct test_resources { float normal_matrix[MAT4_ELEMS]; float test_mvp[MAT4_ELEMS]; + float camera[MAT4_ELEMS]; GLfloat fade_factor; }; diff --git a/src/mat4/mat4.c b/src/mat4/mat4.c @@ -3,6 +3,8 @@ #include <math.h> #include <string.h> +#define PI 3.14159265f + mat4 *mat4_copy(const mat4 *src, mat4 *dst) { memcpy(dst, src, sizeof(float) * 16); return dst; @@ -60,6 +62,95 @@ mat4 *mat4_transpose(mat4 *src, mat4 *dest) { } +/* + * mat4.frustum + * Generates a frustum matrix with the given bounds + * + * Params: + * left, right - scalar, left and right bounds of the frustum + * bottom, top - scalar, bottom and top bounds of the frustum + * near, far - scalar, near and far bounds of the frustum + * dest - Optional, mat4 frustum matrix will be written into + * + * Returns: + * dest if specified, a new mat4 otherwise + */ +mat4 *mat4_frustum (float left, float right, float bottom, + float top, float near, float far, mat4 *dest) { + float rl = (right - left); + float tb = (top - bottom); + float fn = (far - near); + dest[0] = (near*2) / rl; + dest[1] = 0; + dest[2] = 0; + dest[3] = 0; + dest[4] = 0; + dest[5] = (near*2) / tb; + dest[6] = 0; + dest[7] = 0; + dest[8] = (right + left) / rl; + dest[9] = (top + bottom) / tb; + dest[10] = -(far + near) / fn; + dest[11] = -1; + dest[12] = 0; + dest[13] = 0; + dest[14] = -(far*near*2) / fn; + dest[15] = 0; + return dest; +} + +/* + * mat4.translate + * Translates a matrix by the given vector + * + * Params: + * mat - mat4 to translate + * vec - vec3 specifying the translation + * dest - Optional, mat4 receiving operation result. If not specified result is written to mat + * + * Returns: + * dest if specified, mat otherwise + */ +mat4 *mat4_translate (mat4 *mat, float x, float y, float z, mat4 *dest) { + if(!dest || mat == dest) { + mat[12] = mat[0]*x + mat[4]*y + mat[8]*z + mat[12]; + mat[13] = mat[1]*x + mat[5]*y + mat[9]*z + mat[13]; + mat[14] = mat[2]*x + mat[6]*y + mat[10]*z + mat[14]; + mat[15] = mat[3]*x + mat[7]*y + mat[11]*z + mat[15]; + return mat; + } + + float a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3]; + float a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7]; + float a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11]; + + dest[0] = a00; + dest[1] = a01; + dest[2] = a02; + dest[3] = a03; + dest[4] = a10; + dest[5] = a11; + dest[6] = a12; + dest[7] = a13; + dest[8] = a20; + dest[9] = a21; + dest[10] = a22; + dest[11] = a23; + + dest[12] = a00*x + a10*y + a20*z + mat[12]; + dest[13] = a01*x + a11*y + a21*z + mat[13]; + dest[14] = a02*x + a12*y + a22*z + mat[14]; + dest[15] = a03*x + a13*y + a23*z + mat[15]; + return dest; +} + +mat4 *mat4_perspective(float fov, float aspect, float near, + float far, mat4 *dest) { + float top = near * tanf(fov*PI / 360.0f); + float right = top * aspect; + return mat4_frustum(-right, right, -top, top, near, far, dest); +} + mat4 *mat4_inverse(mat4 *src, mat4 *dest) { if(dest == NULL) { dest = src; } diff --git a/src/mat4/mat4.h b/src/mat4/mat4.h @@ -1,6 +1,13 @@ typedef float mat4; +mat4 *mat4_frustum (float left, float right, float bottom, + float top, float near, float far, mat4 *dest); + +mat4 *mat4_perspective(float fov, float aspect, float near, + float far, mat4 *dest); + +mat4 *mat4_translate (mat4 *mat, float x, float y, float z, mat4 *dest); mat4 *mat4_transpose(mat4 *src, mat4 *dest); mat4 *mat4_inverse(mat4 *src, mat4 *dest); mat4 *mat4_copy(const mat4 *src, mat4 *dst); diff --git a/src/render.c b/src/render.c @@ -97,6 +97,9 @@ init_gl(struct test_resources * resources) { ); assert(resources->fragment_shader != 0); + // camera + mat4_perspective(45 /* fov */, 1080 / 720, 1, 100, resources->camera); + // Shader program resources->program = make_program(resources->vertex_shader, resources->fragment_shader); @@ -138,26 +141,32 @@ recalc_normals(GLint norm_uniform, mat4 *mvp, mat4 *normal) { glUniformMatrix4fv(norm_uniform, 1, 0, calc); } +static float tmp_matrix[MAT4_ELEMS] = { 0 }; + void render (struct test_resources * resources) { - float *mvp = &resources->test_mvp[0]; + 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; glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); //clear background screen to black glClear( GL_COLOR_BUFFER_BIT ); static float v3[] = { 1, 1, 0 }; - //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]); + //v3[1] = fade_factor * 0.4f; + mat4_rotate(mvp, 0.004f, v3, mvp); + mat4_multiply(camera, mvp, tmp_matrix); + recalc_normals(resources->uniforms.normal_matrix, mvp, normal); 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); + glUniform3f(resources->uniforms.light_dir, -1, 1, -0.09f); + //glUniform1f(resources->uniforms.fade_factor, fade_factor); + glUniformMatrix4fv(resources->uniforms.mvp, 1, 0, tmp_matrix); bind_vbo(&resources->vertex_buffer, resources->attributes.position);