diff options
-rw-r--r-- | gfx/gl/camera.h | 156 | ||||
-rw-r--r-- | gfx/models/mesh.cpp | 84 | ||||
-rw-r--r-- | gfx/models/mesh.h | 50 | ||||
-rw-r--r-- | gfx/models/texture.cpp | 300 | ||||
-rw-r--r-- | gfx/models/texture.h | 122 | ||||
-rw-r--r-- | ui/icon.cpp | 60 | ||||
-rw-r--r-- | ui/icon.h | 38 | ||||
-rw-r--r-- | ui/window.cpp | 166 | ||||
-rw-r--r-- | ui/window.h | 88 |
9 files changed, 532 insertions, 532 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 {}; +}; diff --git a/ui/icon.cpp b/ui/icon.cpp index ee88317..be1a63c 100644 --- a/ui/icon.cpp +++ b/ui/icon.cpp @@ -1,30 +1,30 @@ -#include "icon.h"
-#include "glArrays.h"
-#include <GL/glew.h>
-#include <gfx/image.h>
-#include <resource.h>
-#include <stb/stb_image.h>
-
-Icon::Icon(const std::filesystem::path & fileName) : Icon {Image {Resource::mapPath(fileName).c_str(), STBI_rgb_alpha}}
-{
-}
-
-Icon::Icon(const Image & tex) : size {tex.width, tex.height}
-{
- glBindTexture(GL_TEXTURE_2D, m_texture);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(tex.width), static_cast<GLsizei>(tex.height), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, tex.data.data());
-}
-
-void
-Icon::Bind() const
-{
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, m_texture);
-}
+#include "icon.h" +#include "glArrays.h" +#include <GL/glew.h> +#include <gfx/image.h> +#include <resource.h> +#include <stb/stb_image.h> + +Icon::Icon(const std::filesystem::path & fileName) : Icon {Image {Resource::mapPath(fileName).c_str(), STBI_rgb_alpha}} +{ +} + +Icon::Icon(const Image & tex) : size {tex.width, tex.height} +{ + glBindTexture(GL_TEXTURE_2D, m_texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(tex.width), static_cast<GLsizei>(tex.height), 0, + GL_RGBA, GL_UNSIGNED_BYTE, tex.data.data()); +} + +void +Icon::Bind() const +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_texture); +} @@ -1,19 +1,19 @@ -#pragma once
-
-#include <filesystem>
-#include <glArrays.h>
-#include <glm/glm.hpp>
-
-class Image;
-
-class Icon {
-public:
- explicit Icon(const std::filesystem::path & fileName);
- explicit Icon(const Image & image);
-
- void Bind() const;
- const glm::vec2 size;
-
-private:
- glTexture m_texture;
-};
+#pragma once + +#include <filesystem> +#include <glArrays.h> +#include <glm/glm.hpp> + +class Image; + +class Icon { +public: + explicit Icon(const std::filesystem::path & fileName); + explicit Icon(const Image & image); + + void Bind() const; + const glm::vec2 size; + +private: + glTexture m_texture; +}; diff --git a/ui/window.cpp b/ui/window.cpp index 5930292..ad071bb 100644 --- a/ui/window.cpp +++ b/ui/window.cpp @@ -1,83 +1,83 @@ -#include "window.h"
-#include "uiComponent.h"
-#include "worldOverlay.h"
-#include <GL/glew.h>
-#include <glm/glm.hpp>
-#include <stdexcept>
-#include <tuple>
-#include <type_traits>
-
-Window::GlewInitHelper::GlewInitHelper()
-{
- [[maybe_unused]] static auto init = []() {
- if (const auto r = glewInit(); r != GLEW_OK) {
- throw std::runtime_error {reinterpret_cast<const char *>(glewGetErrorString(r))};
- }
- else {
- return r;
- }
- }();
-}
-
-Window::Window(size_t width, size_t height, const std::string & title, Uint32 flags) :
- size {static_cast<int>(width), static_cast<int>(height)}, m_window {title.c_str(),
- static_cast<int>(SDL_WINDOWPOS_CENTERED),
- static_cast<int>(SDL_WINDOWPOS_CENTERED), size.x,
- size.y, flags},
- glContext {m_window}, uiShader {width, height}
-{
-}
-
-void
-Window::clear(float r, float g, float b, float a) const
-{
- glClearColor(r, g, b, a);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-void
-Window::swapBuffers() const
-{
- SDL_GL_SwapWindow(m_window);
-}
-
-bool
-Window::handleInput(const SDL_Event & e)
-{
- if (SDL_GetWindowID(m_window) == e.window.windowID) {
- SDL_Event eAdjusted {e};
- switch (e.type) {
- // SDL and OpenGL have coordinates that are vertically opposed.
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- eAdjusted.button.y = size.y - e.button.y;
- break;
- case SDL_MOUSEMOTION:
- eAdjusted.motion.y = size.y - e.motion.y;
- break;
- }
- uiComponents.rapplyOne(&UIComponent::handleInput, eAdjusted, UIComponent::Position {{}, size});
- return true;
- }
- return false;
-}
-
-void
-Window::refresh() const
-{
- SDL_GL_MakeCurrent(m_window, glContext);
- clear(0.0F, 0.0F, 0.0F, 1.0F);
-
- render();
-
- swapBuffers();
-}
-
-void
-Window::render() const
-{
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_DEPTH_TEST);
- uiComponents.apply(&UIComponent::render, uiShader, UIComponent::Position {});
-}
+#include "window.h" +#include "uiComponent.h" +#include "worldOverlay.h" +#include <GL/glew.h> +#include <glm/glm.hpp> +#include <stdexcept> +#include <tuple> +#include <type_traits> + +Window::GlewInitHelper::GlewInitHelper() +{ + [[maybe_unused]] static auto init = []() { + if (const auto r = glewInit(); r != GLEW_OK) { + throw std::runtime_error {reinterpret_cast<const char *>(glewGetErrorString(r))}; + } + else { + return r; + } + }(); +} + +Window::Window(size_t width, size_t height, const std::string & title, Uint32 flags) : + size {static_cast<int>(width), static_cast<int>(height)}, m_window {title.c_str(), + static_cast<int>(SDL_WINDOWPOS_CENTERED), + static_cast<int>(SDL_WINDOWPOS_CENTERED), size.x, + size.y, flags}, + glContext {m_window}, uiShader {width, height} +{ +} + +void +Window::clear(float r, float g, float b, float a) const +{ + glClearColor(r, g, b, a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void +Window::swapBuffers() const +{ + SDL_GL_SwapWindow(m_window); +} + +bool +Window::handleInput(const SDL_Event & e) +{ + if (SDL_GetWindowID(m_window) == e.window.windowID) { + SDL_Event eAdjusted {e}; + switch (e.type) { + // SDL and OpenGL have coordinates that are vertically opposed. + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + eAdjusted.button.y = size.y - e.button.y; + break; + case SDL_MOUSEMOTION: + eAdjusted.motion.y = size.y - e.motion.y; + break; + } + uiComponents.rapplyOne(&UIComponent::handleInput, eAdjusted, UIComponent::Position {{}, size}); + return true; + } + return false; +} + +void +Window::refresh() const +{ + SDL_GL_MakeCurrent(m_window, glContext); + clear(0.0F, 0.0F, 0.0F, 1.0F); + + render(); + + swapBuffers(); +} + +void +Window::render() const +{ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + uiComponents.apply(&UIComponent::render, uiShader, UIComponent::Position {}); +} diff --git a/ui/window.h b/ui/window.h index cb0118a..8b7d870 100644 --- a/ui/window.h +++ b/ui/window.h @@ -1,44 +1,44 @@ -#pragma once
-
-#include "chronology.hpp"
-#include "collection.hpp"
-#include "gfx/gl/uiShader.h"
-#include "ptr.hpp"
-#include "uiComponent.h" // IWYU pragma: keep
-#include <SDL2/SDL.h>
-#include <cstddef>
-#include <special_members.hpp>
-#include <string>
-
-using SDL_WindowPtr = wrapped_ptrt<SDL_Window, SDL_CreateWindow, SDL_DestroyWindow>;
-using GL_Context = std::remove_pointer_t<SDL_GLContext>;
-using SDL_GLContextPtr = wrapped_ptrt<GL_Context, SDL_GL_CreateContext, SDL_GL_DeleteContext>;
-
-class Window {
-public:
- Window(size_t width, size_t height, const std::string & title, Uint32 flags);
- virtual ~Window() = default;
-
- NO_COPY(Window);
- NO_MOVE(Window);
-
- virtual void tick(TickDuration elapsed) = 0;
- void refresh() const;
- bool handleInput(const SDL_Event & e);
-
- void clear(float r, float g, float b, float a) const;
- void swapBuffers() const;
-
-protected:
- virtual void render() const;
- struct GlewInitHelper {
- GlewInitHelper();
- };
-
- const glm::ivec2 size;
- SDL_WindowPtr m_window;
- SDL_GLContextPtr glContext;
- GlewInitHelper glewinithelper;
- Collection<UIComponent> uiComponents;
- UIShader uiShader;
-};
+#pragma once + +#include "chronology.hpp" +#include "collection.hpp" +#include "gfx/gl/uiShader.h" +#include "ptr.hpp" +#include "uiComponent.h" // IWYU pragma: keep +#include <SDL2/SDL.h> +#include <cstddef> +#include <special_members.hpp> +#include <string> + +using SDL_WindowPtr = wrapped_ptrt<SDL_Window, SDL_CreateWindow, SDL_DestroyWindow>; +using GL_Context = std::remove_pointer_t<SDL_GLContext>; +using SDL_GLContextPtr = wrapped_ptrt<GL_Context, SDL_GL_CreateContext, SDL_GL_DeleteContext>; + +class Window { +public: + Window(size_t width, size_t height, const std::string & title, Uint32 flags); + virtual ~Window() = default; + + NO_COPY(Window); + NO_MOVE(Window); + + virtual void tick(TickDuration elapsed) = 0; + void refresh() const; + bool handleInput(const SDL_Event & e); + + void clear(float r, float g, float b, float a) const; + void swapBuffers() const; + +protected: + virtual void render() const; + struct GlewInitHelper { + GlewInitHelper(); + }; + + const glm::ivec2 size; + SDL_WindowPtr m_window; + SDL_GLContextPtr glContext; + GlewInitHelper glewinithelper; + Collection<UIComponent> uiComponents; + UIShader uiShader; +}; |