summaryrefslogtreecommitdiff
path: root/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'gfx')
-rw-r--r--gfx/aabb.h41
-rw-r--r--gfx/camera.cpp (renamed from gfx/gl/camera.cpp)33
-rw-r--r--gfx/camera.h (renamed from gfx/gl/camera.h)26
-rw-r--r--gfx/followCameraController.cpp2
-rw-r--r--gfx/frustum.cpp67
-rw-r--r--gfx/frustum.h45
-rw-r--r--gfx/gl/gldebug.cpp20
-rw-r--r--gfx/gl/gldebug.h52
-rw-r--r--gfx/gl/program.cpp3
-rw-r--r--gfx/gl/program.h5
-rw-r--r--gfx/gl/sceneProvider.cpp4
-rw-r--r--gfx/gl/sceneProvider.h5
-rw-r--r--gfx/gl/sceneRenderer.cpp129
-rw-r--r--gfx/gl/sceneRenderer.h9
-rw-r--r--gfx/gl/sceneShader.cpp61
-rw-r--r--gfx/gl/sceneShader.h12
-rw-r--r--gfx/gl/shader.cpp18
-rw-r--r--gfx/gl/shaders/commonShadowPoint.geom (renamed from gfx/gl/shaders/commonShadowPoint.gs)3
-rw-r--r--gfx/gl/shaders/directionalLight.frag (renamed from gfx/gl/shaders/directionalLight.fs)5
-rw-r--r--gfx/gl/shaders/dynamicPoint.vert (renamed from gfx/gl/shaders/dynamicPoint.vs)3
-rw-r--r--gfx/gl/shaders/dynamicPointInst.vert (renamed from gfx/gl/shaders/dynamicPointInst.vs)3
-rw-r--r--gfx/gl/shaders/fixedPoint.vert (renamed from gfx/gl/shaders/fixedPoint.vs)3
-rw-r--r--gfx/gl/shaders/landmass.frag (renamed from gfx/gl/shaders/landmass.fs)8
-rw-r--r--gfx/gl/shaders/landmass.vert (renamed from gfx/gl/shaders/landmass.vs)6
-rw-r--r--gfx/gl/shaders/lighting.frag (renamed from gfx/gl/shaders/lighting.fs)3
-rw-r--r--gfx/gl/shaders/lighting.vert (renamed from gfx/gl/shaders/lighting.vs)2
-rw-r--r--gfx/gl/shaders/material.frag (renamed from gfx/gl/shaders/material.fs)3
-rw-r--r--gfx/gl/shaders/materialCommon.glsl2
-rw-r--r--gfx/gl/shaders/materialInterface.glsl2
-rw-r--r--gfx/gl/shaders/network.frag (renamed from gfx/gl/shaders/network.fs)3
-rw-r--r--gfx/gl/shaders/networkCommon.glsl10
-rw-r--r--gfx/gl/shaders/networkCurve.geom17
-rw-r--r--gfx/gl/shaders/networkCurve.gs47
-rw-r--r--gfx/gl/shaders/networkCurve.tesc37
-rw-r--r--gfx/gl/shaders/networkCurve.tese45
-rw-r--r--gfx/gl/shaders/networkCurve.vert23
-rw-r--r--gfx/gl/shaders/networkCurve.vs29
-rw-r--r--gfx/gl/shaders/networkStraight.geom (renamed from gfx/gl/shaders/networkStraight.gs)12
-rw-r--r--gfx/gl/shaders/networkStraight.vert (renamed from gfx/gl/shaders/networkStraight.vs)13
-rw-r--r--gfx/gl/shaders/pointLight.frag (renamed from gfx/gl/shaders/pointLight.fs)3
-rw-r--r--gfx/gl/shaders/pointLight.geom (renamed from gfx/gl/shaders/pointLight.gs)4
-rw-r--r--gfx/gl/shaders/pointLight.vert (renamed from gfx/gl/shaders/pointLight.vs)2
-rw-r--r--gfx/gl/shaders/shadowDynamicPoint.vert (renamed from gfx/gl/shaders/shadowDynamicPoint.vs)2
-rw-r--r--gfx/gl/shaders/shadowDynamicPointInst.vert (renamed from gfx/gl/shaders/shadowDynamicPointInst.vs)2
-rw-r--r--gfx/gl/shaders/shadowDynamicPointInstWithTextures.frag (renamed from gfx/gl/shaders/shadowDynamicPointInstWithTextures.fs)3
-rw-r--r--gfx/gl/shaders/shadowDynamicPointInstWithTextures.geom3
-rw-r--r--gfx/gl/shaders/shadowDynamicPointInstWithTextures.gs3
-rw-r--r--gfx/gl/shaders/shadowDynamicPointInstWithTextures.vert (renamed from gfx/gl/shaders/shadowDynamicPointInstWithTextures.vs)3
-rw-r--r--gfx/gl/shaders/shadowDynamicPointStencil.frag (renamed from gfx/gl/shaders/shadowDynamicPointStencil.fs)3
-rw-r--r--gfx/gl/shaders/shadowDynamicPointStencil.geom (renamed from gfx/gl/shaders/shadowDynamicPointStencil.gs)3
-rw-r--r--gfx/gl/shaders/shadowDynamicPointStencil.vert (renamed from gfx/gl/shaders/shadowDynamicPointStencil.vs)3
-rw-r--r--gfx/gl/shaders/shadowLandmass.vert (renamed from gfx/gl/shaders/shadowLandmass.vs)2
-rw-r--r--gfx/gl/shaders/shadowStencil.frag (renamed from gfx/gl/shaders/shadowStencil.fs)3
-rw-r--r--gfx/gl/shaders/shadowStencil.geom (renamed from gfx/gl/shaders/shadowStencil.gs)3
-rw-r--r--gfx/gl/shaders/shadowStencil.vert (renamed from gfx/gl/shaders/shadowStencil.vs)3
-rw-r--r--gfx/gl/shaders/spotLight.frag (renamed from gfx/gl/shaders/spotLight.fs)3
-rw-r--r--gfx/gl/shaders/spotLight.geom (renamed from gfx/gl/shaders/spotLight.gs)4
-rw-r--r--gfx/gl/shaders/spotLight.vert (renamed from gfx/gl/shaders/spotLight.vs)2
-rw-r--r--gfx/gl/shaders/uiShader.fs11
-rw-r--r--gfx/gl/shaders/uiShader.vs13
-rw-r--r--gfx/gl/shaders/uiShaderFont.fs12
-rw-r--r--gfx/gl/shaders/water.frag (renamed from gfx/gl/shaders/water.fs)3
-rw-r--r--gfx/gl/shaders/water.vert (renamed from gfx/gl/shaders/water.vs)2
-rw-r--r--gfx/gl/shadowMapper.cpp79
-rw-r--r--gfx/gl/shadowStenciller.cpp12
-rw-r--r--gfx/gl/uiShader.cpp27
-rw-r--r--gfx/gl/uiShader.h47
-rw-r--r--gfx/gl/vertexArrayObject.h12
-rw-r--r--gfx/models/texture.cpp10
-rw-r--r--gfx/renderable.cpp2
-rw-r--r--gfx/renderable.h5
71 files changed, 664 insertions, 436 deletions
diff --git a/gfx/aabb.h b/gfx/aabb.h
new file mode 100644
index 0000000..ce15a0f
--- /dev/null
+++ b/gfx/aabb.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "maths.h"
+#include <algorithm>
+#include <tuple>
+
+template<Arithmetic T, glm::qualifier Q = glm::defaultp> class AxisAlignedBoundingBox {
+public:
+ using V = glm::vec<3, T, Q>;
+ AxisAlignedBoundingBox() = default;
+
+ AxisAlignedBoundingBox(const V & min, const V & max) : min {min}, max {max} { }
+
+ AxisAlignedBoundingBox &
+ operator+=(const V & point)
+ {
+ min = glm::min(min, point);
+ max = glm::max(max, point);
+ return *this;
+ }
+
+ AxisAlignedBoundingBox
+ operator-(const V & viewPoint) const
+ {
+ return {min - viewPoint, max - viewPoint};
+ }
+
+ [[nodiscard]] static AxisAlignedBoundingBox
+ fromPoints(auto && points)
+ {
+ using Limits = std::numeric_limits<T>;
+ static constexpr const auto INITIAL = std::make_pair(V {Limits::max()}, V {Limits::min()});
+ return std::make_from_tuple<AxisAlignedBoundingBox<T, Q>>(
+ std::ranges::fold_left(points, INITIAL, [](const auto & prev, const auto & point) {
+ auto & [min, max] = prev;
+ return std::make_pair(glm::min(min, point), glm::max(max, point));
+ }));
+ }
+
+ V min {}, max {};
+};
diff --git a/gfx/gl/camera.cpp b/gfx/camera.cpp
index 82b11a6..3bb785d 100644
--- a/gfx/gl/camera.cpp
+++ b/gfx/camera.cpp
@@ -4,28 +4,39 @@
#include <maths.h>
#include <ray.h>
-Camera::Camera(GlobalPosition3D pos, Angle fov, Angle aspect, GlobalDistance zNear, GlobalDistance zFar) :
- position {pos}, forward {::north}, up {::up}, near {zNear}, far {zFar},
- projection {
- glm::perspective(fov, aspect, static_cast<RelativeDistance>(zNear), static_cast<RelativeDistance>(zFar))},
- viewProjection {}, inverseViewProjection {}
+Camera::Camera(GlobalPosition3D pos, Angle fov, Angle aspect, GlobalDistance near, GlobalDistance far) :
+ Camera {pos, fov, aspect, near, far, glm::lookAt({}, ::north, ::up),
+ glm::perspective(fov, aspect, static_cast<RelativeDistance>(near), static_cast<RelativeDistance>(far))}
{
- updateView();
+}
+
+Camera::Camera(GlobalPosition3D pos, Angle fov, Angle aspect, GlobalDistance near, GlobalDistance far,
+ const glm::mat4 & view, const glm::mat4 & projection) :
+ Frustum {pos, view, projection}, fov {fov}, aspect {aspect}, forward {::north}, up {::up}, near {near}, far {far}
+{
+}
+
+void
+Camera::setAspect(Angle aspect)
+{
+ projection = glm::perspective(fov, aspect, static_cast<RelativeDistance>(near), static_cast<RelativeDistance>(far));
+ Frustum::updateCache();
}
Ray<GlobalPosition3D>
Camera::unProject(const ScreenRelCoord & mouse) const
{
- static constexpr const glm::vec4 screen {0, 0, 1, 1};
- const auto mouseProjection = glm::lookAt({}, forward, up);
- return {position, glm::normalize(glm::unProject(mouse || 1.F, mouseProjection, projection, screen))};
+ static constexpr const glm::vec4 SCREEN {0, 0, 1, 1};
+ return {
+ .start = position,
+ .direction = glm::normalize(glm::unProject(mouse || 1.F, view, projection, SCREEN)),
+ };
}
void
Camera::updateView()
{
- viewProjection = projection * glm::lookAt({}, forward, up);
- inverseViewProjection = glm::inverse(viewProjection);
+ Frustum::updateView(glm::lookAt({}, forward, up));
}
Direction3D
diff --git a/gfx/gl/camera.h b/gfx/camera.h
index 8d53261..b17bcbb 100644
--- a/gfx/gl/camera.h
+++ b/gfx/camera.h
@@ -1,22 +1,19 @@
#pragma once
#include "config/types.h"
+#include "frustum.h"
#include <glm/glm.hpp>
#include <maths.h>
#include <ray.h>
-class Camera {
+class Camera : public Frustum {
public:
- Camera(GlobalPosition3D, Angle fov, Angle aspect, GlobalDistance zNear, GlobalDistance zFar);
-
- [[nodiscard]] glm::mat4
- getViewProjection() const
- {
- return viewProjection;
- }
+ Camera(GlobalPosition3D position, Angle fov, Angle aspect, GlobalDistance near, GlobalDistance far);
[[nodiscard]] Ray<GlobalPosition3D> unProject(const ScreenRelCoord &) const;
+ void setAspect(Angle aspect);
+
void
setPosition(const GlobalPosition3D & p)
{
@@ -64,24 +61,17 @@ public:
return forward;
}
- [[nodiscard]] auto
- getPosition() const
- {
- return position;
- }
-
[[nodiscard]] std::array<GlobalPosition4D, 4> extentsAtDist(GlobalDistance) const;
[[nodiscard]] static Direction3D upFromForward(const Direction3D & forward);
private:
+ Camera(GlobalPosition3D position, Angle fov, Angle aspect, GlobalDistance near, GlobalDistance far,
+ const glm::mat4 & view, const glm::mat4 & projection);
void updateView();
- GlobalPosition3D position;
+ Angle fov, aspect;
Direction3D forward;
Direction3D up;
-
GlobalDistance near, far;
- glm::mat4 projection;
- glm::mat4 viewProjection, inverseViewProjection;
};
diff --git a/gfx/followCameraController.cpp b/gfx/followCameraController.cpp
index cf6da34..d7bbc0b 100644
--- a/gfx/followCameraController.cpp
+++ b/gfx/followCameraController.cpp
@@ -1,6 +1,6 @@
#include "followCameraController.h"
#include "game/vehicles/vehicle.h"
-#include <gfx/gl/camera.h>
+#include <gfx/camera.h>
#include <glm/glm.hpp>
#include <location.h>
#include <maths.h>
diff --git a/gfx/frustum.cpp b/gfx/frustum.cpp
new file mode 100644
index 0000000..faa676d
--- /dev/null
+++ b/gfx/frustum.cpp
@@ -0,0 +1,67 @@
+#include "frustum.h"
+#include <algorithm>
+#include <collections.h>
+#include <glm/ext/matrix_transform.hpp>
+
+static constexpr auto PLANES = std::array {0, 1, 2} * std::array {-1.F, 1.F};
+
+Frustum::Frustum(const GlobalPosition3D & pos, const glm::mat4 & view, const glm::mat4 & projection) :
+ position {pos}, view {view}, projection {projection}, viewProjection {}, inverseViewProjection {}, planes {}
+{
+ updateCache();
+}
+
+void
+Frustum::updateView(const glm::mat4 & newView)
+{
+ view = newView;
+ updateCache();
+}
+
+bool
+Frustum::contains(const BoundingBox & aabb) const
+{
+ return boundByPlanes(aabb, FACES);
+}
+
+bool
+Frustum::shadedBy(const BoundingBox & aabb) const
+{
+ return boundByPlanes(aabb, FACES - 1);
+}
+
+bool
+Frustum::boundByPlanes(const BoundingBox & aabb, size_t nplanes) const
+{
+ static constexpr auto EXTENT_CORNER_IDXS = [] {
+ using Extent = GlobalPosition3D BoundingBox::*;
+ constexpr auto EXTENTS = std::array {&BoundingBox::min, &BoundingBox::max};
+ std::array<glm::vec<3, Extent>, 2ZU * 2ZU * 2ZU> out {};
+ std::ranges::copy(std::views::cartesian_product(EXTENTS, EXTENTS, EXTENTS)
+ | std::views::transform(
+ std::make_from_tuple<glm::vec<3, Extent>, std::tuple<Extent, Extent, Extent>>),
+ out.begin());
+ return out;
+ }();
+
+ const std::array<RelativePosition4D, 8> corners
+ = EXTENT_CORNER_IDXS * [relativeAabb = aabb - position](auto idxs) -> glm::vec4 {
+ return {(relativeAabb.*(idxs.x)).x, (relativeAabb.*(idxs.y)).y, (relativeAabb.*(idxs.z)).z, 1.F};
+ };
+ return std::ranges::none_of(std::span(planes).subspan(0, nplanes), [&corners](const auto & frustumPlane) {
+ return (std::ranges::all_of(corners, [&frustumPlane](const auto & corner) {
+ return glm::dot(frustumPlane, corner) < 0.F;
+ }));
+ });
+}
+
+void
+Frustum::updateCache()
+{
+ viewProjection = projection * view;
+ inverseViewProjection = glm::inverse(viewProjection);
+ std::ranges::transform(PLANES, planes.begin(), [vpt = glm::transpose(viewProjection)](const auto & idxs) {
+ const auto [idx, sgn] = idxs;
+ return vpt[3] + (vpt[idx] * sgn);
+ });
+}
diff --git a/gfx/frustum.h b/gfx/frustum.h
new file mode 100644
index 0000000..a2d90e9
--- /dev/null
+++ b/gfx/frustum.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "aabb.h"
+#include "config/types.h"
+#include <array>
+#include <glm/mat4x4.hpp>
+
+class Frustum {
+public:
+ Frustum(const GlobalPosition3D & pos, const glm::mat4 & view, const glm::mat4 & projection);
+
+ [[nodiscard]] auto &
+ getFrustumPlanes() const
+ {
+ return planes;
+ }
+
+ [[nodiscard]] auto &
+ getViewProjection() const
+ {
+ return viewProjection;
+ }
+
+ [[nodiscard]] auto
+ getPosition() const
+ {
+ return position;
+ }
+
+ void updateView(const glm::mat4 & view);
+
+ using BoundingBox = AxisAlignedBoundingBox<GlobalDistance>;
+ [[nodiscard]] bool contains(const BoundingBox &) const;
+ [[nodiscard]] bool shadedBy(const BoundingBox &) const;
+
+protected:
+ static constexpr size_t FACES = 6;
+ void updateCache();
+ [[nodiscard]] bool boundByPlanes(const BoundingBox &, size_t nplanes) const;
+
+ GlobalPosition3D position;
+ glm::mat4 view, projection;
+ glm::mat4 viewProjection, inverseViewProjection;
+ std::array<glm::vec4, FACES> planes;
+};
diff --git a/gfx/gl/gldebug.cpp b/gfx/gl/gldebug.cpp
new file mode 100644
index 0000000..518d4fb
--- /dev/null
+++ b/gfx/gl/gldebug.cpp
@@ -0,0 +1,20 @@
+#if GLDEBUG == 2
+// Level 2 is out of line because its "complex"
+
+# include "gldebug.h"
+# include <format>
+
+glDebugScope::glDebugScope(GLuint id, const std::source_location & location)
+{
+ const auto fullMsg = std::format("{} ({}:{})", location.function_name(), location.file_name(), location.line());
+ glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, id, static_cast<GLsizei>(fullMsg.length()), fullMsg.c_str());
+}
+
+glDebugScope::glDebugScope(GLuint id, const std::string_view msg, const std::source_location & location)
+{
+ const auto fullMsg
+ = std::format("{} @ {} ({}:{})", msg, location.function_name(), location.file_name(), location.line());
+ glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, id, static_cast<GLsizei>(fullMsg.length()), fullMsg.c_str());
+}
+
+#endif
diff --git a/gfx/gl/gldebug.h b/gfx/gl/gldebug.h
new file mode 100644
index 0000000..5cfd099
--- /dev/null
+++ b/gfx/gl/gldebug.h
@@ -0,0 +1,52 @@
+#pragma once
+#ifndef GLDEBUG
+# define GLDEBUG 0
+#endif
+
+#include "special_members.h"
+#include <glad/gl.h>
+#include <source_location>
+#include <string_view>
+
+class [[nodiscard]] glDebugScope {
+public:
+ explicit glDebugScope(GLuint id, const std::source_location & = std::source_location::current());
+ explicit glDebugScope(
+ GLuint id, std::string_view msg, const std::source_location & = std::source_location::current());
+
+ ~glDebugScope();
+
+ constexpr
+ operator bool() const
+ {
+ return true;
+ }
+
+ NO_MOVE(glDebugScope);
+ NO_COPY(glDebugScope);
+};
+
+#if GLDEBUG > 0
+inline glDebugScope::~glDebugScope()
+{
+ glPopDebugGroup();
+}
+# if GLDEBUG == 1
+// Level 1 is inlined for performance because they're thin wrappers
+inline glDebugScope::glDebugScope(GLuint id, const std::source_location & location) :
+ glDebugScope {id, location.function_name()}
+{
+}
+
+inline glDebugScope::glDebugScope(GLuint id, const std::string_view msg, const std::source_location &)
+{
+ glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, id, static_cast<GLsizei>(msg.length()), msg.data());
+}
+# endif
+#else
+inline glDebugScope::glDebugScope(GLuint, const std::source_location &) { }
+
+inline glDebugScope::glDebugScope(GLuint, const std::string_view, const std::source_location &) { }
+
+inline glDebugScope::~glDebugScope() = default;
+#endif
diff --git a/gfx/gl/program.cpp b/gfx/gl/program.cpp
index fdd4c6f..da85456 100644
--- a/gfx/gl/program.cpp
+++ b/gfx/gl/program.cpp
@@ -1,5 +1,5 @@
#include "program.h"
-#include "shader.h"
+#include "gldebug.h"
#include <format>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
@@ -9,6 +9,7 @@
void
Program::linkAndValidate() const
{
+ glDebugScope _ {m_program};
glLinkProgram(m_program);
checkProgramError(m_program, GL_LINK_STATUS, "Error linking shader program");
diff --git a/gfx/gl/program.h b/gfx/gl/program.h
index 20be1aa..2b06d2d 100644
--- a/gfx/gl/program.h
+++ b/gfx/gl/program.h
@@ -1,5 +1,6 @@
#pragma once
+#include "gldebug.h"
#include "shader.h" // IWYU pragma: export
#include <glRef.h>
#include <glad/gl.h>
@@ -14,7 +15,9 @@ class Program {
public:
Program() = delete;
- template<typename... S> explicit Program(const S &... srcs)
+ template<typename... S> explicit Program(const S &... srcs) : Program {glDebugScope {0}, srcs...} { }
+
+ template<typename... S> explicit Program(glDebugScope, const S &... srcs)
{
(glAttachShader(m_program, srcs.compile()), ...);
linkAndValidate();
diff --git a/gfx/gl/sceneProvider.cpp b/gfx/gl/sceneProvider.cpp
index 4e271db..3681c60 100644
--- a/gfx/gl/sceneProvider.cpp
+++ b/gfx/gl/sceneProvider.cpp
@@ -5,10 +5,10 @@ void
SceneProvider::environment(const SceneShader &, const SceneRenderer & renderer) const
{
renderer.setAmbientLight({0.5F, 0.5F, 0.5F});
- renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {{-quarter_pi, -quarter_pi}}, *this);
+ renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {{-quarter_pi, quarter_pi}}, *this);
}
void
-SceneProvider::shadows(const ShadowMapper &) const
+SceneProvider::shadows(const ShadowMapper &, const Frustum &) const
{
}
diff --git a/gfx/gl/sceneProvider.h b/gfx/gl/sceneProvider.h
index f5e8e99..f6b7009 100644
--- a/gfx/gl/sceneProvider.h
+++ b/gfx/gl/sceneProvider.h
@@ -5,6 +5,7 @@
class SceneRenderer;
class ShadowMapper;
class SceneShader;
+class Frustum;
class SceneProvider {
public:
@@ -12,8 +13,8 @@ public:
virtual ~SceneProvider() = default;
DEFAULT_MOVE_COPY(SceneProvider);
- virtual void content(const SceneShader &) const = 0;
+ virtual void content(const SceneShader &, const Frustum &) const = 0;
virtual void environment(const SceneShader &, const SceneRenderer &) const;
virtual void lights(const SceneShader &) const = 0;
- virtual void shadows(const ShadowMapper &) const;
+ virtual void shadows(const ShadowMapper &, const Frustum &) const;
};
diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp
index b2a7d78..5e8241f 100644
--- a/gfx/gl/sceneRenderer.cpp
+++ b/gfx/gl/sceneRenderer.cpp
@@ -1,9 +1,9 @@
#include "sceneRenderer.h"
#include "maths.h"
#include "vertexArrayObject.h"
-#include <gfx/gl/shaders/fs-directionalLight.h>
-#include <gfx/gl/shaders/fs-lighting.h>
-#include <gfx/gl/shaders/vs-lighting.h>
+#include <gfx/gl/shaders/directionalLight-frag.h>
+#include <gfx/gl/shaders/lighting-frag.h>
+#include <gfx/gl/shaders/lighting-vert.h>
#include <glm/gtc/type_ptr.hpp>
static constexpr const std::array<const glm::i8vec4, 4> displayVAOdata {{
@@ -14,9 +14,11 @@ static constexpr const std::array<const glm::i8vec4, 4> displayVAOdata {{
{1, -1, 1, 0},
}};
-SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o) :
+SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o) : SceneRenderer {s, o, glDebugScope {o}} { }
+
+SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o, glDebugScope) :
camera {{-1250000, -1250000, 35.0F}, quarter_pi, ratio(s), 100, 10000000}, size {s}, output {o},
- lighting {lighting_vs, lighting_fs}, shadowMapper {{2048, 2048}}
+ lighting {lighting_vert, lighting_frag}, shadowMapper {{2048, 2048}}
{
shader.setViewPort({0, 0, size.x, size.y});
VertexArrayObject {displayVAO}.addAttribs<glm::i8vec4>(displayVBO, displayVAOdata);
@@ -39,7 +41,7 @@ SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o) :
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
configuregdata(gPosition, {GL_RGB32I}, GL_RGB_INTEGER, GL_COLOR_ATTACHMENT0);
- configuregdata(gNormal, {GL_RGB8_SNORM, GL_RGB16F}, GL_RGB, GL_COLOR_ATTACHMENT1);
+ 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};
@@ -57,57 +59,87 @@ SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o) :
}
void
+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);
+ glTexImage2D(GL_TEXTURE_2D, 0, iformat, size.x, size.y, 0, format, GL_BYTE, nullptr);
+ };
+ 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);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.x, size.y);
+ shader.setViewPort({0, 0, size.x, size.y});
+}
+
+void
SceneRenderer::render(const SceneProvider & scene) const
{
+ glDebugScope _ {output};
shader.setViewProjection(camera.getPosition(), camera.getViewProjection());
glViewport(0, 0, size.x, size.y);
- // Geometry/colour pass - writes albedo, normal and position textures
- glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
- glEnable(GL_BLEND);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_DEPTH_TEST);
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- scene.content(shader);
-
- // 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);
- glBindTexture(GL_TEXTURE_2D, gPosition);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, gNormal);
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMapper);
- glDisable(GL_DEPTH_TEST);
- scene.lights(shader);
-
- // Composition pass - reads albedo and illumination, writes output
- glBindFramebuffer(GL_FRAMEBUFFER, output);
- glViewport(0, 0, size.x, size.y);
- 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);
- lighting.use();
- renderQuad();
+ if (glDebugScope _ {gBuffer, "Geometry/colour pass"}) {
+ // Geometry/colour pass - writes albedo, normal and position textures
+ glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
+ glEnable(GL_BLEND);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_DEPTH_TEST);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ scene.content(shader, camera);
+ }
+
+ if (glDebugScope _ {gBufferIll, "Environment pass"}) {
+ // Environment pass -
+ // * ambient - clears illumination texture - see setAmbientLight
+ // * directional - updates shadowMapper, reads normal and position, writes illumination - see
+ // setDirectionalLight
+ scene.environment(shader, *this);
+ }
+
+ if (glDebugScope _ {gBufferIll, "Scene lighting pass"}) {
+ // Scene lights pass -
+ // * 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);
+ glDisable(GL_DEPTH_TEST);
+ scene.lights(shader);
+ }
+
+ if (glDebugScope _ {output, "Composition pass"}) {
+ // Composition pass - reads albedo and illumination, writes output
+ glBindFramebuffer(GL_FRAMEBUFFER, output);
+ glViewport(0, 0, size.x, size.y);
+ 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);
+ lighting.use();
+ renderQuad();
+ }
}
void
SceneRenderer::setAmbientLight(const RGB & colour) const
{
+ glDebugScope _ {output};
glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll);
glClearColor(colour.r, colour.g, colour.b, 1.0F);
glClear(GL_COLOR_BUFFER_BIT);
@@ -118,6 +150,7 @@ SceneRenderer::setDirectionalLight(
const RGB & colour, const LightDirection & direction, const SceneProvider & scene) const
{
if (colour.r > 0 || colour.g > 0 || colour.b > 0) {
+ glDebugScope _ {output};
const auto lvp = shadowMapper.update(scene, direction, camera);
glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll);
glBlendFunc(GL_ONE, GL_ONE);
@@ -142,7 +175,7 @@ SceneRenderer::renderQuad() const
glBindVertexArray(0);
}
-SceneRenderer::DirectionalLightProgram::DirectionalLightProgram() : Program {lighting_vs, directionalLight_fs} { }
+SceneRenderer::DirectionalLightProgram::DirectionalLightProgram() : Program {lighting_vert, directionalLight_frag} { }
const auto toTextureSpaceMat = glm::translate(glm::identity<glm::mat4>(), glm::vec3 {0.5F})
* glm::scale(glm::identity<glm::mat4>(), glm::vec3 {0.5F});
diff --git a/gfx/gl/sceneRenderer.h b/gfx/gl/sceneRenderer.h
index 93470f5..05921a1 100644
--- a/gfx/gl/sceneRenderer.h
+++ b/gfx/gl/sceneRenderer.h
@@ -1,17 +1,21 @@
#pragma once
-#include "camera.h"
#include "gfx/lightDirection.h"
#include "glArrays.h"
+#include "gldebug.h"
#include "program.h"
#include "sceneProvider.h"
#include "sceneShader.h"
#include "shadowMapper.h"
+#include <gfx/camera.h>
#include <glm/fwd.hpp>
class SceneRenderer {
public:
- explicit SceneRenderer(ScreenAbsCoord size, GLuint output);
+ SceneRenderer(ScreenAbsCoord size, GLuint output);
+ SceneRenderer(ScreenAbsCoord size, GLuint output, glDebugScope);
+
+ void resize(ScreenAbsCoord size);
void render(const SceneProvider &) const;
void setAmbientLight(const RGB & colour) const;
@@ -25,6 +29,7 @@ protected:
ScreenAbsCoord size;
GLuint output;
glFrameBuffer gBuffer, gBufferIll;
+ GLint normaliFormat;
glTexture gPosition, gNormal, gAlbedoSpec, gIllumination;
glRenderBuffer depth;
diff --git a/gfx/gl/sceneShader.cpp b/gfx/gl/sceneShader.cpp
index 571538a..72cde91 100644
--- a/gfx/gl/sceneShader.cpp
+++ b/gfx/gl/sceneShader.cpp
@@ -1,23 +1,25 @@
#include "sceneShader.h"
-#include <gfx/gl/shaders/fs-landmass.h>
-#include <gfx/gl/shaders/fs-material.h>
-#include <gfx/gl/shaders/fs-network.h>
-#include <gfx/gl/shaders/fs-pointLight.h>
-#include <gfx/gl/shaders/fs-spotLight.h>
-#include <gfx/gl/shaders/fs-water.h>
-#include <gfx/gl/shaders/gs-networkCurve.h>
-#include <gfx/gl/shaders/gs-networkStraight.h>
-#include <gfx/gl/shaders/gs-pointLight.h>
-#include <gfx/gl/shaders/gs-spotLight.h>
-#include <gfx/gl/shaders/vs-dynamicPoint.h>
-#include <gfx/gl/shaders/vs-dynamicPointInst.h>
-#include <gfx/gl/shaders/vs-fixedPoint.h>
-#include <gfx/gl/shaders/vs-landmass.h>
-#include <gfx/gl/shaders/vs-networkCurve.h>
-#include <gfx/gl/shaders/vs-networkStraight.h>
-#include <gfx/gl/shaders/vs-pointLight.h>
-#include <gfx/gl/shaders/vs-spotLight.h>
-#include <gfx/gl/shaders/vs-water.h>
+#include <gfx/gl/shaders/dynamicPoint-vert.h>
+#include <gfx/gl/shaders/dynamicPointInst-vert.h>
+#include <gfx/gl/shaders/fixedPoint-vert.h>
+#include <gfx/gl/shaders/landmass-frag.h>
+#include <gfx/gl/shaders/landmass-vert.h>
+#include <gfx/gl/shaders/material-frag.h>
+#include <gfx/gl/shaders/network-frag.h>
+#include <gfx/gl/shaders/networkCurve-geom.h>
+#include <gfx/gl/shaders/networkCurve-tesc.h>
+#include <gfx/gl/shaders/networkCurve-tese.h>
+#include <gfx/gl/shaders/networkCurve-vert.h>
+#include <gfx/gl/shaders/networkStraight-geom.h>
+#include <gfx/gl/shaders/networkStraight-vert.h>
+#include <gfx/gl/shaders/pointLight-frag.h>
+#include <gfx/gl/shaders/pointLight-geom.h>
+#include <gfx/gl/shaders/pointLight-vert.h>
+#include <gfx/gl/shaders/spotLight-frag.h>
+#include <gfx/gl/shaders/spotLight-geom.h>
+#include <gfx/gl/shaders/spotLight-vert.h>
+#include <gfx/gl/shaders/water-frag.h>
+#include <gfx/gl/shaders/water-vert.h>
#include <gfx/gl/vertexArrayObject.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
@@ -34,11 +36,11 @@ SceneShader::allPrograms(auto member, auto &&... ps) const
}
SceneShader::SceneShader() :
- basicInst {dynamicPointInst_vs, material_fs}, landmass {landmass_vs, landmass_fs},
- absolute {fixedPoint_vs, material_fs}, spotLightInst {spotLight_vs, spotLight_gs, spotLight_fs},
- pointLightInst {pointLight_vs, pointLight_gs, pointLight_fs},
- networkStraight {networkStraight_vs, networkStraight_gs, network_fs},
- networkCurve {networkCurve_vs, networkCurve_gs, network_fs}
+ basicInst {dynamicPointInst_vert, material_frag}, absolute {fixedPoint_vert, material_frag},
+ spotLightInst {spotLight_vert, spotLight_geom, spotLight_frag},
+ pointLightInst {pointLight_vert, pointLight_geom, pointLight_frag}, landmass {landmass_vert, landmass_frag},
+ networkStraight {networkStraight_vert, networkStraight_geom, network_frag},
+ networkCurve {networkCurve_vert, networkCurve_tesc, networkCurve_tese, networkCurve_geom, network_frag}
{
}
@@ -71,7 +73,7 @@ SceneShader::SceneProgram::setViewPort(const ViewPort & viewPort) const
}
}
-SceneShader::BasicProgram::BasicProgram() : SceneProgram {dynamicPoint_vs, material_fs} { }
+SceneShader::BasicProgram::BasicProgram() : SceneProgram {dynamicPoint_vert, material_frag} { }
void
SceneShader::BasicProgram::setModel(Location const & location) const
@@ -88,6 +90,13 @@ SceneShader::BasicProgram::use(Location const & location) const
}
void
+SceneShader::LandmassProgram::use(const glm::vec3 colourBias) const
+{
+ Program::use();
+ glUniform(colourBiasLos, colourBias);
+}
+
+void
SceneShader::NetworkProgram::use(
const std::span<const glm::vec3> profile, const std::span<const float> texturePos) const
{
@@ -97,7 +106,7 @@ SceneShader::NetworkProgram::use(
glUniform(profileLengthLoc, static_cast<GLuint>(profile.size()));
}
-SceneShader::WaterProgram::WaterProgram() : SceneProgram {water_vs, water_fs} { }
+SceneShader::WaterProgram::WaterProgram() : SceneProgram {water_vert, water_frag} { }
void
SceneShader::WaterProgram::use(float waveCycle) const
diff --git a/gfx/gl/sceneShader.h b/gfx/gl/sceneShader.h
index 51f0e21..47d4397 100644
--- a/gfx/gl/sceneShader.h
+++ b/gfx/gl/sceneShader.h
@@ -50,6 +50,15 @@ class SceneShader {
RequiredUniformLocation profileLengthLoc {*this, "profileLength"};
};
+ class LandmassProgram : public AbsolutePosProgram {
+ public:
+ using AbsolutePosProgram::AbsolutePosProgram;
+ void use(const glm::vec3) const;
+
+ private:
+ RequiredUniformLocation colourBiasLos {*this, "colourBias"};
+ };
+
class WaterProgram : public SceneProgram {
public:
WaterProgram();
@@ -64,7 +73,8 @@ public:
BasicProgram basic;
WaterProgram water;
- AbsolutePosProgram basicInst, landmass, absolute, spotLightInst, pointLightInst;
+ AbsolutePosProgram basicInst, absolute, spotLightInst, pointLightInst;
+ LandmassProgram landmass;
NetworkProgram networkStraight, networkCurve;
void setViewProjection(const GlobalPosition3D & viewPoint, const glm::mat4 & viewProjection) const;
diff --git a/gfx/gl/shader.cpp b/gfx/gl/shader.cpp
index 9a4c270..319726f 100644
--- a/gfx/gl/shader.cpp
+++ b/gfx/gl/shader.cpp
@@ -8,17 +8,18 @@
namespace {
auto
- getInt(GLenum e)
+ getInt(GLenum pname)
{
- GLint i {};
- glGetIntegerv(e, &i);
- return std::to_string(i);
+ GLint data {};
+ glGetIntegerv(pname, &data);
+ return std::to_string(data);
}
using LookUpFunction = std::string (*)(GLenum);
- constexpr std::array<std::tuple<std::string_view, GLenum, LookUpFunction>, 1> LOOKUPS {{
+ constexpr auto LOOKUPS = std::to_array<std::tuple<std::string_view, GLenum, LookUpFunction>>({
{"GL_MAX_GEOMETRY_OUTPUT_VERTICES", GL_MAX_GEOMETRY_OUTPUT_VERTICES, getInt},
- }};
+ {"GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS", GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, getInt},
+ });
struct ShaderCompileError : public MsgException<std::invalid_argument> {
explicit ShaderCompileError(GLuint shader, Shader::Source src) :
@@ -63,7 +64,7 @@ Shader::compile() const
};
if (lookups) {
std::basic_string<GLchar> textMod {text};
- for (const auto & match : ctre::search_all<R"(\bGL_[A-Z_]+\b)">(textMod)) {
+ while (const auto match = ctre::search<R"(\bGL_[A-Z_]+\b)">(textMod)) {
if (const auto * const lookup = std::find_if(LOOKUPS.begin(), LOOKUPS.end(),
[&match](const auto & lookup) {
return std::get<std::string_view>(lookup) == match;
@@ -72,6 +73,9 @@ Shader::compile() const
const auto & [name, pname, getFunction] = *lookup;
textMod.replace(match.begin(), match.end(), getFunction(pname));
}
+ else {
+ throw std::domain_error(std::format("Unknown shader constant: {}", match.view()));
+ }
}
source(textMod.c_str(), static_cast<GLint>(textMod.length()));
}
diff --git a/gfx/gl/shaders/commonShadowPoint.gs b/gfx/gl/shaders/commonShadowPoint.geom
index 2413cc0..a515d97 100644
--- a/gfx/gl/shaders/commonShadowPoint.gs
+++ b/gfx/gl/shaders/commonShadowPoint.geom
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_viewport_array : enable
+#version 460 core
ifdef(`TEXTURES', include(`materialDetail.glsl'))
diff --git a/gfx/gl/shaders/directionalLight.fs b/gfx/gl/shaders/directionalLight.frag
index cdf0389..e5ebfb0 100644
--- a/gfx/gl/shaders/directionalLight.fs
+++ b/gfx/gl/shaders/directionalLight.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
const int MAX_MAPS = 4;
@@ -48,7 +47,7 @@ isShaded(vec4 Position)
return getShadow(positionInLightSpace, m, texelSize);
}
}
- return 1;
+ return 1.0;
}
void
diff --git a/gfx/gl/shaders/dynamicPoint.vs b/gfx/gl/shaders/dynamicPoint.vert
index 97d2983..cd5fc26 100644
--- a/gfx/gl/shaders/dynamicPoint.vs
+++ b/gfx/gl/shaders/dynamicPoint.vert
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 1) uniform usampler2DRect materialData;
diff --git a/gfx/gl/shaders/dynamicPointInst.vs b/gfx/gl/shaders/dynamicPointInst.vert
index a85f9c9..46fead9 100644
--- a/gfx/gl/shaders/dynamicPointInst.vs
+++ b/gfx/gl/shaders/dynamicPointInst.vert
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 1) uniform usampler2DRect materialData;
diff --git a/gfx/gl/shaders/fixedPoint.vs b/gfx/gl/shaders/fixedPoint.vert
index 435b3d1..9201251 100644
--- a/gfx/gl/shaders/fixedPoint.vs
+++ b/gfx/gl/shaders/fixedPoint.vert
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 1) uniform usampler2DRect materialData;
diff --git a/gfx/gl/shaders/landmass.fs b/gfx/gl/shaders/landmass.frag
index 55e3c24..b5c7fa1 100644
--- a/gfx/gl/shaders/landmass.fs
+++ b/gfx/gl/shaders/landmass.frag
@@ -1,12 +1,12 @@
-#version 330 core
+#version 460 core
include(`materialOut.glsl')
in vec3 FragPos;
in vec3 Normal;
-flat in vec3 ColourBias;
uniform sampler2D texture0;
uniform ivec3 viewPoint;
+uniform vec3 colourBias;
const vec3 grass = vec3(.1, .4, .05);
const vec3 slope = vec3(.6, .6, .4);
@@ -35,8 +35,8 @@ main()
vec3 color = texture(texture0, vec2(position.xy % 10000) / 10000.0).rgb;
int height = position.z;
- if (ColourBias.r >= 0) {
- color *= ColourBias;
+ if (colourBias.r >= 0) {
+ color *= colourBias;
}
else if (height < beachline) { // Sandy beach
color *= sand;
diff --git a/gfx/gl/shaders/landmass.vs b/gfx/gl/shaders/landmass.vert
index 9617cb9..91fc7f8 100644
--- a/gfx/gl/shaders/landmass.vs
+++ b/gfx/gl/shaders/landmass.vert
@@ -1,13 +1,10 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(location = 0) in ivec3 position;
layout(location = 1) in vec3 normal;
-layout(location = 2) in vec3 colourBias;
out vec3 FragPos;
out vec3 Normal;
-flat out vec3 ColourBias;
uniform mat4 viewProjection;
uniform ivec3 viewPoint;
@@ -17,7 +14,6 @@ main()
{
FragPos = position - viewPoint;
Normal = normal;
- ColourBias = colourBias;
gl_Position = viewProjection * vec4(FragPos, 1);
}
diff --git a/gfx/gl/shaders/lighting.fs b/gfx/gl/shaders/lighting.frag
index 4646b75..b5c6c8b 100644
--- a/gfx/gl/shaders/lighting.fs
+++ b/gfx/gl/shaders/lighting.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
out vec3 FragColor;
diff --git a/gfx/gl/shaders/lighting.vs b/gfx/gl/shaders/lighting.vert
index e07cd0a..1046379 100644
--- a/gfx/gl/shaders/lighting.vs
+++ b/gfx/gl/shaders/lighting.vert
@@ -1,4 +1,4 @@
-#version 330 core
+#version 460 core
in ivec4 position;
diff --git a/gfx/gl/shaders/material.fs b/gfx/gl/shaders/material.frag
index 37f2e27..18a3169 100644
--- a/gfx/gl/shaders/material.fs
+++ b/gfx/gl/shaders/material.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 0) uniform sampler2D textureAlbedo;
diff --git a/gfx/gl/shaders/materialCommon.glsl b/gfx/gl/shaders/materialCommon.glsl
index 3fe2237..4c2fbf8 100644
--- a/gfx/gl/shaders/materialCommon.glsl
+++ b/gfx/gl/shaders/materialCommon.glsl
@@ -13,7 +13,7 @@ map(uint mapmode, float value)
discard;
}
}
- return 0;
+ return 0.0;
}
vec2
diff --git a/gfx/gl/shaders/materialInterface.glsl b/gfx/gl/shaders/materialInterface.glsl
index f2ca297..bf78290 100644
--- a/gfx/gl/shaders/materialInterface.glsl
+++ b/gfx/gl/shaders/materialInterface.glsl
@@ -1,6 +1,6 @@
include(`materialDetail.glsl')
-define(INOUT, ifelse(TYPE, .fs, in, out));
+define(INOUT, ifelse(TYPE, .frag, in, out))
INOUT vec3 FragPos;
INOUT vec2 TexCoords;
diff --git a/gfx/gl/shaders/network.fs b/gfx/gl/shaders/network.frag
index 4e347b4..2f291ea 100644
--- a/gfx/gl/shaders/network.fs
+++ b/gfx/gl/shaders/network.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
include(`materialOut.glsl')
in vec3 rposition;
diff --git a/gfx/gl/shaders/networkCommon.glsl b/gfx/gl/shaders/networkCommon.glsl
index 0bc3c1c..7aa911d 100644
--- a/gfx/gl/shaders/networkCommon.glsl
+++ b/gfx/gl/shaders/networkCommon.glsl
@@ -12,13 +12,19 @@ out vec2 texCoord;
out vec3 rposition;
float
+viewPointDist(const ivec3 position)
+{
+ return length(vec3(viewPoint - position));
+}
+
+float
segDist(const ivec3 a, const ivec3 b)
{
- return min(distance(viewPoint, a), distance(viewPoint, b));
+ return min(viewPointDist(a), viewPointDist(b));
}
ifelse(
- TYPE, .gs,
+ TYPE, .geom,
// Begin: Geometry shader only function
void doVertex(const ivec3 end, const uint v, const float texY, const mat2 rot) {
ivec3 vpos = end + ivec3(rot * profile[v].xy, profile[v].z);
diff --git a/gfx/gl/shaders/networkCurve.geom b/gfx/gl/shaders/networkCurve.geom
new file mode 100644
index 0000000..4a5b3db
--- /dev/null
+++ b/gfx/gl/shaders/networkCurve.geom
@@ -0,0 +1,17 @@
+#version 460 core
+
+layout(lines) in;
+layout(triangle_strip, max_vertices = 10) out;
+
+flat in ivec3 pos[];
+flat in mat2 rot[];
+flat in float tpos[];
+flat in float dist[];
+
+include(`networkCommon.glsl')
+
+void
+main()
+{
+ doSeg(min(dist[0], dist[1]), pos[0], pos[1], tpos[0], tpos[1], rot[0], rot[1]);
+}
diff --git a/gfx/gl/shaders/networkCurve.gs b/gfx/gl/shaders/networkCurve.gs
deleted file mode 100644
index 7cb6c42..0000000
--- a/gfx/gl/shaders/networkCurve.gs
+++ /dev/null
@@ -1,47 +0,0 @@
-#version 330 core
-
-flat in ivec3 apos[];
-flat in ivec3 bpos[];
-flat in ivec3 cpos[];
-flat in float reps[];
-flat in float aangle[];
-flat in float bangle[];
-flat in float radius[];
-
-layout(points) in;
-layout(triangle_strip, max_vertices = GL_MAX_GEOMETRY_OUTPUT_VERTICES) out;
-
-const mat2 rot = mat2(1);
-
-include(`networkCommon.glsl')
-
-mat2
-getRot(float angle)
-{
- return mat2(cos(angle), sin(angle), -sin(angle), cos(angle));
-}
-
-void
-main()
-{
- float segs = clamp(
- round(reps[0] * radius[0] / 1000), 4, floor(uint(GL_MAX_GEOMETRY_OUTPUT_VERTICES) / (profileLength * 2u)));
- vec3 arcstep = vec3((bangle[0] - aangle[0]), // angle
- reps[0], // texture
- (bpos[0].z - apos[0].z)) // height
- / segs;
-
- ivec3 prevPos = apos[0];
- mat2 prevRot = getRot(aangle[0]);
- float prevTex = 0;
- for (vec3 arc = arcstep; arc.y < reps[0] - 0.01; arc += arcstep) {
- mat2 rot = getRot(arc.x + aangle[0]);
- ivec3 pos = cpos[0] + ivec3(rot * vec2(radius[0], 0), arc.z);
- float tex = arc.y;
- doSeg(segDist(prevPos, pos), pos, prevPos, tex, prevTex, rot, prevRot);
- prevPos = pos;
- prevRot = rot;
- prevTex = tex;
- }
- doSeg(segDist(prevPos, bpos[0]), bpos[0], prevPos, reps[0], prevTex, getRot(bangle[0]), prevRot);
-}
diff --git a/gfx/gl/shaders/networkCurve.tesc b/gfx/gl/shaders/networkCurve.tesc
new file mode 100644
index 0000000..5a6e449
--- /dev/null
+++ b/gfx/gl/shaders/networkCurve.tesc
@@ -0,0 +1,37 @@
+#version 460 core
+
+layout(vertices = 1) out;
+
+flat in ivec3 pos[][2];
+flat in ivec2 cpos[];
+flat in float reps[];
+flat in float angles[][2];
+flat in float radius[];
+
+flat out ivec3 c_pos[][2];
+flat out ivec2 c_cpos[];
+flat out float c_reps[];
+flat out float c_angles[][2];
+flat out float c_radius[];
+
+float
+segments()
+{
+ const float arc = angles[gl_InvocationID][0] - angles[gl_InvocationID][1];
+ const float error = 100.;
+ const float diff = acos(1.f - (error / radius[gl_InvocationID]));
+ return clamp(arc / diff, arc, 180);
+}
+
+void
+main()
+{
+ c_pos[gl_InvocationID] = pos[gl_InvocationID];
+ c_cpos[gl_InvocationID] = cpos[gl_InvocationID];
+ c_reps[gl_InvocationID] = reps[gl_InvocationID];
+ c_angles[gl_InvocationID] = angles[gl_InvocationID];
+ c_radius[gl_InvocationID] = radius[gl_InvocationID];
+
+ gl_TessLevelOuter[0] = 1;
+ gl_TessLevelOuter[1] = segments();
+}
diff --git a/gfx/gl/shaders/networkCurve.tese b/gfx/gl/shaders/networkCurve.tese
new file mode 100644
index 0000000..9cc31e2
--- /dev/null
+++ b/gfx/gl/shaders/networkCurve.tese
@@ -0,0 +1,45 @@
+#version 460 core
+
+layout(isolines, equal_spacing, cw) in;
+
+flat in ivec3 c_pos[][2];
+flat in ivec2 c_cpos[];
+flat in float c_reps[];
+flat in float c_angles[][2];
+flat in float c_radius[];
+
+flat out ivec3 pos;
+flat out mat2 rot;
+flat out float tpos;
+flat out float dist;
+
+const float startTolerance = 1. / 200.;
+const float endTolerance = 1. - startTolerance;
+
+include(`networkCommon.glsl')
+
+mat2
+getRot(float angle)
+{
+ return mat2(cos(angle), sin(angle), -sin(angle), cos(angle));
+}
+
+void
+main()
+{
+ const float angle = mix(c_angles[0][1], c_angles[0][0], gl_TessCoord.x);
+ rot = getRot(angle);
+ if (gl_TessCoord.x < startTolerance) {
+ pos = c_pos[0][1];
+ }
+ else if (gl_TessCoord.x > endTolerance) {
+ pos = c_pos[0][0];
+ }
+ else {
+ const int height = int(mix(c_pos[0][1].z, c_pos[0][0].z, gl_TessCoord.x));
+ pos = ivec3(c_cpos[0] + ivec2(rot * vec2(c_radius[0], 0)), height);
+ }
+
+ tpos = c_reps[0] * gl_TessCoord.x;
+ dist = viewPointDist(pos);
+}
diff --git a/gfx/gl/shaders/networkCurve.vert b/gfx/gl/shaders/networkCurve.vert
new file mode 100644
index 0000000..7e363d3
--- /dev/null
+++ b/gfx/gl/shaders/networkCurve.vert
@@ -0,0 +1,23 @@
+#version 460 core
+
+layout(location = 0) in ivec3 v_pos[2];
+layout(location = 2) in ivec3 v_centre;
+layout(location = 3) in float v_reps;
+layout(location = 4) in float v_angles[2];
+layout(location = 6) in float v_radius;
+
+flat out ivec3 pos[2];
+flat out ivec2 cpos;
+flat out float reps;
+flat out float angles[2];
+flat out float radius;
+
+void
+main()
+{
+ pos = v_pos;
+ cpos = v_centre.xy;
+ reps = v_reps;
+ angles = v_angles;
+ radius = v_radius;
+}
diff --git a/gfx/gl/shaders/networkCurve.vs b/gfx/gl/shaders/networkCurve.vs
deleted file mode 100644
index f51bb87..0000000
--- a/gfx/gl/shaders/networkCurve.vs
+++ /dev/null
@@ -1,29 +0,0 @@
-#version 330 core
-
-layout(location = 0) in ivec3 v_apos;
-layout(location = 1) in ivec3 v_bpos;
-layout(location = 2) in ivec3 v_centre;
-layout(location = 3) in float v_reps;
-layout(location = 4) in float v_aangle;
-layout(location = 5) in float v_bangle;
-layout(location = 6) in float v_radius;
-
-flat out ivec3 apos;
-flat out ivec3 bpos;
-flat out ivec3 cpos;
-flat out float reps;
-flat out float aangle;
-flat out float bangle;
-flat out float radius;
-
-void
-main()
-{
- apos = v_apos;
- bpos = v_bpos;
- cpos = v_centre;
- reps = v_reps;
- aangle = v_aangle;
- bangle = v_bangle;
- radius = v_radius;
-}
diff --git a/gfx/gl/shaders/networkStraight.gs b/gfx/gl/shaders/networkStraight.geom
index 51df5fb..a0e57c8 100644
--- a/gfx/gl/shaders/networkStraight.gs
+++ b/gfx/gl/shaders/networkStraight.geom
@@ -1,17 +1,17 @@
-#version 330 core
+#version 460 core
-flat in ivec3 apos[];
-flat in ivec3 bpos[];
+layout(points) in;
+layout(triangle_strip, max_vertices = 10) out;
+
+flat in ivec3 pos[][2];
flat in mat2 rot[];
flat in float reps[];
flat in float dist[];
-layout(points) in;
-layout(triangle_strip, max_vertices = 10) out;
include(`networkCommon.glsl')
void
main()
{
- doSeg(dist[0], apos[0], bpos[0], 0.f, reps[0], rot[0], rot[0]);
+ doSeg(dist[0], pos[0][0], pos[0][1], 0.f, reps[0], rot[0], rot[0]);
}
diff --git a/gfx/gl/shaders/networkStraight.vs b/gfx/gl/shaders/networkStraight.vert
index 55f9c4f..91ba955 100644
--- a/gfx/gl/shaders/networkStraight.vs
+++ b/gfx/gl/shaders/networkStraight.vert
@@ -1,12 +1,10 @@
-#version 330 core
+#version 460 core
-layout(location = 0) in ivec3 v_apos;
-layout(location = 1) in ivec3 v_bpos;
+layout(location = 0) in ivec3 v_pos[2];
layout(location = 2) in mat2 v_rot;
layout(location = 4) in float v_reps;
-flat out ivec3 apos;
-flat out ivec3 bpos;
+flat out ivec3 pos[2];
flat out mat2 rot;
flat out float reps;
flat out float dist;
@@ -16,9 +14,8 @@ include(`networkCommon.glsl')
void
main()
{
- apos = v_apos;
- bpos = v_bpos;
+ pos = v_pos;
rot = v_rot;
reps = v_reps;
- dist = segDist(v_apos, v_bpos);
+ dist = segDist(v_pos[0], v_pos[1]);
}
diff --git a/gfx/gl/shaders/pointLight.fs b/gfx/gl/shaders/pointLight.frag
index 7531d3e..bb2c453 100644
--- a/gfx/gl/shaders/pointLight.fs
+++ b/gfx/gl/shaders/pointLight.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
out vec3 FragColor;
diff --git a/gfx/gl/shaders/pointLight.gs b/gfx/gl/shaders/pointLight.geom
index fc1d7c3..1ee7e06 100644
--- a/gfx/gl/shaders/pointLight.gs
+++ b/gfx/gl/shaders/pointLight.geom
@@ -1,6 +1,4 @@
-#version 330 core
-#extension GL_ARB_enhanced_layouts : enable
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
const vec3[] cube = vec3[]( // http://www.cs.umd.edu/gvil/papers/av_ts.pdf
vec3(-1, 1, 1), // Front-top-left
diff --git a/gfx/gl/shaders/pointLight.vs b/gfx/gl/shaders/pointLight.vert
index fbd031c..2fd5418 100644
--- a/gfx/gl/shaders/pointLight.vs
+++ b/gfx/gl/shaders/pointLight.vert
@@ -1,4 +1,4 @@
-#version 330 core
+#version 460 core
layout(location = 0) in vec3 v_position;
layout(location = 1) in vec3 v_colour;
diff --git a/gfx/gl/shaders/shadowDynamicPoint.vs b/gfx/gl/shaders/shadowDynamicPoint.vert
index 7335b9a..907378e 100644
--- a/gfx/gl/shaders/shadowDynamicPoint.vs
+++ b/gfx/gl/shaders/shadowDynamicPoint.vert
@@ -1,4 +1,4 @@
-#version 330 core
+#version 460 core
include(`meshIn.glsl')
diff --git a/gfx/gl/shaders/shadowDynamicPointInst.vs b/gfx/gl/shaders/shadowDynamicPointInst.vert
index d0eb649..da4a76f 100644
--- a/gfx/gl/shaders/shadowDynamicPointInst.vs
+++ b/gfx/gl/shaders/shadowDynamicPointInst.vert
@@ -1,4 +1,4 @@
-#version 330 core
+#version 460 core
include(`meshIn.glsl')
diff --git a/gfx/gl/shaders/shadowDynamicPointInstWithTextures.fs b/gfx/gl/shaders/shadowDynamicPointInstWithTextures.frag
index 47ce9c0..cad9d9d 100644
--- a/gfx/gl/shaders/shadowDynamicPointInstWithTextures.fs
+++ b/gfx/gl/shaders/shadowDynamicPointInstWithTextures.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 3) uniform sampler2D textureAlbedo;
diff --git a/gfx/gl/shaders/shadowDynamicPointInstWithTextures.geom b/gfx/gl/shaders/shadowDynamicPointInstWithTextures.geom
new file mode 100644
index 0000000..3aaf9a8
--- /dev/null
+++ b/gfx/gl/shaders/shadowDynamicPointInstWithTextures.geom
@@ -0,0 +1,3 @@
+define(`TEXTURES', 1)
+
+include(`commonShadowPoint.geom')
diff --git a/gfx/gl/shaders/shadowDynamicPointInstWithTextures.gs b/gfx/gl/shaders/shadowDynamicPointInstWithTextures.gs
deleted file mode 100644
index e6e213e..0000000
--- a/gfx/gl/shaders/shadowDynamicPointInstWithTextures.gs
+++ /dev/null
@@ -1,3 +0,0 @@
-define(`TEXTURES', 1)
-
-include(`commonShadowPoint.gs')
diff --git a/gfx/gl/shaders/shadowDynamicPointInstWithTextures.vs b/gfx/gl/shaders/shadowDynamicPointInstWithTextures.vert
index a76c87f..41a47b0 100644
--- a/gfx/gl/shaders/shadowDynamicPointInstWithTextures.vs
+++ b/gfx/gl/shaders/shadowDynamicPointInstWithTextures.vert
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 4) uniform usampler2DRect materialData;
diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.fs b/gfx/gl/shaders/shadowDynamicPointStencil.frag
index fe91b07..d6b8a0e 100644
--- a/gfx/gl/shaders/shadowDynamicPointStencil.fs
+++ b/gfx/gl/shaders/shadowDynamicPointStencil.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 0) uniform sampler2DArray stencilDepth;
flat in vec3 scale;
diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.gs b/gfx/gl/shaders/shadowDynamicPointStencil.geom
index 7e81d97..df8be8d 100644
--- a/gfx/gl/shaders/shadowDynamicPointStencil.gs
+++ b/gfx/gl/shaders/shadowDynamicPointStencil.geom
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_viewport_array : enable
+#version 460 core
const vec2[] corners = vec2[4](vec2(-1, -1), vec2(-1, 1), vec2(1, -1), vec2(1, 1));
const float tau = 6.28318531;
diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.vs b/gfx/gl/shaders/shadowDynamicPointStencil.vert
index 0dd2d79..b750b3e 100644
--- a/gfx/gl/shaders/shadowDynamicPointStencil.vs
+++ b/gfx/gl/shaders/shadowDynamicPointStencil.vert
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(location = 0) in ivec3 worldPos;
layout(location = 1) in float modelYaw;
diff --git a/gfx/gl/shaders/shadowLandmass.vs b/gfx/gl/shaders/shadowLandmass.vert
index becf142..cf68fe5 100644
--- a/gfx/gl/shaders/shadowLandmass.vs
+++ b/gfx/gl/shaders/shadowLandmass.vert
@@ -1,4 +1,4 @@
-#version 330 core
+#version 460 core
layout(location = 0) in ivec3 position;
diff --git a/gfx/gl/shaders/shadowStencil.fs b/gfx/gl/shaders/shadowStencil.frag
index 1164cc9..3269f69 100644
--- a/gfx/gl/shaders/shadowStencil.fs
+++ b/gfx/gl/shaders/shadowStencil.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 0) uniform sampler2D textureAlbedo;
diff --git a/gfx/gl/shaders/shadowStencil.gs b/gfx/gl/shaders/shadowStencil.geom
index 2c3f9bd..53a4c19 100644
--- a/gfx/gl/shaders/shadowStencil.gs
+++ b/gfx/gl/shaders/shadowStencil.geom
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_viewport_array : enable
+#version 460 core
include(`materialDetail.glsl')
diff --git a/gfx/gl/shaders/shadowStencil.vs b/gfx/gl/shaders/shadowStencil.vert
index a15c4fb..e6286e6 100644
--- a/gfx/gl/shaders/shadowStencil.vs
+++ b/gfx/gl/shaders/shadowStencil.vert
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
layout(binding = 1) uniform usampler2DRect materialData;
diff --git a/gfx/gl/shaders/spotLight.fs b/gfx/gl/shaders/spotLight.frag
index ad33458..1305dbd 100644
--- a/gfx/gl/shaders/spotLight.fs
+++ b/gfx/gl/shaders/spotLight.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
out vec3 FragColor;
diff --git a/gfx/gl/shaders/spotLight.gs b/gfx/gl/shaders/spotLight.geom
index 194812a..fec191e 100644
--- a/gfx/gl/shaders/spotLight.gs
+++ b/gfx/gl/shaders/spotLight.geom
@@ -1,6 +1,4 @@
-#version 330 core
-#extension GL_ARB_enhanced_layouts : enable
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
const vec3[] pyramid = vec3[]( // four-sided
vec3(0, 0, 0), // Apex
diff --git a/gfx/gl/shaders/spotLight.vs b/gfx/gl/shaders/spotLight.vert
index e0196c3..36d2ee5 100644
--- a/gfx/gl/shaders/spotLight.vs
+++ b/gfx/gl/shaders/spotLight.vert
@@ -1,4 +1,4 @@
-#version 330 core
+#version 460 core
layout(location = 0) in vec3 v_position;
layout(location = 1) in vec3 v_direction;
diff --git a/gfx/gl/shaders/uiShader.fs b/gfx/gl/shaders/uiShader.fs
deleted file mode 100644
index c5f4e92..0000000
--- a/gfx/gl/shaders/uiShader.fs
+++ /dev/null
@@ -1,11 +0,0 @@
-#version 330 core
-
-in vec2 texCoord0;
-
-uniform sampler2D sampler;
-
-void
-main()
-{
- gl_FragColor = texture(sampler, texCoord0);
-}
diff --git a/gfx/gl/shaders/uiShader.vs b/gfx/gl/shaders/uiShader.vs
deleted file mode 100644
index e9e4373..0000000
--- a/gfx/gl/shaders/uiShader.vs
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 330 core
-
-in vec4 position;
-
-out vec2 texCoord0;
-uniform mat4 uiProjection;
-
-void
-main()
-{
- gl_Position = uiProjection * vec4(position.xy, 0.0, 1.0);
- texCoord0 = position.zw;
-}
diff --git a/gfx/gl/shaders/uiShaderFont.fs b/gfx/gl/shaders/uiShaderFont.fs
deleted file mode 100644
index a1ef6ef..0000000
--- a/gfx/gl/shaders/uiShaderFont.fs
+++ /dev/null
@@ -1,12 +0,0 @@
-#version 330 core
-
-in vec2 texCoord0;
-
-uniform sampler2D sampler;
-uniform vec3 colour;
-
-void
-main()
-{
- gl_FragColor = vec4(colour, texture(sampler, texCoord0).r);
-}
diff --git a/gfx/gl/shaders/water.fs b/gfx/gl/shaders/water.frag
index 0918d9f..a09e754 100644
--- a/gfx/gl/shaders/water.fs
+++ b/gfx/gl/shaders/water.frag
@@ -1,5 +1,4 @@
-#version 330 core
-#extension GL_ARB_shading_language_420pack : enable
+#version 460 core
in vec3 FragPos;
in vec2 TexCoords;
diff --git a/gfx/gl/shaders/water.vs b/gfx/gl/shaders/water.vert
index 58bf7b6..60e4fb8 100644
--- a/gfx/gl/shaders/water.vs
+++ b/gfx/gl/shaders/water.vert
@@ -1,4 +1,4 @@
-#version 330 core
+#version 460 core
layout(location = 0) in ivec3 position;
out vec3 FragPos;
diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp
index 1b95aa3..7035162 100644
--- a/gfx/gl/shadowMapper.cpp
+++ b/gfx/gl/shadowMapper.cpp
@@ -1,37 +1,39 @@
#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/aabb.h"
#include "gfx/gl/shadowStenciller.h"
#include "gfx/lightDirection.h"
#include "gfx/renderable.h"
#include "gl_traits.h"
+#include "gldebug.h"
#include "location.h"
#include "maths.h"
#include "sceneProvider.h"
#include "sceneShader.h"
-#include "sorting.h"
+#include <gfx/camera.h>
+#include <gfx/gl/shaders/commonShadowPoint-geom.h>
+#include <gfx/gl/shaders/shadowDynamicPoint-vert.h>
+#include <gfx/gl/shaders/shadowDynamicPointInst-vert.h>
+#include <gfx/gl/shaders/shadowDynamicPointInstWithTextures-frag.h>
+#include <gfx/gl/shaders/shadowDynamicPointInstWithTextures-geom.h>
+#include <gfx/gl/shaders/shadowDynamicPointInstWithTextures-vert.h>
+#include <gfx/gl/shaders/shadowDynamicPointStencil-frag.h>
+#include <gfx/gl/shaders/shadowDynamicPointStencil-geom.h>
+#include <gfx/gl/shaders/shadowDynamicPointStencil-vert.h>
+#include <gfx/gl/shaders/shadowLandmass-vert.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/matrix.hpp>
#include <vector>
ShadowMapper::ShadowMapper(const TextureAbsCoord & s) :
- landmess {shadowLandmass_vs}, dynamicPointInst {shadowDynamicPointInst_vs},
- dynamicPointInstWithTextures {shadowDynamicPointInstWithTextures_vs, shadowDynamicPointInstWithTextures_gs,
- shadowDynamicPointInstWithTextures_fs},
+ landmess {shadowLandmass_vert}, dynamicPointInst {shadowDynamicPointInst_vert},
+ dynamicPointInstWithTextures {shadowDynamicPointInstWithTextures_vert, shadowDynamicPointInstWithTextures_geom,
+ shadowDynamicPointInstWithTextures_frag},
size {s}
{
+ glDebugScope _ {depthMap};
glBindTexture(GL_TEXTURE_2D_ARRAY, depthMap);
glTexImage3D(
GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT, size.x, size.y, 4, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
@@ -56,7 +58,7 @@ constexpr auto shadowBands
= []<GlobalDistance... ints>(const float scaleFactor, std::integer_sequence<GlobalDistance, ints...>) {
const auto base = 10'000'000 / pow(scaleFactor, sizeof...(ints) - 1);
return std::array {1, static_cast<GlobalDistance>((base * pow(scaleFactor, ints)))...};
- }(6.6F, std::make_integer_sequence<GlobalDistance, ShadowMapper::SHADOW_BANDS>());
+ }(4.6F, std::make_integer_sequence<GlobalDistance, ShadowMapper::SHADOW_BANDS>());
static_assert(shadowBands.front() == 1);
static_assert(shadowBands.back() == 10'000'000);
@@ -83,12 +85,13 @@ ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightV
ShadowMapper::Definitions
ShadowMapper::update(const SceneProvider & scene, const LightDirection & dir, const Camera & camera) const
{
+ glDebugScope _ {depthMap};
glCullFace(GL_FRONT);
glEnable(GL_DEPTH_TEST);
shadowStenciller.setLightDirection(dir);
for (const auto & [id, asset] : gameState->assets) {
- if (const auto r = std::dynamic_pointer_cast<const Renderable>(asset)) {
+ if (const auto r = asset.getAs<const Renderable>()) {
r->updateStencil(shadowStenciller);
}
}
@@ -102,37 +105,37 @@ ShadowMapper::update(const SceneProvider & scene, const LightDirection & dir, co
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, &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[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);
+ using ExtentsBoundingBox = AxisAlignedBoundingBox<RelativeDistance>;
+ std::ranges::transform(bandViewExtents | std::views::pairwise, std::back_inserter(out),
+ [&lightViewDir, &sizes](const auto & band) mutable {
+ const auto & [near, far] = band;
+ auto extents = ExtentsBoundingBox::fromPoints(std::span {near.begin(), far.end()});
+ extents.min.z -= 10'000.F;
+ extents.max.z += 10'000.F;
+ const auto lightProjection = glm::ortho(
+ extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z);
+ sizes.emplace_back(extents.max - extents.min);
return lightProjection * lightViewDir;
});
for (const auto p : std::initializer_list<const ShadowProgram *> {
&landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures, &stencilShadowProgram}) {
p->setView(out, sizes, lightViewPoint);
}
- scene.shadows(*this);
+ ExtentsBoundingBox extents {lightViewPoint, lightViewPoint};
+ for (const auto & point : bandViewExtents.back()) {
+ extents += point;
+ }
+ const auto lightProjection
+ = glm::ortho(extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z);
+ Frustum frustum {lightViewPoint, lightViewDir, lightProjection};
+ scene.shadows(*this, frustum);
glCullFace(GL_BACK);
return out;
}
-ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs) : Program {vs, commonShadowPoint_gs} { }
+ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs) : Program {vs, commonShadowPoint_geom} { }
ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs, const Shader & gs, const Shader & fs) :
Program {vs, gs, fs}
@@ -158,7 +161,7 @@ ShadowMapper::ShadowProgram::use() const
glUseProgram(*this);
}
-ShadowMapper::DynamicPoint::DynamicPoint() : ShadowProgram {shadowDynamicPoint_vs} { }
+ShadowMapper::DynamicPoint::DynamicPoint() : ShadowProgram {shadowDynamicPoint_vert} { }
void
ShadowMapper::DynamicPoint::use(const Location & location) const
@@ -175,7 +178,7 @@ ShadowMapper::DynamicPoint::setModel(const Location & location) const
}
ShadowMapper::StencilShadowProgram::StencilShadowProgram() :
- ShadowProgram {shadowDynamicPointStencil_vs, shadowDynamicPointStencil_gs, shadowDynamicPointStencil_fs}
+ ShadowProgram {shadowDynamicPointStencil_vert, shadowDynamicPointStencil_geom, shadowDynamicPointStencil_frag}
{
}
diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp
index 86b77e4..aee7161 100644
--- a/gfx/gl/shadowStenciller.cpp
+++ b/gfx/gl/shadowStenciller.cpp
@@ -1,18 +1,19 @@
#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/lightDirection.h"
#include "gfx/models/mesh.h"
#include "glArrays.h"
#include "gl_traits.h"
+#include "gldebug.h"
#include "maths.h"
+#include <gfx/gl/shaders/shadowStencil-frag.h>
+#include <gfx/gl/shaders/shadowStencil-geom.h>
+#include <gfx/gl/shaders/shadowStencil-vert.h>
#include <stdexcept>
ShadowStenciller::ShadowStenciller() :
- shadowCaster {shadowStencil_vs, shadowStencil_gs, shadowStencil_fs}, viewProjections {}
+ shadowCaster {shadowStencil_vert, shadowStencil_geom, shadowStencil_frag}, viewProjections {}
{
+ glDebugScope _ {fbo};
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
@@ -50,6 +51,7 @@ ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height)
void
ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh, const Texture::AnyPtr texture) const
{
+ glDebugScope _ {fbo};
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, stencil, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
diff --git a/gfx/gl/uiShader.cpp b/gfx/gl/uiShader.cpp
deleted file mode 100644
index 23da9dc..0000000
--- a/gfx/gl/uiShader.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "uiShader.h"
-#include "gl_traits.h"
-#include <gfx/gl/program.h>
-#include <gfx/gl/shader.h>
-#include <gfx/gl/shaders/fs-uiShader.h>
-#include <gfx/gl/shaders/fs-uiShaderFont.h>
-#include <gfx/gl/shaders/vs-uiShader.h>
-#include <glm/glm.hpp>
-#include <glm/gtc/type_ptr.hpp>
-
-UIShader::IconProgram::IconProgram(const glm::mat4 & vp) : UIProgram {vp, uiShader_vs, uiShader_fs} { }
-
-UIShader::TextProgram::TextProgram(const glm::mat4 & vp) : UIProgram {vp, uiShader_vs, uiShaderFont_fs} { }
-
-UIShader::UIShader(size_t width, size_t height) :
- UIShader {glm::ortho<float>(0, static_cast<float>(width), 0, static_cast<float>(height))}
-{
-}
-
-UIShader::UIShader(const glm::mat4 & viewProjection) : icon {viewProjection}, text {viewProjection} { }
-
-void
-UIShader::TextProgram::use(const RGB & colour) const
-{
- Program::use();
- glUniform(colorLoc, colour);
-}
diff --git a/gfx/gl/uiShader.h b/gfx/gl/uiShader.h
deleted file mode 100644
index 6d00166..0000000
--- a/gfx/gl/uiShader.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-#include "config/types.h"
-#include "gl_traits.h"
-#include "program.h"
-#include <cstddef>
-#include <glad/gl.h>
-#include <glm/glm.hpp>
-#include <glm/gtc/type_ptr.hpp>
-
-class UIShader {
-public:
- UIShader(std::size_t width, std::size_t height);
-
-private:
- explicit UIShader(const glm::mat4 & viewProjection);
-
- class UIProgram : public Program {
- public:
- template<typename... S>
- explicit UIProgram(const glm::mat4 & vp, S &&... srcs) : Program {std::forward<S>(srcs)...}
- {
- const RequiredUniformLocation uiProjectionLoc {*this, "uiProjection"};
- glUseProgram(*this);
- glUniform(uiProjectionLoc, vp);
- }
- };
-
- class IconProgram : public UIProgram {
- public:
- explicit IconProgram(const glm::mat4 & vp);
- using Program::use;
- };
-
- class TextProgram : public UIProgram {
- public:
- explicit TextProgram(const glm::mat4 & vp);
- void use(const RGB & colour) const;
-
- private:
- RequiredUniformLocation colorLoc {*this, "colour"};
- };
-
-public:
- IconProgram icon;
- TextProgram text;
-};
diff --git a/gfx/gl/vertexArrayObject.h b/gfx/gl/vertexArrayObject.h
index 57daaf3..d008897 100644
--- a/gfx/gl/vertexArrayObject.h
+++ b/gfx/gl/vertexArrayObject.h
@@ -21,14 +21,15 @@ public:
NO_COPY(VertexArrayObject);
template<typename m, typename T> struct MP {
- constexpr MP(m T::*p) : P {p} { }
+ constexpr MP(m T::* p) : P {p} { }
+ constexpr
operator void *() const
{
return &(static_cast<T *>(nullptr)->*P);
}
- m T::*P;
+ m T::* P;
using value_type = m;
};
@@ -69,6 +70,13 @@ public:
return *this;
}
+ VertexArrayObject &
+ data(const GLuint arrayBuffer, GLenum target)
+ {
+ glBindBuffer(target, arrayBuffer);
+ return *this;
+ }
+
template<typename Data>
static void
data(const Data & data, const GLuint arrayBuffer, GLenum target)
diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp
index a508421..3457fb5 100644
--- a/gfx/models/texture.cpp
+++ b/gfx/models/texture.cpp
@@ -50,6 +50,16 @@ Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOption
glTexParameter(type, GL_TEXTURE_MIN_FILTER, to.minFilter);
glTexParameter(type, GL_TEXTURE_MAG_FILTER, to.magFilter);
glTexImage2D(type, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ auto isMimmap = [](auto value) {
+ auto eqAnyOf = [value](auto... test) {
+ return (... || (value == test));
+ };
+ 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);
+ }
}
void
diff --git a/gfx/renderable.cpp b/gfx/renderable.cpp
index 3594968..27f2459 100644
--- a/gfx/renderable.cpp
+++ b/gfx/renderable.cpp
@@ -6,7 +6,7 @@ Renderable::lights(const SceneShader &) const
}
void
-Renderable::shadows(const ShadowMapper &) const
+Renderable::shadows(const ShadowMapper &, const Frustum &) const
{
}
diff --git a/gfx/renderable.h b/gfx/renderable.h
index 83522e3..140c570 100644
--- a/gfx/renderable.h
+++ b/gfx/renderable.h
@@ -3,6 +3,7 @@
#include <special_members.h>
class SceneShader;
+class Frustum;
class ShadowMapper;
class ShadowStenciller;
@@ -12,9 +13,9 @@ public:
virtual ~Renderable() = default;
DEFAULT_MOVE_COPY(Renderable);
- virtual void render(const SceneShader & shader) const = 0;
+ virtual void render(const SceneShader & shader, const Frustum &) const = 0;
virtual void lights(const SceneShader & shader) const;
- virtual void shadows(const ShadowMapper & shadowMapper) const;
+ virtual void shadows(const ShadowMapper & shadowMapper, const Frustum &) const;
virtual void updateStencil(const ShadowStenciller & lightDir) const;
};