Added uncompressed tga loader

dev
Shariq Shah 10 years ago
parent 7de6726c06
commit fc10cb9357
  1. 4
      orgfile.org
  2. 21
      src/game.c
  3. 13
      src/model.c
  4. 1
      src/renderer.c
  5. 44
      src/shader.c
  6. 318
      src/texture.c
  7. 13
      src/texture.h

@ -36,8 +36,10 @@ while using as few libraries as possible.
- State "DONE" from "TODO" [2015-08-02 Sun 19:09]
** TODO Fix readme markdown
** TODO Framebuffer and resolution independent rendering
** TODO Entity
** DONE Entity
- State "DONE" from "TODO" [2015-09-15 Tue 12:17]
** TODO Positive and negative values for input_maps and returning corresponding values when they are true
** TODO Textures
** DONE Camera
- State "DONE" from "TODO" [2015-08-19 Wed 13:30]
** DONE Test render

@ -18,11 +18,13 @@
#include "model.h"
#include "scene.h"
#include "utils.h"
#include "texture.h"
void run(void);
void update(float dt);
void render(void);
void debug(float dt);
void scene_setup(void);
int player_node = -1;
int player_pitch_node = -1;
@ -35,14 +37,22 @@ void game_init(void)
renderer_init(window);
io_file_init("/mnt/Dev/Projects/Symmetry/assets/");/* TODO: Implement proper way of getting binary directory */
shader_init();
texture_init();
transform_init();
camera_init();
geom_init();
model_init();
entity_init();
scene_init();
/* Debug scene setup */
scene_setup();
run();
}
void scene_setup(void)
{
int forward_keys[2] = {'W', GLFW_KEY_UP};
int backward_keys[2] = {'S', GLFW_KEY_DOWN};
int up_keys[2] = {'Q'};
@ -63,8 +73,8 @@ void game_init(void)
input_map_create("Turn_Left", turn_left_keys, 1);
input_map_create("Turn_Up", turn_up_keys, 1);
input_map_create("Turn_Down", turn_down_keys, 1);
shader_create("unshaded.vert", "unshaded.frag");
shader_create("unshaded_textured.vert", "unshaded_textured.frag");
struct Entity* player = scene_add_new("player", "None");
player_node = player->node;
vec3 viewer_pos = {0, 0, 10};
@ -96,7 +106,7 @@ void game_init(void)
transform_set_position(ground_tran, &pos);
transform_scale(ground_tran, &scale_ground);
run();
texture_create_from_file("test.tga");
}
void debug(float dt)
@ -258,5 +268,6 @@ void game_cleanup(void)
input_cleanup();
renderer_cleanup();
io_file_cleanup();
texture_cleanup();
shader_cleanup();
}

@ -6,12 +6,16 @@
#include "entity.h"
#include "shader.h"
#include "transform.h"
#include "texture.h"
#include "renderer.h"
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <assert.h>
static struct Model* model_list;
static int* empty_indices;
struct Model* model_get(int index)
{
struct Model* model = NULL;
@ -89,6 +93,7 @@ void model_cleanup(void)
void model_render_all(struct Camera* camera)
{
int texture = texture_find("test.tga");
mat4 mvp;
for(int i = 0; i < array_len(model_list); i++)
{
@ -98,10 +103,14 @@ void model_render_all(struct Camera* camera)
mat4_identity(&mvp);
shader_bind(model->shader);
/* shader_set_uniform_int(model->shader, "sampler", (GL_TEXTURE0 + 4) - GL_TEXTURE0); */
texture_bind(texture, 4);
renderer_check_glerror("model:render_all");
mat4_mul(&mvp, &camera->view_proj_mat, &transform->trans_mat);
shader_set_uniform_mat4(model->shader, "mvp", &mvp);
shader_set_uniform_vec4(model->shader, "color", &model->color);
shader_set_uniform_vec4(model->shader, "diffuseColor", &model->color);
geom_render(model->geometry_index);
texture_unbind(4);
shader_unbind();
}
}

@ -11,6 +11,7 @@ void renderer_init(GLFWwindow* window)
{
glClearColor(0.3f, 0.6f, 0.9f, 1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glfwSetFramebufferSizeCallback(window, on_framebuffer_size_change);
}

@ -14,21 +14,13 @@
#include "GL/glew.h"
#include "GLFW/glfw3.h"
struct Shader_Object
{
unsigned int vertex_shader;
unsigned int fragment_shader;
unsigned int program;
};
typedef struct Shader_Object 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 struct Shader_Object* shader_list;
static uint* shader_list;
static int* empty_indices;
void debug_print_shader(const char* shaderText)
@ -91,7 +83,7 @@ char* run_preprocessor(char* shader_text)
void shader_init(void)
{
shader_list = array_new(Shader_Object);
shader_list = array_new(uint);
empty_indices = array_new(int);
}
@ -198,25 +190,27 @@ int shader_create(const char* vert_shader_name, const char* frag_shader_name)
return -1;
}
/* Safe to delete shaders now */
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
/* add new object or overwrite existing one */
Shader_Object* new_object = NULL;
uint* new_shader = 0;
int index = -1;
int empty_len = array_len(empty_indices);
if(empty_len != 0)
{
index = empty_indices[empty_len - 1];
array_pop(empty_indices);
new_object = &shader_list[index];
new_shader = &shader_list[index];
}
else
{
new_object = array_grow(shader_list, struct Shader_Object);
new_shader = array_grow(shader_list, uint);
index = array_len(shader_list) - 1;
}
assert(new_object);
new_object->vertex_shader = vert_shader;
new_object->fragment_shader = frag_shader;
new_object->program = program;
assert(new_shader);
*new_shader = program;
log_message("%s, %s compiled into shader program", vert_shader_name, frag_shader_name);
free(vs_path);
@ -227,7 +221,7 @@ int shader_create(const char* vert_shader_name, const char* frag_shader_name)
void shader_bind(const int shader_index)
{
glUseProgram(shader_list[shader_index].program);
glUseProgram(shader_list[shader_index]);
}
void shader_unbind(void)
@ -237,7 +231,7 @@ void shader_unbind(void)
int shader_get_uniform_location(const int shader_index, const char* name)
{
GLint handle = glGetUniformLocation(shader_list[shader_index].program, name);
GLint handle = glGetUniformLocation(shader_list[shader_index], name);
if(handle == -1)
log_error("shader:get_uniform_location", "Invalid uniform %s", name);
@ -288,11 +282,13 @@ void shader_set_uniform_mat4(const int shader_index, const char* name, const ma
void shader_remove(const int shader_index)
{
Shader_Object* shader_object = &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;
uint shader = shader_list[shader_index];
int curr_program = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, &curr_program);
if((uint)curr_program == shader)
glUseProgram(0);
glDeleteProgram(shader);
shader_list[shader_index] = 0;
array_push(empty_indices, shader_index, int);
}

@ -0,0 +1,318 @@
#include "texture.h"
#include "array.h"
#include "file_io.h"
#include "string_utils.h"
#include "log.h"
#include "num_types.h"
#include "renderer.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "GL/glew.h"
#include "GLFW/glfw3.h"
struct Texture
{
char* name;
uint handle;
int ref_count;
};
#pragma pack(push, 1)
struct Tga_Header
{
char idlength;
char colourmaptype;
char datatypecode;
short colourmaporigin;
short colourmaplength;
char colourmapdepth;
short x_origin;
short y_origin;
short width;
short height;
char bitsperpixel;
char imagedescriptor;
};
#pragma pack(pop)
static struct Texture* texture_list;
static int* empty_indices;
int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt, int* internal_fmt);
void texture_debug_write_tga(struct Tga_Header* header, GLubyte* image_data);
void texture_init(void)
{
texture_list = array_new(struct Texture);
empty_indices = array_new(int);
}
int texture_create_from_file(const char* filename)
{
assert(filename);
int index = -1;
uint handle = 0;
char* full_path = str_new("textures/");
full_path = str_concat(full_path, filename);
FILE* file = io_file_open(full_path, "rb");
int img_load_success = -1;
if(file)
{
/* Load texture here */
int width, height, internal_fmt, fmt;
GLubyte* img_data = NULL;
width = height = internal_fmt = fmt = -1;
img_load_success = load_img(file, &img_data, &width, &height, &fmt, &internal_fmt);
if(img_load_success)
{
struct Texture* new_texture = NULL;
if(array_len(empty_indices) > 0)
{
index = *array_get_last(empty_indices, int);
array_pop(empty_indices);
new_texture = &texture_list[index];
}
else
{
new_texture = array_grow(texture_list, struct Texture);
index = array_len(texture_list) - 1;
}
assert(new_texture);
log_message("\nWidth : %d\nHeight : %d\nFormat : %s",
width, height, fmt == GL_RGB ? "RGB" : "RGBA");
glGenTextures(1, &handle);
if(new_texture->name) free(new_texture->name);
new_texture->name = str_new(filename);
new_texture->ref_count = 1;
new_texture->handle = handle;
glBindTexture(GL_TEXTURE_2D, handle);
texture_param_set(index, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture_param_set(index, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture_param_set(index,GL_TEXTURE_WRAP_S,GL_REPEAT);
texture_param_set(index,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, internal_fmt, width, height, 0, fmt, GL_UNSIGNED_BYTE, img_data);
renderer_check_glerror("texture:create");
glBindTexture(GL_TEXTURE_2D, 0);
free(img_data);
}
fclose(file);
}
else
{
log_error("texture:create_from_file", "Could not open file %s", filename);
}
free(full_path);
return index;
}
void texture_remove(int index)
{
if(index > -1 && index < array_len(texture_list))
{
struct Texture* texture = &texture_list[index];
if(texture->ref_count >= 0)
{
texture->ref_count--;
if(texture->ref_count < 0)
{
glDeleteTextures(1, &texture->handle);
if(texture->name) free(texture->name);
texture->ref_count = -1;
array_push(empty_indices, index, int);
}
}
}
}
int texture_find(const char* name)
{
assert(name);
int index = -1;
for(int i = 0; i < array_len(texture_list); i++)
{
struct Texture* texture = &texture_list[i];
if(texture->name && strcmp(texture->name, name) == 0)
{
index = i;
break;
}
}
return index;
}
void texture_cleanup(void)
{
for(int i = 0; i < array_len(texture_list); i++)
texture_remove(i);
array_free(texture_list);
array_free(empty_indices);
}
void texture_bind(int index, int texture_unit)
{
assert(index > -1 && index < array_len(texture_list));
//glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_2D, texture_list[index].handle);
}
void texture_unbind(int texture_unit)
{
//glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_2D, 0);
}
int load_img(FILE* file, GLubyte** image_data, int* width, int* height, int* fmt, int* internal_fmt)
{
int success = 0;
struct Tga_Header header;
size_t items_read = fread(&header, sizeof(struct Tga_Header), 1, file);
if(items_read == 1)
{
/* log_message("sizeof struct : %d", sizeof(struct Tga_Header)); */
/* log_message("%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n", */
/* header.idlength, */
/* header.colourmaptype, */
/* header.datatypecode, */
/* header.colourmaporigin, */
/* header.colourmaplength, */
/* header.colourmapdepth, */
/* header.x_origin, */
/* header.y_origin, */
/* header.width, */
/* header.height, */
/* header.bitsperpixel, */
/* header.imagedescriptor); */
if(header.datatypecode == 0)
{
log_error("texture:load_img", "No image data in file");
success = 0;
}
else
{
/* only compressed and uncompressed true color image data supported yet */
if(header.datatypecode != 2 && header.datatypecode != 10)
{
log_error("texture:load_img", "Unsupported image data type");
success = 0;
return success;
}
if(header.bitsperpixel != 24 && header.bitsperpixel != 32)
{
log_error("texture:load_img",
"Unsupported bitsperpixel size(%d), only 24 and 32 supported", header.bitsperpixel);
success = 0;
return success;
}
if(header.width <= 0 || header.height <= 0)
{
log_error("texture:load_img", "Invalid width and height (%d:%d)", header.width, header.height);
success = 0;
return success;
}
size_t bytes_per_pixel = header.bitsperpixel / 8;
size_t image_size = (bytes_per_pixel * header.width * header.height);
*image_data = malloc(image_size);
if(!*image_data)
{
log_error("texture:load_img", "Out of memory");
success = 0;
return success;
}
/* skip over unnecessary things like colormap data */
int skipover = 0;
skipover += header.idlength;
skipover += header.colourmaptype * header.colourmaplength;
fseek(file, skipover, SEEK_CUR);
/* Start reading pixel by pixel */
GLubyte pixel[bytes_per_pixel];
GLubyte* curr_pixel = *image_data;
for(int i = 0; i < header.width * header.height; i++)
{
if(header.datatypecode == 2) /* uncompressed image data */
{
if(fread(&pixel, 1, bytes_per_pixel, file) != bytes_per_pixel)
{
success = 0;
log_error("texture:load_img", "Unexpected end of file at pixel %d", i);
free(image_data);
return success;
}
/* Swap BGR to RGB */
curr_pixel[0] = pixel[2];
curr_pixel[1] = pixel[1];
curr_pixel[2] = pixel[0];
if(bytes_per_pixel == 4) curr_pixel[3] = pixel[3];
curr_pixel += bytes_per_pixel;
}
else if(header.datatypecode == 10) /* compressed image data */
{
log_message("Not implemented yet!");
}
}
texture_debug_write_tga(&header, *image_data);
*height = header.height;
*width = header.width;
*fmt = bytes_per_pixel == 3 ? GL_RGB : GL_RGBA;
*internal_fmt = *fmt;
success = 1;
}
}
else
{
log_error("texture:load_img", "Could not read header");
success = 0;
}
return success;
}
void texture_param_set(int index, int parameter, int value)
{
struct Texture* texture = NULL;
if(index > -1 && index < array_len(texture_list))
texture = &texture_list[index];
else
return;
GLint curr_texture = 0;
glGetIntegerv(GL_TEXTURE_2D, &curr_texture);
glBindTexture(GL_TEXTURE_2D, texture->handle);
glTexParameteri(GL_TEXTURE_2D, parameter, value);
renderer_check_glerror("texture:param_set");
if(curr_texture != 0)
glBindTexture(GL_TEXTURE_2D, curr_texture);
}
void texture_debug_write_tga(struct Tga_Header* header, GLubyte* image_data)
{
/* Debug only, write the loaded image to file */
FILE* fptr = NULL;
if ((fptr = fopen("tga_debug.tga","w")) == NULL) {
fprintf(stderr,"Failed to open outputfile\n");
exit(-1);
}
fwrite(header, sizeof(struct Tga_Header), 1, fptr);
for (int i = 0; i < header->height * header->width; i++)
{
putc(image_data[2], fptr);
putc(image_data[1], fptr);
putc(image_data[0], fptr);
image_data += 3;
}
fclose(fptr);
}

@ -0,0 +1,13 @@
#ifndef texture_H
#define texture_H
void texture_init(void);
int texture_create_from_file(const char* filename);
void texture_remove(int index);
int texture_find(const char* name);
void texture_cleanup(void);
void texture_bind(int index, int texture_unit);
void texture_unbind(int texture_unit);
void texture_param_set(int index, int parameter, int value);
#endif
Loading…
Cancel
Save