From 64ede41ebaade64ad6705f7f55ca4a778a156481 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 2 Mar 2026 13:17:28 +0000 Subject: Wrap up some low level texture operations in glTexture class Fixes previously hard coded billboard texture size. --- game/scenary/foliage.cpp | 12 ++++-------- gfx/gl/billboardPainter.cpp | 6 +++--- gfx/gl/glTexture.cpp | 18 ++++++++++++++++++ gfx/gl/glTexture.h | 17 +++++++++++++++++ gfx/gl/sceneRenderer.cpp | 32 ++++++++++++-------------------- gfx/gl/shadowMapper.cpp | 2 +- gfx/gl/shadowMapper.h | 6 +++--- gfx/gl/shadowStenciller.cpp | 5 ++--- gfx/models/texture.cpp | 23 +++++------------------ gfx/models/texture.h | 3 +-- lib/glArrays.h | 2 -- test/test-ui.cpp | 2 +- test/testRenderOutput.cpp | 4 ++-- ui/font.cpp | 4 ++-- ui/font.h | 2 +- ui/icon.cpp | 2 +- ui/icon.h | 2 +- ui/svgIcon.cpp | 2 +- ui/svgIcon.h | 2 +- 19 files changed, 76 insertions(+), 70 deletions(-) create mode 100644 gfx/gl/glTexture.cpp create mode 100644 gfx/gl/glTexture.h diff --git a/game/scenary/foliage.cpp b/game/scenary/foliage.cpp index 6b471fc..cefee9f 100644 --- a/game/scenary/foliage.cpp +++ b/game/scenary/foliage.cpp @@ -77,12 +77,9 @@ Foliage::render(const SceneShader & shader, const Frustum &) const glDebugScope _ {0, "Billboard"}; const auto dimensions = bodyMesh->getDimensions(); shader.billboard.use(dimensions.size, dimensions.centre); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, billboard[0]); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D_ARRAY, billboard[1]); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D_ARRAY, billboard[2]); + 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); glBindVertexArray(instancePointVAO); glDrawArrays(GL_POINTS, static_cast(instancePartitions.second.first), static_cast(count)); glBindVertexArray(0); @@ -107,8 +104,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); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, shadowStencil); + shadowStencil.bind(GL_TEXTURE_2D_ARRAY, GL_TEXTURE0); glBindVertexArray(instancePointVAO); glDrawArrays(GL_POINTS, static_cast(instancePartitions.second.first), static_cast(count)); glBindVertexArray(0); diff --git a/gfx/gl/billboardPainter.cpp b/gfx/gl/billboardPainter.cpp index e72e72d..06e13ca 100644 --- a/gfx/gl/billboardPainter.cpp +++ b/gfx/gl/billboardPainter.cpp @@ -40,8 +40,8 @@ BillboardPainter::createBillBoardTextures(GLsizei width, GLsizei height) glTextures<3> textures; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - const auto configuregdata = [width, height](const GLuint texture, const GLint iformat, const GLenum format) { - glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + const auto configuregdata = [width, height](const auto & texture, const GLint iformat, const GLenum format) { + texture.bind(GL_TEXTURE_2D_ARRAY); glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -78,7 +78,7 @@ BillboardPainter::renderBillBoard( } glUseProgram(program); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - const TextureDimensions billboardSize = {256, 256, 8}; // Texture::getSize(billboard[0]); + const TextureDimensions billboardSize = billboard[0].getSize(); glViewport(0, 0, billboardSize.x, billboardSize.y); const auto & centre = mesh.getDimensions().centre; const auto & size = mesh.getDimensions().size; diff --git a/gfx/gl/glTexture.cpp b/gfx/gl/glTexture.cpp new file mode 100644 index 0000000..8dcf16f --- /dev/null +++ b/gfx/gl/glTexture.cpp @@ -0,0 +1,18 @@ +#include "glTexture.h" + +TextureDimensions +Impl::glTexture::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); + return size; +} + +void +Impl::glTexture::bind(GLenum type, GLenum unit) const +{ + glActiveTexture(unit); + glBindTexture(type, name); +} diff --git a/gfx/gl/glTexture.h b/gfx/gl/glTexture.h new file mode 100644 index 0000000..c482198 --- /dev/null +++ b/gfx/gl/glTexture.h @@ -0,0 +1,17 @@ +#pragma once + +#include "config/types.h" +#include "glArrays.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; + }; +} + +// NOLINTBEGIN(readability-identifier-naming) +template using glTextures = glManagedArray; +using glTexture = glManagedSingle; +// NOLINTEND(readability-identifier-naming) diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp index e693787..efa08ef 100644 --- a/gfx/gl/sceneRenderer.cpp +++ b/gfx/gl/sceneRenderer.cpp @@ -24,9 +24,9 @@ SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o, glDebugScope) : shader.setViewPort({0, 0, size.x, size.y}); VertexArrayObject {displayVAO}.addAttribs(displayVBO, displayVAOdata); - const auto configuregdata = [this](const GLuint data, const std::initializer_list iformats, + const auto configuregdata = [this](const auto & data, const std::initializer_list iformats, const GLenum format, const GLenum attachment) { - glBindTexture(GL_TEXTURE_2D, data); + data.bind(); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); for (const auto iformat : iformats) { @@ -65,8 +65,8 @@ SceneRenderer::resize(ScreenAbsCoord newSize) glDebugScope _ {output}; size = newSize; camera.setAspect(ratio(size)); - const auto configuregdata = [this](const GLuint data, const GLint iformat, const GLenum format) { - glBindTexture(GL_TEXTURE_2D, data); + 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); }; configuregdata(gPosition, GL_RGB32I, GL_RGB_INTEGER); @@ -124,12 +124,9 @@ SceneRenderer::render(const SceneProvider & scene) const // * per light - reads normal and position, writes illumination glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll); glBlendFunc(GL_ONE, GL_ONE); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, gPosition); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, gNormal); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMapper); + gPosition.bind(GL_TEXTURE_2D, GL_TEXTURE0); + gNormal.bind(GL_TEXTURE_2D, GL_TEXTURE1); + shadowMapper.bind(GL_TEXTURE2); glDisable(GL_DEPTH_TEST); scene.lights(shader); } @@ -141,10 +138,8 @@ SceneRenderer::render(const SceneProvider & scene) const glCullFace(GL_BACK); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, gAlbedoSpec); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, gIllumination); + gAlbedoSpec.bind(GL_TEXTURE_2D, GL_TEXTURE2); + gIllumination.bind(GL_TEXTURE_2D, GL_TEXTURE3); lighting.use(); renderQuad(); } @@ -168,12 +163,9 @@ SceneRenderer::setDirectionalLight( const auto lvp = shadowMapper.update(scene, direction, camera); glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll); glBlendFunc(GL_ONE, GL_ONE); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, gPosition); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, gNormal); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMapper); + gPosition.bind(GL_TEXTURE_2D, GL_TEXTURE0); + gNormal.bind(GL_TEXTURE_2D, GL_TEXTURE1); + shadowMapper.bind(GL_TEXTURE2); glViewport(0, 0, size.x, size.y); dirLight.use(); dirLight.setDirectionalLight(colour, direction.vector(), camera.getPosition(), lvp); diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index 35c225b..03851f5 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -32,7 +32,7 @@ ShadowMapper::ShadowMapper(const TextureAbsCoord & s) : size {s}, frustum {{}, {}, {}} { glDebugScope _ {depthMap}; - glBindTexture(GL_TEXTURE_2D_ARRAY, 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); glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h index 8b5e0b6..0d9763a 100644 --- a/gfx/gl/shadowMapper.h +++ b/gfx/gl/shadowMapper.h @@ -68,10 +68,10 @@ public: DynamicPoint dynamicPoint; StencilShadowProgram stencilShadowProgram; - // NOLINTNEXTLINE(hicpp-explicit-conversions) - operator GLuint() const + void + bind(GLenum unit) const { - return depthMap; + depthMap.bind(GL_TEXTURE_2D_ARRAY, unit); } private: diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index aee7161..7a0fc9b 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -1,7 +1,6 @@ #include "shadowStenciller.h" #include "gfx/lightDirection.h" #include "gfx/models/mesh.h" -#include "glArrays.h" #include "gl_traits.h" #include "gldebug.h" #include "maths.h" @@ -34,7 +33,7 @@ glTexture ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) { glTexture stencil; - glBindTexture(GL_TEXTURE_2D_ARRAY, stencil); + stencil.bind(GL_TEXTURE_2D_ARRAY); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -62,7 +61,7 @@ ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh } glUseProgram(shadowCaster); glClear(GL_DEPTH_BUFFER_BIT); - const auto stencilSize = Texture::getSize(stencil); + const auto stencilSize = stencil.getSize(); glViewport(0, 0, stencilSize.x, stencilSize.y); const auto & centre = mesh.getDimensions().centre; const auto & size = mesh.getDimensions().size; diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index 3457fb5..46bdff8 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -1,6 +1,5 @@ #include "texture.h" #include "config/types.h" -#include "glArrays.h" #include "tga.h" #include #include @@ -41,7 +40,7 @@ Texture::Texture(GLsizei width, GLsizei height, TextureOptions to) : Texture {wi Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOptions to) : type {to.type} { - glBindTexture(type, m_texture); + m_texture.bind(type); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameter(type, GL_TEXTURE_WRAP_S, TextureOptions::glMapMode(to.wrapU)); @@ -65,25 +64,14 @@ Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOption void Texture::bind(GLenum unit) const { - glActiveTexture(unit); - glBindTexture(type, m_texture); -} - -TextureDimensions -Texture::getSize(const glTexture & texture) -{ - TextureDimensions size {}; - glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_WIDTH, &size.x); - glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_HEIGHT, &size.y); - glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_DEPTH, &size.z); - return size; + 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 = getSize(texture); + const auto size = texture.getSize(); const size_t dataSize = (static_cast(size.x * size.y * size.z * channels)); const size_t fileSize = dataSize + sizeof(TGAHead); @@ -132,7 +120,7 @@ Texture::saveNormal(const glTexture & texture, const char * path) TextureAtlas::TextureAtlas(GLsizei width, GLsizei height, GLuint count) : Texture(width, height, nullptr, {}) { - glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas); + m_atlas.bind(GL_TEXTURE_RECTANGLE); glTexParameter(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameter(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -147,8 +135,7 @@ void TextureAtlas::bind(GLenum unit) const { Texture::bind(unit); - glActiveTexture(unit + 1); - glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas); + m_atlas.bind(GL_TEXTURE_RECTANGLE, unit + 1); } GLuint diff --git a/gfx/models/texture.h b/gfx/models/texture.h index d8c3b29..03d296a 100644 --- a/gfx/models/texture.h +++ b/gfx/models/texture.h @@ -1,7 +1,7 @@ #pragma once #include "config/types.h" -#include "glArrays.h" +#include "gfx/gl/glTexture.h" #include "stdTypeDefs.h" #include #include @@ -38,7 +38,6 @@ public: static void saveDepth(const glTexture &, const char * path); static void saveNormal(const glTexture &, const char * path); static void savePosition(const glTexture &, const char * path); - static TextureDimensions getSize(const glTexture &); protected: static void save(const glTexture &, GLenum, GLenum, uint8_t channels, const char * path, uint8_t tgaFormat); diff --git a/lib/glArrays.h b/lib/glArrays.h index 3327d8a..48bd577 100644 --- a/lib/glArrays.h +++ b/lib/glArrays.h @@ -123,8 +123,6 @@ template using glVertexArrays = glManagedArray; template using glBuffers = glManagedArray; using glBuffer = glManagedSingle; -template using glTextures = glManagedArray; -using glTexture = glManagedSingle; template using glFrameBuffers = glManagedArray; using glFrameBuffer = glManagedSingle; template diff --git a/test/test-ui.cpp b/test/test-ui.cpp index 40c041a..c648c2c 100644 --- a/test/test-ui.cpp +++ b/test/test-ui.cpp @@ -15,7 +15,7 @@ BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); BOOST_AUTO_TEST_CASE(LoadFromFile) { SvgIcon svg(ImageDimensions {RENDER_SIZE}, Resource::mapPath("ui/icon/rails.svg")); - const auto size = Texture::getSize(svg.texture); + 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()); } diff --git a/test/testRenderOutput.cpp b/test/testRenderOutput.cpp index 2c74ceb..ae2e60d 100644 --- a/test/testRenderOutput.cpp +++ b/test/testRenderOutput.cpp @@ -6,8 +6,8 @@ TestRenderOutput::TestRenderOutput(TextureAbsCoord outputSize) : size {outputSiz { glBindFramebuffer(GL_FRAMEBUFFER, output); const auto configuregdata - = [this](const GLuint data, const GLint format, const GLenum type, const GLenum attachment) { - glBindTexture(GL_TEXTURE_2D, data); + = [this](const auto & 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); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/ui/font.cpp b/ui/font.cpp index ebd29d0..d8e1257 100644 --- a/ui/font.cpp +++ b/ui/font.cpp @@ -116,12 +116,12 @@ Font::getTextureWithSpace(unsigned int adv) const return (ft.used + adv) < size.x; }); itr != fontTextures.end()) { - glBindTexture(GL_TEXTURE_2D, itr->texture); + itr->texture.bind(); return static_cast(itr - fontTextures.begin()); } auto & texture = fontTextures.emplace_back(); - glBindTexture(GL_TEXTURE_2D, texture.texture); + texture.texture.bind(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, static_cast(size.x), static_cast(size.y), 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); diff --git a/ui/font.h b/ui/font.h index 3254f80..8cf3229 100644 --- a/ui/font.h +++ b/ui/font.h @@ -1,9 +1,9 @@ #pragma once +#include "gfx/gl/glTexture.h" #include #include #include -#include #include #include #include diff --git a/ui/icon.cpp b/ui/icon.cpp index 0bdc91a..0422804 100644 --- a/ui/icon.cpp +++ b/ui/icon.cpp @@ -11,7 +11,7 @@ Icon::Icon(const std::filesystem::path & fileName) : Icon {Image {Resource::mapP Icon::Icon(const Image & tex) : size {tex.width, tex.height} { - glBindTexture(GL_TEXTURE_2D, m_texture); + m_texture.bind(); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); diff --git a/ui/icon.h b/ui/icon.h index 14aa79b..2023be8 100644 --- a/ui/icon.h +++ b/ui/icon.h @@ -1,7 +1,7 @@ #pragma once +#include "gfx/gl/glTexture.h" #include -#include #include #include diff --git a/ui/svgIcon.cpp b/ui/svgIcon.cpp index 499d9cc..42e046a 100644 --- a/ui/svgIcon.cpp +++ b/ui/svgIcon.cpp @@ -15,7 +15,7 @@ SvgIcon::SvgIcon(ImageDimensions dim, const std::filesystem::path & path) } bitmap.convertToRGBA(); - glBindTexture(GL_TEXTURE_2D, texture); + texture.bind(); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); diff --git a/ui/svgIcon.h b/ui/svgIcon.h index 02c1e53..be01446 100644 --- a/ui/svgIcon.h +++ b/ui/svgIcon.h @@ -1,6 +1,6 @@ #pragma once -#include "glArrays.h" +#include "gfx/gl/glTexture.h" #include #include #include -- cgit v1.3