summaryrefslogtreecommitdiff
path: root/gfx
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-04-29 18:50:02 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-04-29 18:50:02 +0100
commit4fb3a5ae0f53a6fa3f4901f92e64f1de8d2dbb17 (patch)
tree6f4bd0c999e3b4a11410aed234622e80842261ad /gfx
parentLookup material details once in the vertex shader (diff)
downloadilt-4fb3a5ae0f53a6fa3f4901f92e64f1de8d2dbb17.tar.bz2
ilt-4fb3a5ae0f53a6fa3f4901f92e64f1de8d2dbb17.tar.xz
ilt-4fb3a5ae0f53a6fa3f4901f92e64f1de8d2dbb17.zip
Dunno how, but some DOS new lines got in here!
Diffstat (limited to 'gfx')
-rw-r--r--gfx/gl/camera.h156
-rw-r--r--gfx/models/mesh.cpp84
-rw-r--r--gfx/models/mesh.h50
-rw-r--r--gfx/models/texture.cpp300
-rw-r--r--gfx/models/texture.h122
5 files changed, 356 insertions, 356 deletions
diff --git a/gfx/gl/camera.h b/gfx/gl/camera.h
index b5611f8..5c168e7 100644
--- a/gfx/gl/camera.h
+++ b/gfx/gl/camera.h
@@ -1,78 +1,78 @@
-#pragma once
-
-#include <glm/glm.hpp>
-#include <maths.h>
-#include <ray.hpp>
-
-class Camera {
-public:
- Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar);
-
- [[nodiscard]] glm::mat4
- getViewProjection() const
- {
- return viewProjection;
- }
- [[nodiscard]] Ray unProject(const glm::vec2 &) const;
-
- void
- setPosition(const glm::vec3 & p)
- {
- position = p;
- updateView();
- }
- void
- setForward(const glm::vec3 & f)
- {
- setForward(f, upFromForward(f));
- }
- void
- setForward(const glm::vec3 & f, const glm::vec3 & u)
- {
- forward = f;
- up = u;
- updateView();
- }
- void
- setView(const glm::vec3 & p, const glm::vec3 & f)
- {
- position = p;
- setForward(f);
- }
- void
- setView(const glm::vec3 & p, const glm::vec3 & f, const glm::vec3 & u)
- {
- position = p;
- setView(f, u);
- }
- void
- lookAt(const glm::vec3 & target)
- {
- setForward(glm::normalize(target - position));
- }
- [[nodiscard]] auto
- getForward() const
- {
- return forward;
- }
- [[nodiscard]] auto
- getPosition() const
- {
- return position;
- }
-
- [[nodiscard]] std::array<glm::vec4, 4> extentsAtDist(float) const;
-
- [[nodiscard]] static glm::vec3 upFromForward(const glm::vec3 & forward);
-
-private:
- void updateView();
-
- glm::vec3 position;
- glm::vec3 forward;
- glm::vec3 up;
-
- float near, far;
- glm::mat4 projection;
- glm::mat4 viewProjection, inverseViewProjection;
-};
+#pragma once
+
+#include <glm/glm.hpp>
+#include <maths.h>
+#include <ray.hpp>
+
+class Camera {
+public:
+ Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar);
+
+ [[nodiscard]] glm::mat4
+ getViewProjection() const
+ {
+ return viewProjection;
+ }
+ [[nodiscard]] Ray unProject(const glm::vec2 &) const;
+
+ void
+ setPosition(const glm::vec3 & p)
+ {
+ position = p;
+ updateView();
+ }
+ void
+ setForward(const glm::vec3 & f)
+ {
+ setForward(f, upFromForward(f));
+ }
+ void
+ setForward(const glm::vec3 & f, const glm::vec3 & u)
+ {
+ forward = f;
+ up = u;
+ updateView();
+ }
+ void
+ setView(const glm::vec3 & p, const glm::vec3 & f)
+ {
+ position = p;
+ setForward(f);
+ }
+ void
+ setView(const glm::vec3 & p, const glm::vec3 & f, const glm::vec3 & u)
+ {
+ position = p;
+ setView(f, u);
+ }
+ void
+ lookAt(const glm::vec3 & target)
+ {
+ setForward(glm::normalize(target - position));
+ }
+ [[nodiscard]] auto
+ getForward() const
+ {
+ return forward;
+ }
+ [[nodiscard]] auto
+ getPosition() const
+ {
+ return position;
+ }
+
+ [[nodiscard]] std::array<glm::vec4, 4> extentsAtDist(float) const;
+
+ [[nodiscard]] static glm::vec3 upFromForward(const glm::vec3 & forward);
+
+private:
+ void updateView();
+
+ glm::vec3 position;
+ glm::vec3 forward;
+ glm::vec3 up;
+
+ float near, far;
+ glm::mat4 projection;
+ glm::mat4 viewProjection, inverseViewProjection;
+};
diff --git a/gfx/models/mesh.cpp b/gfx/models/mesh.cpp
index 52c9275..7c5ddd4 100644
--- a/gfx/models/mesh.cpp
+++ b/gfx/models/mesh.cpp
@@ -1,42 +1,42 @@
-#include "mesh.h"
-#include "gfx/gl/vertexArrayObject.hpp"
-#include "glArrays.h"
-#include "vertex.hpp"
-#include <cstddef>
-
-Mesh::Mesh(const std::span<const Vertex> vertices, const std::span<const unsigned int> indices, GLenum m) :
- m_numIndices {static_cast<GLsizei>(indices.size())}, mode {m}
-{
- VertexArrayObject::data(vertices, m_vertexArrayBuffers[0], GL_ARRAY_BUFFER);
- VertexArrayObject::data(indices, m_vertexArrayBuffers[1], GL_ARRAY_BUFFER);
- configureVAO(m_vertexArrayObject);
-}
-
-VertexArrayObject &
-Mesh::configureVAO(VertexArrayObject && vao) const
-{
- return vao
- .addAttribs<Vertex, &Vertex::pos, &Vertex::texCoord, &Vertex::normal, &Vertex::colour, &Vertex::material>(
- m_vertexArrayBuffers[0])
- .addIndices(m_vertexArrayBuffers[1]);
-}
-
-void
-Mesh::Draw() const
-{
- glBindVertexArray(m_vertexArrayObject);
-
- glDrawElements(mode, m_numIndices, GL_UNSIGNED_INT, nullptr);
-
- glBindVertexArray(0);
-}
-
-void
-Mesh::DrawInstanced(GLuint vao, GLsizei count) const
-{
- glBindVertexArray(vao);
-
- glDrawElementsInstanced(mode, m_numIndices, GL_UNSIGNED_INT, nullptr, count);
-
- glBindVertexArray(0);
-}
+#include "mesh.h"
+#include "gfx/gl/vertexArrayObject.hpp"
+#include "glArrays.h"
+#include "vertex.hpp"
+#include <cstddef>
+
+Mesh::Mesh(const std::span<const Vertex> vertices, const std::span<const unsigned int> indices, GLenum m) :
+ m_numIndices {static_cast<GLsizei>(indices.size())}, mode {m}
+{
+ VertexArrayObject::data(vertices, m_vertexArrayBuffers[0], GL_ARRAY_BUFFER);
+ VertexArrayObject::data(indices, m_vertexArrayBuffers[1], GL_ARRAY_BUFFER);
+ configureVAO(m_vertexArrayObject);
+}
+
+VertexArrayObject &
+Mesh::configureVAO(VertexArrayObject && vao) const
+{
+ return vao
+ .addAttribs<Vertex, &Vertex::pos, &Vertex::texCoord, &Vertex::normal, &Vertex::colour, &Vertex::material>(
+ m_vertexArrayBuffers[0])
+ .addIndices(m_vertexArrayBuffers[1]);
+}
+
+void
+Mesh::Draw() const
+{
+ glBindVertexArray(m_vertexArrayObject);
+
+ glDrawElements(mode, m_numIndices, GL_UNSIGNED_INT, nullptr);
+
+ glBindVertexArray(0);
+}
+
+void
+Mesh::DrawInstanced(GLuint vao, GLsizei count) const
+{
+ glBindVertexArray(vao);
+
+ glDrawElementsInstanced(mode, m_numIndices, GL_UNSIGNED_INT, nullptr, count);
+
+ glBindVertexArray(0);
+}
diff --git a/gfx/models/mesh.h b/gfx/models/mesh.h
index 538c57a..9b22b02 100644
--- a/gfx/models/mesh.h
+++ b/gfx/models/mesh.h
@@ -1,25 +1,25 @@
-#pragma once
-
-#include <GL/glew.h>
-#include <glArrays.h>
-#include <memory>
-#include <span>
-#include <stdTypeDefs.hpp>
-
-class Vertex;
-class VertexArrayObject;
-
-class Mesh : public ConstTypeDefs<Mesh> {
-public:
- Mesh(const std::span<const Vertex> vertices, const std::span<const unsigned int> indices, GLenum = GL_TRIANGLES);
-
- void Draw() const;
- void DrawInstanced(GLuint vao, GLsizei count) const;
- VertexArrayObject & configureVAO(VertexArrayObject &&) const;
-
-private:
- glVertexArray m_vertexArrayObject;
- glBuffers<2> m_vertexArrayBuffers;
- GLsizei m_numIndices;
- GLenum mode;
-};
+#pragma once
+
+#include <GL/glew.h>
+#include <glArrays.h>
+#include <memory>
+#include <span>
+#include <stdTypeDefs.hpp>
+
+class Vertex;
+class VertexArrayObject;
+
+class Mesh : public ConstTypeDefs<Mesh> {
+public:
+ Mesh(const std::span<const Vertex> vertices, const std::span<const unsigned int> indices, GLenum = GL_TRIANGLES);
+
+ void Draw() const;
+ void DrawInstanced(GLuint vao, GLsizei count) const;
+ VertexArrayObject & configureVAO(VertexArrayObject &&) const;
+
+private:
+ glVertexArray m_vertexArrayObject;
+ glBuffers<2> m_vertexArrayBuffers;
+ GLsizei m_numIndices;
+ GLenum mode;
+};
diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp
index e014f80..3003319 100644
--- a/gfx/models/texture.cpp
+++ b/gfx/models/texture.cpp
@@ -1,150 +1,150 @@
-#include "texture.h"
-#include "glArrays.h"
-#include "tga.h"
-#include <GL/glew.h>
-#include <cache.h>
-#include <fcntl.h>
-#include <filesystem.h>
-#include <gfx/image.h>
-#include <glm/geometric.hpp>
-#include <resource.h>
-#include <stb/stb_image.h>
-#include <sys/mman.h>
-
-Cache<Texture, std::filesystem::path> Texture::cachedTexture;
-
-GLint
-TextureOptions::glMapMode(TextureOptions::MapMode mm)
-{
- switch (mm) {
- case MapMode::Repeat:
- return GL_REPEAT;
- case MapMode::Clamp:
- return GL_CLAMP_TO_EDGE;
- case MapMode::Mirror:
- return GL_MIRRORED_REPEAT;
- default:
- throw std::domain_error("Invalid MapMode value");
- }
-}
-
-Texture::Texture(const std::filesystem::path & fileName, TextureOptions to) :
- Texture {Image {Resource::mapPath(fileName).c_str(), STBI_rgb_alpha}, to}
-{
-}
-
-Texture::Texture(const Image & tex, TextureOptions to) :
- Texture {static_cast<GLsizei>(tex.width), static_cast<GLsizei>(tex.height), tex.data.data(), to}
-{
-}
-
-Texture::Texture(GLsizei width, GLsizei height, TextureOptions to) : Texture {width, height, nullptr, to} { }
-
-Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOptions to) : type {to.type}
-{
- glBindTexture(type, m_texture);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- glTexParameteri(type, GL_TEXTURE_WRAP_S, TextureOptions::glMapMode(to.wrapU));
- glTexParameteri(type, GL_TEXTURE_WRAP_T, TextureOptions::glMapMode(to.wrapV));
-
- glTexParameteri(type, GL_TEXTURE_MIN_FILTER, to.minFilter);
- glTexParameteri(type, GL_TEXTURE_MAG_FILTER, to.magFilter);
- glTexImage2D(type, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-}
-
-void
-Texture::bind(GLenum unit) const
-{
- glActiveTexture(unit);
- glBindTexture(type, m_texture);
-}
-
-glm::ivec2
-Texture::getSize(const glTexture & texture)
-{
- glm::ivec2 size;
- glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_WIDTH, &size.x);
- glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_HEIGHT, &size.y);
- return size;
-}
-
-void
-Texture::save(
- const glTexture & texture, GLenum format, GLenum type, uint8_t channels, const char * path, uint8_t tgaFormat)
-{
- const auto size = getSize(texture);
- const size_t dataSize = (static_cast<size_t>(size.x * size.y * channels));
- const size_t fileSize = dataSize + sizeof(TGAHead);
-
- filesystem::fh out {path, O_RDWR | O_CREAT, 0660};
- out.truncate(fileSize);
- auto tga = out.mmap(fileSize, 0, PROT_WRITE, MAP_SHARED);
- *tga.get<TGAHead>() = {
- .format = tgaFormat,
- .size = size,
- .pixelDepth = static_cast<uint8_t>(8 * channels),
- };
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glGetTextureImage(texture, 0, format, type, static_cast<GLsizei>(dataSize), tga.get<TGAHead>() + 1);
- tga.msync(MS_ASYNC);
-}
-
-void
-Texture::save(const char * path) const
-{
- save(m_texture, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2);
-}
-
-void
-Texture::save(const glTexture & texture, const char * path)
-{
- save(texture, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2);
-}
-
-void
-Texture::saveDepth(const glTexture & texture, const char * path)
-{
- save(texture, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 1, path, 3);
-}
-
-void
-Texture::saveNormal(const glTexture & texture, const char * path)
-{
- save(texture, GL_BGR, GL_BYTE, 3, path, 2);
-}
-
-TextureAtlas::TextureAtlas(GLsizei width, GLsizei height, GLuint count) : Texture(width, height, nullptr, {})
-{
- glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas);
-
- glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA16UI, 2, static_cast<GLsizei>(count), 0, GL_RGBA_INTEGER,
- GL_UNSIGNED_BYTE, nullptr);
-}
-
-void
-TextureAtlas::bind(GLenum unit) const
-{
- Texture::bind(unit);
- glActiveTexture(unit + 1);
- glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas);
-}
-
-GLuint
-TextureAtlas::add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions to)
-{
- glTextureSubImage2D(m_texture, 0, position.x, position.y, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, data);
- struct Material {
- glm::vec<2, uint16_t> position, size;
- TextureOptions::MapMode wrapU;
- TextureOptions::MapMode wrapV;
- } material {position, size, to.wrapU, to.wrapV};
- static_assert(sizeof(Material) <= 32);
- glTextureSubImage2D(m_atlas, 0, 0, static_cast<GLsizei>(used), 2, 1, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, &material);
- return ++used;
-}
+#include "texture.h"
+#include "glArrays.h"
+#include "tga.h"
+#include <GL/glew.h>
+#include <cache.h>
+#include <fcntl.h>
+#include <filesystem.h>
+#include <gfx/image.h>
+#include <glm/geometric.hpp>
+#include <resource.h>
+#include <stb/stb_image.h>
+#include <sys/mman.h>
+
+Cache<Texture, std::filesystem::path> Texture::cachedTexture;
+
+GLint
+TextureOptions::glMapMode(TextureOptions::MapMode mm)
+{
+ switch (mm) {
+ case MapMode::Repeat:
+ return GL_REPEAT;
+ case MapMode::Clamp:
+ return GL_CLAMP_TO_EDGE;
+ case MapMode::Mirror:
+ return GL_MIRRORED_REPEAT;
+ default:
+ throw std::domain_error("Invalid MapMode value");
+ }
+}
+
+Texture::Texture(const std::filesystem::path & fileName, TextureOptions to) :
+ Texture {Image {Resource::mapPath(fileName).c_str(), STBI_rgb_alpha}, to}
+{
+}
+
+Texture::Texture(const Image & tex, TextureOptions to) :
+ Texture {static_cast<GLsizei>(tex.width), static_cast<GLsizei>(tex.height), tex.data.data(), to}
+{
+}
+
+Texture::Texture(GLsizei width, GLsizei height, TextureOptions to) : Texture {width, height, nullptr, to} { }
+
+Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOptions to) : type {to.type}
+{
+ glBindTexture(type, m_texture);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glTexParameteri(type, GL_TEXTURE_WRAP_S, TextureOptions::glMapMode(to.wrapU));
+ glTexParameteri(type, GL_TEXTURE_WRAP_T, TextureOptions::glMapMode(to.wrapV));
+
+ glTexParameteri(type, GL_TEXTURE_MIN_FILTER, to.minFilter);
+ glTexParameteri(type, GL_TEXTURE_MAG_FILTER, to.magFilter);
+ glTexImage2D(type, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+}
+
+void
+Texture::bind(GLenum unit) const
+{
+ glActiveTexture(unit);
+ glBindTexture(type, m_texture);
+}
+
+glm::ivec2
+Texture::getSize(const glTexture & texture)
+{
+ glm::ivec2 size;
+ glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_WIDTH, &size.x);
+ glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_HEIGHT, &size.y);
+ return size;
+}
+
+void
+Texture::save(
+ const glTexture & texture, GLenum format, GLenum type, uint8_t channels, const char * path, uint8_t tgaFormat)
+{
+ const auto size = getSize(texture);
+ const size_t dataSize = (static_cast<size_t>(size.x * size.y * channels));
+ const size_t fileSize = dataSize + sizeof(TGAHead);
+
+ filesystem::fh out {path, O_RDWR | O_CREAT, 0660};
+ out.truncate(fileSize);
+ auto tga = out.mmap(fileSize, 0, PROT_WRITE, MAP_SHARED);
+ *tga.get<TGAHead>() = {
+ .format = tgaFormat,
+ .size = size,
+ .pixelDepth = static_cast<uint8_t>(8 * channels),
+ };
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glGetTextureImage(texture, 0, format, type, static_cast<GLsizei>(dataSize), tga.get<TGAHead>() + 1);
+ tga.msync(MS_ASYNC);
+}
+
+void
+Texture::save(const char * path) const
+{
+ save(m_texture, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2);
+}
+
+void
+Texture::save(const glTexture & texture, const char * path)
+{
+ save(texture, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2);
+}
+
+void
+Texture::saveDepth(const glTexture & texture, const char * path)
+{
+ save(texture, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 1, path, 3);
+}
+
+void
+Texture::saveNormal(const glTexture & texture, const char * path)
+{
+ save(texture, GL_BGR, GL_BYTE, 3, path, 2);
+}
+
+TextureAtlas::TextureAtlas(GLsizei width, GLsizei height, GLuint count) : Texture(width, height, nullptr, {})
+{
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas);
+
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA16UI, 2, static_cast<GLsizei>(count), 0, GL_RGBA_INTEGER,
+ GL_UNSIGNED_BYTE, nullptr);
+}
+
+void
+TextureAtlas::bind(GLenum unit) const
+{
+ Texture::bind(unit);
+ glActiveTexture(unit + 1);
+ glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas);
+}
+
+GLuint
+TextureAtlas::add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions to)
+{
+ glTextureSubImage2D(m_texture, 0, position.x, position.y, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ struct Material {
+ glm::vec<2, uint16_t> position, size;
+ TextureOptions::MapMode wrapU;
+ TextureOptions::MapMode wrapV;
+ } material {position, size, to.wrapU, to.wrapV};
+ static_assert(sizeof(Material) <= 32);
+ glTextureSubImage2D(m_atlas, 0, 0, static_cast<GLsizei>(used), 2, 1, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, &material);
+ return ++used;
+}
diff --git a/gfx/models/texture.h b/gfx/models/texture.h
index 86e76a0..1b66c64 100644
--- a/gfx/models/texture.h
+++ b/gfx/models/texture.h
@@ -1,61 +1,61 @@
-#pragma once
-
-#include <cache.h>
-#include <filesystem>
-#include <glArrays.h>
-#include <glm/fwd.hpp>
-
-// IWYU pragma: no_forward_declare Cache
-class Image;
-
-struct TextureOptions {
- enum class MapMode {
- Repeat,
- Clamp,
- Mirror,
- Decal,
- };
- MapMode wrapU {MapMode::Repeat}, wrapV {MapMode::Repeat};
- GLint minFilter {GL_LINEAR}, magFilter {GL_LINEAR};
- GLenum type {GL_TEXTURE_2D};
- static GLint glMapMode(MapMode);
-};
-
-class Texture {
-public:
- virtual ~Texture() = default;
- DEFAULT_MOVE_NO_COPY(Texture);
-
- explicit Texture(const std::filesystem::path & fileName, TextureOptions = {});
- explicit Texture(const Image & image, TextureOptions = {});
- explicit Texture(GLsizei width, GLsizei height, TextureOptions = {});
- explicit Texture(GLsizei width, GLsizei height, const void * data, TextureOptions = {});
-
- static Cache<Texture, std::filesystem::path> cachedTexture;
-
- virtual void bind(GLenum unit = GL_TEXTURE0) const;
-
- void save(const char * path) const;
- static void save(const glTexture &, const char * path);
- static void saveDepth(const glTexture &, const char * path);
- static void saveNormal(const glTexture &, const char * path);
-
-protected:
- static void save(const glTexture &, GLenum, GLenum, uint8_t channels, const char * path, uint8_t tgaFormat);
- static glm::ivec2 getSize(const glTexture &);
-
- glTexture m_texture;
- GLenum type;
-};
-
-class TextureAtlas : public Texture {
-public:
- TextureAtlas(GLsizei width, GLsizei height, GLuint count);
-
- void bind(GLenum unit = GL_TEXTURE0) const override;
- GLuint add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions = {});
-
-private:
- glTexture m_atlas;
- GLuint used {};
-};
+#pragma once
+
+#include <cache.h>
+#include <filesystem>
+#include <glArrays.h>
+#include <glm/fwd.hpp>
+
+// IWYU pragma: no_forward_declare Cache
+class Image;
+
+struct TextureOptions {
+ enum class MapMode {
+ Repeat,
+ Clamp,
+ Mirror,
+ Decal,
+ };
+ MapMode wrapU {MapMode::Repeat}, wrapV {MapMode::Repeat};
+ GLint minFilter {GL_LINEAR}, magFilter {GL_LINEAR};
+ GLenum type {GL_TEXTURE_2D};
+ static GLint glMapMode(MapMode);
+};
+
+class Texture {
+public:
+ virtual ~Texture() = default;
+ DEFAULT_MOVE_NO_COPY(Texture);
+
+ explicit Texture(const std::filesystem::path & fileName, TextureOptions = {});
+ explicit Texture(const Image & image, TextureOptions = {});
+ explicit Texture(GLsizei width, GLsizei height, TextureOptions = {});
+ explicit Texture(GLsizei width, GLsizei height, const void * data, TextureOptions = {});
+
+ static Cache<Texture, std::filesystem::path> cachedTexture;
+
+ virtual void bind(GLenum unit = GL_TEXTURE0) const;
+
+ void save(const char * path) const;
+ static void save(const glTexture &, const char * path);
+ static void saveDepth(const glTexture &, const char * path);
+ static void saveNormal(const glTexture &, const char * path);
+
+protected:
+ static void save(const glTexture &, GLenum, GLenum, uint8_t channels, const char * path, uint8_t tgaFormat);
+ static glm::ivec2 getSize(const glTexture &);
+
+ glTexture m_texture;
+ GLenum type;
+};
+
+class TextureAtlas : public Texture {
+public:
+ TextureAtlas(GLsizei width, GLsizei height, GLuint count);
+
+ void bind(GLenum unit = GL_TEXTURE0) const override;
+ GLuint add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions = {});
+
+private:
+ glTexture m_atlas;
+ GLuint used {};
+};