summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2022-11-19 15:04:30 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2022-11-23 18:38:43 +0000
commitffdaa93edf5eeaf9db7dc17e51554a77dd9d596d (patch)
tree5ec8af60e0761417d4f80a012679e3071de59888
parentShared context, persist main window in test, send test for upcoming pointlight (diff)
downloadilt-ffdaa93edf5eeaf9db7dc17e51554a77dd9d596d.tar.bz2
ilt-ffdaa93edf5eeaf9db7dc17e51554a77dd9d596d.tar.xz
ilt-ffdaa93edf5eeaf9db7dc17e51554a77dd9d596d.zip
Separate out the illumation of the scene
-rw-r--r--gfx/gl/shaders/directionalLight.fs18
-rw-r--r--gfx/gl/shaders/lightingShader.fs52
-rw-r--r--test/test-render.cpp29
-rw-r--r--ui/gameMainWindow.cpp17
-rw-r--r--ui/gameMainWindow.h6
-rw-r--r--ui/sceneRenderer.cpp67
-rw-r--r--ui/sceneRenderer.h25
-rw-r--r--ui/window.cpp1
8 files changed, 141 insertions, 74 deletions
diff --git a/gfx/gl/shaders/directionalLight.fs b/gfx/gl/shaders/directionalLight.fs
new file mode 100644
index 0000000..7562f96
--- /dev/null
+++ b/gfx/gl/shaders/directionalLight.fs
@@ -0,0 +1,18 @@
+#version 330 core
+#extension GL_ARB_shading_language_420pack : enable
+
+out vec3 FragColor;
+
+in vec2 TexCoords;
+
+layout(binding = 1) uniform sampler2D gNormal;
+
+uniform vec3 lightDirection;
+uniform vec3 lightColour;
+
+void
+main()
+{
+ const vec3 Normal = texture(gNormal, TexCoords).rgb;
+ FragColor = dot(-lightDirection, Normal) * lightColour;
+}
diff --git a/gfx/gl/shaders/lightingShader.fs b/gfx/gl/shaders/lightingShader.fs
index b0ca20a..4646b75 100644
--- a/gfx/gl/shaders/lightingShader.fs
+++ b/gfx/gl/shaders/lightingShader.fs
@@ -5,58 +5,14 @@ out vec3 FragColor;
in vec2 TexCoords;
-layout(binding = 0) uniform sampler2D gPosition;
-layout(binding = 1) uniform sampler2D gNormal;
layout(binding = 2) uniform sampler2D gAlbedoSpec;
-
-// struct Light {
-// vec3 Position;
-// vec3 Color;
-
-// float Linear;
-// float Quadratic;
-// float Radius;
-//};
-// const int NR_LIGHTS_MAX = 12;
-// uniform Light lights[NR_LIGHTS_MAX];
-// uniform vec3 viewPos;
-
-uniform vec3 lightDirection = normalize(vec3(1, 0, -1));
-uniform vec3 lightColor = vec3(0.6, 0.6, 0.6);
-uniform vec3 ambientColor = vec3(0.5, 0.5, 0.5);
+layout(binding = 3) uniform sampler2D gIllumination;
void
main()
{
- // retrieve data from gbuffer
- // const vec3 FragPos = texture(gPosition, TexCoords).rgb;
- const vec3 Normal = texture(gNormal, TexCoords).rgb;
- const vec3 Diffuse = texture(gAlbedoSpec, TexCoords).rgb;
- // float Specular = texture(gAlbedoSpec, TexCoords).a;
-
- // then calculate lighting as usual
- // vec3 lighting = Diffuse;
- const vec3 lighting = ambientColor + clamp((dot(-lightDirection, Normal) * lightColor), 0, 0.5);
- // vec3 viewDir = normalize(viewPos - FragPos);
- // for (int i = 0; i < NR_LIGHTS_MAX; ++i) {
- // calculate distance between light source and current fragment
- // float distance = length(lights[i].Position - FragPos);
- // if (distance < lights[i].Radius) {
- // diffuse
- // vec3 lightDir = normalize(lights[i].Position - FragPos);
- // vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lights[i].Color;
- // specular
- // vec3 halfwayDir = normalize(lightDir + viewDir);
- // float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0);
- // vec3 specular = lights[i].Color * spec * Specular;
- // attenuation
- // float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);
- // diffuse *= attenuation;
- // specular *= attenuation;
- // lighting += diffuse + specular;
- //}
- //}
- // FragColor = vec4(lighting, 1.0);
+ const vec3 Albedo = texture(gAlbedoSpec, TexCoords).rgb;
+ const vec3 Illumination = texture(gIllumination, TexCoords).rgb;
- FragColor = vec3(Diffuse * lighting);
+ FragColor = Albedo * Illumination;
}
diff --git a/test/test-render.cpp b/test/test-render.cpp
index 62090e3..d5a79ec 100644
--- a/test/test-render.cpp
+++ b/test/test-render.cpp
@@ -54,6 +54,19 @@ public:
}
};
+class TestScene : public SceneRenderer::SceneProvider {
+ Terrain terrain {[]() {
+ auto gd = std::make_shared<GeoData>(GeoData::Limits {{0, 0}, {100, 100}});
+ gd->generateRandom();
+ return gd;
+ }()};
+ void
+ content(const SceneShader & shader) const
+ {
+ terrain.render(shader);
+ }
+};
+
BOOST_GLOBAL_FIXTURE(ApplicationBase);
BOOST_GLOBAL_FIXTURE(TestMainWindow);
@@ -61,29 +74,21 @@ BOOST_FIXTURE_TEST_SUITE(w, TestRenderOutput);
BOOST_AUTO_TEST_CASE(basic)
{
- auto gd = std::make_shared<GeoData>(GeoData::Limits {{0, 0}, {100, 100}});
- gd->generateRandom();
- Terrain terrain {gd};
SceneRenderer ss {size, output};
ss.camera.pos = {-10, -10, 60};
ss.camera.forward = glm::normalize(glm::vec3 {1, 1, -0.5F});
- ss.render([&terrain](const auto & shader) {
- terrain.render(shader);
- });
+ TestScene scene;
+ ss.render(scene);
Texture::save(outImage, size, "/tmp/basic.tga");
}
BOOST_AUTO_TEST_CASE(pointlight)
{
- auto gd = std::make_shared<GeoData>(GeoData::Limits {{0, 0}, {100, 100}});
- gd->generateRandom();
- Terrain terrain {gd};
SceneRenderer ss {size, output};
ss.camera.pos = {-10, -10, 60};
ss.camera.forward = glm::normalize(glm::vec3 {1, 1, -0.5F});
- ss.render([&terrain](const auto & shader) {
- terrain.render(shader);
- });
+ TestScene scene;
+ ss.render(scene);
Texture::save(outImage, size, "/tmp/pointlight.tga");
}
diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp
index c31265a..0e861b4 100644
--- a/ui/gameMainWindow.cpp
+++ b/ui/gameMainWindow.cpp
@@ -45,9 +45,18 @@ GameMainWindow::tick(TickDuration)
void
GameMainWindow::render() const
{
- SceneRenderer::render([this](const auto & shader) {
- gameState->world.apply<Renderable>(&Renderable::render, shader);
- uiComponents.apply<WorldOverlay>(&WorldOverlay::render, shader);
- });
+ SceneRenderer::render(*this);
Window::render();
}
+void
+GameMainWindow::content(const SceneShader & shader) const
+{
+ gameState->world.apply<Renderable>(&Renderable::render, shader);
+ uiComponents.apply<WorldOverlay>(&WorldOverlay::render, shader);
+}
+void
+GameMainWindow::environment(const SceneShader & s, const SceneRenderer & r) const
+{
+ // default for now
+ SceneRenderer::SceneProvider::environment(s, r);
+}
diff --git a/ui/gameMainWindow.h b/ui/gameMainWindow.h
index 1e6af20..8485266 100644
--- a/ui/gameMainWindow.h
+++ b/ui/gameMainWindow.h
@@ -5,11 +5,15 @@
#include "window.h"
#include <cstddef>
-class GameMainWindow : public Window, SceneRenderer {
+class GameMainWindow : public Window, SceneRenderer, public SceneRenderer::SceneProvider {
public:
GameMainWindow(size_t w, size_t h);
void tick(TickDuration) override;
void render() const override;
+
+private:
+ void content(const SceneShader &) const override;
+ void environment(const SceneShader &, const SceneRenderer &) const override;
};
diff --git a/ui/sceneRenderer.cpp b/ui/sceneRenderer.cpp
index 6a68ac6..c3cff7a 100644
--- a/ui/sceneRenderer.cpp
+++ b/ui/sceneRenderer.cpp
@@ -1,5 +1,6 @@
#include "sceneRenderer.h"
#include "maths.h"
+#include <gfx/gl/shaders/fs-directionalLight.h>
#include <gfx/gl/shaders/fs-lightingShader.h>
#include <gfx/gl/shaders/vs-lightingShader.h>
#include <glm/gtc/type_ptr.hpp>
@@ -34,9 +35,7 @@ SceneRenderer::SceneRenderer(glm::ivec2 s, GLuint o) :
configuregdata(gPosition, GL_RGBA16F, GL_FLOAT, GL_COLOR_ATTACHMENT0);
configuregdata(gNormal, GL_RGBA16F, GL_FLOAT, GL_COLOR_ATTACHMENT1);
configuregdata(gAlbedoSpec, GL_RGBA, GL_UNSIGNED_BYTE, GL_COLOR_ATTACHMENT2);
- static constexpr std::array<unsigned int, 3> attachments {
- GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
- glDrawBuffers(attachments.size(), attachments.data());
+ configuregdata(gIllumination, GL_RGBA16F, GL_FLOAT, GL_COLOR_ATTACHMENT3);
glBindRenderbuffer(GL_RENDERBUFFER, depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.x, size.y);
@@ -50,20 +49,35 @@ SceneRenderer::SceneRenderer(glm::ivec2 s, GLuint o) :
}
void
-SceneRenderer::render(std::function<void(const SceneShader &)> content) const
+SceneRenderer::render(const SceneProvider & scene) const
{
shader.setView(camera.GetViewProjection());
glViewport(0, 0, size.x, size.y);
// Geometry pass
+ glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
+ static constexpr std::array<unsigned int, 3> attachments {
+ GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
+ glDrawBuffers(attachments.size(), attachments.data());
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
- glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
+ glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- content(shader);
+ scene.content(shader);
+
+ // Illumination pass
+ glDrawBuffer(GL_COLOR_ATTACHMENT3);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, gPosition);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, gNormal);
+ scene.environment(shader, *this);
// Lighting pass
glBindFramebuffer(GL_FRAMEBUFFER, output);
@@ -75,9 +89,48 @@ SceneRenderer::render(std::function<void(const SceneShader &)> content) const
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
- // TODO Configure lights
+ glActiveTexture(GL_TEXTURE3);
+ glBindTexture(GL_TEXTURE_2D, gIllumination);
lighting.use();
glBindVertexArray(displayVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
}
+
+void
+SceneRenderer::setAmbientLight(const glm::vec3 & colour) const
+{
+ glClearColor(colour.r, colour.g, colour.b, 1.0F);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void
+SceneRenderer::setDirectionalLight(const glm::vec3 & colour, const glm::vec3 & direction) const
+{
+ dirLight.use();
+ dirLight.setDirectionalLight(colour, direction);
+ glBindVertexArray(displayVAO);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glBindVertexArray(0);
+}
+
+SceneRenderer::DirectionalLightProgram::DirectionalLightProgram() :
+ Program {lightingShader_vs, directionalLight_fs}, directionLoc {*this, "lightDirection"}, colourLoc {*this,
+ "lightColour"}
+{
+}
+
+void
+SceneRenderer::DirectionalLightProgram::setDirectionalLight(const glm::vec3 & c, const glm::vec3 & d) const
+{
+ glUniform3fv(colourLoc, 1, glm::value_ptr(c));
+ const auto nd = glm::normalize(d);
+ glUniform3fv(directionLoc, 1, glm::value_ptr(nd));
+}
+
+void
+SceneRenderer::SceneProvider::environment(const SceneShader &, const SceneRenderer & renderer) const
+{
+ renderer.setAmbientLight({0.5F, 0.5F, 0.5F});
+ renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {1, 0, -1});
+}
diff --git a/ui/sceneRenderer.h b/ui/sceneRenderer.h
index c06fa83..8b81d0c 100644
--- a/ui/sceneRenderer.h
+++ b/ui/sceneRenderer.h
@@ -9,9 +9,18 @@
class SceneRenderer {
public:
+ class SceneProvider {
+ public:
+ virtual ~SceneProvider() = default;
+ virtual void content(const SceneShader &) const = 0;
+ virtual void environment(const SceneShader &, const SceneRenderer &) const;
+ };
+
explicit SceneRenderer(glm::ivec2 size, GLuint output);
- void render(std::function<void(const SceneShader &)> content) const;
+ void render(const SceneProvider &) const;
+ void setAmbientLight(const glm::vec3 & colour) const;
+ void setDirectionalLight(const glm::vec3 & colour, const glm::vec3 & direction) const;
Camera camera;
@@ -19,14 +28,26 @@ private:
glm::ivec2 size;
GLuint output;
glFrameBuffer gBuffer;
- glTexture gPosition, gNormal, gAlbedoSpec;
+ glTexture gPosition, gNormal, gAlbedoSpec, gIllumination;
glRenderBuffer depth;
class DeferredLightProgram : public Program {
public:
using Program::Program;
using Program::use;
};
+ class DirectionalLightProgram : public Program {
+ public:
+ DirectionalLightProgram();
+ using Program::use;
+
+ void setDirectionalLight(const glm::vec3 &, const glm::vec3 &) const;
+
+ private:
+ RequiredUniformLocation directionLoc, colourLoc;
+ };
+
DeferredLightProgram lighting;
+ DirectionalLightProgram dirLight;
glVertexArray displayVAO;
glBuffer displayVBO;
SceneShader shader;
diff --git a/ui/window.cpp b/ui/window.cpp
index 51aa827..5930292 100644
--- a/ui/window.cpp
+++ b/ui/window.cpp
@@ -77,6 +77,7 @@ void
Window::render() const
{
glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
uiComponents.apply(&UIComponent::render, uiShader, UIComponent::Position {});
}