dev
parent
a40b11870d
commit
6d56ff2bb1
@ -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 |
@ -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 |
Loading…
Reference in new issue