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 /gfx | |
| 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
Diffstat (limited to 'gfx')
| -rw-r--r-- | gfx/gl/billboardPainter.cpp | 19 | ||||
| -rw-r--r-- | gfx/gl/billboardPainter.h | 4 | ||||
| -rw-r--r-- | gfx/gl/glTexture.cpp | 161 | ||||
| -rw-r--r-- | gfx/gl/glTexture.h | 58 | ||||
| -rw-r--r-- | gfx/gl/sceneRenderer.cpp | 73 | ||||
| -rw-r--r-- | gfx/gl/sceneRenderer.h | 3 | ||||
| -rw-r--r-- | gfx/gl/shadowMapper.cpp | 5 | ||||
| -rw-r--r-- | gfx/gl/shadowMapper.h | 4 | ||||
| -rw-r--r-- | gfx/gl/shadowStenciller.cpp | 13 | ||||
| -rw-r--r-- | gfx/gl/shadowStenciller.h | 4 | ||||
| -rw-r--r-- | gfx/models/texture.cpp | 86 | ||||
| -rw-r--r-- | gfx/models/texture.h | 19 |
12 files changed, 289 insertions, 160 deletions
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 {}; }; |
