Ported Shader and Geometry code from Project Abstraction. Minor additions to array and string utils

dev
Shariq Shah 10 years ago
parent a40b11870d
commit 6d56ff2bb1
  1. 6
      src/array.c
  2. 10
      src/array.h
  3. 39
      src/game.c
  4. 254
      src/geometry.c
  5. 10
      src/geometry.h
  6. 11
      src/input.c
  7. 3
      src/input.h
  8. 104
      src/linmath.h
  9. 10
      src/log.c
  10. 1
      src/log.h
  11. 40
      src/renderer.c
  12. 1
      src/renderer.h
  13. 309
      src/shader.c
  14. 20
      src/shader.h
  15. 7
      src/string_utils.c

@ -7,13 +7,13 @@
static bool array_reallocate(Array* array); static bool array_reallocate(Array* array);
Array* array_new_(size_t object_size) Array* array_new_(size_t object_size, int capacity)
{ {
Array* newArray = malloc(sizeof(Array)); Array* newArray = malloc(sizeof(Array));
newArray->object_size = object_size; newArray->object_size = object_size;
newArray->length = 0; newArray->length = 0;
newArray->capacity = ARRAY_MIN_CAPACITY; newArray->capacity = capacity == 0 ? ARRAY_MIN_CAPACITY : capacity;
newArray->data = malloc(newArray->object_size * newArray->capacity); newArray->data = malloc(newArray->object_size * newArray->capacity);
return newArray; return newArray;
@ -60,7 +60,7 @@ void* array_add(Array* array)
void array_reset(Array* array, unsigned int length) void array_reset(Array* array, unsigned int length)
{ {
free(array->data); if(array->data) free(array->data);
array->length = length; array->length = length;
array->capacity = length < ARRAY_MIN_CAPACITY ? ARRAY_MIN_CAPACITY : length; array->capacity = length < ARRAY_MIN_CAPACITY ? ARRAY_MIN_CAPACITY : length;
array->data = malloc(array->object_size * array->capacity); array->data = malloc(array->object_size * array->capacity);

@ -12,19 +12,25 @@ typedef struct
size_t object_size; // size per element size_t object_size; // size per element
} Array; } Array;
Array* array_new_(size_t object_size); Array* array_new_(size_t object_size, int capacity);
#define array_new(type) array_new_(sizeof(type)); // Use this for array creation #define array_new(type) array_new_(sizeof(type), 0); // Use this for array creation
#define array_new_cap(type, capacity) array_new_(sizeof(type), capacity); // Use this for array with specific capacity
void array_free(Array* array); void array_free(Array* array);
// All the macros with _val return by value while the function returns pointer // All the macros with _val return by value while the function returns pointer
void* array_get(Array* array, unsigned int index); void* array_get(Array* array, unsigned int index);
#define array_get_val(array, type, index) (*((type*) array_get(array, index))) #define array_get_val(array, type, index) (*((type*) array_get(array, index)))
#define array_get_last_val(array, type) array_get_val(array, type, array->length - 1)
#define array_get_raw(array, type) (type*) array->data
void* array_top(Array* array); void* array_top(Array* array);
#define array_top_val(array, type) (*((type*) array_top(array))) #define array_top_val(array, type) (*((type*) array_top(array)))
void* array_add(Array* array); void* array_add(Array* array);
#define array_add_val(array, type) (*((type*) array_add(array))) #define array_add_val(array, type) (*((type*) array_add(array)))
#define array_push(array, value, type) \
type* new_val = array_add(array); \
*new_val = value;
void array_reset(Array* array, unsigned int length); // Resize to length objects whose data is unspecified void array_reset(Array* array, unsigned int length); // Resize to length objects whose data is unspecified
#define array_clear(array) array_reset(array, 0) #define array_clear(array) array_reset(array, 0)

@ -1,10 +1,13 @@
#include "game.h" #include <stdlib.h>
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include "game.h"
#include "window_system.h" #include "window_system.h"
#include "input.h" #include "input.h"
#include "renderer.h" #include "renderer.h"
#include "log.h" #include "log.h"
#include "file_io.h"
#include "shader.h"
void run(void); void run(void);
void update(void); void update(void);
@ -13,16 +16,22 @@ void render(void);
void game_init(void) void game_init(void)
{ {
GLFWwindow* window = window_get_active(); GLFWwindow* window = window_get_active();
/* Init systems */
input_init(window); input_init(window);
renderer_init(window); renderer_init(window);
int keys[2] = {GLFW_KEY_W, GLFW_KEY_UP}; io_file_initialize("/mnt/Dev/Projects/Symmetry/assets/");/* TODO: Implement proper way of getting binary directory */
int keys2[2] = {GLFW_KEY_S, GLFW_KEY_DOWN}; shader_initialize();
int keys3[1] = {GLFW_KEY_J};
int keys4[1] = {GLFW_KEY_K}; int keys[2] = {'W', GLFW_KEY_UP};
int keys2[2] = {'S', GLFW_KEY_DOWN};
int keys3[1] = {'J'};
int keys4[1] = {'K'};
input_map_create("MoveUp", keys, 2); input_map_create("MoveUp", keys, 2);
input_map_create("MoveDown", keys2, 2); input_map_create("MoveDown", keys2, 2);
input_map_create("Test", keys3, 1); input_map_create("Test", keys3, 1);
input_map_create("Test2", keys4, 1); input_map_create("Test2", keys4, 1);
int shader = shader_create("phong.vert", "phong.frag");
run(); run();
} }
@ -39,24 +48,6 @@ void run(void)
void update(void) void update(void)
{ {
if(input_map_state_get("MoveUp", GLFW_RELEASE))
log_message("MoveUp pressed!");
if(input_map_state_get("MoveDown", GLFW_RELEASE))
log_message("MoveDown pressed!");
if(input_map_state_get("Test", GLFW_RELEASE))
log_message("Test released");
if(input_map_state_get("Test2", GLFW_RELEASE))
{
input_map_name_set("Test2", "NewTest");
log_message("Test2 released!");
}
if(input_map_state_get("NewTest", GLFW_RELEASE))
log_message("NewTest released");
input_update(); input_update();
} }
@ -69,4 +60,6 @@ void game_cleanup(void)
{ {
input_cleanup(); input_cleanup();
renderer_cleanup(); renderer_cleanup();
io_file_cleanup();
shader_cleanup();
} }

@ -0,0 +1,254 @@
#include "geometry.h"
#include "array.h"
#include "num_types.h"
#include "linmath.h"
#include "string_utils.h"
#include "file_io.h"
#include "log.h"
#include "renderer.h"
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef struct
{
char* filename;
bool draw_indexed;
Array* vertices;
Array* vertex_colors;
Array* normals;
Array* uvs;
Array* indices;
uint vao;
uint vertex_vbo;
uint uv_vbo;
uint normal_vbo;
uint color_vbo;
uint index_vbo;
uint ref_count;
/* BoundingBox boundingBox; */
/* BoundingSphere boundingSphere; */
} Geometry;
/* Data */
static Array* geometry_list;
static Array* empty_indices;
/* Function definitions */
bool load_from_file(Geometry* geometry, const char* filename);
void create_vao(Geometry* geometry);
void geom_initialize(void)
{
geometry_list = array_new(Geometry);
empty_indices = array_new(int);
}
int geom_find(const char* filename)
{
int index = -1;
for(int i = 0; i < (int)geometry_list->length; i++)
{
Geometry* geometry = array_get(geometry_list, i);
if(strcmp(geometry->filename, filename) == 0)
{
index = i;
break;
}
}
return index;
}
int geom_create(const char* name)
{
// check if exists
int index = geom_find(name);
if(index == -1)
{
/* add new geometry object or overwrite existing one */
Geometry* new_geo = NULL;
int index = -1;
if(empty_indices->length != 0)
{
index = array_get_last_val(empty_indices, int);
array_pop(empty_indices);
new_geo = array_get(geometry_list, index);
}
else
{
new_geo = array_add(geometry_list);
index = geometry_list->length - 1;
}
assert(new_geo);
if(load_from_file(new_geo, name))
{
create_vao(new_geo);
//generateBoundingBox(index);
}
else
{
/* TODO: Some error here, find it and fix it */
array_pop(geometry_list);
index = -1;
}
}
else
{
Geometry* raw_geom_array = array_get_raw(geometry_list, Geometry);
raw_geom_array[index].ref_count++;
}
return index;
}
void geom_remove(int index)
{
if(index >= 0 && index < (int)geometry_list->length)
{
Geometry* geometry = array_get(geometry_list, index);
array_free(geometry->indices);
array_free(geometry->vertices);
array_free(geometry->uvs);
array_free(geometry->normals);
array_free(geometry->vertex_colors);
free(geometry->filename);
array_push(empty_indices, index, int);
}
}
void geom_cleanup(void)
{
for(uint i = 0; i < geometry_list->length; i++)
geom_remove(i);
array_free(geometry_list);
array_free(empty_indices);
}
bool load_from_file(Geometry* geometry, const char* filename)
{
assert(filename);
bool success = true;
char* full_path = str_new("models/");
full_path = str_concat(full_path, filename);
FILE* file = io_file_open(full_path, "rb");
free(full_path);
if(file)
{
const uint32 INDEX_SIZE = sizeof(uint32);
const uint32 VEC3_SIZE = sizeof(vec3);
const uint32 VEC2_SIZE = sizeof(vec2);
uint32 header[4];
size_t bytes_read = 0;
if((bytes_read = fread(header, INDEX_SIZE, 4, file)) <= 0)
{
log_error("geometry:load_from_file", "Read failed");
success = false;
}
else
{
uint32 indices_count = header[0];
uint32 vertices_count = header[1];
uint32 normals_count = header[2];
uint32 uvs_count = header[3];
// Indices
geometry->indices = array_new_cap(uint, indices_count);
fread(geometry->indices->data, INDEX_SIZE, indices_count, file);
// Vertices
geometry->vertices = array_new_cap(uint, vertices_count);
fread(geometry->vertices->data, VEC3_SIZE, vertices_count, file);
// Normals
geometry->normals = array_new_cap(uint, normals_count);
fread(&geometry->normals->data, VEC3_SIZE, normals_count, file);
// Uvs
geometry->uvs = array_new_cap(uint, uvs_count);
fread(&geometry->uvs->data, VEC2_SIZE, uvs_count, file);
}
fclose(file);
geometry->filename = str_new(filename);
geometry->draw_indexed = true;
geometry->ref_count++;
}
else
{
success = false;
}
return success;
}
void create_vao(Geometry* geometry)
{
// TODO : Add support for different model formats and interleaving VBO
assert(geometry);
glGenVertexArrays(1, &geometry->vao);
glBindVertexArray(geometry->vao);
glGenBuffers(1, &geometry->vertex_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->vertex_vbo);
glBufferData(GL_ARRAY_BUFFER,
geometry->vertices->length * sizeof(vec3),
geometry->vertices->data,
GL_STATIC_DRAW);
renderer_check_glerror("Geometry::create_vbo::vertex");
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
if(geometry->normals->length > 0)
{
glGenBuffers(1, &geometry->normal_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->normal_vbo);
glBufferData(GL_ARRAY_BUFFER,
geometry->normals->length * sizeof(vec3),
geometry->normals->data,
GL_STATIC_DRAW);
renderer_check_glerror("Geometry::create_vbo::normal");
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, 0);
}
if(geometry->uvs->length > 0)
{
glGenBuffers(1, &geometry->uv_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->uv_vbo);
glBufferData(GL_ARRAY_BUFFER,
geometry->uvs->length * sizeof(vec2),
geometry->uvs->data,
GL_STATIC_DRAW);
renderer_check_glerror("Geometry::create_vbo::uv");
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
if(geometry->vertex_colors->length > 0)
{
glGenBuffers(1, &geometry->color_vbo);
glBindBuffer(GL_ARRAY_BUFFER, geometry->color_vbo);
glBufferData(GL_ARRAY_BUFFER,
geometry->vertex_colors->length * sizeof(vec3),
geometry->vertex_colors->data,
GL_STATIC_DRAW);
renderer_check_glerror("Geometry::create_vbo::color");
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0);
}
if(geometry->indices->length > 0)
{
glGenBuffers(1, &geometry->index_vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->index_vbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
geometry->indices->length * sizeof(GLuint),
geometry->indices->data,
GL_STATIC_DRAW);
geometry->draw_indexed = true;
}
glBindVertexArray(0);
}

@ -0,0 +1,10 @@
#ifndef geometry_H
#define geometry_H
void geom_initialize(void);
int geom_ceate(const char* name);
int geom_find(const char* filename);
void geom_remove(int index);
void geom_cleanup(void);
#endif

@ -22,7 +22,6 @@ void input_init(GLFWwindow* window)
glfwSetMouseButtonCallback(window, input_on_mousebutton); glfwSetMouseButtonCallback(window, input_on_mousebutton);
glfwSetKeyCallback(window, input_on_key); glfwSetKeyCallback(window, input_on_key);
glfwSetCursorPosCallback(window, input_on_cursor_move); glfwSetCursorPosCallback(window, input_on_cursor_move);
glfwSetInputMode(window, GLFW_STICKY_KEYS, 1);
input_map_list = array_new(Input_Map); input_map_list = array_new(Input_Map);
} }
@ -42,7 +41,7 @@ static void input_on_cursor_move(GLFWwindow* window, double xpos, double ypos)
} }
void input_get_cursor_pos(double* xpos, double* ypos) void input_cursor_pos_get(double* xpos, double* ypos)
{ {
assert(xpos && ypos); assert(xpos && ypos);
GLFWwindow* window = window_get_active(); GLFWwindow* window = window_get_active();
@ -68,7 +67,9 @@ static void input_on_key(GLFWwindow* window, int key, int scancode, int action,
static void input_on_mousebutton(GLFWwindow* window, int button, int action, int mods) static void input_on_mousebutton(GLFWwindow* window, int button, int action, int mods)
{ {
/* Probably add 'mouse maps', same as input maps for keyvboard but with buttons
Do we even need that?
*/
} }
void input_cursor_mode_set(Cursor_Mode mode) void input_cursor_mode_set(Cursor_Mode mode)
@ -98,7 +99,7 @@ bool input_map_state_get(const char* map_name, int state)
return state == current_state ? true : false; return state == current_state ? true : false;
} }
bool inputkey_state_get(int key, int state_type) bool input_key_state_get(int key, int state_type)
{ {
GLFWwindow* window = window_get_active(); GLFWwindow* window = window_get_active();
int current_state = glfwGetKey(window, key); int current_state = glfwGetKey(window, key);
@ -137,7 +138,7 @@ void input_update(void)
} }
} }
bool input_map_remvove(const char* name) bool input_map_remove(const char* name)
{ {
assert(name); assert(name);
bool success = false; bool success = false;

@ -13,7 +13,6 @@ typedef enum
} Cursor_Mode; } Cursor_Mode;
typedef struct typedef struct
{ {
Array* keys; Array* keys;
@ -31,7 +30,7 @@ void input_cursor_mode_set(Cursor_Mode mode);
void input_update(void); void input_update(void);
bool input_map_state_get(const char* map_name, int state); bool input_map_state_get(const char* map_name, int state);
void input_map_create(const char* name, int* keys, size_t num_keys); void input_map_create(const char* name, int* keys, size_t num_keys);
bool input_map_remvove(const char* name); bool input_map_remove(const char* name);
bool input_map_keys_set(const char* name, int* keys, int num_keys); bool input_map_keys_set(const char* name, int* keys, int num_keys);
bool input_map_name_set(const char* name, const char* new_name); bool input_map_name_set(const char* name, const char* new_name);

@ -76,9 +76,9 @@ static inline void vec4_reflect(vec4 r, vec4 v, vec4 n)
r[i] = v[i] - p*n[i]; r[i] = v[i] - p*n[i];
} }
typedef vec4 mat4x4[4]; typedef vec4 mat4[4];
static inline void mat4x4_identity(mat4x4 M) static inline void mat4_identity(mat4 M)
{ {
int i, j; int i, j;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
@ -86,7 +86,7 @@ static inline void mat4x4_identity(mat4x4 M)
M[i][j] = i==j ? 1.f : 0.f; M[i][j] = i==j ? 1.f : 0.f;
} }
static inline void mat4x4_dup(mat4x4 M, mat4x4 N) static inline void mat4_dup(mat4 M, mat4 N)
{ {
int i, j; int i, j;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
@ -94,21 +94,21 @@ static inline void mat4x4_dup(mat4x4 M, mat4x4 N)
M[i][j] = N[i][j]; M[i][j] = N[i][j];
} }
static inline void mat4x4_row(vec4 r, mat4x4 M, int i) static inline void mat4_row(vec4 r, mat4 M, int i)
{ {
int k; int k;
for(k=0; k<4; ++k) for(k=0; k<4; ++k)
r[k] = M[k][i]; r[k] = M[k][i];
} }
static inline void mat4x4_col(vec4 r, mat4x4 M, int i) static inline void mat4_col(vec4 r, mat4 M, int i)
{ {
int k; int k;
for(k=0; k<4; ++k) for(k=0; k<4; ++k)
r[k] = M[i][k]; r[k] = M[i][k];
} }
static inline void mat4x4_transpose(mat4x4 M, mat4x4 N) static inline void mat4_transpose(mat4 M, mat4 N)
{ {
int i, j; int i, j;
for(j=0; j<4; ++j) for(j=0; j<4; ++j)
@ -116,28 +116,28 @@ static inline void mat4x4_transpose(mat4x4 M, mat4x4 N)
M[i][j] = N[j][i]; M[i][j] = N[j][i];
} }
static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b) static inline void mat4_add(mat4 M, mat4 a, mat4 b)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
vec4_add(M[i], a[i], b[i]); vec4_add(M[i], a[i], b[i]);
} }
static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b) static inline void mat4_sub(mat4 M, mat4 a, mat4 b)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
vec4_sub(M[i], a[i], b[i]); vec4_sub(M[i], a[i], b[i]);
} }
static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k) static inline void mat4_scale(mat4 M, mat4 a, float k)
{ {
int i; int i;
for(i=0; i<4; ++i) for(i=0; i<4; ++i)
vec4_scale(M[i], a[i], k); vec4_scale(M[i], a[i], k);
} }
static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z) static inline void mat4_scale_aniso(mat4 M, mat4 a, float x, float y, float z)
{ {
int i; int i;
vec4_scale(M[0], a[0], x); vec4_scale(M[0], a[0], x);
@ -148,19 +148,19 @@ static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, floa
} }
} }
static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b) static inline void mat4_mul(mat4 M, mat4 a, mat4 b)
{ {
mat4x4 temp; mat4 temp;
int k, r, c; int k, r, c;
for(c=0; c<4; ++c) for(r=0; r<4; ++r) { for(c=0; c<4; ++c) for(r=0; r<4; ++r) {
temp[c][r] = 0.f; temp[c][r] = 0.f;
for(k=0; k<4; ++k) for(k=0; k<4; ++k)
temp[c][r] += a[k][r] * b[c][k]; temp[c][r] += a[k][r] * b[c][k];
} }
mat4x4_dup(M, temp); mat4_dup(M, temp);
} }
static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v) static inline void mat4_mul_vec4(vec4 r, mat4 M, vec4 v)
{ {
int i, j; int i, j;
for(j=0; j<4; ++j) { for(j=0; j<4; ++j) {
@ -170,101 +170,101 @@ static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v)
} }
} }
static inline void mat4x4_translate(mat4x4 T, float x, float y, float z) static inline void mat4_translate(mat4 T, float x, float y, float z)
{ {
mat4x4_identity(T); mat4_identity(T);
T[3][0] = x; T[3][0] = x;
T[3][1] = y; T[3][1] = y;
T[3][2] = z; T[3][2] = z;
} }
static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z) static inline void mat4_translate_in_place(mat4 M, float x, float y, float z)
{ {
vec4 t = {x, y, z, 0}; vec4 t = {x, y, z, 0};
vec4 r; vec4 r;
int i; int i;
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
mat4x4_row(r, M, i); mat4_row(r, M, i);
M[3][i] += vec4_mul_inner(r, t); M[3][i] += vec4_mul_inner(r, t);
} }
} }
static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b) static inline void mat4_from_vec3_mul_outer(mat4 M, vec3 a, vec3 b)
{ {
int i, j; int i, j;
for(i=0; i<4; ++i) for(j=0; j<4; ++j) for(i=0; i<4; ++i) for(j=0; j<4; ++j)
M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f; M[i][j] = i<3 && j<3 ? a[i] * b[j] : 0.f;
} }
static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle) static inline void mat4_rotate(mat4 R, mat4 M, float x, float y, float z, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
float c = cosf(angle); float c = cosf(angle);
vec3 u = {x, y, z}; vec3 u = {x, y, z};
if(vec3_len(u) > 1e-4) { if(vec3_len(u) > 1e-4) {
vec3_norm(u, u); vec3_norm(u, u);
mat4x4 T; mat4 T;
mat4x4_from_vec3_mul_outer(T, u, u); mat4_from_vec3_mul_outer(T, u, u);
mat4x4 S = { mat4 S = {
{ 0, u[2], -u[1], 0}, { 0, u[2], -u[1], 0},
{-u[2], 0, u[0], 0}, {-u[2], 0, u[0], 0},
{ u[1], -u[0], 0, 0}, { u[1], -u[0], 0, 0},
{ 0, 0, 0, 0} { 0, 0, 0, 0}
}; };
mat4x4_scale(S, S, s); mat4_scale(S, S, s);
mat4x4 C; mat4 C;
mat4x4_identity(C); mat4_identity(C);
mat4x4_sub(C, C, T); mat4_sub(C, C, T);
mat4x4_scale(C, C, c); mat4_scale(C, C, c);
mat4x4_add(T, T, C); mat4_add(T, T, C);
mat4x4_add(T, T, S); mat4_add(T, T, S);
T[3][3] = 1.; T[3][3] = 1.;
mat4x4_mul(R, M, T); mat4_mul(R, M, T);
} else { } else {
mat4x4_dup(R, M); mat4_dup(R, M);
} }
} }
static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle) static inline void mat4_rotate_X(mat4 Q, mat4 M, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
float c = cosf(angle); float c = cosf(angle);
mat4x4 R = { mat4 R = {
{1.f, 0.f, 0.f, 0.f}, {1.f, 0.f, 0.f, 0.f},
{0.f, c, s, 0.f}, {0.f, c, s, 0.f},
{0.f, -s, c, 0.f}, {0.f, -s, c, 0.f},
{0.f, 0.f, 0.f, 1.f} {0.f, 0.f, 0.f, 1.f}
}; };
mat4x4_mul(Q, M, R); mat4_mul(Q, M, R);
} }
static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle) static inline void mat4_rotate_Y(mat4 Q, mat4 M, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
float c = cosf(angle); float c = cosf(angle);
mat4x4 R = { mat4 R = {
{ c, 0.f, s, 0.f}, { c, 0.f, s, 0.f},
{ 0.f, 1.f, 0.f, 0.f}, { 0.f, 1.f, 0.f, 0.f},
{ -s, 0.f, c, 0.f}, { -s, 0.f, c, 0.f},
{ 0.f, 0.f, 0.f, 1.f} { 0.f, 0.f, 0.f, 1.f}
}; };
mat4x4_mul(Q, M, R); mat4_mul(Q, M, R);
} }
static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle) static inline void mat4_rotate_Z(mat4 Q, mat4 M, float angle)
{ {
float s = sinf(angle); float s = sinf(angle);
float c = cosf(angle); float c = cosf(angle);
mat4x4 R = { mat4 R = {
{ c, s, 0.f, 0.f}, { c, s, 0.f, 0.f},
{ -s, c, 0.f, 0.f}, { -s, c, 0.f, 0.f},
{ 0.f, 0.f, 1.f, 0.f}, { 0.f, 0.f, 1.f, 0.f},
{ 0.f, 0.f, 0.f, 1.f} { 0.f, 0.f, 0.f, 1.f}
}; };
mat4x4_mul(Q, M, R); mat4_mul(Q, M, R);
} }
static inline void mat4x4_invert(mat4x4 T, mat4x4 M) static inline void mat4_invert(mat4 T, mat4 M)
{ {
float s[6]; float s[6];
float c[6]; float c[6];
@ -300,9 +300,9 @@ static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet; T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
} }
static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M) static inline void mat4_orthonormalize(mat4 R, mat4 M)
{ {
mat4x4_dup(R, M); mat4_dup(R, M);
float s = 1.; float s = 1.;
vec3 h; vec3 h;
vec3_norm(R[2], R[2]); vec3_norm(R[2], R[2]);
@ -320,7 +320,7 @@ static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
vec3_norm(R[0], R[0]); vec3_norm(R[0], R[0]);
} }
static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f) static inline void mat4_frustum(mat4 M, float l, float r, float b, float t, float n, float f)
{ {
M[0][0] = 2.f*n/(r-l); M[0][0] = 2.f*n/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f; M[0][1] = M[0][2] = M[0][3] = 0.f;
@ -334,7 +334,7 @@ static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t,
M[3][0] = M[3][1] = M[3][3] = 0.f; M[3][0] = M[3][1] = M[3][3] = 0.f;
} }
static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f) static inline void mat4_ortho(mat4 M, float l, float r, float b, float t, float n, float f)
{ {
M[0][0] = 2.f/(r-l); M[0][0] = 2.f/(r-l);
M[0][1] = M[0][2] = M[0][3] = 0.f; M[0][1] = M[0][2] = M[0][3] = 0.f;
@ -348,7 +348,7 @@ static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, fl
M[3][3] = 1.f; M[3][3] = 1.f;
} }
static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f) static inline void mat4_perspective(mat4 m, float y_fov, float aspect, float n, float f)
{ {
/* NOTE: Degrees are an unhandy unit to work with. /* NOTE: Degrees are an unhandy unit to work with.
* linmath.h uses radians for everything! */ * linmath.h uses radians for everything! */
@ -371,7 +371,7 @@ static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float
m[3][3] = 0.f; m[3][3] = 0.f;
} }
static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up) static inline void mat4_look_at(mat4 m, vec3 eye, vec3 center, vec3 up)
{ {
/* Adapted from Android's OpenGL Matrix.java. */ /* Adapted from Android's OpenGL Matrix.java. */
/* See the OpenGL GLUT documentation for gluLookAt for a description */ /* See the OpenGL GLUT documentation for gluLookAt for a description */
@ -402,7 +402,7 @@ static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
m[3][1] = 0.f; m[3][1] = 0.f;
m[3][2] = 0.f; m[3][2] = 0.f;
m[3][3] = 1.f; m[3][3] = 1.f;
mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]); mat4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
} }
typedef float quat[4]; typedef float quat[4];
@ -482,7 +482,7 @@ static inline void quat_mul_vec3(vec3 r, quat q, vec3 v)
quat_mul(r, q, r); quat_mul(r, q, r);
} }
static inline void mat4x4_from_quat(mat4x4 M, quat q) static inline void mat4_from_quat(mat4 M, quat q)
{ {
float a = q[3]; float a = q[3];
float b = q[0]; float b = q[0];
@ -508,7 +508,7 @@ static inline void mat4x4_from_quat(mat4x4 M, quat q)
M[3][3] = 1.f; M[3][3] = 1.f;
} }
static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q) static inline void mat4o_mul_quat(mat4 R, mat4 M, quat q)
{ {
/* XXX: The way this is written only works for othogonal matrices. */ /* XXX: The way this is written only works for othogonal matrices. */
/* TODO: Take care of non-orthogonal case. */ /* TODO: Take care of non-orthogonal case. */
@ -519,7 +519,7 @@ static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q)
R[3][3] = 1.f; R[3][3] = 1.f;
} }
static inline void quat_from_mat4x4(quat q, mat4x4 M) static inline void quat_from_mat4(quat q, mat4 M)
{ {
float r=0.f; float r=0.f;
int i; int i;

@ -13,6 +13,16 @@ void log_message(const char* message, ...)
printf("\n"); printf("\n");
} }
void log_warning(const char* message, ...)
{
printf("WRN : ");
va_list list;
va_start(list, message);
vprintf(message, list);
va_end(list);
printf("\n");
}
void log_error(const char* context, const char* error, ...) void log_error(const char* context, const char* error, ...)
{ {
printf("ERR (%s) : ", context); printf("ERR (%s) : ", context);

@ -2,6 +2,7 @@
#define log_H #define log_H
void log_message(const char* message, ...); void log_message(const char* message, ...);
void log_warning(const char* message, ...);
void log_error(const char* context, const char* error, ...); void log_error(const char* context, const char* error, ...);
#endif #endif

@ -1,6 +1,8 @@
#include "renderer.h" #include "renderer.h"
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include "log.h"
void on_framebuffer_size_change(GLFWwindow* window, int width, int height); void on_framebuffer_size_change(GLFWwindow* window, int width, int height);
void renderer_init(GLFWwindow* window) void renderer_init(GLFWwindow* window)
@ -28,3 +30,41 @@ void renderer_set_clearcolor(float red, float green, float blue, float alpha)
{ {
glClearColor(red, green, blue, alpha); glClearColor(red, green, blue, alpha);
} }
void renderer_check_glerror(const char* context)
{
GLenum error = glGetError();
const char* errorString = "No Error";
switch(error)
{
case GL_INVALID_OPERATION:
errorString = "Invalid Operation";
break;
case GL_NO_ERROR:
errorString = "No Error";
break;
case GL_INVALID_ENUM:
errorString = "Invalid ENUM";
break;
case GL_INVALID_VALUE:
errorString = "Invalid Value";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
errorString = "Invalid FrameBuffer Operation";
break;
case GL_OUT_OF_MEMORY:
errorString = "Out of Memory";
break;
case GL_STACK_UNDERFLOW:
errorString = "Stack Underflow";
break;
case GL_STACK_OVERFLOW:
errorString = "Stack Overflow";
break;
}
if(error != GL_NO_ERROR)
{
log_error(context, errorString);
}
}

@ -7,5 +7,6 @@ void renderer_init(GLFWwindow* window);
void renderer_draw(void); void renderer_draw(void);
void renderer_cleanup(void); void renderer_cleanup(void);
void renderer_set_clearcolor(float r, float g, float b, float a); void renderer_set_clearcolor(float r, float g, float b, float a);
void renderer_check_glerror(const char* context);
#endif #endif

@ -0,0 +1,309 @@
#include "shader.h"
#include "file_io.h"
#include "array.h"
#include "num_types.h"
#include "string_utils.h"
#include "log.h"
#include "renderer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "GL/glew.h"
#include "GLFW/glfw3.h"
typedef struct
{
unsigned int vertex_shader;
unsigned int fragment_shader;
unsigned int program;
} Shader_Object;
// Constants for locations of attributes inside all shaders
const int POSITION_LOC = 0;
const int NORMAL_LOC = 1;
const int UV_LOC = 2;
const int COLOR_LOC = 3;
static Array* shader_list;
static Array* empty_indices;
void debug_print_shader(const char* shaderText)
{
size_t len = strlen(shaderText);
int line_count = 1;
printf("%d. ", line_count);
for(uint i = 0; i < len; i++)
{
if(shaderText[i] != '\n')
printf("%c", shaderText[i]);
else
printf("\n%d. ", ++line_count);
}
printf("\n END_DEBUG_PRINT\n\n");
}
char* run_preprocessor(char* shader_text)
{
char* include_loc = strstr(shader_text, "//include");
if(include_loc)
{
char* line_end = strchr(include_loc, '\n');
int line_size = line_end - include_loc;
char* inc_line = malloc((sizeof(char) * line_size) + 1);
strncpy(inc_line, include_loc, line_size);
inc_line[line_size] = '\0';
char* filename = strtok(inc_line, " ");
while(filename)
{
filename = strtok(NULL, " ");
if(filename)
{
char* path = str_new("shaders/");
path = str_concat(path, filename);
char* file = io_file_read(path);
char* shader_copy = str_new(shader_text);
char* temp = realloc(shader_text, (strlen(shader_text) + strlen(file) + 2));
if(temp)
{
shader_text = temp;
strcpy(shader_text, file);
strcat(shader_text, shader_copy);
}
else
{
log_warning("Realloc failed in Shader::run_preprocessor");
}
free(path);
free(shader_copy);
free(file);
}
}
free(inc_line);
}
return shader_text;
}
void shader_initialize(void)
{
shader_list = array_new(Shader_Object);
empty_indices = array_new(int);
}
int shader_create(const char* vert_shader_name, const char* frag_shader_name)
{
char* vs_path = str_new("shaders/");
vs_path = str_concat(vs_path, vert_shader_name);
char* fs_path = str_new("shaders/");
fs_path = str_concat(fs_path, frag_shader_name);
GLuint vert_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
char* vert_source = io_file_read(vs_path);
char* frag_source = io_file_read(fs_path);
assert(vert_source != NULL);
assert(frag_source != NULL);
vert_source = run_preprocessor(vert_source);
frag_source = run_preprocessor(frag_source);
GLint v_size = (GLint)strlen(vert_source);
GLint f_size = (GLint)strlen(frag_source);
const char* vert_sourcePtr = vert_source;
const char* frag_sourcePtr = frag_source;
const GLint* vert_size = &v_size;
const GLint* frag_size = &f_size;
glShaderSource(vert_shader, 1, &vert_sourcePtr, vert_size);
glShaderSource(frag_shader, 1, &frag_sourcePtr, frag_size);
glCompileShader(vert_shader);
glCompileShader(frag_shader);
GLint is_vert_compiled = 0;
GLint is_frag_compiled = 0;
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &is_vert_compiled);
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &is_frag_compiled);
if(!is_vert_compiled)
{
GLint log_size = 0;
glGetShaderiv(vert_shader, GL_INFO_LOG_LENGTH, &log_size);
char* message = (char *)malloc(sizeof(char) * log_size);
glGetShaderInfoLog(vert_shader, log_size, NULL, message);
log_error("shader:create", "COMPILING VS %s : %s", vert_shader_name, message);
debug_print_shader(vert_source);
free(message);
}
if(!is_frag_compiled)
{
GLint log_size = 0;
glGetShaderiv(frag_shader, GL_INFO_LOG_LENGTH, &log_size);
char* message = (char *)malloc(sizeof(char) * log_size);
glGetShaderInfoLog(frag_shader, log_size, NULL, message);
log_error("shader:create", "COMPILING FS %s : %s", frag_shader_name, message);
debug_print_shader(frag_source);
free(message);
}
free(vert_source);
free(frag_source);
if(!is_vert_compiled || !is_frag_compiled)
{
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
return -1;
}
GLuint program = glCreateProgram();
glAttachShader(program, vert_shader);
glAttachShader(program, frag_shader);
// Bind attribute locations
glBindAttribLocation(program, POSITION_LOC, "vPosition");
glBindAttribLocation(program, NORMAL_LOC, "vNormal");
glBindAttribLocation(program, UV_LOC, "vUV");
glBindAttribLocation(program, COLOR_LOC, "vColor");
renderer_check_glerror("shader:create");
glLinkProgram(program);
GLint is_linked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &is_linked);
if(!is_linked)
{
GLint log_size = 0;
glGetProgramiv(program, GL_LINK_STATUS, &log_size);
char* message = (char *)malloc(sizeof(char) * log_size);
glGetProgramInfoLog(program, log_size, NULL, message);
log_error("shader:create", "LINK SHADER : %s", message);
free(message);
glDeleteProgram(program);
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
return -1;
}
/* add new object or overwrite existing one */
Shader_Object* new_object = NULL;
int index = -1;
if(empty_indices->length != 0)
{
index = array_get_last_val(empty_indices, int);
array_pop(empty_indices);
new_object = array_get(shader_list, index);
}
else
{
new_object = array_add(shader_list);
index = shader_list->length - 1;
}
assert(new_object);
new_object->vertex_shader = vert_shader;
new_object->fragment_shader = frag_shader;
new_object->program = program;
log_message("%s, %s compiled into shader program", vert_shader_name, frag_shader_name);
free(vs_path);
free(fs_path);
return index;
}
void shader_bind(const int shader_index)
{
Shader_Object* shader_object = array_get(shader_list, shader_index);
glUseProgram(shader_object->program);
}
void shader_unbind(void)
{
glUseProgram(0);
}
int get_uniform_location(const int shader_index, const char* name)
{
Shader_Object shader_object = array_get_val(shader_list, Shader_Object, shader_index);
GLint handle = glGetUniformLocation(shader_object.program, name);
if(handle == -1)
log_error("shader:get_uniform_location", "Invalid uniform %s", name);
return handle;
}
void set_uniform_int(const int shader_index, const char* name, const int value)
{
GLint location = get_uniform_location(shader_index, name);
if(location >= 0)
glUniform1i(location, value);
}
void set_uniform_float(const int shader_index, const char* name, const float value)
{
GLint location = get_uniform_location(shader_index, name);
if(location >= 0)
glUniform1f(location, value);
}
void set_uniform_vec2(const int shader_index, const char* name, const vec2 value)
{
GLint location = get_uniform_location(shader_index, name);
if(location >= 0)
glUniform2fv(location, 1, value);
}
void set_uniform_vec3(const int shader_index, const char* name, const vec3 value)
{
GLint location = get_uniform_location(shader_index, name);
if(location >= 0)
glUniform3fv(location, 1, value);
}
void set_uniform_vec4(const int shader_index, const char* name, const vec4 value)
{
GLint location = get_uniform_location(shader_index, name);
if(location >= 0)
glUniform4fv(location, 1, value);
}
void setUniformMat4(const int shader_index, const char* name, const mat4 value)
{
GLint location = get_uniform_location(shader_index, name);
if(location >= 0)
glUniformMatrix4fv(location, 1, GL_FALSE, *value);
}
void shader_remove(const int shader_index)
{
Shader_Object* shader_object = array_get(shader_list, shader_index);
glDeleteProgram(shader_object->program);
glDeleteShader(shader_object->vertex_shader);
glDeleteShader(shader_object->fragment_shader);
shader_object->fragment_shader = shader_object->vertex_shader = shader_object->program = -1;
array_push(empty_indices, shader_index, int);
}
void shader_cleanup(void)
{
for(int i = 0; i < (int)shader_list->length; i++)
shader_remove(i);
array_free(shader_list);
array_free(empty_indices);
}

@ -0,0 +1,20 @@
#ifndef shader_H
#define shader_H
#include "linmath.h"
int shader_create(const char* vert_shader_name, const char* frag_shader_name);
void shader_initialize(void);
void shader_bind(const int shader_index);
void shader_remove(const int shader_index);
void shader_unbind(void);
void shader_set_uniform_int(const int shaderIndex, const char* name, const int value);
void shader_set_uniform_float(const int shaderIndex, const char* name, const float value);
void shader_set_uniform_vec2(const int shaderIndex, const char* name, const vec2 value);
void shader_set_uniform_vec3(const int shaderIndex, const char* name, const vec3 value);
void shader_set_uniform_vec4(const int shaderIndex, const char* name, const vec4 value);
void shader_set_uniform_mat4(const int shaderIndex, const char* name, const mat4 value);
void shader_cleanup(void);
int shader_uniform_location_get(const int shader_index, const char* name);
#endif

@ -98,10 +98,3 @@ char* str_replace(char* string, const char* pattern, const char* replacement)
return NULL; return NULL;
} }
} }

Loading…
Cancel
Save