From c38e3bc4a16883d29e41e4c05f4ef2fbb2af4ef4 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Fri, 4 Jan 2019 14:27:39 -0500 Subject: [PATCH] add paletted texture storage to render_state --- data/palette.png | Bin 0 -> 6279 bytes data/scene_schema.json | 6 ++-- data/test_scene.json | 6 ++-- src/hexgame.cpp | 2 +- src/render_group.cpp | 34 +++++++++++----------- src/render_group.h | 2 ++ src/renderer.cpp | 64 +++++++++++++++-------------------------- src/renderer.h | 5 ++-- src/scene_loader.cpp | 10 ++----- src/scene_loader.h | 1 + src/util.cpp | 28 ++++++++++++++++++ src/util.h | 13 +++++++-- 12 files changed, 95 insertions(+), 76 deletions(-) create mode 100644 data/palette.png diff --git a/data/palette.png b/data/palette.png new file mode 100644 index 0000000000000000000000000000000000000000..3b38adf6f900012111ddef8b1b631ebf6ad34060 GIT binary patch literal 6279 zcmeAS@N?(olHy`uVBq!ia0y~yU;#2&7&zE~RK2WrGmzpe@Q5sCV9-+rVaAH3_GLgp z_7YEDSN6w@%tETV2jlm}0fi(>Tq8=H^K)}k^GX<;i&7IyQd1PlGfOfQ+&z5*!W;R- z85krOJzX3_DsH{Gy>RVRN0HWxdrx}se45(i9C*li;sb#z4U5=V`dE%?Gqx_CqHg%Z zS$gu!tyVXli+_LSz06Y$Xvu+#VS4%uzMsB*U7h{?|F6&H=i~3i?*9Mq^ZA;pe-&^4 zt>?f0>G#jSTYulT`LpAn`-6`kKi+!l@9+Qf`@?(r|36h56~DJ{*!Jyq{{Fw;Zr9Hh zX9SuF@-l-1h#<@asb>%X5e$Tw4q#Qp8BUyuNLJFyaN?YcWIMXc8|Ipvv|t8$eNL|G z$uoO-7pw&aG&r>3g#3A7P|%?3MDiU5lN4tWiWelq9T*Cj28&BTK|+Z)Z+K7cF$S7( z;AYsQGk0z?+`0u1aA^4d|7Zga8;fg1v5=`Yt3h)?%9<`$h9u)5Ap@I|<4j}o_1drUS zMGvjfCJiWwIDiPGghP-C(SVd~2{O_1^=PLR6y)GwLr;_VLZ4tbqboo+d^Ev>!rcKx z;0tH;V1sC2Vfb;sPnH{`m*>;=dB^$=alniLF`&jWftX+e8bB;aB%{k$aNZ9V{MW4) QQ3F!q>FVdQ&MBb@0A9)>;{X5v literal 0 HcmV?d00001 diff --git a/data/scene_schema.json b/data/scene_schema.json index 9860114..6a55791 100644 --- a/data/scene_schema.json +++ b/data/scene_schema.json @@ -50,9 +50,9 @@ "type": "object", "properties": { "position": { "$ref": "#/definitions/vector3" }, - "fill_color" : { "type": "string" }, - "selected_fill_color" : { "type": "string" }, - "hex_line_color" : { "type": "string" }, + "fill_color" : { "type": "number" }, + "selected_fill_color" : { "type": "number" }, + "hex_line_color" : { "type": "number" }, "hexlib_orientation" : { "type": "string" }, "hex_size" : { "type": "number" }, "grid_type" : { "type": "string" }, diff --git a/data/test_scene.json b/data/test_scene.json index c75c8ab..4c329dd 100644 --- a/data/test_scene.json +++ b/data/test_scene.json @@ -24,9 +24,9 @@ "z" : 0 }, "hex_size" : 10, - "fill_color" : "0x565656FF", - "selected_fill_color": "0xF46000FF", - "hex_line_color": "0x00000000", + "fill_color" : 6, + "selected_fill_color": 7, + "hex_line_color": 5, "hexlib_orientation" : "layout_flat", "grid_type" : "hexagon", "hex_radius" : 20 diff --git a/src/hexgame.cpp b/src/hexgame.cpp index e193225..1280702 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -1,7 +1,6 @@ /******************************************************************************* * TODO: * - renderer - * - clean up main(), split out initialization and scene loading to new functions * - move input handling out to new file, controller? * - check over renderer, camera, gooey init after changes * - 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 * to opengl * - 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 * - add cpu perforcmace counters in render loop * - test YAML for scene loading https://yaml.org/ diff --git a/src/render_group.cpp b/src/render_group.cpp index 086de85..92aa4d1 100644 --- a/src/render_group.cpp +++ b/src/render_group.cpp @@ -20,7 +20,6 @@ render_object * allocateRenderObject(uint buffer_len, uint index_len = 0); 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); 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; } +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 // then just call into convertMeshInfo directly bool @@ -139,7 +153,7 @@ rgInitEntity(Entity* e) if (mesh->use_texture) { 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"; return false; } @@ -312,6 +326,7 @@ freeRenderObject(render_object* ro) return; } + glDeleteTextures(1, &ro->tex_id); utilSafeFree(ro->vertex_buffer.buffer); utilSafeFree(ro->normal_buffer.buffer); utilSafeFree(ro->color_buffer.buffer); @@ -388,21 +403,6 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_ 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 sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target) { diff --git a/src/render_group.h b/src/render_group.h index 3f68af5..75c4e68 100644 --- a/src/render_group.h +++ b/src/render_group.h @@ -78,6 +78,8 @@ bool rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const bool rgInitEntity(Entity* e); +bool rgInitGLTexture(GLuint& tex_id, util_image image); + void rgBufferData(gl_buffer* buffer, GLenum usage, GLenum target); void rgDraw(render_group* rg, glm::mat4 model_matrix, diff --git a/src/renderer.cpp b/src/renderer.cpp index 247c96d..7f98f71 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -3,7 +3,6 @@ #include // trig functions #include // calloc -#include #if defined (_WIN32) #include #else @@ -22,15 +21,15 @@ #define DEFAULT_VERTEX_SHADER_FILE "../data/default.vs" #define DEFAULT_FRAGMENT_SHADER_FILE "../data/default.fs" #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 -{ - 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 }; +// TODO: add this to json scene properties and render_state +util_RGBA g_clear_col; // forward declarations @@ -106,14 +105,25 @@ renInit(render_state* rs) utilSafeFree(vs_code); utilSafeFree(fs_code); + if (shader_error) { + LOG(ERROR) << "Error initializing shader program\n"; + return false; + } + rs->max_lights = MAX_LIGHTS; rs->lights = UTIL_ALLOC(rs->max_lights, rg_point_light); + rs->palette_image = utilLoadImage(DEFAULT_PALETTE_DIR, DEFAULT_PALETTE_FILE); - if (shader_error) { - LOG(ERROR) << "Error initializing shader program\n"; + if (!rgInitGLTexture(rs->palette_id, rs->palette_image)) { + LOG(ERROR) << "Error creating texture\n"; 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; } @@ -121,41 +131,13 @@ void renFreeBuffers(render_state* rs) { utilSafeFree(rs->lights); + utilFreeImage(rs->palette_image); + glDeleteTextures(1, &rs->palette_id); rgFree(rs->filled_hex_render_group); rgFree(rs->hex_line_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 renCreateScene(render_state* rs, Entity* entities, uint32 entity_count) { diff --git a/src/renderer.h b/src/renderer.h index 4287c52..883588f 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -8,6 +8,7 @@ #else #include #endif +#include #include #include "camera.h" @@ -32,6 +33,8 @@ struct render_state bool is_debug_draw; SDL_Handles handles; camera cam; + util_image palette_image; + GLuint palette_id = UINT_MAX; render_group* filled_hex_render_group; render_group* hex_line_render_group; @@ -48,8 +51,6 @@ bool renInit(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); void renRenderFrame(render_state* rs, std::vector* hexes, Entity* entities, uint32 entity_count); diff --git a/src/scene_loader.cpp b/src/scene_loader.cpp index 47ab5bd..741a1f7 100644 --- a/src/scene_loader.cpp +++ b/src/scene_loader.cpp @@ -131,12 +131,9 @@ slParseHexGrid(slSceneDoc* sd, hexgrid& hg) hg.position.x = pos.x; hg.position.y = pos.y; hg.position.z = pos.z; - std::string fill_color_str = json_grid["fill_color"].GetString(); - hg.fill_color = std::stoul(fill_color_str, nullptr, 16); - std::string selected_fill_color_str = json_grid["selected_fill_color"].GetString(); - 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); + hg.fill_color = json_grid["fill_color"].GetInt(); + hg.selected_fill_color = json_grid["selected_fill_color"].GetInt(); + hg.hex_line_color = json_grid["hex_line_color"].GetInt(); std::string orientation_str = json_grid["hexlib_orientation"].GetString(); 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)); @@ -147,7 +144,6 @@ slParseHexGrid(slSceneDoc* sd, hexgrid& hg) } } - bool slCreateHexRenderGroups(hexgrid& hg, render_state* rs) { diff --git a/src/scene_loader.h b/src/scene_loader.h index 0f3bbf5..617f32e 100644 --- a/src/scene_loader.h +++ b/src/scene_loader.h @@ -9,6 +9,7 @@ struct slSceneDoc; +struct render_state; slSceneDoc* slLoadFile(const char* data_dir, const char* scene_file, const char* schema_file); diff --git a/src/util.cpp b/src/util.cpp index 4631620..bb9520e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -10,6 +10,10 @@ #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_STRING_LENGTH = 1024; @@ -114,3 +118,27 @@ utilFreeImage(util_image image) std::memset(image.file_path, 0, std::strlen(image.file_path) + 1); 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; +} diff --git a/src/util.h b/src/util.h index f4338b0..1702794 100644 --- a/src/util.h +++ b/src/util.h @@ -49,6 +49,14 @@ struct v4i int32 y1; }; +struct util_RGBA +{ + real32 R = 1.f; + real32 G = 1.f; + real32 B = 1.f; + real32 A = 1.f; +}; + struct util_image { 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__) 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); util_image utilLoadImage(const char* base_dir, const char* filename); void utilFreeImage(util_image image); -void utilSafeFree(const void* mem); - +util_RGBA utilGetPaletteColor(util_image& palette_image, uint color_index);