summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2020-10-27 19:38:53 -0400
committerAndrew Opalach <andrew@akon.city> 2020-10-27 19:38:53 -0400
commit99c22028164d423377a37873572cb1654756591f (patch)
tree43cd168018fa9f0d40089f0a611f43b6869ae082 /src
parent3c5f029889db977dae80455144d8a473d369a395 (diff)
downloadmauri-99c22028164d423377a37873572cb1654756591f.tar.gz
mauri-99c22028164d423377a37873572cb1654756591f.tar.bz2
mauri-99c22028164d423377a37873572cb1654756591f.zip
add write to file, finish gifs, gl fixes
Diffstat (limited to 'src')
-rw-r--r--src/assets.cc63
-rw-r--r--src/assets.h7
-rw-r--r--src/gl.cc123
-rw-r--r--src/gl.h15
-rw-r--r--src/mauri.cc6
-rw-r--r--src/objects/model.cc1
-rw-r--r--src/objects/object.cc6
-rw-r--r--src/objects/object.h2
-rw-r--r--src/objects/pass.cc27
-rw-r--r--src/objects/pass.h4
-rw-r--r--src/objects/scene.cc4
-rw-r--r--src/texture.cc75
-rw-r--r--src/texture.h6
13 files changed, 269 insertions, 70 deletions
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 <array>
+#include <filesystem>
#include <fstream>
#include <iostream>
+#include <math.h>
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<Asset *> 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<u32> 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<Texture *, MAX_TEXTURES> textures = {0};
+
void draw(Engine *engine);
private:
@@ -93,8 +95,6 @@ class RenderPass
mat4x4 *model;
RenderObject *robject;
-
- std::array<Texture *, MAX_TEXTURES> 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 <stb_image.h>
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include <stb_image_write.h>
+
#include <s3tc.h>
#include <glad/gl.h>
@@ -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<u32>();
- // 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<u32>();
auto mheight = asset->read<u32>();
+ 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<char *>(buffer), decompressed,
+ LZ4_decompress_safe((char *)buffer, decompressed,
byte_count, decompressed_byte_count);
- buffer = reinterpret_cast<byte *>(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<byte *>(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<byte *>(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