summaryrefslogtreecommitdiff
path: root/gfx/gl
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl')
-rw-r--r--gfx/gl/sceneShader.cpp34
-rw-r--r--gfx/gl/sceneShader.h13
-rw-r--r--gfx/gl/shader.cpp37
-rw-r--r--gfx/gl/shader.h11
-rw-r--r--gfx/gl/shaders/network.fs17
-rw-r--r--gfx/gl/shaders/networkCommon.glsl43
-rw-r--r--gfx/gl/shaders/networkCurve.gs47
-rw-r--r--gfx/gl/shaders/networkCurve.vs29
-rw-r--r--gfx/gl/shaders/networkStraight.gs17
-rw-r--r--gfx/gl/shaders/networkStraight.vs24
10 files changed, 261 insertions, 11 deletions
diff --git a/gfx/gl/sceneShader.cpp b/gfx/gl/sceneShader.cpp
index 1b3b27c..bc64a88 100644
--- a/gfx/gl/sceneShader.cpp
+++ b/gfx/gl/sceneShader.cpp
@@ -1,14 +1,19 @@
#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-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>
@@ -21,15 +26,17 @@
SceneShader::SceneShader() :
basicInst {dynamicPointInst_vs, material_fs}, landmass {fixedPoint_vs, landmass_fs},
absolute {fixedPoint_vs, material_fs}, spotLightInst {spotLight_vs, spotLight_gs, spotLight_fs},
- pointLightInst {pointLight_vs, pointLight_gs, pointLight_fs}
+ pointLightInst {pointLight_vs, pointLight_gs, pointLight_fs},
+ networkStraight {networkStraight_vs, networkStraight_gs, network_fs},
+ networkCurve {networkCurve_vs, networkCurve_gs, network_fs}
{
}
void
SceneShader::setViewProjection(const GlobalPosition3D & viewPoint, const glm::mat4 & viewProjection) const
{
- for (const auto & prog : std::initializer_list<const SceneProgram *> {
- &basic, &basicInst, &water, &landmass, &absolute, &pointLightInst, &spotLightInst}) {
+ for (const auto & prog : std::initializer_list<const SceneProgram *> {&basic, &basicInst, &water, &landmass,
+ &absolute, &pointLightInst, &spotLightInst, &networkStraight, &networkCurve}) {
prog->setViewProjection(viewPoint, viewProjection);
}
}
@@ -37,8 +44,8 @@ SceneShader::setViewProjection(const GlobalPosition3D & viewPoint, const glm::ma
void
SceneShader::setViewPort(const ViewPort & viewPort) const
{
- for (const auto & prog : std::initializer_list<const SceneProgram *> {
- &basic, &basicInst, &water, &landmass, &absolute, &pointLightInst, &spotLightInst}) {
+ for (const auto & prog : std::initializer_list<const SceneProgram *> {&basic, &basicInst, &water, &landmass,
+ &absolute, &pointLightInst, &spotLightInst, &networkStraight, &networkCurve}) {
prog->setViewPort(viewPort);
}
}
@@ -79,6 +86,23 @@ SceneShader::BasicProgram::use(Location const & location) const
setModel(location);
}
+template<typename... S>
+SceneShader::NetworkProgram::NetworkProgram(S &&... s) :
+ AbsolutePosProgram {std::forward<S>(s)...}, profileLoc {*this, "profile"}, texturePosLoc {*this, "texturePos"},
+ profileLengthLoc {*this, "profileLength"}
+{
+}
+
+void
+SceneShader::NetworkProgram::use(
+ const std::span<const glm::vec3> profile, const std::span<const float> texturePos) const
+{
+ Program::use();
+ glUniform(profileLoc, profile);
+ glUniform(texturePosLoc, texturePos);
+ glUniform(profileLengthLoc, static_cast<GLuint>(profile.size()));
+}
+
SceneShader::WaterProgram::WaterProgram() : SceneProgram {water_vs, water_fs}, waveLoc {*this, "waves"} { }
void
diff --git a/gfx/gl/sceneShader.h b/gfx/gl/sceneShader.h
index 813c1bf..8621442 100644
--- a/gfx/gl/sceneShader.h
+++ b/gfx/gl/sceneShader.h
@@ -3,6 +3,7 @@
#include "config/types.h"
#include "program.h"
#include <glArrays.h>
+#include <span>
class Location;
@@ -41,8 +42,17 @@ class SceneShader {
using SceneProgram::SceneProgram;
};
- class WaterProgram : public SceneProgram {
+ class NetworkProgram : public AbsolutePosProgram {
public:
+ template<typename... S> explicit NetworkProgram(S &&...);
+
+ void use(const std::span<const glm::vec3>, const std::span<const float>) const;
+
+ private:
+ RequiredUniformLocation profileLoc, texturePosLoc, profileLengthLoc;
+ };
+
+ class WaterProgram : public SceneProgram {
public:
WaterProgram();
void use(float waveCycle) const;
@@ -57,6 +67,7 @@ public:
BasicProgram basic;
WaterProgram water;
AbsolutePosProgram basicInst, landmass, absolute, spotLightInst, pointLightInst;
+ NetworkProgram networkStraight, networkCurve;
void setViewProjection(const GlobalPosition3D & viewPoint, const glm::mat4 & viewProjection) const;
void setViewPort(const ViewPort & viewPort) const;
diff --git a/gfx/gl/shader.cpp b/gfx/gl/shader.cpp
index 5f83b83..0f75817 100644
--- a/gfx/gl/shader.cpp
+++ b/gfx/gl/shader.cpp
@@ -1,13 +1,48 @@
#include "shader.h"
+#include <algorithm>
#include <array>
#include <stdexcept>
#include <string>
+namespace {
+ auto
+ getInt(GLenum e)
+ {
+ GLint i {};
+ glGetIntegerv(e, &i);
+ return std::to_string(i);
+ }
+
+ using LookUpFunction = std::string (*)(GLenum);
+ constexpr std::array<std::tuple<std::string_view, GLenum, LookUpFunction>, 1> LOOKUPS {{
+ {"GL_MAX_GEOMETRY_OUTPUT_VERTICES", GL_MAX_GEOMETRY_OUTPUT_VERTICES, getInt},
+ }};
+}
+
Shader::ShaderRef
Shader::compile() const
{
ShaderRef shader {type};
- glShaderSource(shader, 1, &text, &len);
+ auto source = [&shader](auto text, GLint len) {
+ glShaderSource(shader, 1, &text, &len);
+ };
+ if (lookups) {
+ std::basic_string<GLchar> textMod {text};
+ for (const auto & match : ctre::range<R"(\bGL_[A-Z_]+\b)">(textMod)) {
+ if (const auto lookup = std::find_if(LOOKUPS.begin(), LOOKUPS.end(),
+ [&match](const auto & lookup) {
+ return std::get<std::string_view>(lookup) == match;
+ });
+ lookup != LOOKUPS.end()) {
+ const auto & [name, pname, getFunction] = *lookup;
+ textMod.replace(match.begin(), match.end(), getFunction(pname));
+ }
+ }
+ source(textMod.c_str(), static_cast<GLint>(textMod.length()));
+ }
+ else {
+ source(text.data(), static_cast<GLint>(text.length()));
+ }
glCompileShader(shader);
CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error compiling shader!");
diff --git a/gfx/gl/shader.h b/gfx/gl/shader.h
index cff2281..c6b45af 100644
--- a/gfx/gl/shader.h
+++ b/gfx/gl/shader.h
@@ -2,20 +2,23 @@
#include <glRef.h>
#include <glad/gl.h>
-#include <optional>
#include <string_view>
+#include <thirdparty/ctre/include/ctre.hpp>
class Shader {
public:
using ShaderRef = glRef<GLuint, &glCreateShader, &glDeleteShader>;
- constexpr Shader(const GLchar * text, GLint len, GLuint type) : text {text}, len {len}, type {type} { }
+ constexpr Shader(const GLchar * text, GLuint type) :
+ text {text}, type {type}, lookups {ctre::search<R"(\bGL_[A-Z_]+\b)">(this->text)}
+ {
+ }
[[nodiscard]] ShaderRef compile() const;
static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, std::string_view errorMessage);
private:
- const GLchar * text;
- GLint len;
+ const std::basic_string_view<GLchar> text;
GLuint type;
+ bool lookups;
};
diff --git a/gfx/gl/shaders/network.fs b/gfx/gl/shaders/network.fs
new file mode 100644
index 0000000..4e347b4
--- /dev/null
+++ b/gfx/gl/shaders/network.fs
@@ -0,0 +1,17 @@
+#version 330 core
+#extension GL_ARB_shading_language_420pack : enable
+
+include(`materialOut.glsl')
+in vec3 rposition;
+in vec2 texCoord;
+
+layout(binding = 0) uniform sampler2D texture0;
+uniform ivec3 viewPoint;
+
+void
+main()
+{
+ gPosition = ivec4(viewPoint + rposition, 1);
+ gNormal = vec4(0, 0, 1, 1);
+ gAlbedoSpec = texture(texture0, texCoord);
+}
diff --git a/gfx/gl/shaders/networkCommon.glsl b/gfx/gl/shaders/networkCommon.glsl
new file mode 100644
index 0000000..0bc3c1c
--- /dev/null
+++ b/gfx/gl/shaders/networkCommon.glsl
@@ -0,0 +1,43 @@
+uniform vec3[10] profile;
+uniform float[10] texturePos;
+uniform uint profileLength;
+
+uniform mat4 viewProjection;
+uniform ivec3 viewPoint;
+
+uniform float clipDistance = 5000000;
+uniform float flatDistance = 1000000;
+
+out vec2 texCoord;
+out vec3 rposition;
+
+float
+segDist(const ivec3 a, const ivec3 b)
+{
+ return min(distance(viewPoint, a), distance(viewPoint, b));
+}
+
+ifelse(
+ TYPE, .gs,
+ // 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);
+ rposition = vpos - viewPoint;
+ gl_Position = viewProjection * vec4(rposition, 1);
+ texCoord = vec2(texturePos[v], texY);
+ EmitVertex();
+ }
+
+ void doSeg(const float dist, const ivec3 apos, const ivec3 bpos, const float atexY, const float btexY,
+ const mat2 arot, const mat2 brot) {
+ if (dist < clipDistance) {
+ uint vstep = (dist < flatDistance) ? 1u : profileLength - 1u;
+ for (uint v = 0u; v < profileLength; v += vstep) {
+ doVertex(bpos, v, btexY, brot);
+ doVertex(apos, v, atexY, arot);
+ }
+ EndPrimitive();
+ }
+ }
+ // End: Geometry shader only function
+)
diff --git a/gfx/gl/shaders/networkCurve.gs b/gfx/gl/shaders/networkCurve.gs
new file mode 100644
index 0000000..7cb6c42
--- /dev/null
+++ b/gfx/gl/shaders/networkCurve.gs
@@ -0,0 +1,47 @@
+#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.vs b/gfx/gl/shaders/networkCurve.vs
new file mode 100644
index 0000000..f51bb87
--- /dev/null
+++ b/gfx/gl/shaders/networkCurve.vs
@@ -0,0 +1,29 @@
+#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.gs
new file mode 100644
index 0000000..51df5fb
--- /dev/null
+++ b/gfx/gl/shaders/networkStraight.gs
@@ -0,0 +1,17 @@
+#version 330 core
+
+flat in ivec3 apos[];
+flat in ivec3 bpos[];
+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]);
+}
diff --git a/gfx/gl/shaders/networkStraight.vs b/gfx/gl/shaders/networkStraight.vs
new file mode 100644
index 0000000..55f9c4f
--- /dev/null
+++ b/gfx/gl/shaders/networkStraight.vs
@@ -0,0 +1,24 @@
+#version 330 core
+
+layout(location = 0) in ivec3 v_apos;
+layout(location = 1) in ivec3 v_bpos;
+layout(location = 2) in mat2 v_rot;
+layout(location = 4) in float v_reps;
+
+flat out ivec3 apos;
+flat out ivec3 bpos;
+flat out mat2 rot;
+flat out float reps;
+flat out float dist;
+
+include(`networkCommon.glsl')
+
+void
+main()
+{
+ apos = v_apos;
+ bpos = v_bpos;
+ rot = v_rot;
+ reps = v_reps;
+ dist = segDist(v_apos, v_bpos);
+}