summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assetFactory/assetFactory.cpp1
-rw-r--r--game/network/rail.cpp2
-rw-r--r--game/scenary/foliage.cpp16
-rw-r--r--game/scenary/foliage.h4
-rw-r--r--game/scenary/illuminator.cpp2
-rw-r--r--game/terrain.cpp2
-rw-r--r--game/vehicles/railVehicleClass.cpp2
-rw-r--r--game/water.cpp2
-rw-r--r--gfx/gl/billboardPainter.cpp19
-rw-r--r--gfx/gl/billboardPainter.h4
-rw-r--r--gfx/gl/glTexture.cpp161
-rw-r--r--gfx/gl/glTexture.h58
-rw-r--r--gfx/gl/sceneRenderer.cpp73
-rw-r--r--gfx/gl/sceneRenderer.h3
-rw-r--r--gfx/gl/shadowMapper.cpp5
-rw-r--r--gfx/gl/shadowMapper.h4
-rw-r--r--gfx/gl/shadowStenciller.cpp13
-rw-r--r--gfx/gl/shadowStenciller.h4
-rw-r--r--gfx/models/texture.cpp86
-rw-r--r--gfx/models/texture.h19
-rw-r--r--test/test-assetFactory.cpp2
-rw-r--r--test/test-geoData.cpp2
-rw-r--r--test/test-render.cpp14
-rw-r--r--test/test-ui.cpp4
-rw-r--r--test/testRenderOutput.cpp16
-rw-r--r--test/testRenderOutput.h2
-rw-r--r--ui/editNetwork.cpp2
-rw-r--r--ui/font.cpp8
-rw-r--r--ui/font.h2
-rw-r--r--ui/icon.cpp6
-rw-r--r--ui/icon.h2
-rw-r--r--ui/svgIcon.cpp7
-rw-r--r--ui/svgIcon.h2
33 files changed, 335 insertions, 214 deletions
diff --git a/assetFactory/assetFactory.cpp b/assetFactory/assetFactory.cpp
index 426fecc..b96e527 100644
--- a/assetFactory/assetFactory.cpp
+++ b/assetFactory/assetFactory.cpp
@@ -140,6 +140,7 @@ AssetFactory::createTexutre() const
size++;
return decltype(textureFragmentPositions)::value_type {i.first->id, m};
});
+ texture->complete();
}
}
diff --git a/game/network/rail.cpp b/game/network/rail.cpp
index d0a8bdd..1ae5aca 100644
--- a/game/network/rail.cpp
+++ b/game/network/rail.cpp
@@ -169,7 +169,7 @@ void
RailLinks::render(const SceneShader & shader, const Frustum &) const
{
if (auto _ = glDebugScope(0); !links.empty()) {
- texture->bind();
+ texture->bind(0);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1, 0);
renderType<RailLinkStraight>(*this, shader.networkStraight, GL_POINTS);
diff --git a/game/scenary/foliage.cpp b/game/scenary/foliage.cpp
index bd88a06..528d3e1 100644
--- a/game/scenary/foliage.cpp
+++ b/game/scenary/foliage.cpp
@@ -43,8 +43,8 @@ Foliage::postLoad()
const auto & size = bodyMesh->getDimensions().size;
billboardSize = billboardTextureSizeForObject(size);
- ShadowStenciller::configureStencilTexture(shadowStencil, billboardSize, billboardSize);
- BillboardPainter::configureBillBoardTextures(billboard, billboardSize, billboardSize);
+ ShadowStenciller::configureStencilTexture(shadowStencil, {billboardSize, billboardSize});
+ BillboardPainter::configureBillBoardTextures(billboard, {billboardSize, billboardSize});
useMeshClipDist = (ASSUMED_VIEWPORT * OVER_SAMPLE_MULTIPLIER * size) / static_cast<RelativeDistance>(billboardSize);
}
@@ -98,9 +98,9 @@ Foliage::render(const SceneShader & shader, const Frustum &) const
glDebugScope _ {0, "Billboard"};
const auto dimensions = bodyMesh->getDimensions();
shader.billboard.use(dimensions.size, dimensions.centre);
- billboard[0].bind(GL_TEXTURE_2D_ARRAY, GL_TEXTURE0);
- billboard[1].bind(GL_TEXTURE_2D_ARRAY, GL_TEXTURE1);
- billboard[2].bind(GL_TEXTURE_2D_ARRAY, GL_TEXTURE2);
+ billboard[0].bind(0);
+ billboard[1].bind(1);
+ billboard[2].bind(2);
glBindVertexArray(instancePointVAO);
instancePointVAO.useBuffer(0, instances);
glDrawArrays(GL_POINTS, static_cast<GLint>(instancePartitions.second.first), static_cast<GLsizei>(count));
@@ -110,7 +110,7 @@ Foliage::render(const SceneShader & shader, const Frustum &) const
glDebugScope _ {0, "Mesh"};
shader.basicInst.use();
if (texture) {
- texture->bind();
+ texture->bind(0);
}
instanceVAO.useBuffer(1, instances);
bodyMesh->drawInstanced(instanceVAO, static_cast<GLsizei>(count));
@@ -127,7 +127,7 @@ Foliage::shadows(const ShadowMapper & mapper, const Frustum &) const
if (const auto count = instancePartitions.second.second - instancePartitions.second.first) {
const auto dimensions = bodyMesh->getDimensions();
mapper.stencilShadowProgram.use(dimensions.centre, dimensions.size);
- shadowStencil.bind(GL_TEXTURE_2D_ARRAY, GL_TEXTURE0);
+ shadowStencil.bind(0);
glBindVertexArray(instancePointVAO);
instancePointVAO.useBuffer(0, instances);
glDrawArrays(GL_POINTS, static_cast<GLint>(instancePartitions.second.first), static_cast<GLsizei>(count));
@@ -135,7 +135,7 @@ Foliage::shadows(const ShadowMapper & mapper, const Frustum &) const
}
if (const auto count = instancePartitions.second.first) {
if (texture) {
- texture->bind(GL_TEXTURE3);
+ texture->bind(3);
mapper.dynamicPointInstWithTextures.use();
}
else {
diff --git a/game/scenary/foliage.h b/game/scenary/foliage.h
index 3d73573..bf98d55 100644
--- a/game/scenary/foliage.h
+++ b/game/scenary/foliage.h
@@ -38,9 +38,9 @@ protected:
GLsizei billboardSize {};
RelativeDistance useMeshClipDist {};
mutable Direction2D shadowStencilDir {std::numeric_limits<Direction2D::value_type>::infinity()};
- glTexture shadowStencil;
+ glTexture<GL_TEXTURE_2D_ARRAY> shadowStencil;
mutable Angle billboardAngle = std::numeric_limits<Angle>::infinity();
- glTextures<3> billboard;
+ glTextures<GL_TEXTURE_2D_ARRAY, 3> billboard;
private:
InstanceVertices<Foliage::LocationVertex>::PartitionResult instancePartitions;
diff --git a/game/scenary/illuminator.cpp b/game/scenary/illuminator.cpp
index 0c5919a..382cc60 100644
--- a/game/scenary/illuminator.cpp
+++ b/game/scenary/illuminator.cpp
@@ -72,7 +72,7 @@ Illuminator::render(const SceneShader & shader, const Frustum &) const
if (const auto count = instances.size()) {
shader.basicInst.use();
if (texture) {
- texture->bind();
+ texture->bind(0);
}
instanceVAO.useBuffer(1, instances);
bodyMesh->drawInstanced(instanceVAO, static_cast<GLsizei>(count));
diff --git a/game/terrain.cpp b/game/terrain.cpp
index 25ecca9..8bef36e 100644
--- a/game/terrain.cpp
+++ b/game/terrain.cpp
@@ -127,7 +127,7 @@ Terrain::afterChange()
void
Terrain::render(const SceneShader & shader, const Frustum & frustum) const
{
- grass->bind();
+ grass->bind(0);
const auto chunkBySurface = std::views::chunk_by([](const auto & itr1, const auto & itr2) {
return itr1.first.surface == itr2.first.surface;
diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp
index 6e8870a..21a5666 100644
--- a/game/vehicles/railVehicleClass.cpp
+++ b/game/vehicles/railVehicleClass.cpp
@@ -49,7 +49,7 @@ RailVehicleClass::render(const SceneShader & shader, const Frustum &) const
{
if (const auto count = static_cast<GLsizei>(instances.size())) {
if (texture) {
- texture->bind();
+ texture->bind(0);
}
shader.basicInst.use();
instanceVAO.useBuffer(1, instances);
diff --git a/game/water.cpp b/game/water.cpp
index 0f72918..b5d7fc6 100644
--- a/game/water.cpp
+++ b/game/water.cpp
@@ -105,6 +105,6 @@ void
Water::render(const SceneShader & shader, const Frustum &) const
{
shader.water.use(waveCycle);
- water->bind();
+ water->bind(0);
meshes.apply(&MeshT<GlobalPosition3D>::draw);
}
diff --git a/gfx/gl/billboardPainter.cpp b/gfx/gl/billboardPainter.cpp
index 3b03c87..91d9168 100644
--- a/gfx/gl/billboardPainter.cpp
+++ b/gfx/gl/billboardPainter.cpp
@@ -38,27 +38,26 @@ BillboardPainter::getAngle() const
}
void
-BillboardPainter::configureBillBoardTextures(glTextures<3> & textures, GLsizei width, GLsizei height)
+BillboardPainter::configureBillBoardTextures(glTextures<GL_TEXTURE_2D_ARRAY, 3> & textures, ImageDimensions size)
{
glDebugScope _ {0};
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- const auto configuregdata = [width, height](Impl::glTexture & texture, const GLint iformat, const GLenum format) {
- texture.bind(GL_TEXTURE_2D_ARRAY);
+ const auto configuregdata = [size](Impl::glTexture<GL_TEXTURE_2D_ARRAY> & texture, const GLenum iformat) {
+ texture.storage(1, iformat, size || VIEW_ANGLES<GLsizei>);
texture.parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture.parameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texture.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, iformat, width, height, VIEW_ANGLES<GLint>, 0, format, GL_BYTE, nullptr);
};
- configuregdata(textures[0], GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT);
- configuregdata(textures[1], GL_RGB8_SNORM, GL_RGB);
- configuregdata(textures[2], GL_RGB5_A1, GL_RGBA);
+ configuregdata(textures[0], GL_DEPTH_COMPONENT16);
+ configuregdata(textures[1], GL_RGB8_SNORM);
+ configuregdata(textures[2], GL_RGB5_A1);
}
void
-BillboardPainter::renderBillBoard(
- const glTextures<3> & billboard, const MeshBase & mesh, const Texture::AnyPtr texture) const
+BillboardPainter::renderBillBoard(const glTextures<GL_TEXTURE_2D_ARRAY, 3> & billboard, const MeshBase & mesh,
+ const Texture::AnyPtr texture) const
{
glDebugScope _ {fbo};
glEnable(GL_BLEND);
@@ -75,7 +74,7 @@ BillboardPainter::renderBillBoard(
throw std::runtime_error("Billboard framebuffer not complete!");
}
if (texture) {
- texture->bind();
+ texture->bind(0);
}
glUseProgram(program);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
diff --git a/gfx/gl/billboardPainter.h b/gfx/gl/billboardPainter.h
index 0f6334a..9f3a39a 100644
--- a/gfx/gl/billboardPainter.h
+++ b/gfx/gl/billboardPainter.h
@@ -13,10 +13,10 @@ public:
BillboardPainter();
- static void configureBillBoardTextures(glTextures<3> &, GLsizei width, GLsizei height);
+ static void configureBillBoardTextures(glTextures<GL_TEXTURE_2D_ARRAY, 3> &, ImageDimensions);
void setView(Angle angle, const glm::mat4 &);
[[nodiscard]] Angle getAngle() const;
- void renderBillBoard(const glTextures<3> &, const MeshBase &, Texture::AnyPtr texture) const;
+ void renderBillBoard(const glTextures<GL_TEXTURE_2D_ARRAY, 3> &, const MeshBase &, Texture::AnyPtr texture) const;
private:
glFrameBuffer fbo;
diff --git a/gfx/gl/glTexture.cpp b/gfx/gl/glTexture.cpp
index 8dcf16f..e334d5e 100644
--- a/gfx/gl/glTexture.cpp
+++ b/gfx/gl/glTexture.cpp
@@ -1,18 +1,161 @@
#include "glTexture.h"
+#include "filesystem.h"
+#include "gfx/models/tga.h"
+#include <fcntl.h>
+#include <ranges>
+#include <sys/mman.h>
-TextureDimensions
-Impl::glTexture::getSize() const
+void
+Impl::glTextureBase::bind(const GLuint unit) const
+{
+ glBindTextureUnit(unit, name);
+}
+
+void
+Impl::glTextureBase::generateMipmap()
+{
+ glGenerateTextureMipmap(name);
+}
+
+template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+glm::vec<Dims, GLsizei>
+Impl::glTextureDims<Dims>::getSize() const
{
- TextureDimensions size {};
- glGetTextureLevelParameteriv(name, 0, GL_TEXTURE_WIDTH, &size.x);
- glGetTextureLevelParameteriv(name, 0, GL_TEXTURE_HEIGHT, &size.y);
- glGetTextureLevelParameteriv(name, 0, GL_TEXTURE_DEPTH, &size.z);
+ static constexpr std::array<GLenum, 3> PARAMS {GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH};
+ glm::vec<Dims, GLsizei> size {};
+ for (auto [dim, param] : std::views::enumerate(PARAMS) | std::views::take(Dims)) {
+ glGetTextureLevelParameteriv(name, 0, param, &size[static_cast<glm::length_t>(dim)]);
+ }
return size;
}
+template<>
+void
+Impl::glTextureDims<1>::storage(const GLsizei levels, const GLenum internalformat, glm::vec<1, GLsizei> dims)
+{
+ glTextureStorage1D(name, levels, internalformat, dims.x);
+}
+
+template<>
+void
+Impl::glTextureDims<2>::storage(const GLsizei levels, const GLenum internalformat, glm::vec<2, GLsizei> dims)
+{
+ glTextureStorage2D(name, levels, internalformat, dims.x, dims.y);
+}
+
+template<>
+void
+Impl::glTextureDims<3>::storage(const GLsizei levels, const GLenum internalformat, glm::vec<3, GLsizei> dims)
+{
+ glTextureStorage3D(name, levels, internalformat, dims.x, dims.y, dims.z);
+}
+
+template<>
+void
+Impl::glTextureDims<1>::subImage(
+ glm::vec<1, GLint> offset, glm::vec<1, GLint> size, const GLenum format, const GLenum type, const void * pixels)
+{
+ glTextureSubImage1D(name, 0, offset.x, size.x, format, type, pixels);
+}
+
+template<>
+void
+Impl::glTextureDims<2>::subImage(
+ glm::vec<2, GLint> offset, glm::vec<2, GLint> size, const GLenum format, const GLenum type, const void * pixels)
+{
+ glTextureSubImage2D(name, 0, offset.x, offset.y, size.x, size.y, format, type, pixels);
+}
+
+template<>
void
-Impl::glTexture::bind(GLenum type, GLenum unit) const
+Impl::glTextureDims<3>::subImage(
+ glm::vec<3, GLint> offset, glm::vec<3, GLint> size, const GLenum format, const GLenum type, const void * pixels)
{
- glActiveTexture(unit);
- glBindTexture(type, name);
+ glTextureSubImage3D(name, 0, offset.x, offset.y, offset.z, size.x, size.y, size.z, format, type, pixels);
}
+
+template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+void
+Impl::glTextureDims<Dims>::image(
+ glm::vec<Dims, GLint> size, const GLenum format, const GLenum type, const void * pixels)
+{
+ subImage({}, size, format, type, pixels);
+}
+
+template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+void
+Impl::glTextureDims<Dims>::image(const GLenum format, const GLenum type, const void * pixels)
+{
+ image(getSize(), format, type, pixels);
+}
+
+namespace {
+ template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+ void
+ save(const Impl::glTextureDims<Dims> & texture, const GLenum format, const GLenum type, uint8_t channels,
+ const char * path, uint8_t tgaFormat)
+ {
+ const auto size = texture.getSize();
+ const auto area = [size]() {
+ size_t area = 1;
+ for (auto dim = 0; dim < Dims; ++dim) {
+ area *= static_cast<size_t>(size[dim]);
+ }
+ return area;
+ }();
+ size_t dataSize = area * 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.x, 1 * (area / static_cast<size_t>(size.x))},
+ .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);
+ }
+}
+
+template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+void
+Impl::glTextureDims<Dims>::saveColour(const char * path) const
+{
+ save(*this, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2);
+}
+
+template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+void
+Impl::glTextureDims<Dims>::savePosition(const char * path) const
+{
+ save(*this, GL_BGR_INTEGER, GL_UNSIGNED_BYTE, 3, path, 2);
+}
+
+template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+void
+Impl::glTextureDims<Dims>::saveDepth(const char * path) const
+{
+ save(*this, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 1, path, 3);
+}
+
+template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+void
+Impl::glTextureDims<Dims>::saveNormal(const char * path) const
+{
+ save(*this, GL_BGR, GL_BYTE, 3, path, 2);
+}
+
+template struct Impl::glTextureDims<1>;
+template struct Impl::glTextureDims<2>;
+template struct Impl::glTextureDims<3>;
diff --git a/gfx/gl/glTexture.h b/gfx/gl/glTexture.h
index 5e5c838..3472c4a 100644
--- a/gfx/gl/glTexture.h
+++ b/gfx/gl/glTexture.h
@@ -1,14 +1,34 @@
#pragma once
-#include "config/types.h"
#include "glArrays.h"
#include "gl_traits.h"
namespace Impl {
- // NOLINTNEXTLINE(readability-identifier-naming)
- struct glTexture : Detail::glNamed {
- [[nodiscard]] TextureDimensions getSize() const;
- void bind(GLenum type = GL_TEXTURE_2D, GLenum unit = GL_TEXTURE0) const;
+ template<GLenum> struct TextureTargetTraits;
+
+ template<GLenum Target> struct TextureTargetTraitsCommon {
+ static void
+ create(GLsizei count, GLuint * textures)
+ {
+ glCreateTextures(Target, count, textures);
+ }
+ };
+
+ template<> struct TextureTargetTraits<GL_TEXTURE_2D> : TextureTargetTraitsCommon<GL_TEXTURE_2D> {
+ constexpr static glm::length_t dims = 2;
+ };
+
+ template<> struct TextureTargetTraits<GL_TEXTURE_2D_ARRAY> : TextureTargetTraitsCommon<GL_TEXTURE_2D_ARRAY> {
+ constexpr static glm::length_t dims = 3;
+ };
+
+ template<> struct TextureTargetTraits<GL_TEXTURE_RECTANGLE> : TextureTargetTraitsCommon<GL_TEXTURE_RECTANGLE> {
+ constexpr static glm::length_t dims = 2;
+ };
+
+ struct glTextureBase : Detail::glNamed {
+ void bind(GLuint unit) const;
+ void generateMipmap();
template<has_glTextureParameter T>
void
@@ -24,9 +44,29 @@ namespace Impl {
(*gl_traits<T>::glTextureParametervFunc)(name, pname, glm::value_ptr(param));
}
};
+
+ template<glm::length_t Dims>
+ requires(Dims >= 1 && Dims <= 3)
+ struct glTextureDims : glTextureBase {
+ [[nodiscard]] glm::vec<Dims, GLsizei> getSize() const;
+ void storage(GLsizei levels, GLenum internalformat, glm::vec<Dims, GLsizei> dims);
+ void image(GLenum format, GLenum type, const void * pixels);
+ void image(glm::vec<Dims, GLint> size, GLenum format, GLenum type, const void * pixels);
+ void subImage(glm::vec<Dims, GLint> offset, glm::vec<Dims, GLint> size, GLenum format, GLenum type,
+ const void * pixels);
+
+ void saveColour(const char * path) const;
+ void saveDepth(const char * path) const;
+ void saveNormal(const char * path) const;
+ void savePosition(const char * path) const;
+ };
+
+ template<GLenum Target> struct glTexture : glTextureDims<TextureTargetTraits<Target>::dims> { };
}
-// NOLINTBEGIN(readability-identifier-naming)
-template<size_t N> using glTextures = glManagedArray<Impl::glTexture, N, &glGenTextures, &glDeleteTextures>;
-using glTexture = glManagedSingle<Impl::glTexture, &glGenTextures, &glDeleteTextures>;
-// NOLINTEND(readability-identifier-naming)
+template<GLenum Target, size_t N>
+using glTextures
+ = glManagedArray<Impl::glTexture<Target>, N, &Impl::TextureTargetTraits<Target>::create, &glDeleteTextures>;
+template<GLenum Target>
+using glTexture
+ = glManagedSingle<Impl::glTexture<Target>, &Impl::TextureTargetTraits<Target>::create, &glDeleteTextures>;
diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp
index d4812df..343321f 100644
--- a/gfx/gl/sceneRenderer.cpp
+++ b/gfx/gl/sceneRenderer.cpp
@@ -23,28 +23,21 @@ SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o, glDebugScope) :
shader.setViewPort({0, 0, size.x, size.y});
displayVAO.configure().addAttribs<glm::i8vec4>(0, displayVBO, displayVAOdata);
- const auto configuregdata = [this](glTexture & data, const std::initializer_list<GLint> iformats,
- const GLenum format, const GLenum attachment) {
- data.bind();
+ const auto configuregdata = [this](glTexture<GL_TEXTURE_2D> & data, const GLenum iformat, const GLenum attachment) {
+ data.storage(1, iformat, size);
data.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
data.parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- for (const auto iformat : iformats) {
- glTexImage2D(GL_TEXTURE_2D, 0, iformat, size.x, size.y, 0, format, GL_BYTE, nullptr);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, data, 0);
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
- return iformat;
- }
- }
- throw std::runtime_error("Framebuffer could not be completed!");
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, data, 0);
};
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
- configuregdata(gPosition, {GL_RGB32I}, GL_RGB_INTEGER, GL_COLOR_ATTACHMENT0);
- normaliFormat = configuregdata(gNormal, {GL_RGB8_SNORM, GL_RGB16F}, GL_RGB, GL_COLOR_ATTACHMENT1);
- configuregdata(gAlbedoSpec, {GL_RGB8}, GL_RGB, GL_COLOR_ATTACHMENT2);
- constexpr std::array<unsigned int, 3> attachments {
- GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
+ configuregdata(gPosition, GL_RGB32I, GL_COLOR_ATTACHMENT0);
+ configuregdata(gNormal, GL_RGB8_SNORM, GL_COLOR_ATTACHMENT1);
+ configuregdata(gAlbedoSpec, GL_RGB8, GL_COLOR_ATTACHMENT2);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ throw std::runtime_error("Framebuffer could not be completed! (setup gBuffer)");
+ }
+ constexpr std::array<GLenum, 3> attachments {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(attachments.size(), attachments.data());
glBindRenderbuffer(GL_RENDERBUFFER, depth);
@@ -52,7 +45,10 @@ SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o, glDebugScope) :
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll);
- configuregdata(gIllumination, {GL_RGB8}, GL_RGB, GL_COLOR_ATTACHMENT0);
+ configuregdata(gIllumination, GL_RGB8, GL_COLOR_ATTACHMENT0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ throw std::runtime_error("Framebuffer could not be completed! (setup gBufferIll)");
+ }
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_FRAMEBUFFER, output);
@@ -64,16 +60,27 @@ SceneRenderer::resize(ScreenAbsCoord newSize)
glDebugScope _ {output};
size = newSize;
camera.setAspect(ratio(size));
- const auto configuregdata = [this](const auto & data, const GLint iformat, const GLenum format) {
- data.bind();
- glTexImage2D(GL_TEXTURE_2D, 0, iformat, size.x, size.y, 0, format, GL_BYTE, nullptr);
+ const auto configuregdata = [this](glTexture<GL_TEXTURE_2D> & data, const GLenum iformat, const GLenum attachment) {
+ data = {};
+ data.storage(1, iformat, size);
+ data.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ data.parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, data, 0);
};
- configuregdata(gPosition, GL_RGB32I, GL_RGB_INTEGER);
- configuregdata(gNormal, normaliFormat, GL_RGB);
- configuregdata(gAlbedoSpec, GL_RGB8, GL_RGB);
- configuregdata(gIllumination, GL_RGB8, GL_RGB);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
+ configuregdata(gPosition, GL_RGB32I, GL_COLOR_ATTACHMENT0);
+ configuregdata(gNormal, GL_RGB8_SNORM, GL_COLOR_ATTACHMENT1);
+ configuregdata(gAlbedoSpec, GL_RGB8, GL_COLOR_ATTACHMENT2);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.x, size.y);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ throw std::runtime_error("Framebuffer could not be completed! (resize gBuffer)");
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll);
+ configuregdata(gIllumination, GL_RGB8, GL_COLOR_ATTACHMENT0);
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ throw std::runtime_error("Framebuffer could not be completed! (resize gBufferIll)");
+ }
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
shader.setViewPort({0, 0, size.x, size.y});
}
@@ -123,9 +130,9 @@ SceneRenderer::render(const SceneProvider & scene) const
// * per light - reads normal and position, writes illumination
glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll);
glBlendFunc(GL_ONE, GL_ONE);
- gPosition.bind(GL_TEXTURE_2D, GL_TEXTURE0);
- gNormal.bind(GL_TEXTURE_2D, GL_TEXTURE1);
- shadowMapper.bind(GL_TEXTURE2);
+ gPosition.bind(0);
+ gNormal.bind(1);
+ shadowMapper.bind(2);
glDisable(GL_DEPTH_TEST);
scene.lights(shader);
}
@@ -137,8 +144,8 @@ SceneRenderer::render(const SceneProvider & scene) const
glCullFace(GL_BACK);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
- gAlbedoSpec.bind(GL_TEXTURE_2D, GL_TEXTURE2);
- gIllumination.bind(GL_TEXTURE_2D, GL_TEXTURE3);
+ gAlbedoSpec.bind(2);
+ gIllumination.bind(3);
lighting.use();
renderQuad();
}
@@ -162,9 +169,9 @@ SceneRenderer::setDirectionalLight(
const auto lvp = shadowMapper.update(scene, direction, camera);
glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll);
glBlendFunc(GL_ONE, GL_ONE);
- gPosition.bind(GL_TEXTURE_2D, GL_TEXTURE0);
- gNormal.bind(GL_TEXTURE_2D, GL_TEXTURE1);
- shadowMapper.bind(GL_TEXTURE2);
+ gPosition.bind(0);
+ gNormal.bind(1);
+ shadowMapper.bind(2);
glViewport(0, 0, size.x, size.y);
dirLight.use();
dirLight.setDirectionalLight(colour, direction.vector(), camera.getPosition(), lvp);
diff --git a/gfx/gl/sceneRenderer.h b/gfx/gl/sceneRenderer.h
index a7f7770..e9cafb4 100644
--- a/gfx/gl/sceneRenderer.h
+++ b/gfx/gl/sceneRenderer.h
@@ -31,8 +31,7 @@ protected:
ScreenAbsCoord size;
GLuint output;
glFrameBuffer gBuffer, gBufferIll;
- GLint normaliFormat;
- glTexture gPosition, gNormal, gAlbedoSpec, gIllumination;
+ glTexture<GL_TEXTURE_2D> gPosition, gNormal, gAlbedoSpec, gIllumination;
glRenderBuffer depth;
class DeferredLightProgram : public Program {
diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp
index fb57668..28ab360 100644
--- a/gfx/gl/shadowMapper.cpp
+++ b/gfx/gl/shadowMapper.cpp
@@ -24,6 +24,7 @@
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/matrix.hpp>
+#include <maths.h>
ShadowMapper::ShadowMapper(const TextureAbsCoord & s) :
landmess {shadowLandmass_vert}, dynamicPointInst {shadowDynamicPointInst_vert},
@@ -32,9 +33,7 @@ ShadowMapper::ShadowMapper(const TextureAbsCoord & s) :
size {s}, frustum {{}, {}, {}}
{
glDebugScope _ {depthMap};
- depthMap.bind(GL_TEXTURE_2D_ARRAY);
- glTexImage3D(
- GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT, size.x, size.y, 4, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
+ depthMap.storage(1, GL_DEPTH_COMPONENT16, size || static_cast<GLsizei>(SHADOW_BANDS));
depthMap.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
depthMap.parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
depthMap.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h
index 0d9763a..adae847 100644
--- a/gfx/gl/shadowMapper.h
+++ b/gfx/gl/shadowMapper.h
@@ -71,14 +71,14 @@ public:
void
bind(GLenum unit) const
{
- depthMap.bind(GL_TEXTURE_2D_ARRAY, unit);
+ depthMap.bind(unit);
}
private:
using BandViewExtents = std::array<std::array<RelativePosition3D, 4>, SHADOW_BANDS + 1>;
[[nodiscard]] static size_t getBandViewExtents(BandViewExtents &, const Camera &, const glm::mat4 & lightView);
glFrameBuffer depthMapFBO;
- glTexture depthMap;
+ glTexture<GL_TEXTURE_2D_ARRAY> depthMap;
TextureAbsCoord size;
BandViewExtents bandViewExtents;
diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp
index a5f9d68..cafae02 100644
--- a/gfx/gl/shadowStenciller.cpp
+++ b/gfx/gl/shadowStenciller.cpp
@@ -37,22 +37,19 @@ ShadowStenciller::getLightDirection() const
}
void
-ShadowStenciller::configureStencilTexture(glTexture & stencil, GLsizei width, GLsizei height)
+ShadowStenciller::configureStencilTexture(glTexture<GL_TEXTURE_2D_ARRAY> & stencil, ImageDimensions size)
{
- stencil.bind(GL_TEXTURE_2D_ARRAY);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
+ stencil.storage(1, GL_DEPTH_COMPONENT16, size || STENCIL_ANGLES<GLsizei>);
stencil.parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
stencil.parameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stencil.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
stencil.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT, width, height, STENCIL_ANGLES<GLint>, 0,
- GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr);
}
void
-ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh, const Texture::AnyPtr texture) const
+ShadowStenciller::renderStencil(
+ const glTexture<GL_TEXTURE_2D_ARRAY> & stencil, const MeshBase & mesh, const Texture::AnyPtr texture) const
{
glDebugScope _ {fbo};
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
@@ -61,7 +58,7 @@ ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh
throw std::runtime_error("Stencil framebuffer not complete!");
}
if (texture) {
- texture->bind();
+ texture->bind(0);
}
glUseProgram(shadowCaster);
glClear(GL_DEPTH_BUFFER_BIT);
diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h
index 028bfa1..70dbca9 100644
--- a/gfx/gl/shadowStenciller.h
+++ b/gfx/gl/shadowStenciller.h
@@ -13,10 +13,10 @@ public:
ShadowStenciller();
- static void configureStencilTexture(glTexture &, GLsizei width, GLsizei height);
+ static void configureStencilTexture(glTexture<GL_TEXTURE_2D_ARRAY> &, ImageDimensions);
void setLightDirection(const LightDirection & lightDir);
[[nodiscard]] Direction2D getLightDirection() const;
- void renderStencil(const glTexture &, const MeshBase &, Texture::AnyPtr texture) const;
+ void renderStencil(const glTexture<GL_TEXTURE_2D_ARRAY> &, const MeshBase &, Texture::AnyPtr texture) const;
private:
glFrameBuffer fbo;
diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp
index d175b34..7e413d4 100644
--- a/gfx/models/texture.cpp
+++ b/gfx/models/texture.cpp
@@ -1,6 +1,5 @@
#include "texture.h"
#include "config/types.h"
-#include "tga.h"
#include <fcntl.h>
#include <filesystem.h>
#include <gfx/image.h>
@@ -11,6 +10,8 @@
#include <stb/stb_image.h>
#include <sys/mman.h>
+using std::ceil;
+
GLint
TextureOptions::glMapMode(TextureOptions::MapMode mm)
{
@@ -38,16 +39,17 @@ Texture::Texture(const Image & tex, TextureOptions 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}
+Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOptions to)
{
- m_texture.bind(type);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ const auto levels = static_cast<GLsizei>(ceil(std::log2(std::max(width, height))));
+ m_texture.storage(levels, GL_RGBA8, {width, height});
m_texture.parameter(GL_TEXTURE_WRAP_S, TextureOptions::glMapMode(to.wrapU));
m_texture.parameter(GL_TEXTURE_WRAP_T, TextureOptions::glMapMode(to.wrapV));
m_texture.parameter(GL_TEXTURE_MIN_FILTER, to.minFilter);
m_texture.parameter(GL_TEXTURE_MAG_FILTER, to.magFilter);
- glTexImage2D(type, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ m_texture.image({width, height}, GL_RGBA, GL_UNSIGNED_BYTE, data);
auto isMimmap = [](auto value) {
auto eqAnyOf = [value](auto... test) {
return (... || (value == test));
@@ -55,91 +57,37 @@ Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOption
return eqAnyOf(
GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR);
};
- if (isMimmap(to.minFilter) || isMimmap(to.magFilter)) {
- glGenerateMipmap(type);
+ if (levels > 1 && (isMimmap(to.minFilter) || isMimmap(to.magFilter))) {
+ m_texture.generateMipmap();
}
}
void
Texture::bind(GLenum unit) const
{
- m_texture.bind(type, unit);
-}
-
-void
-Texture::save(
- const glTexture & texture, GLenum format, GLenum type, uint8_t channels, const char * path, uint8_t tgaFormat)
-{
- const auto size = texture.getSize();
- const size_t dataSize = (static_cast<size_t>(size.x * size.y * size.z * 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.x, size.y * size.z},
- .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::savePosition(const glTexture & texture, const char * path)
-{
- save(texture, GL_BGR_INTEGER, 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);
+ m_texture.bind(unit);
}
-TextureAtlas::TextureAtlas(GLsizei width, GLsizei height, GLuint count) : Texture(width, height, nullptr, {})
+TextureAtlas::TextureAtlas(GLsizei width, GLsizei height, GLuint count) : Texture(width, height)
{
- m_atlas.bind(GL_TEXTURE_RECTANGLE);
-
m_atlas.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_atlas.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_atlas.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_atlas.parameter(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);
+ m_atlas.storage(1, GL_RGBA16UI, {2, count});
}
void
TextureAtlas::bind(GLenum unit) const
{
Texture::bind(unit);
- m_atlas.bind(GL_TEXTURE_RECTANGLE, unit + 1);
+ m_atlas.bind(unit + 1);
}
GLuint
TextureAtlas::add(TextureAbsCoord position, TextureAbsCoord size, void * data, TextureOptions to)
{
- glTextureSubImage2D(m_texture, 0, position.x, position.y, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ m_texture.subImage(position, size, GL_RGBA, GL_UNSIGNED_BYTE, data);
struct Material {
glm::vec<2, uint16_t> position, size;
@@ -148,6 +96,12 @@ TextureAtlas::add(TextureAbsCoord position, TextureAbsCoord size, void * data, T
} 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);
+ m_atlas.subImage({0, used}, {2, 1}, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, &material);
return ++used;
}
+
+void
+TextureAtlas::complete()
+{
+ m_texture.generateMipmap();
+}
diff --git a/gfx/models/texture.h b/gfx/models/texture.h
index 03d296a..19a2ebe 100644
--- a/gfx/models/texture.h
+++ b/gfx/models/texture.h
@@ -17,7 +17,6 @@ struct TextureOptions {
};
MapMode wrapU {MapMode::Repeat}, wrapV {MapMode::Repeat};
GLint minFilter {GL_LINEAR}, magFilter {GL_LINEAR};
- GLenum type {GL_TEXTURE_2D};
static GLint glMapMode(MapMode);
};
@@ -31,29 +30,21 @@ public:
explicit Texture(GLsizei width, GLsizei height, TextureOptions = {});
explicit Texture(GLsizei width, GLsizei height, const void * data, TextureOptions = {});
- 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);
- static void savePosition(const glTexture &, const char * path);
+ virtual void bind(GLuint unit) const;
protected:
- static void save(const glTexture &, GLenum, GLenum, uint8_t channels, const char * path, uint8_t tgaFormat);
-
- glTexture m_texture;
- GLenum type;
+ glTexture<GL_TEXTURE_2D> m_texture;
};
class TextureAtlas : public Texture {
public:
TextureAtlas(GLsizei width, GLsizei height, GLuint count);
- void bind(GLenum unit = GL_TEXTURE0) const override;
+ void bind(GLuint unit) const override;
GLuint add(TextureAbsCoord position, TextureAbsCoord size, void * data, TextureOptions = {});
+ void complete();
private:
- glTexture m_atlas;
+ glTexture<GL_TEXTURE_RECTANGLE> m_atlas;
GLuint used {};
};
diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp
index fee1822..90fae9b 100644
--- a/test/test-assetFactory.cpp
+++ b/test/test-assetFactory.cpp
@@ -38,7 +38,7 @@ namespace {
auto outpath = (ANALYSIS_DIRECTORY / boost::unit_test::framework::current_test_case().full_name())
.replace_extension(".tga");
std::filesystem::create_directories(outpath.parent_path());
- Texture::save(outImage, outpath.c_str());
+ outImage.saveColour(outpath.c_str());
}
void
diff --git a/test/test-geoData.cpp b/test/test-geoData.cpp
index 80d3a08..e489925 100644
--- a/test/test-geoData.cpp
+++ b/test/test-geoData.cpp
@@ -300,7 +300,7 @@ BOOST_DATA_TEST_CASE(Deform, loadFixtureJson<DeformTerrainData>("geoData/deform/
std::for_each(cams.begin(), cams.end(), [&renderer, &terrain, &tro](const auto & cam) {
renderer.camera.setView(cam.first.first, glm::normalize(cam.first.second));
BOOST_CHECK_NO_THROW(renderer.render(terrain));
- Texture::save(tro.outImage, (ANALYSIS_DIRECTORY / cam.second).c_str());
+ tro.outImage.saveColour((ANALYSIS_DIRECTORY / cam.second).c_str());
});
}
diff --git a/test/test-render.cpp b/test/test-render.cpp
index 1a6e1ae..0b47ce8 100644
--- a/test/test-render.cpp
+++ b/test/test-render.cpp
@@ -165,10 +165,10 @@ BOOST_AUTO_TEST_CASE(Basic)
saveBuffers(const std::filesystem::path & prefix) const
{
std::filesystem::create_directories(prefix);
- Texture::save(gAlbedoSpec, (prefix / "albedo.tga").c_str());
- Texture::savePosition(gPosition, (prefix / "position.tga").c_str());
- Texture::saveNormal(gNormal, (prefix / "normal.tga").c_str());
- Texture::save(gIllumination, (prefix / "illumination.tga").c_str());
+ gAlbedoSpec.saveColour((prefix / "albedo.tga").c_str());
+ gPosition.savePosition((prefix / "position.tga").c_str());
+ gNormal.saveNormal((prefix / "normal.tga").c_str());
+ gIllumination.saveColour((prefix / "illumination.tga").c_str());
}
};
@@ -178,7 +178,7 @@ BOOST_AUTO_TEST_CASE(Basic)
renderer.preFrame(scene, gameState.environment->getSunPos());
renderer.render(scene);
renderer.saveBuffers(ANALYSIS_DIRECTORY / "basic");
- Texture::save(outImage, (ANALYSIS_DIRECTORY / "basic/final.tga").c_str());
+ outImage.saveColour((ANALYSIS_DIRECTORY / "basic/final.tga").c_str());
}
BOOST_AUTO_TEST_CASE(TerrainSD19)
@@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(TerrainSD19)
TestTerrain testTerrain;
renderer.preFrame(testTerrain, gameState.environment->getSunPos());
renderer.render(testTerrain);
- Texture::save(outImage, (ANALYSIS_DIRECTORY / "terrain.tga").c_str());
+ outImage.saveColour((ANALYSIS_DIRECTORY / "terrain.tga").c_str());
}
BOOST_AUTO_TEST_CASE(RailNetwork)
@@ -279,7 +279,7 @@ BOOST_AUTO_TEST_CASE(RailNetwork)
};
renderer.render(TestRail {});
- Texture::save(outImage, (ANALYSIS_DIRECTORY / "railnet.tga").c_str());
+ outImage.saveColour((ANALYSIS_DIRECTORY / "railnet.tga").c_str());
}
BOOST_AUTO_TEST_SUITE_END();
diff --git a/test/test-ui.cpp b/test/test-ui.cpp
index c648c2c..74953b3 100644
--- a/test/test-ui.cpp
+++ b/test/test-ui.cpp
@@ -16,6 +16,6 @@ BOOST_AUTO_TEST_CASE(LoadFromFile)
{
SvgIcon svg(ImageDimensions {RENDER_SIZE}, Resource::mapPath("ui/icon/rails.svg"));
const auto size = svg.texture.getSize();
- BOOST_CHECK_EQUAL(size, TextureDimensions(RENDER_SIZE, RENDER_SIZE, 1));
- Texture::save(svg.texture, (ANALYSIS_DIRECTORY / "rails.tga").c_str());
+ BOOST_CHECK_EQUAL(size, ImageDimensions(RENDER_SIZE, RENDER_SIZE));
+ svg.texture.saveColour((ANALYSIS_DIRECTORY / "rails.tga").c_str());
}
diff --git a/test/testRenderOutput.cpp b/test/testRenderOutput.cpp
index 7243032..b86469a 100644
--- a/test/testRenderOutput.cpp
+++ b/test/testRenderOutput.cpp
@@ -5,15 +5,13 @@
TestRenderOutput::TestRenderOutput(TextureAbsCoord outputSize) : size {outputSize}
{
glBindFramebuffer(GL_FRAMEBUFFER, output);
- const auto configuregdata
- = [this](glTexture & data, const GLint format, const GLenum type, const GLenum attachment) {
- data.bind();
- glTexImage2D(GL_TEXTURE_2D, 0, format, size.x, size.y, 0, GL_RGBA, type, nullptr);
- data.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- data.parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, data, 0);
- };
- configuregdata(outImage, GL_RGBA, GL_UNSIGNED_BYTE, GL_COLOR_ATTACHMENT0);
+ const auto configuregdata = [this](glTexture<GL_TEXTURE_2D> & data, const GLenum format, const GLenum attachment) {
+ data.storage(1, format, size);
+ data.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ data.parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, data, 0);
+ };
+ configuregdata(outImage, GL_RGBA8, GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBindRenderbuffer(GL_RENDERBUFFER, depth);
diff --git a/test/testRenderOutput.h b/test/testRenderOutput.h
index 79908b1..248485c 100644
--- a/test/testRenderOutput.h
+++ b/test/testRenderOutput.h
@@ -17,7 +17,7 @@ public:
const TextureAbsCoord size;
glFrameBuffer output;
glRenderBuffer depth;
- glTexture outImage;
+ glTexture<GL_TEXTURE_2D> outImage;
GameState gameState;
};
diff --git a/ui/editNetwork.cpp b/ui/editNetwork.cpp
index 6ee0210..0215468 100644
--- a/ui/editNetwork.cpp
+++ b/ui/editNetwork.cpp
@@ -41,7 +41,7 @@ void
EditNetwork::render(const SceneShader & shader, const Frustum & frustum) const
{
if (builder) {
- blue.bind();
+ blue.bind(0);
shader.absolute.use();
builder->render(shader, frustum);
}
diff --git a/ui/font.cpp b/ui/font.cpp
index b028c52..9c3d770 100644
--- a/ui/font.cpp
+++ b/ui/font.cpp
@@ -92,8 +92,7 @@ Font::generateChars(const utf8_string_view chars) const
const auto textureIdx = getTextureWithSpace(glyph->bitmap.width);
auto & texture = fontTextures[textureIdx];
- glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(texture.used), 0,
- static_cast<GLsizei>(glyph->bitmap.width), static_cast<GLsizei>(glyph->bitmap.rows), GL_RED,
+ texture.texture.subImage({texture.used, 0}, {glyph->bitmap.width, glyph->bitmap.rows}, GL_RED,
GL_UNSIGNED_BYTE, glyph->bitmap.buffer);
const auto & cd = charsData
@@ -115,14 +114,11 @@ Font::getTextureWithSpace(unsigned int adv) const
return (ft.used + adv) < size.x;
});
itr != fontTextures.end()) {
- itr->texture.bind();
return static_cast<std::size_t>(itr - fontTextures.begin());
}
auto & texture = fontTextures.emplace_back();
- texture.texture.bind();
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast<GLsizei>(size.x), static_cast<GLsizei>(size.y), 0, GL_RED,
- GL_UNSIGNED_BYTE, nullptr);
+ texture.texture.storage(1, GL_R8, size);
texture.texture.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.texture.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.texture.parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
diff --git a/ui/font.h b/ui/font.h
index 8cf3229..bc11b76 100644
--- a/ui/font.h
+++ b/ui/font.h
@@ -28,7 +28,7 @@ public:
};
struct FontTexture {
- glTexture texture;
+ glTexture<GL_TEXTURE_2D> texture;
unsigned int used;
};
diff --git a/ui/icon.cpp b/ui/icon.cpp
index 5ab9c64..e0399e5 100644
--- a/ui/icon.cpp
+++ b/ui/icon.cpp
@@ -10,14 +10,12 @@ Icon::Icon(const std::filesystem::path & fileName) : Icon {Image {Resource::mapP
Icon::Icon(const Image & tex) : size {tex.width, tex.height}
{
- m_texture.bind();
-
+ m_texture.storage(1, GL_RGBA8, size);
m_texture.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
m_texture.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
m_texture.parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
m_texture.parameter(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());
+ m_texture.image(size, GL_RGBA, GL_UNSIGNED_BYTE, tex.data.data());
}
ImTextureID
diff --git a/ui/icon.h b/ui/icon.h
index 2023be8..4479910 100644
--- a/ui/icon.h
+++ b/ui/icon.h
@@ -16,5 +16,5 @@ public:
ImTextureID operator*() const;
private:
- glTexture m_texture;
+ glTexture<GL_TEXTURE_2D> m_texture;
};
diff --git a/ui/svgIcon.cpp b/ui/svgIcon.cpp
index 82ef69d..2c73b5d 100644
--- a/ui/svgIcon.cpp
+++ b/ui/svgIcon.cpp
@@ -14,19 +14,18 @@ SvgIcon::SvgIcon(ImageDimensions dim, const std::filesystem::path & path)
}
bitmap.convertToRGBA();
- texture.bind();
-
+ texture.storage(1, GL_RGBA8, dim);
texture.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
texture.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
texture.parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
texture.parameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dim.x, dim.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.data());
+ texture.image(dim, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.data());
}
ImTextureID
SvgIcon::operator*() const
{
- static_assert(sizeof(glTexture) <= sizeof(ImTextureID));
+ static_assert(sizeof(glTexture<GL_TEXTURE_2D>) <= sizeof(ImTextureID));
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr) This is how ImGui works
return reinterpret_cast<ImTextureID>(*texture);
}
diff --git a/ui/svgIcon.h b/ui/svgIcon.h
index be01446..8009891 100644
--- a/ui/svgIcon.h
+++ b/ui/svgIcon.h
@@ -14,5 +14,5 @@ public:
private:
friend class LoadFromFile; // Test case verifying size/content
- glTexture texture;
+ glTexture<GL_TEXTURE_2D> texture;
};