From 99c22028164d423377a37873572cb1654756591f Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Tue, 27 Oct 2020 19:38:53 -0400 Subject: add write to file, finish gifs, gl fixes --- src/assets.cc | 63 +++++++++++++++++++++++++- src/assets.h | 7 ++- src/gl.cc | 123 ++++++++++++++++++++++++++++++++++++++++---------- src/gl.h | 15 ++++-- src/mauri.cc | 6 ++- src/objects/model.cc | 1 + src/objects/object.cc | 6 ++- src/objects/object.h | 2 + src/objects/pass.cc | 27 +++++++++-- src/objects/pass.h | 4 +- src/objects/scene.cc | 4 +- src/texture.cc | 75 +++++++++++++++++++----------- src/texture.h | 6 ++- 13 files changed, 269 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/assets.cc b/src/assets.cc index 9c47c61..fdfdd0d 100644 --- a/src/assets.cc +++ b/src/assets.cc @@ -4,8 +4,10 @@ #include "texture.h" #include +#include #include #include +#include using namespace Mauri; @@ -28,20 +30,24 @@ Asset::Asset() pos = 0; data = nullptr; lasset = nullptr; + ltype = NONE; } static Asset asset_void = Asset(); Asset::Asset(const std::string &path, byte *begin, byte *end) + : path(path) { type = ASSET_SLICE; size = end - begin; pos = 0; data = begin; lasset = nullptr; + ltype = NONE; } Asset::Asset(const std::string &path) + : path(path) { std::ifstream file(path, std::ios::binary | std::ios::ate); @@ -69,6 +75,7 @@ Asset::Asset(const std::string &path) type = ASSET_FILE; lasset = nullptr; + ltype = NONE; } Asset::~Asset() @@ -201,7 +208,7 @@ Asset *AssetManager::get_file(const std::string &part, FileTypeHint hint) if (asset->lasset == nullptr) { - switch (hint) + switch (asset->ltype) { case TEXTURE: asset->lasset = new Texture(asset); @@ -214,6 +221,60 @@ Asset *AssetManager::get_file(const std::string &part, FileTypeHint hint) return asset; } +void AssetManager::write_files(const std::string &output_path) +{ + std::cout << std::filesystem::create_directories(output_path) << "\n"; + + for (auto &asset : files) + { + std::stringstream path; + + path << output_path; + + if (output_path.back() != '/') + { + path << '/'; + } + + auto index = asset->path.find_last_of('/'); + + if (index != std::string::npos) + { + std::filesystem::create_directories(path.str() + asset->path.substr(0, index)); + } + + path << asset->path; + + switch (asset->ltype) + { + case TEXTURE: { + auto texture = ((Texture *)asset->lasset); + texture->save_to_file(path.str() + ".png"); + std::ofstream file(path.str() + ".flags"); + file << "NO_INTERPOLATION " << texture->flags.map.NO_INTERPOLATION << "\n"; + file << "CLAMP_UV " << texture->flags.map.CLAMP_UV << "\n"; + file << "IS_GIF " << texture->flags.map.IS_GIF << "\n"; + file.close(); + break; + } + case FRAGMENT_SHADER: + case VERTEX_SHADER: + case SHADER: { + std::ofstream file(path.str()); + file << asset->as_string(); + file.close(); + break; + } + case NONE: { + std::ofstream file(path.str(), std::ios::binary); + file << asset->as_string(); + file.close(); + break; + } + } + } +} + AssetManager::~AssetManager() { for (auto &file : files) diff --git a/src/assets.h b/src/assets.h index 72fd58b..e3fc47c 100644 --- a/src/assets.h +++ b/src/assets.h @@ -39,6 +39,8 @@ class Asset // free'd along with this asset. AssetType type; + std::string path; + // Info about loaded asset FileTypeHint ltype; void *lasset; @@ -104,10 +106,11 @@ class AssetManager std::vector files; - bool load_package(const std::string &path); - Asset *get_file(const std::string &part, FileTypeHint hint); + bool load_package(const std::string &path); + void write_files(const std::string &output_path); + private: Asset *pkg; }; diff --git a/src/gl.cc b/src/gl.cc index 53d8d59..14bc6f7 100644 --- a/src/gl.cc +++ b/src/gl.cc @@ -5,12 +5,28 @@ #include "gl.h" #include "log.h" +#include "texture.h" #include "util.h" using namespace Mauri; static bool gl_initialized = true; +static u32 pack_rgba(byte r, byte g, byte b, byte a) +{ + return (a << 24 | b << 16 | g << 8 | r); +} + +static u32 pack_rg(byte r, byte g) +{ + return (1 << 24 | 0 << 16 | g << 8 | r); +} + +static u32 pack_red(byte r) +{ + return (1 << 24 | 0 << 16 | 0 << 8 | r); +} + void RenderObject::set_data(f32 *vertices, s32 vertex_count) { #ifdef _DEBUG_ @@ -99,6 +115,18 @@ RenderObject::RenderObject(RenderObjType type, f32 width, f32 height) set_data(vertices, sizeof(vertices)); break; } + case RenderObjType::OBJECT_FLIPPED: { + f32 vertices[] = { + -width, height, 0.f, 0.f, 1.f, + width, -height, 0.f, 1.f, 0.f, + -width, -height, 0.f, 0.f, 0.f, + -width, height, 0.f, 0.f, 1.f, + width, height, 0.f, 1.f, 1.f, + width, -height, 0.f, 1.f, 0.f + }; + set_data(vertices, sizeof(vertices)); + break; + } } } @@ -244,7 +272,7 @@ void RenderTexture::bind(s32 index) glBindTexture(GL_TEXTURE_2D, id); } -RenderTexture::RenderTexture(bool interp, bool clamp_uv, s32 mm_count) +RenderTexture::RenderTexture(bool no_interp, bool clamp_uv, bool filtering, s32 mm_count) { #ifdef _DEBUG_ if (!gl_initialized) return; @@ -254,10 +282,21 @@ RenderTexture::RenderTexture(bool interp, bool clamp_uv, s32 mm_count) glBindTexture(GL_TEXTURE_2D, id); - if (interp) + if (filtering) + { + f32 aniso; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso); + } + + if (no_interp) + { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -268,10 +307,8 @@ RenderTexture::RenderTexture(bool interp, bool clamp_uv, s32 mm_count) } else { - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); @@ -280,7 +317,7 @@ RenderTexture::RenderTexture(bool interp, bool clamp_uv, s32 mm_count) glBindTexture(GL_TEXTURE_2D, 0); } -void RenderTexture::upload(byte *data, s32 width, s32 height, s32 level, u32 format, bool scale, bool dxt) +void RenderTexture::upload(byte *data, s32 width, s32 height, s32 level, bool dxt, bool scale) { #ifdef _DEBUG_ if (!gl_initialized) return; @@ -288,29 +325,65 @@ void RenderTexture::upload(byte *data, s32 width, s32 height, s32 level, u32 for bind(0); - if (scale) + // Save pixels in RGBA format as a simple utility. + if (data != nullptr && level == 0) { - s32 _width = next_power_of_two(width); - s32 _height = next_power_of_two(height); + pixels.reserve(width * height); - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, _width, _height, 0, - format, GL_UNSIGNED_BYTE, nullptr); - - if (dxt) + switch (format) { - glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, - format, GL_UNSIGNED_INT_8_8_8_8, data); + case GL_RGBA: { + byte *dp = data; + for (int i = 0; i < width * height; i++) + { + pixels[i] = pack_rgba(*dp, *(dp + 1), *(dp + 2), *(dp + 3)); + dp += 4; + } + break; } - else - { - glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, - format, GL_UNSIGNED_BYTE, data); + case GL_RG: { + byte *dp = data; + for (int i = 0; i < width * height; i++) + { + pixels[i] = pack_rg(*dp, *(dp + 1)); + dp += 2; + } + break; } + case GL_RED: { + byte *dp = data; + for (int i = 0; i < width * height; i++) + { + pixels[i] = pack_red(*dp); + dp += 1; + } + break; + } + } + } + + s32 iformat = GL_UNSIGNED_BYTE; + + if (dxt) + { + iformat = GL_UNSIGNED_INT_8_8_8_8; + } + + if (scale) + { + s32 scaled_width = next_power_of_two(width); + s32 scaled_height = next_power_of_two(height); + + glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, scaled_width, scaled_height, 0, + format, iformat, nullptr); + + glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, width, height, + format, iformat, data); } else { glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, - format, GL_UNSIGNED_BYTE, data); + format, iformat, data); } } @@ -330,8 +403,10 @@ RenderFramebuffer::RenderFramebuffer(f32 width0, f32 height0, f32 scale) if (!gl_initialized) return; #endif - texture = new RenderTexture(false, false, 1); - texture->upload(nullptr, width, height, 0, GL_RGBA, false); + texture = new RenderTexture(false, true, false, 1); + + texture->format = GL_RGBA; + texture->upload(nullptr, width, height, 0, false, false); glGenFramebuffers(1, &id); glBindFramebuffer(GL_FRAMEBUFFER, id); diff --git a/src/gl.h b/src/gl.h index ead497f..a0f044e 100644 --- a/src/gl.h +++ b/src/gl.h @@ -17,7 +17,8 @@ enum RenderObjType { DEFAULT, UV_SCALE, - OBJECT + OBJECT, + OBJECT_FLIPPED }; enum UniformType @@ -68,13 +69,21 @@ class RenderShader class RenderTexture { public: - RenderTexture(bool interp, bool clamp_uv, s32 mm_count); + RenderTexture(bool no_interp, bool clamp_uv, bool filtering, s32 mm_count); ~RenderTexture(); u32 id = 0; + f32 width; + f32 height; + + s32 format; + + std::vector pixels; + void bind(int index); - void upload(byte *data, s32 width, s32 height, s32 level, u32 format, bool scale, bool dxt = false); + void upload(byte *data, s32 width, s32 height, s32 level, + bool dxt = false, bool scale = true); }; class RenderFramebuffer diff --git a/src/mauri.cc b/src/mauri.cc index 83e811f..7871a52 100644 --- a/src/mauri.cc +++ b/src/mauri.cc @@ -33,8 +33,8 @@ s32 main(s32 argc, char *argv[]) //Context *context = new ContextX11(2560, 1440, "mauri", true); //Context *context = new ContextGLFW(720, 1280, "mauri", false); - //Context *context = new ContextGLFW(1920, 1080, "mauri", false); - Context *context = new ContextGLFW(720, 1280, "mauri", false); + Context *context = new ContextGLFW(1920, 1080, "mauri", false); + //Context *context = new ContextGLFW(720, 1280, "mauri", false); //Context *context = new ContextX11(1920, 1080, "mauri", false); //Context *context = new ContextNull(1920, 1080, "mauri", false); @@ -54,6 +54,8 @@ s32 main(s32 argc, char *argv[]) Engine engine(scene, context, &parser, true); + //asset_manager()->write_files("./output"); + engine.run(); delete scene; diff --git a/src/objects/model.cc b/src/objects/model.cc index 68aa04b..7fac34b 100644 --- a/src/objects/model.cc +++ b/src/objects/model.cc @@ -4,6 +4,7 @@ #include "objects/material.h" #include "objects/model.h" +#include "objects/pass.h" using namespace Mauri; diff --git a/src/objects/object.cc b/src/objects/object.cc index a0e4485..ab6d7d1 100644 --- a/src/objects/object.cc +++ b/src/objects/object.cc @@ -160,9 +160,11 @@ void Object::load(Engine *engine) ortho = glm::ortho(-size[0], size[0], -size[1], size[1], 0.f, 1.f); - gl_object = new RenderObject(OBJECT, size[0], size[1]); gl_uv_object = new RenderObject(UV_SCALE, size[0], size[1]); + gl_object = new RenderObject(OBJECT, size[0], size[1]); + gl_object_flipped = new RenderObject(OBJECT_FLIPPED, size[0], size[1]); + if (image != nullptr) { image->load(engine, this); @@ -206,7 +208,7 @@ void Object::draw(Engine *engine) { for (auto &dep : deps) { - engine->scene->get_object_by_id(dep)->draw(engine); + //engine->scene->get_object_by_id(dep)->draw(engine); } #if FRAME_STEP diff --git a/src/objects/object.h b/src/objects/object.h index 5ca7702..138c6e0 100644 --- a/src/objects/object.h +++ b/src/objects/object.h @@ -48,7 +48,9 @@ class Object mat4x4 model; RenderObject *gl_uv_object = nullptr; + RenderObject *gl_object = nullptr; + RenderObject *gl_object_flipped = nullptr; s32 color_blend_mode; diff --git a/src/objects/pass.cc b/src/objects/pass.cc index 2301321..00a5eae 100644 --- a/src/objects/pass.cc +++ b/src/objects/pass.cc @@ -78,6 +78,13 @@ Pass::Pass(Parser &p, json &root, PassStage stage) auto _textures = root["textures"]; + /* + if (_textures.is_array()) + { + textures.fill("null"); + } + */ + for (int i = 0; i < _textures.size(); i++) { auto texture = _textures[i]; @@ -197,7 +204,7 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) shader = new Shader(engine->parser, pass->shader); - for (int i = 0; i < MAX_TEXTURES; i++) + for (int i = 0; i < shader->texture_count; i++) { if (!shader->textures[i].empty()) { @@ -296,7 +303,14 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) else if (combine) { model = &pass->object->model; - robject = pass->object->gl_uv_object; + if (textures[0]->is_gif) + { + robject = pass->object->gl_object_flipped; + } + else + { + robject = pass->object->gl_uv_object; + } } // The object with UV's that scale the texture @@ -305,7 +319,14 @@ RenderPass::RenderPass(Engine *engine, Pass *pass) else { model = &pass->object->ortho; - robject = pass->object->gl_uv_object; + if (textures[0]->is_gif) + { + robject = pass->object->gl_object_flipped; + } + else + { + robject = pass->object->gl_uv_object; + } } } else diff --git a/src/objects/pass.h b/src/objects/pass.h index 75e5563..ad645bf 100644 --- a/src/objects/pass.h +++ b/src/objects/pass.h @@ -81,6 +81,8 @@ class RenderPass Shader *shader = nullptr; + std::array textures = {0}; + void draw(Engine *engine); private: @@ -93,8 +95,6 @@ class RenderPass mat4x4 *model; RenderObject *robject; - - std::array textures = {0}; }; } // namespace Mauri diff --git a/src/objects/scene.cc b/src/objects/scene.cc index 97b9f58..b39921c 100644 --- a/src/objects/scene.cc +++ b/src/objects/scene.cc @@ -75,8 +75,8 @@ void Scene::draw(Engine *engine) { for (auto &object : objects) { - if (object->loaded_as_dep) - continue; + //if (object->loaded_as_dep) + // continue; object->draw(engine); } } diff --git a/src/texture.cc b/src/texture.cc index e4a848b..04ebcce 100644 --- a/src/texture.cc +++ b/src/texture.cc @@ -2,6 +2,9 @@ #define STB_IMAGE_IMPLEMENTATION #include +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include + #include #include @@ -16,12 +19,6 @@ using namespace Mauri; -static byte *load_image_rgba(byte *data, s32 len) -{ - s32 w, h, channels; - return stbi_load_from_memory(data, len, &w, &h, &channels, 4); -} - Texture::Texture(Asset *asset) { hash = asset->hash; @@ -77,18 +74,27 @@ Texture::Texture(Asset *asset) log_error("%s", "unknown texture version"); } + textures.reserve(image_count); + for (int s = 0; s < image_count; s++) { auto mm_count = asset->read(); - // TODO this can be figured out through renderdoc - auto _texture = new RenderTexture(flags.map.NO_INTERPOLATION, flags.map.CLAMP_UV, mm_count); + textures[s] = new RenderTexture(flags.map.NO_INTERPOLATION, flags.map.CLAMP_UV, true, mm_count); + + texture = textures[s]; for (int i = 0; i < mm_count; i++) { auto mwidth = asset->read(); auto mheight = asset->read(); + if (i == 0) + { + texture->width = mwidth; + texture->height = mheight; + } + auto lz4_compressed = false; auto decompressed_byte_count = 0; @@ -108,9 +114,9 @@ Texture::Texture(Asset *asset) if (lz4_compressed) { auto decompressed = new char[decompressed_byte_count]; - LZ4_decompress_safe(reinterpret_cast(buffer), decompressed, + LZ4_decompress_safe((char *)buffer, decompressed, byte_count, decompressed_byte_count); - buffer = reinterpret_cast(decompressed); + buffer = (byte *)decompressed; } if (iformat == -1) @@ -118,32 +124,36 @@ Texture::Texture(Asset *asset) switch (format) { case RGBA8888: { - _texture->upload(buffer, mwidth, mheight, i, GL_RGBA, true); + texture->format = GL_RGBA; + texture->upload(buffer, mwidth, mheight, i); break; } case DXT5: { auto decompressed = new u32[decompressed_byte_count]; BlockDecompressImageDXT5(mwidth, mheight, buffer, decompressed); - _texture->upload(reinterpret_cast(decompressed), - mwidth, mheight, i, GL_RGBA, true, true); + texture->format = GL_RGBA; + texture->upload((byte *)decompressed, mwidth, mheight, i, true); delete[] decompressed; break; } case DXT1: { auto decompressed = new u32[decompressed_byte_count * 2]; BlockDecompressImageDXT1(mwidth, mheight, buffer, decompressed); - _texture->upload(reinterpret_cast(decompressed), - mwidth, mheight, i, GL_RGBA, true, true); + texture->format = GL_RGBA; + texture->upload((byte *)decompressed, mwidth, mheight, i, true); delete[] decompressed; break; } case DXT3: + log_warn("%s", "DXT3 Texture"); break; case RG88: - _texture->upload(buffer, mwidth, mheight, i, GL_RG, true); + texture->format = GL_RG; + texture->upload(buffer, mwidth, mheight, i); break; case R8: - _texture->upload(buffer, mwidth, mheight, i, GL_RED, true); + texture->format = GL_RED; + texture->upload(buffer, mwidth, mheight, i); break; default: log_warn("%s", "Uknown Texture"); @@ -152,8 +162,10 @@ Texture::Texture(Asset *asset) } else { - auto data = load_image_rgba(buffer, decompressed_byte_count); - _texture->upload(data, mwidth, mheight, i, GL_RGBA, true); + s32 w, h, channels; + byte *data = stbi_load_from_memory(buffer, byte_count, &w, &h, &channels, 4); + texture->format = GL_RGBA; + texture->upload(data, mwidth, mheight, i); free(data); } @@ -161,12 +173,11 @@ Texture::Texture(Asset *asset) delete[] buffer; asset->seek(byte_count); - } - textures.push_back(_texture); + } } - texture = textures[0]; + texture = textures.front(); if (is_gif) { @@ -200,9 +211,16 @@ Texture::Texture(Asset *asset) asset->reset(); } +void Texture::save_to_file(const std::string &filename) +{ + stbi_write_png(filename.c_str(), texture->width, texture->height, + 4, texture->pixels.data(), 4 * texture->width); +} + void Texture::update(f32 time) { - if (!is_gif || wrapped) return; + if (!is_gif || wrapped) + return; if (time >= gif_update) { @@ -210,13 +228,16 @@ void Texture::update(f32 time) texture = textures[frame->id]; - texture_rotation[0] = 0.06201; + // Scale texture cordinates to size of one frame. + texture_rotation[0] = frame->width / texture->width; texture_rotation[1] = 0.0; texture_rotation[2] = 0.0; - texture_rotation[3] = 0.06885; + texture_rotation[3] = frame->height / texture->height; - texture_translation[0] = 0.74414; - texture_translation[1] = 0.61963; + // Offset texture cordinates to the current frame + // in the spritesheet. + texture_translation[0] = frame->x / texture->width; + texture_translation[1] = frame->y / texture->height; gif_frame_index++; diff --git a/src/texture.h b/src/texture.h index c379c8d..058c947 100644 --- a/src/texture.h +++ b/src/texture.h @@ -62,8 +62,8 @@ class Texture s32 height; union { - TextureFlags map; u32 i; + TextureFlags map; } flags; u64 hash; @@ -84,7 +84,7 @@ class Texture vec4 texture_resolution; vec2 texture_translation; - vec4 texture_rotation = vec4(0.f); + vec4 texture_rotation; RenderTexture *texture; @@ -92,6 +92,8 @@ class Texture void bind(s32 index); void update(f32 time); + void save_pixels(byte *buffer, s32 mwidth, s32 mheight); + void save_to_file(const std::string &filename); }; } // namespace Mauri -- cgit v1.2.3-101-g0448