diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2024-09-23 20:12:48 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2024-09-23 20:12:48 +0100 |
commit | dbbfd39eef3b4d063ab7cdeb8d139b1bc11ba72c (patch) | |
tree | 0a880b2d14ac152014649d32088b73f17bf77297 /gfx | |
parent | Merge branch 'sunpos' (diff) | |
parent | Populate all layers of shadow stencil with view from all around (diff) | |
download | ilt-dbbfd39eef3b4d063ab7cdeb8d139b1bc11ba72c.tar.bz2 ilt-dbbfd39eef3b4d063ab7cdeb8d139b1bc11ba72c.tar.xz ilt-dbbfd39eef3b4d063ab7cdeb8d139b1bc11ba72c.zip |
Psycho-rebased branch billboard-shadows on top of main
Diffstat (limited to 'gfx')
-rw-r--r-- | gfx/gl/program.h | 6 | ||||
-rw-r--r-- | gfx/gl/sceneRenderer.cpp | 20 | ||||
-rw-r--r-- | gfx/gl/sceneShader.cpp | 2 | ||||
-rw-r--r-- | gfx/gl/shaders/shadowDynamicPointStencil.fs | 16 | ||||
-rw-r--r-- | gfx/gl/shaders/shadowDynamicPointStencil.gs | 33 | ||||
-rw-r--r-- | gfx/gl/shaders/shadowDynamicPointStencil.vs | 17 | ||||
-rw-r--r-- | gfx/gl/shaders/shadowStencil.fs | 18 | ||||
-rw-r--r-- | gfx/gl/shaders/shadowStencil.gs | 28 | ||||
-rw-r--r-- | gfx/gl/shaders/shadowStencil.vs | 20 | ||||
-rw-r--r-- | gfx/gl/shadowMapper.cpp | 59 | ||||
-rw-r--r-- | gfx/gl/shadowMapper.h | 18 | ||||
-rw-r--r-- | gfx/gl/shadowStenciller.cpp | 77 | ||||
-rw-r--r-- | gfx/gl/shadowStenciller.h | 24 | ||||
-rw-r--r-- | gfx/models/mesh.cpp | 28 | ||||
-rw-r--r-- | gfx/models/mesh.h | 30 | ||||
-rw-r--r-- | gfx/models/texture.cpp | 9 | ||||
-rw-r--r-- | gfx/models/texture.h | 2 | ||||
-rw-r--r-- | gfx/renderable.cpp | 5 | ||||
-rw-r--r-- | gfx/renderable.h | 3 |
19 files changed, 390 insertions, 25 deletions
diff --git a/gfx/gl/program.h b/gfx/gl/program.h index c89a128..20be1aa 100644 --- a/gfx/gl/program.h +++ b/gfx/gl/program.h @@ -33,6 +33,12 @@ public: return location; } + explicit + operator bool() const + { + return location >= 0; + } + protected: GLint location; }; diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp index e0938f2..7aace49 100644 --- a/gfx/gl/sceneRenderer.cpp +++ b/gfx/gl/sceneRenderer.cpp @@ -62,7 +62,7 @@ SceneRenderer::render(const SceneProvider & scene) const shader.setViewProjection(camera.getPosition(), camera.getViewProjection()); glViewport(0, 0, size.x, size.y); - // Geometry pass + // Geometry/colour pass - writes albedo, normal and position textures glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); @@ -73,7 +73,13 @@ SceneRenderer::render(const SceneProvider & scene) const glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); scene.content(shader); - // Illumination pass + // Environment pass - + // * ambient - clears illumination texture - see setAmbientLight + // * directional - updates shadowMapper, reads normal and position, writes illumination - see setDirectionalLight + scene.environment(shader, *this); + + // Scene lights pass - + // * per light - reads normal and position, writes illumination glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll); glBlendFunc(GL_ONE, GL_ONE); glActiveTexture(GL_TEXTURE0); @@ -82,11 +88,10 @@ SceneRenderer::render(const SceneProvider & scene) const glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMapper); - scene.environment(shader, *this); glDisable(GL_DEPTH_TEST); scene.lights(shader); - // Lighting pass + // Composition pass - reads albedo and illumination, writes output glBindFramebuffer(GL_FRAMEBUFFER, output); glViewport(0, 0, size.x, size.y); glCullFace(GL_BACK); @@ -114,6 +119,13 @@ SceneRenderer::setDirectionalLight(const RGB & colour, const Direction3D & direc if (colour.r > 0 || colour.g > 0 || colour.b > 0) { 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); glViewport(0, 0, size.x, size.y); dirLight.use(); dirLight.setDirectionalLight(colour, direction, camera.getPosition(), lvp); diff --git a/gfx/gl/sceneShader.cpp b/gfx/gl/sceneShader.cpp index 4cbccb3..571538a 100644 --- a/gfx/gl/sceneShader.cpp +++ b/gfx/gl/sceneShader.cpp @@ -65,7 +65,7 @@ SceneShader::SceneProgram::setViewProjection(const GlobalPosition3D & viewPoint, void SceneShader::SceneProgram::setViewPort(const ViewPort & viewPort) const { - if (viewPortLoc >= 0) { + if (viewPortLoc) { glUseProgram(*this); glUniform(viewPortLoc, viewPort); } diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.fs b/gfx/gl/shaders/shadowDynamicPointStencil.fs new file mode 100644 index 0000000..e612691 --- /dev/null +++ b/gfx/gl/shaders/shadowDynamicPointStencil.fs @@ -0,0 +1,16 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +layout(binding = 0) uniform sampler2DArray stencilDepth; +flat in vec3 scale; +in vec3 texCoord; + +void +main() +{ + float stDepth = texture(stencilDepth, texCoord).r; + if (stDepth >= 1) { + discard; + } + gl_FragDepth = gl_FragCoord.z + (stDepth * scale.z); +} diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.gs b/gfx/gl/shaders/shadowDynamicPointStencil.gs new file mode 100644 index 0000000..b91937d --- /dev/null +++ b/gfx/gl/shaders/shadowDynamicPointStencil.gs @@ -0,0 +1,33 @@ +#version 330 core +#extension GL_ARB_viewport_array : enable + +const vec2[] corners = vec2[4](vec2(-1, -1), vec2(-1, 1), vec2(1, -1), vec2(1, 1)); + +uniform mat4 viewProjection[4]; +uniform int viewProjections; +uniform vec3 sizes[4]; +uniform float size; + +in ivec3 vworldPos[]; + +flat out vec3 scale; +out vec3 texCoord; + +layout(points) in; +layout(triangle_strip, max_vertices = 16) out; + +void +main() +{ + for (gl_Layer = 0; gl_Layer < viewProjections; ++gl_Layer) { + scale = 2.0 * size / sizes[gl_Layer]; + vec4 pos = viewProjection[gl_Layer] * vec4(vworldPos[0], 1); + for (int c = 0; c < corners.length(); ++c) { + gl_Position = pos + vec4(scale.xy * corners[c], 0, 0); + gl_Position.z = max(gl_Position.z, -1); + texCoord = vec3((corners[c] * 0.5) + 0.5, 0); + EmitVertex(); + } + EndPrimitive(); + } +} diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.vs b/gfx/gl/shaders/shadowDynamicPointStencil.vs new file mode 100644 index 0000000..dadf9c2 --- /dev/null +++ b/gfx/gl/shaders/shadowDynamicPointStencil.vs @@ -0,0 +1,17 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +layout(location = 0) in mat3 model; +layout(location = 3) in ivec3 worldPos; +uniform ivec3 viewPoint; +uniform vec3 centre; + +out mat3 vmodel; +out ivec3 vworldPos; + +void +main() +{ + vmodel = model; + vworldPos = worldPos - viewPoint + ivec3(centre); +} diff --git a/gfx/gl/shaders/shadowStencil.fs b/gfx/gl/shaders/shadowStencil.fs new file mode 100644 index 0000000..1164cc9 --- /dev/null +++ b/gfx/gl/shaders/shadowStencil.fs @@ -0,0 +1,18 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +layout(binding = 0) uniform sampler2D textureAlbedo; + +include(`materialDetail.glsl') +include(`materialCommon.glsl') +in vec2 gTexCoords; +flat in MaterialDetail gMaterial; + +void +main() +{ + if (getTextureColour(gMaterial, gTexCoords).a < 0.5) { + discard; + } + gl_FragDepth = gl_FragCoord.z; +} diff --git a/gfx/gl/shaders/shadowStencil.gs b/gfx/gl/shaders/shadowStencil.gs new file mode 100644 index 0000000..2c3f9bd --- /dev/null +++ b/gfx/gl/shaders/shadowStencil.gs @@ -0,0 +1,28 @@ +#version 330 core +#extension GL_ARB_viewport_array : enable + +include(`materialDetail.glsl') + +layout(triangles) in; +layout(triangle_strip, max_vertices = 24) out; + +uniform mat4 viewProjection[8]; +in vec3 FragPos[]; +in vec2 TexCoords[]; +flat in MaterialDetail Material[]; +out vec2 gTexCoords; +flat out MaterialDetail gMaterial; + +void +main() +{ + for (gl_Layer = 0; gl_Layer < viewProjection.length(); ++gl_Layer) { + for (int v = 0; v < FragPos.length(); ++v) { + gl_Position = viewProjection[gl_Layer] * vec4(FragPos[v], 1); + gTexCoords = TexCoords[v]; + gMaterial = Material[v]; + EmitVertex(); + } + EndPrimitive(); + } +} diff --git a/gfx/gl/shaders/shadowStencil.vs b/gfx/gl/shaders/shadowStencil.vs new file mode 100644 index 0000000..a15c4fb --- /dev/null +++ b/gfx/gl/shaders/shadowStencil.vs @@ -0,0 +1,20 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +layout(binding = 1) uniform usampler2DRect materialData; + +include(`meshIn.glsl') +include(`materialDetail.glsl') +include(`getMaterialDetail.glsl') + +out vec3 FragPos; +out vec2 TexCoords; +flat out MaterialDetail Material; + +void +main() +{ + TexCoords = texCoord; + Material = getMaterialDetail(material); + FragPos = position; +} diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index a846a3d..b08538d 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -1,13 +1,19 @@ #include "shadowMapper.h" #include "camera.h" #include "collections.h" +#include "game/gamestate.h" #include "gfx/gl/shaders/fs-shadowDynamicPointInstWithTextures.h" +#include "gfx/gl/shaders/fs-shadowDynamicPointStencil.h" #include "gfx/gl/shaders/gs-commonShadowPoint.h" #include "gfx/gl/shaders/gs-shadowDynamicPointInstWithTextures.h" +#include "gfx/gl/shaders/gs-shadowDynamicPointStencil.h" #include "gfx/gl/shaders/vs-shadowDynamicPoint.h" #include "gfx/gl/shaders/vs-shadowDynamicPointInst.h" #include "gfx/gl/shaders/vs-shadowDynamicPointInstWithTextures.h" +#include "gfx/gl/shaders/vs-shadowDynamicPointStencil.h" #include "gfx/gl/shaders/vs-shadowLandmass.h" +#include "gfx/gl/shadowStenciller.h" +#include "gfx/renderable.h" #include "gl_traits.h" #include "location.h" #include "maths.h" @@ -74,32 +80,47 @@ ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightV ShadowMapper::Definitions ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const Camera & camera) const { + glCullFace(GL_FRONT); + glEnable(GL_DEPTH_TEST); + + shadowStenciller.setLightDirection(dir, up); + for (const auto & [id, asset] : gameState->assets) { + if (const auto r = std::dynamic_pointer_cast<const Renderable>(asset)) { + r->updateStencil(shadowStenciller); + } + } + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glClear(GL_DEPTH_BUFFER_BIT); - glCullFace(GL_FRONT); glViewport(0, 0, size.x, size.y); const auto lightViewDir = glm::lookAt({}, dir, up); const auto lightViewPoint = camera.getPosition(); const auto bandViewExtents = getBandViewExtents(camera, lightViewDir); Definitions out; + Sizes sizes; std::transform(bandViewExtents.begin(), std::prev(bandViewExtents.end()), std::next(bandViewExtents.begin()), std::back_inserter(out), - [bands = bandViewExtents.size() - 2, &lightViewDir](const auto & near, const auto & far) mutable { - const auto extents_minmax = [extents = std::span {near.begin(), far.end()}](auto && comp) { - const auto mm = std::minmax_element(extents.begin(), extents.end(), comp); - return std::make_pair(comp.get(*mm.first), comp.get(*mm.second)); - }; + [bands = bandViewExtents.size() - 2, &lightViewDir, &sizes](const auto & near, const auto & far) mutable { + const auto extents_minmax + = [extents = std::span {near.begin(), far.end()}](auto && comp, RelativeDistance extra) { + const auto mm = std::minmax_element(extents.begin(), extents.end(), comp); + return std::make_pair(comp.get(*mm.first) - extra, comp.get(*mm.second) + extra); + }; + const std::array extents = {extents_minmax(CompareBy {0}, 0), extents_minmax(CompareBy {1}, 0), + extents_minmax(CompareBy {2}, 10'000)}; const auto lightProjection = [](const auto & x, const auto & y, const auto & z) { return glm::ortho(x.first, x.second, y.first, y.second, -z.second, -z.first); - }(extents_minmax(CompareBy {0}), extents_minmax(CompareBy {1}), extents_minmax(CompareBy {2})); + }(extents[0], extents[1], extents[2]); + sizes.emplace_back(extents[0].second - extents[0].first, extents[1].second - extents[1].first, + extents[2].second - extents[2].first); return lightProjection * lightViewDir; }); for (const auto p : std::initializer_list<const ShadowProgram *> { - &landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures}) { - p->setView(out, lightViewPoint); + &landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures, &stencilShadowProgram}) { + p->setView(out, sizes, lightViewPoint); } scene.shadows(*this); @@ -116,12 +137,15 @@ ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs, const Shader & gs, } void -ShadowMapper::ShadowProgram::setView( - const std::span<const glm::mat4> viewProjection, const GlobalPosition3D viewPoint) const +ShadowMapper::ShadowProgram::setView(const std::span<const glm::mat4x4> viewProjection, + const std::span<const RelativePosition3D> sizes, const GlobalPosition3D viewPoint) const { use(); glUniform(viewPointLoc, viewPoint); glUniform(viewProjectionLoc, viewProjection); + if (sizesLoc) { + glUniform(sizesLoc, sizes); + } glUniform(viewProjectionsLoc, static_cast<GLint>(viewProjection.size())); } @@ -146,3 +170,16 @@ ShadowMapper::DynamicPoint::setModel(const Location & location) const glUniform(modelLoc, location.getRotationTransform()); glUniform(modelPosLoc, location.pos); } + +ShadowMapper::StencilShadowProgram::StencilShadowProgram() : + ShadowProgram {shadowDynamicPointStencil_vs, shadowDynamicPointStencil_gs, shadowDynamicPointStencil_fs} +{ +} + +void +ShadowMapper::StencilShadowProgram::use(const RelativePosition3D & centre, const float size) const +{ + Program::use(); + glUniform(centreLoc, centre); + glUniform(sizeLoc, size); +} diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h index 73dadd0..3aa224e 100644 --- a/gfx/gl/shadowMapper.h +++ b/gfx/gl/shadowMapper.h @@ -1,6 +1,7 @@ #pragma once #include "config/types.h" +#include "gfx/gl/shadowStenciller.h" #include "lib/glArrays.h" #include "program.h" #include <gfx/models/texture.h> @@ -18,6 +19,7 @@ public: static constexpr std::size_t SHADOW_BANDS {4}; using Definitions = std::vector<glm::mat4x4>; + using Sizes = std::vector<RelativePosition3D>; [[nodiscard]] Definitions update(const SceneProvider &, const Direction3D & direction, const Camera &) const; @@ -26,12 +28,14 @@ public: explicit ShadowProgram(const Shader & vs); explicit ShadowProgram(const Shader & vs, const Shader & gs, const Shader & fs); - void setView(const std::span<const glm::mat4>, const GlobalPosition3D) const; + void setView(const std::span<const glm::mat4x4>, const std::span<const RelativePosition3D>, + const GlobalPosition3D) const; void use() const; private: RequiredUniformLocation viewProjectionLoc {*this, "viewProjection"}; RequiredUniformLocation viewProjectionsLoc {*this, "viewProjections"}; + UniformLocation sizesLoc {*this, "sizes"}; RequiredUniformLocation viewPointLoc {*this, "viewPoint"}; }; @@ -46,8 +50,19 @@ public: RequiredUniformLocation modelPosLoc {*this, "modelPos"}; }; + class StencilShadowProgram : public ShadowProgram { + public: + StencilShadowProgram(); + void use(const RelativePosition3D & centre, const float size) const; + + private: + RequiredUniformLocation centreLoc {*this, "centre"}; + RequiredUniformLocation sizeLoc {*this, "size"}; + }; + ShadowProgram landmess, dynamicPointInst, dynamicPointInstWithTextures; DynamicPoint dynamicPoint; + StencilShadowProgram stencilShadowProgram; // NOLINTNEXTLINE(hicpp-explicit-conversions) operator GLuint() const @@ -61,4 +76,5 @@ private: glFrameBuffer depthMapFBO; glTexture depthMap; TextureAbsCoord size; + mutable ShadowStenciller shadowStenciller; }; diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp new file mode 100644 index 0000000..da2b3a0 --- /dev/null +++ b/gfx/gl/shadowStenciller.cpp @@ -0,0 +1,77 @@ +#include "shadowStenciller.h" +#include "gfx/gl/program.h" +#include "gfx/gl/shaders/fs-shadowStencil.h" +#include "gfx/gl/shaders/gs-shadowStencil.h" +#include "gfx/gl/shaders/vs-shadowStencil.h" +#include "gfx/models/mesh.h" +#include "glArrays.h" +#include "gl_traits.h" +#include "maths.h" +#include <stdexcept> + +namespace { + static constexpr std::array<float, 8> anglesEigthPi {-3, -2, -1, 0, 1, 2, 3, 4}; + static const auto angles = anglesEigthPi * [](auto ep) { + return rotate_yaw(ep * quarter_pi); + }; +} + +ShadowStenciller::ShadowStenciller() : + shadowCaster {shadowStencil_vs, shadowStencil_gs, shadowStencil_fs}, viewProjections {} +{ + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void +ShadowStenciller::setLightDirection(const Direction3D & lightDir, const Direction3D & lightDirUp) +{ + lightDirMat = glm::lookAt(-lightDir, {}, lightDirUp); + viewProjections = angles * [this](const auto & a) { + return lightDirMat * a; + }; +} + +glTexture +ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) +{ + glTexture stencil; + glBindTexture(GL_TEXTURE_2D_ARRAY, stencil); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + 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); + glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT, width, height, 8, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, + nullptr); + + return stencil; +} + +void +ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh, const Texture::AnyPtr texture) const +{ + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, stencil, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + throw std::runtime_error("Stencil framebuffer not complete!"); + } + if (texture) { + texture->bind(); + } + glUseProgram(shadowCaster); + glClear(GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, 256, 256); + const auto & centre = mesh.getDimensions().centre; + const auto & size = mesh.getDimensions().size; + const auto extentsMat + = glm::translate(glm::ortho(-size, size, -size, size, -size, size), {-centre.x, -centre.z, -centre.y}); + glUniform(viewProjectionLoc, std::span<const glm::mat4> {viewProjections * [&](const auto & vp) { + return extentsMat * vp; + }}); + mesh.Draw(); +} diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h new file mode 100644 index 0000000..2edb955 --- /dev/null +++ b/gfx/gl/shadowStenciller.h @@ -0,0 +1,24 @@ +#pragma once + +#include "gfx/gl/program.h" +#include "gfx/models/mesh.h" +#include "gfx/models/texture.h" +#include "glArrays.h" + +class ShadowStenciller { +public: + ShadowStenciller(); + + [[nodiscard]] + static glTexture createStencilTexture(GLsizei width, GLsizei height); + void setLightDirection(const Direction3D & lightDir, const Direction3D & lightDirUp); + void renderStencil(const glTexture &, const MeshBase &, const Texture::AnyPtr texture) const; + +private: + glFrameBuffer fbo; + Program shadowCaster; + Program::RequiredUniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; + + glm::mat4 lightDirMat {}; + std::array<glm::mat4, 8> viewProjections; +}; diff --git a/gfx/models/mesh.cpp b/gfx/models/mesh.cpp index e7474ca..2eae160 100644 --- a/gfx/models/mesh.cpp +++ b/gfx/models/mesh.cpp @@ -1,6 +1,32 @@ #include "mesh.h" -MeshBase::MeshBase(GLsizei m_numIndices, GLenum mode) : m_numIndices {m_numIndices}, mode {mode} { } +MeshBase::MeshBase(GLsizei m_numIndices, GLenum mode, const std::vector<RelativePosition3D> & positions) : + m_numIndices {m_numIndices}, mode {mode}, dimensions {positions} +{ +} + +MeshBase::Dimensions::Dimensions(const std::span<const RelativePosition3D> positions) : + Dimensions {positions, {extents(positions, 0), extents(positions, 1), extents(positions, 2)}} +{ +} + +MeshBase::Dimensions::Dimensions( + const std::span<const RelativePosition3D> positions, const std::array<Extents1D, 3> & extents1ds) : + minExtent(extents1ds[0].min, extents1ds[1].min, extents1ds[2].min), + maxExtent(extents1ds[0].max, extents1ds[1].max, extents1ds[2].max), centre {(minExtent + maxExtent) / 2.0F}, + size {std::ranges::max(positions | std::views::transform([this](const auto & v) { + return glm::distance(v, centre); + }))} +{ +} + +MeshBase::Dimensions::Extents1D +MeshBase::Dimensions::extents(const std::span<const RelativePosition3D> positions, glm::length_t D) +{ + return std::ranges::minmax(positions | std::views::transform([D](const auto & v) { + return v[D]; + })); +} void MeshBase::Draw() const diff --git a/gfx/models/mesh.h b/gfx/models/mesh.h index 248cb8f..8791aed 100644 --- a/gfx/models/mesh.h +++ b/gfx/models/mesh.h @@ -1,8 +1,10 @@ #pragma once +#include "config/types.h" #include "gfx/gl/vertexArrayObject.h" #include <glArrays.h> #include <glad/gl.h> +#include <ranges> #include <span> #include <stdTypeDefs.h> @@ -10,22 +12,46 @@ class Vertex; class MeshBase { public: + class Dimensions { + public: + using Extents1D = std::ranges::minmax_result<RelativeDistance>; + explicit Dimensions(const std::span<const RelativePosition3D>); + + RelativePosition3D minExtent, maxExtent; + RelativePosition3D centre; + RelativeDistance size; + + private: + Dimensions(const std::span<const RelativePosition3D>, const std::array<Extents1D, 3> &); + static Extents1D extents(const std::span<const RelativePosition3D>, glm::length_t D); + }; + void Draw() const; void DrawInstanced(GLuint vao, GLsizei count, GLuint base = 0) const; + [[nodiscard]] const Dimensions & + getDimensions() const + { + return dimensions; + } + protected: - MeshBase(GLsizei m_numIndices, GLenum mode); + MeshBase(GLsizei m_numIndices, GLenum mode, const std::vector<RelativePosition3D> &); glVertexArray m_vertexArrayObject; glBuffers<2> m_vertexArrayBuffers; GLsizei m_numIndices; GLenum mode; + Dimensions dimensions; }; template<typename V> class MeshT : public MeshBase, public ConstTypeDefs<MeshT<V>> { public: MeshT(const std::span<const V> vertices, const std::span<const unsigned int> indices, GLenum mode = GL_TRIANGLES) : - MeshBase {static_cast<GLsizei>(indices.size()), mode} + MeshBase {static_cast<GLsizei>(indices.size()), mode, + materializeRange(vertices | std::views::transform([](const auto & v) { + return static_cast<RelativePosition3D>(v.pos); + }))} { VertexArrayObject::data(vertices, m_vertexArrayBuffers[0], GL_ARRAY_BUFFER); VertexArrayObject::data(indices, m_vertexArrayBuffers[1], GL_ARRAY_BUFFER); diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index 51223aa..a508421 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -59,12 +59,13 @@ Texture::bind(GLenum unit) const glBindTexture(type, m_texture); } -TextureAbsCoord +TextureDimensions Texture::getSize(const glTexture & texture) { - TextureAbsCoord size; + 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; } @@ -73,7 +74,7 @@ Texture::save( const glTexture & texture, GLenum format, GLenum type, uint8_t channels, const char * path, uint8_t tgaFormat) { const auto size = getSize(texture); - const size_t dataSize = (static_cast<size_t>(size.x * size.y * channels)); + const size_t 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}; @@ -81,7 +82,7 @@ Texture::save( auto tga = out.mmap(fileSize, 0, PROT_WRITE, MAP_SHARED); *tga.get<TGAHead>() = { .format = tgaFormat, - .size = size, + .size = {size.x, size.y * size.z}, .pixelDepth = static_cast<uint8_t>(8 * channels), }; glPixelStorei(GL_PACK_ALIGNMENT, 1); diff --git a/gfx/models/texture.h b/gfx/models/texture.h index 8cb8128..3329511 100644 --- a/gfx/models/texture.h +++ b/gfx/models/texture.h @@ -41,7 +41,7 @@ public: protected: static void save(const glTexture &, GLenum, GLenum, uint8_t channels, const char * path, uint8_t tgaFormat); - static TextureAbsCoord getSize(const glTexture &); + static TextureDimensions getSize(const glTexture &); glTexture m_texture; GLenum type; diff --git a/gfx/renderable.cpp b/gfx/renderable.cpp index 0340189..3594968 100644 --- a/gfx/renderable.cpp +++ b/gfx/renderable.cpp @@ -9,3 +9,8 @@ void Renderable::shadows(const ShadowMapper &) const { } + +void +Renderable::updateStencil(const ShadowStenciller &) const +{ +} diff --git a/gfx/renderable.h b/gfx/renderable.h index e126fff..83522e3 100644 --- a/gfx/renderable.h +++ b/gfx/renderable.h @@ -4,6 +4,7 @@ class SceneShader; class ShadowMapper; +class ShadowStenciller; class Renderable { public: @@ -14,4 +15,6 @@ public: virtual void render(const SceneShader & shader) const = 0; virtual void lights(const SceneShader & shader) const; virtual void shadows(const ShadowMapper & shadowMapper) const; + + virtual void updateStencil(const ShadowStenciller & lightDir) const; }; |