Browse Source

add paletted texture storage to render_state

master
cinnaboot 8 years ago
parent
commit
c38e3bc4a1
  1. BIN
      data/palette.png
  2. 6
      data/scene_schema.json
  3. 6
      data/test_scene.json
  4. 2
      src/hexgame.cpp
  5. 34
      src/render_group.cpp
  6. 2
      src/render_group.h
  7. 64
      src/renderer.cpp
  8. 5
      src/renderer.h
  9. 10
      src/scene_loader.cpp
  10. 1
      src/scene_loader.h
  11. 28
      src/util.cpp
  12. 13
      src/util.h

BIN
data/palette.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

6
data/scene_schema.json

@ -50,9 +50,9 @@
"type": "object", "type": "object",
"properties": { "properties": {
"position": { "$ref": "#/definitions/vector3" }, "position": { "$ref": "#/definitions/vector3" },
"fill_color" : { "type": "string" }, "fill_color" : { "type": "number" },
"selected_fill_color" : { "type": "string" }, "selected_fill_color" : { "type": "number" },
"hex_line_color" : { "type": "string" }, "hex_line_color" : { "type": "number" },
"hexlib_orientation" : { "type": "string" }, "hexlib_orientation" : { "type": "string" },
"hex_size" : { "type": "number" }, "hex_size" : { "type": "number" },
"grid_type" : { "type": "string" }, "grid_type" : { "type": "string" },

6
data/test_scene.json

@ -24,9 +24,9 @@
"z" : 0 "z" : 0
}, },
"hex_size" : 10, "hex_size" : 10,
"fill_color" : "0x565656FF", "fill_color" : 6,
"selected_fill_color": "0xF46000FF", "selected_fill_color": 7,
"hex_line_color": "0x00000000", "hex_line_color": 5,
"hexlib_orientation" : "layout_flat", "hexlib_orientation" : "layout_flat",
"grid_type" : "hexagon", "grid_type" : "hexagon",
"hex_radius" : 20 "hex_radius" : 20

2
src/hexgame.cpp

@ -1,7 +1,6 @@
/******************************************************************************* /*******************************************************************************
* TODO: * TODO:
* - renderer * - renderer
* - clean up main(), split out initialization and scene loading to new functions
* - move input handling out to new file, controller? * - move input handling out to new file, controller?
* - check over renderer, camera, gooey init after changes * - check over renderer, camera, gooey init after changes
* - pass in frame time to camera movement functions to decouple speed from framerate * - pass in frame time to camera movement functions to decouple speed from framerate
@ -21,6 +20,7 @@
* - actually don't need to save the vertex/normal buffers after passing * - actually don't need to save the vertex/normal buffers after passing
* to opengl * to opengl
* - use a storage pool for assimp meshes allowing reuse across entities * - use a storage pool for assimp meshes allowing reuse across entities
* - also cache textures from loaded meshes for re-use
* - replace remaining calls to malloc/free with safe(r) function in util.h * - replace remaining calls to malloc/free with safe(r) function in util.h
* - add cpu perforcmace counters in render loop * - add cpu perforcmace counters in render loop
* - test YAML for scene loading https://yaml.org/ * - test YAML for scene loading https://yaml.org/

34
src/render_group.cpp

@ -20,7 +20,6 @@
render_object * allocateRenderObject(uint buffer_len, uint index_len = 0); render_object * allocateRenderObject(uint buffer_len, uint index_len = 0);
void freeRenderObject(render_object* ro); void freeRenderObject(render_object* ro);
bool initGLTexture(render_object* ro, util_image image);
bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture); bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture);
void sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target); void sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target);
@ -102,6 +101,21 @@ rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char
return true; return true;
} }
bool
rgInitGLTexture(GLuint& tex_id, util_image image)
{
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
GLenum pixel_format = (image.num_channels == 3) ? GL_RGB : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, pixel_format, image.w, image.h, 0,
pixel_format, GL_UNSIGNED_BYTE, image.pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return (glGetError() == GL_NO_ERROR);
}
// TODO: move Entity initialization to Entity.h/.cpp to fix circular dependancy // TODO: move Entity initialization to Entity.h/.cpp to fix circular dependancy
// then just call into convertMeshInfo directly // then just call into convertMeshInfo directly
bool bool
@ -139,7 +153,7 @@ rgInitEntity(Entity* e)
if (mesh->use_texture) { if (mesh->use_texture) {
ro->use_texture = true; ro->use_texture = true;
if (!initGLTexture(ro, mesh->diffuse_texture)) { if (!rgInitGLTexture(ro->tex_id, mesh->diffuse_texture)) {
LOG(ERROR) << "Error initializing GL texture\n"; LOG(ERROR) << "Error initializing GL texture\n";
return false; return false;
} }
@ -312,6 +326,7 @@ freeRenderObject(render_object* ro)
return; return;
} }
glDeleteTextures(1, &ro->tex_id);
utilSafeFree(ro->vertex_buffer.buffer); utilSafeFree(ro->vertex_buffer.buffer);
utilSafeFree(ro->normal_buffer.buffer); utilSafeFree(ro->normal_buffer.buffer);
utilSafeFree(ro->color_buffer.buffer); utilSafeFree(ro->color_buffer.buffer);
@ -388,21 +403,6 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_
return true; return true;
} }
bool
initGLTexture(render_object* ro, util_image image)
{
glGenTextures(1, &ro->tex_id);
glBindTexture(GL_TEXTURE_2D, ro->tex_id);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
GLenum pixel_format = (image.num_channels == 3) ? GL_RGB : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, pixel_format, image.w, image.h, 0,
pixel_format, GL_UNSIGNED_BYTE, image.pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return (glGetError() == GL_NO_ERROR);
}
void void
sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target) sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target)
{ {

2
src/render_group.h

@ -78,6 +78,8 @@ bool rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const
bool rgInitEntity(Entity* e); bool rgInitEntity(Entity* e);
bool rgInitGLTexture(GLuint& tex_id, util_image image);
void rgBufferData(gl_buffer* buffer, GLenum usage, GLenum target); void rgBufferData(gl_buffer* buffer, GLenum usage, GLenum target);
void rgDraw(render_group* rg, glm::mat4 model_matrix, void rgDraw(render_group* rg, glm::mat4 model_matrix,

64
src/renderer.cpp

@ -3,7 +3,6 @@
#include <cmath> // trig functions #include <cmath> // trig functions
#include <cstdlib> // calloc #include <cstdlib> // calloc
#include <GL/gl3w.h>
#if defined (_WIN32) #if defined (_WIN32)
#include <SDL.h> #include <SDL.h>
#else #else
@ -22,15 +21,15 @@
#define DEFAULT_VERTEX_SHADER_FILE "../data/default.vs" #define DEFAULT_VERTEX_SHADER_FILE "../data/default.vs"
#define DEFAULT_FRAGMENT_SHADER_FILE "../data/default.fs" #define DEFAULT_FRAGMENT_SHADER_FILE "../data/default.fs"
#define MAX_LIGHTS 10 // NOTE: needs to match the fragment shader source #define MAX_LIGHTS 10 // NOTE: needs to match the fragment shader source
#define DEFAULT_PALETTE_DIR "../data"
#define DEFAULT_PALETTE_FILE "palette.png"
#define CLEAR_COL_R 75.f / 255.f
#define CLEAR_COL_G 135.f / 255.f
#define CLEAR_COL_B 135.f / 255.f
#define CLEAR_COL_A 1.f
struct clear_col // TODO: add this to json scene properties and render_state
{ util_RGBA g_clear_col;
real32 R;
real32 G;
real32 B;
real32 A;
};
clear_col g_clear_col { 75.f / 255.f, 135.f / 255.f, 135.f / 255.f, 1.f };
// forward declarations // forward declarations
@ -106,14 +105,25 @@ renInit(render_state* rs)
utilSafeFree(vs_code); utilSafeFree(vs_code);
utilSafeFree(fs_code); utilSafeFree(fs_code);
if (shader_error) {
LOG(ERROR) << "Error initializing shader program\n";
return false;
}
rs->max_lights = MAX_LIGHTS; rs->max_lights = MAX_LIGHTS;
rs->lights = UTIL_ALLOC(rs->max_lights, rg_point_light); rs->lights = UTIL_ALLOC(rs->max_lights, rg_point_light);
rs->palette_image = utilLoadImage(DEFAULT_PALETTE_DIR, DEFAULT_PALETTE_FILE);
if (shader_error) { if (!rgInitGLTexture(rs->palette_id, rs->palette_image)) {
LOG(ERROR) << "Error initializing shader program\n"; LOG(ERROR) << "Error creating texture\n";
return false; return false;
} }
g_clear_col.R = CLEAR_COL_R;
g_clear_col.B = CLEAR_COL_B;
g_clear_col.G = CLEAR_COL_G;
g_clear_col.A = CLEAR_COL_A;
return true; return true;
} }
@ -121,41 +131,13 @@ void
renFreeBuffers(render_state* rs) renFreeBuffers(render_state* rs)
{ {
utilSafeFree(rs->lights); utilSafeFree(rs->lights);
utilFreeImage(rs->palette_image);
glDeleteTextures(1, &rs->palette_id);
rgFree(rs->filled_hex_render_group); rgFree(rs->filled_hex_render_group);
rgFree(rs->hex_line_render_group); rgFree(rs->hex_line_render_group);
rgFree(rs->debug_render_group); rgFree(rs->debug_render_group);
} }
bool
renAddTexture(SDL_Handles &handles, const char * path)
{
// TODO: saved here for moving to stb_image implementation
#if 0
// testing
LOG(INFO) << "Loading image: " << path << "\n";
SDL_Surface* image = IMG_Load(path);
if (!image)
{
LOG(ERROR) << "IMG_Load: " << IMG_GetError() << "\n";
return false;
}
GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// store opengl id in SDL_Surface.userdat
image->userdata = (void*)(intptr_t) tex_id;
handles.texSurfaces.push_back(image);
#endif
return true;
}
bool bool
renCreateScene(render_state* rs, Entity* entities, uint32 entity_count) renCreateScene(render_state* rs, Entity* entities, uint32 entity_count)
{ {

5
src/renderer.h

@ -8,6 +8,7 @@
#else #else
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#endif #endif
#include <GL/gl3w.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "camera.h" #include "camera.h"
@ -32,6 +33,8 @@ struct render_state
bool is_debug_draw; bool is_debug_draw;
SDL_Handles handles; SDL_Handles handles;
camera cam; camera cam;
util_image palette_image;
GLuint palette_id = UINT_MAX;
render_group* filled_hex_render_group; render_group* filled_hex_render_group;
render_group* hex_line_render_group; render_group* hex_line_render_group;
@ -48,8 +51,6 @@ bool renInit(render_state* rs);
void renFreeBuffers(render_state* rs); void renFreeBuffers(render_state* rs);
bool renAddTexture(SDL_Handles &handles, const char * path);
bool renCreateScene(render_state* rs, Entity* entities, uint32 entity_count); bool renCreateScene(render_state* rs, Entity* entities, uint32 entity_count);
void renRenderFrame(render_state* rs, std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count); void renRenderFrame(render_state* rs, std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count);

10
src/scene_loader.cpp

@ -131,12 +131,9 @@ slParseHexGrid(slSceneDoc* sd, hexgrid& hg)
hg.position.x = pos.x; hg.position.x = pos.x;
hg.position.y = pos.y; hg.position.y = pos.y;
hg.position.z = pos.z; hg.position.z = pos.z;
std::string fill_color_str = json_grid["fill_color"].GetString(); hg.fill_color = json_grid["fill_color"].GetInt();
hg.fill_color = std::stoul(fill_color_str, nullptr, 16); hg.selected_fill_color = json_grid["selected_fill_color"].GetInt();
std::string selected_fill_color_str = json_grid["selected_fill_color"].GetString(); hg.hex_line_color = json_grid["hex_line_color"].GetInt();
hg.selected_fill_color = std::stoul(selected_fill_color_str, nullptr, 16);
std::string hex_line_color_str = json_grid["hex_line_color"].GetString();
hg.hex_line_color = std::stoul(hex_line_color_str, nullptr, 16);
std::string orientation_str = json_grid["hexlib_orientation"].GetString(); std::string orientation_str = json_grid["hexlib_orientation"].GetString();
hg.hexlib_orientation = (orientation_str == "layout_flat") ? layout_flat : layout_pointy; hg.hexlib_orientation = (orientation_str == "layout_flat") ? layout_flat : layout_pointy;
Layout lo(hg.hexlib_orientation, Point(hg.hex_size, hg.hex_size), Point(hg.position.x, hg.position.y)); Layout lo(hg.hexlib_orientation, Point(hg.hex_size, hg.hex_size), Point(hg.position.x, hg.position.y));
@ -147,7 +144,6 @@ slParseHexGrid(slSceneDoc* sd, hexgrid& hg)
} }
} }
bool bool
slCreateHexRenderGroups(hexgrid& hg, render_state* rs) slCreateHexRenderGroups(hexgrid& hg, render_state* rs)
{ {

1
src/scene_loader.h

@ -9,6 +9,7 @@
struct slSceneDoc; struct slSceneDoc;
struct render_state;
slSceneDoc* slLoadFile(const char* data_dir, const char* scene_file, const char* schema_file); slSceneDoc* slLoadFile(const char* data_dir, const char* scene_file, const char* schema_file);

28
src/util.cpp

@ -10,6 +10,10 @@
#include "util.h" #include "util.h"
#define PALETTE_ROWS 16
#define PALETTE_COLUMNS 16
#define PALETTE_BORDER 1
const uint MAX_FILESIZE = 2 * 1024 * 1024; // 2MB const uint MAX_FILESIZE = 2 * 1024 * 1024; // 2MB
const uint MAX_STRING_LENGTH = 1024; const uint MAX_STRING_LENGTH = 1024;
@ -114,3 +118,27 @@ utilFreeImage(util_image image)
std::memset(image.file_path, 0, std::strlen(image.file_path) + 1); std::memset(image.file_path, 0, std::strlen(image.file_path) + 1);
utilSafeFree(image.pixels); utilSafeFree(image.pixels);
} }
// need to init default values from scene file, or finally make default config?
util_RGBA
renGetPaletteColor(util_image& palette_image, uint color_index)
{
util_RGBA color;
if (PALETTE_ROWS * PALETTE_COLUMNS < color_index) {
LOG(ERROR) << "index out of range\n";
return color;
}
if (palette_image.pixels == nullptr) {
LOG(ERROR) << "palatte image not loaded\n";
return color;
}
// get start of pixel (remember to account for palette border)
// read num_channels bytes
// pad extra 0xFF byte if 3 channels
// convert 4 uint8 bytes to normalized RGBA floats
return color;
}

13
src/util.h

@ -49,6 +49,14 @@ struct v4i
int32 y1; int32 y1;
}; };
struct util_RGBA
{
real32 R = 1.f;
real32 G = 1.f;
real32 B = 1.f;
real32 A = 1.f;
};
struct util_image struct util_image
{ {
int32 w = 0; int32 w = 0;
@ -92,11 +100,12 @@ const char* utilBaseName(const char* path_str);
#define UTIL_ALLOC(len, type) (type *) utilLogAlloc((len), sizeof(type), __FILE__, __LINE__) #define UTIL_ALLOC(len, type) (type *) utilLogAlloc((len), sizeof(type), __FILE__, __LINE__)
void* utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int line); void* utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int line);
void utilSafeFree(const void* mem);
char* utilDumpTextFile(const char* filename); char* utilDumpTextFile(const char* filename);
util_image utilLoadImage(const char* base_dir, const char* filename); util_image utilLoadImage(const char* base_dir, const char* filename);
void utilFreeImage(util_image image); void utilFreeImage(util_image image);
void utilSafeFree(const void* mem); util_RGBA utilGetPaletteColor(util_image& palette_image, uint color_index);

Loading…
Cancel
Save