diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-08 16:02:56 +0000 |
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-08 16:02:56 +0000 |
| commit | 00fc3cb9b2c06026fab0e4760609fe02e027b6df (patch) | |
| tree | b84b527824ac1d5c999fc4a974fcf2c356b422ab | |
| parent | Replace gl_traits glTexParameter with glTexture::parameter DSA wrapper (diff) | |
| download | ilt-00fc3cb9b2c06026fab0e4760609fe02e027b6df.tar.bz2 ilt-00fc3cb9b2c06026fab0e4760609fe02e027b6df.tar.xz ilt-00fc3cb9b2c06026fab0e4760609fe02e027b6df.zip | |
Move all low level texture operations to DSA helpers in glTexture
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); @@ -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 @@ -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; }; |
