Commit 3860aaee authored by Dario Seyb's avatar Dario Seyb

basic deferred shading

parent 6bd94a5f
#version 330
uniform sampler2D uSamplerColor;
float A = 0.15;
float B = 0.50;
float C = 0.10;
float D = 0.20;
float E = 0.02;
float F = 0.30;
float W = 11.2;
in vec2 vTexCoord;
out vec4 oColor;
vec3 Uncharted2Tonemap(vec3 x)
{
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}
void main()
{
vec3 texColor = texture(uSamplerColor, vTexCoord).rgb;
texColor *= 16; // Hardcoded Exposure Adjustment
float ExposureBias = 2.0f;
vec3 curr = Uncharted2Tonemap(ExposureBias*texColor);
vec3 whiteScale = vec3(1.0f)/Uncharted2Tonemap(vec3(W));
vec3 color = curr*whiteScale;
vec3 retColor = pow(color, vec3(1.0/2.2));
oColor = vec4(retColor,1);
}
#version 330
out vec2 vTexCoord;
const vec2 quad[4] = vec2[] (
vec2(-1.0, 1.0),
vec2(-1.0,-1.0),
vec2( 1.0, 1.0),
vec2( 1.0,-1.0)
);
void main()
{
vec2 p = quad[ gl_VertexID ];
vTexCoord = p * vec2(0.5, 0.5) + vec2(0.5, 0.5);
gl_Position = vec4(p, 0.0, 1.0);
}
in vec3 vNormal;
in vec2 vTexCoord;
out vec4 oColor;
out vec4 oNormal;
\ No newline at end of file
layout(std140) uniform bGlobalMatrices
{
mat4 uViewMatrix;
mat4 uProjectionMatrix;
};
uniform mat4 uModelMatrix;
in vec3 aPosition;
in vec3 aNormal;
in vec2 aTexCoord;
out vec3 vNormal;
out vec2 vTexCoord;
\ No newline at end of file
#version 330
uniform sampler2D uSamplerColor;
uniform sampler2D uSamplerNormal;
uniform sampler2D uSamplerPosition;
uniform sampler2D uSamplerDepth;
uniform vec3 uLightPosition;
uniform vec4 uLightColor;
uniform float uNear;
uniform float uFar;
uniform mat4 uViewProjectionInverseMatrix;
in vec2 vTexCoord;
out vec4 oColor;
vec3 unpackNormal(vec4 norm) {
return (norm.xyz * 2) - vec3(1, 1, 1);
}
float linearizeDepth(float depth) {
return (2.0 * uNear) / (uFar + uNear - depth * (uFar - uNear)); // convert to linear values
}
vec3 unpackWorldPosition(float depth) {
vec4 clipSpaceLocation;
clipSpaceLocation.xy = vTexCoord * 2.0f - 1.0f;
clipSpaceLocation.z = depth* 2.0f - 1.0f;;
clipSpaceLocation.w = 1.0f;
vec4 homogenousLocation = uViewProjectionInverseMatrix * clipSpaceLocation;
return homogenousLocation.xyz / homogenousLocation.w;
}
void main()
{
vec4 color = texture(uSamplerColor, vTexCoord);
vec3 normal = unpackNormal(texture(uSamplerNormal, vTexCoord));
vec3 position = texture(uSamplerPosition, vTexCoord).xyz;
float depth = texture(uSamplerDepth, vTexCoord).r;
if(depth == 1) discard;
vec3 worldPosition = unpackWorldPosition(depth);
vec3 lightDir = uLightPosition - worldPosition;
float lightDistance = length(lightDir);
lightDir /= lightDistance;
float diffuseFactor = dot(lightDir, normal) * uLightColor.a/lightDistance;
if(diffuseFactor < 0) diffuseFactor = 0;
vec3 diffuseColor = diffuseFactor * uLightColor.rgb * color.rgb;
oColor = vec4(diffuseColor, 1);
}
#version 330
out vec2 vTexCoord;
const vec2 quad[4] = vec2[] (
vec2(-1.0, 1.0),
vec2(-1.0,-1.0),
vec2( 1.0, 1.0),
vec2( 1.0,-1.0)
);
void main()
{
vec2 p = quad[ gl_VertexID ];
vTexCoord = p * vec2(0.5, 0.5) + vec2(0.5, 0.5);
gl_Position = vec4(p, 0.0, 1.0);
}
#version 330
in vec3 vNormal;
in vec2 vTexCoord;
uniform sampler2D uTexture;
out vec4 oColor;
out vec4 oNormal;
void main()
{
vec3 color = texture(uTexture, vTexCoord).rgb;
oColor = vec4(color, 1.0);
oNormal = vec4(normalize(vNormal) * 0.5 + 0.5, 0.0);
}
#version 330
uniform mat4 uModelMatrix;
uniform mat4 uViewProjectionMatrix;
in vec3 aNormal;
in vec3 aPosition;
in vec2 aTexCoord;
out vec3 vNormal;
out vec2 vTexCoord;
void main()
{
vNormal = inverse(transpose(mat3(uModelMatrix))) * aNormal;
vTexCoord = aTexCoord;
vec4 worldPosition = uModelMatrix * vec4(aPosition, 1.0);
gl_Position = uViewProjectionMatrix * worldPosition;
}
......@@ -122,7 +122,7 @@ ACGL_SMARTPOINTER_TYPEDEFS(ShaderParser)
* @brief A ShaderParser that recognizes shader includes
*
* e.g.
* #pragma ACGLimport "matrices.glsl"
* #pragma import "matrices.glsl"
*/
class IncludingShaderParser : public ShaderParser
{
......@@ -131,7 +131,7 @@ public:
IncludingShaderParser( std::string const& _filename );
/**
* Processes "#pragma ACGLimport filename"
* Processes "#pragma import filename"
*/
virtual bool processPragma(std::vector<std::string> const& _tokens, std::string const& _filename);
};
......
......@@ -198,7 +198,7 @@ IncludingShaderParser::IncludingShaderParser(const std::string &_filename) :
bool IncludingShaderParser::processPragma(const std::vector<std::string> &_tokens, const std::string &_filename)
{
if ( _tokens.size() == 2 && _tokens[0] == "ACGLimport" )
if ( _tokens.size() == 2 && _tokens[0] == "import" )
{
std::string fileToImport(_tokens[1]);
......
......@@ -2,6 +2,7 @@
#include <engine/events/Event.hpp>
struct DrawEvent : public Event<DrawEvent> {
DrawEvent(double i) : interp(i) { }
DrawEvent(double i, double totalTime) : interp(i), totalTime(totalTime) { }
double interp;
double totalTime;
};
\ No newline at end of file
#pragma once
#include <engine/events/Event.hpp>
#include <ACGL/Math/Math.hh>
struct ResizeWindowEvent : public Event<ResizeWindowEvent> {
ResizeWindowEvent(glm::vec2 newSize) : newSize(newSize) {}
glm::vec2 newSize;
};
\ No newline at end of file
......@@ -9,6 +9,8 @@
#include <engine/graphics/Camera.hpp>
#include <engine/scene/Transform.hpp>
#include <ACGL/OpenGL/Objects.hh>
class RendererSystem : public System {
private:
EventSystem *m_events;
......@@ -16,6 +18,14 @@ private:
Stack<DrawCall> m_submittedDrawCalls;
Entity m_mainCamera;
std::vector<ACGL::OpenGL::SharedTexture2D> m_gBufferTextures;
ACGL::OpenGL::SharedFrameBufferObject m_gBufferObject;
ACGL::OpenGL::SharedFrameBufferObject m_compositingBuffer;
SharedShaderProgram m_deferredCombineProgram;
SharedShaderProgram m_blitProgram;
public:
CONSTRUCT_SYSTEM(RendererSystem), m_submittedDrawCalls(kilobytes(4)) {}
......@@ -27,5 +37,5 @@ public:
m_submittedDrawCalls.push(drawCall);
}
void frame(double interp);
void frame(double interp, double totalTime);
};
\ No newline at end of file
......@@ -8,6 +8,7 @@
#include <engine/events/MouseEvent.hpp>
#include <engine/events/TouchEvent.hpp>
#include <engine/events/WindowEvent.hpp>
#include <engine/events/ResizeWindowEvent.hpp>
bool GameLoopSystem::startup() {
......@@ -58,6 +59,9 @@ void GameLoopSystem::run() {
switch (e.type) {
case SDL_WINDOWEVENT:
m_events->fire<WindowEvent>({ e });
if (e.window.type == SDL_WINDOWEVENT_RESIZED) {
m_events->fire<ResizeWindowEvent>(ResizeWindowEvent{ {e.window.data1, e.window.data2} });
}
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
......@@ -106,7 +110,7 @@ void GameLoopSystem::run() {
const double alpha = double(accumulator) / dt;
m_events->fire<"PrepareDraw"_sh>();
m_events->fire<DrawEvent>({ alpha });
m_events->fire<DrawEvent>({ alpha, float(t) / 1000 });
m_window->swap();
m_events->fire<"EndFrame"_sh>();
......
......@@ -83,7 +83,7 @@ bool WindowSystem::createWindow() {
// request an OpenGL debug context:
m_sdlWindow = SDL_CreateWindow(
"ACGL GLFWExamples", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
"Edge of Space", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
m_windowSize.x, m_windowSize.y, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!m_sdlWindow) {
......@@ -139,10 +139,8 @@ bool WindowSystem::startup() {
}
/////////////////////////////////////////////////////////////////////////////////////
// Set window title to binary name (without the path):
std::vector<std::string> tmp =
StringHelpers::split(std::string("Test Window"), '/');
SDL_SetWindowTitle(m_sdlWindow, tmp[tmp.size() - 1].c_str());
// Set window title
SDL_SetWindowTitle(m_sdlWindow, "Edge of Space");
return true;
}
......
......@@ -3,23 +3,75 @@
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/glloaders/extensions.hh>
#include <ACGL/OpenGL/Objects.hh>
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>
#include <ACGL/OpenGL/Creator/Texture2DCreator.hh>
#include <ACGL/OpenGL/Data/TextureLoadStore.hh>
#include <ACGL/OpenGL/Managers.hh>
#include <engine/graphics/DrawCall.hpp>
#include <engine/events/DrawEvent.hpp>
#include <engine/events/ResizeWindowEvent.hpp>
#include <glm/ext.hpp>
using namespace ACGL::OpenGL;
using namespace ACGL::Base;
using namespace ACGL::Utils;
bool RendererSystem::startup() {
RESOLVE_DEPENDENCY(m_events);
RESOLVE_DEPENDENCY(m_window);
m_events->subscribe<DrawEvent>([this](const DrawEvent& e) { frame(e.interp); });
m_events->subscribe<DrawEvent>(
[this](const DrawEvent &e) { frame(e.interp, e.totalTime); });
// Set up framebuffer for deferred shading
auto windowSize = m_window->getSize();
glViewport(0, 0, windowSize.x, windowSize.y);
m_gBufferTextures.push_back(
SharedTexture2D(new Texture2D(windowSize))); // RGBA per default
m_gBufferTextures.push_back(
SharedTexture2D(new Texture2D(windowSize))); // RGBA per default
m_gBufferTextures.push_back(
SharedTexture2D(new Texture2D(windowSize, GL_DEPTH24_STENCIL8)));
m_gBufferTextures.push_back(SharedTexture2D(
new Texture2D(windowSize, GL_RGBA32F))); // RGBA per default
m_gBufferTextures[0]->setMinFilter(GL_NEAREST);
m_gBufferTextures[1]->setMinFilter(GL_NEAREST);
m_gBufferTextures[2]->setMinFilter(GL_NEAREST);
m_gBufferTextures[3]->setMinFilter(GL_NEAREST);
m_gBufferTextures[0]->setMagFilter(GL_NEAREST);
m_gBufferTextures[1]->setMagFilter(GL_NEAREST);
m_gBufferTextures[2]->setMagFilter(GL_NEAREST);
m_gBufferTextures[3]->setMagFilter(GL_NEAREST);
m_gBufferObject = SharedFrameBufferObject(new FrameBufferObject());
m_gBufferObject->attachColorTexture("oColor", m_gBufferTextures[0]);
m_gBufferObject->attachColorTexture("oNormal", m_gBufferTextures[1]);
m_gBufferObject->setDepthTexture(m_gBufferTextures[2]);
m_gBufferObject->validate(); // always a good idea
m_compositingBuffer = SharedFrameBufferObject(new FrameBufferObject());
m_compositingBuffer->attachColorTexture("oColor", m_gBufferTextures[3]);
m_compositingBuffer->validate();
m_deferredCombineProgram = ShaderProgramCreator("DeferredCombine").create();
m_blitProgram = ShaderProgramCreator("Blit").create();
m_events->subscribe<ResizeWindowEvent>([this](const ResizeWindowEvent &e) {
glViewport(0, 0, e.newSize.x, e.newSize.y);
for (auto tex : m_gBufferTextures) {
tex->resize(e.newSize);
}
});
return true;
}
void RendererSystem::frame(double interp) {
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
void RendererSystem::frame(double interp, double totalTime) {
if (!m_mainCamera.valid()) {
return;
}
......@@ -33,21 +85,92 @@ void RendererSystem::frame(double interp) {
return;
}
static glm::mat4 FIX_CAM_ROTATION = glm::rotate<float>(M_PI, glm::vec3(0, 0, 1));
m_gBufferObject->setClearColor(glm::vec4{0, 0, 0, 0});
m_gBufferObject->bind();
m_gBufferObject->clearBuffers();
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ZERO);
auto windowSize = m_window->getSize();
auto projectioMatrix = glm::perspectiveFov<float>(cam->fov, windowSize.x, windowSize.y, cam->near, cam->far) *
glm::inverse(glm::translate<float>(trans->position) * trans->rotation);
auto projectionMatrix =
glm::perspectiveFov<float>(cam->fov, windowSize.x, windowSize.y,
cam->near, cam->far) *
glm::inverse(glm::translate<float>(trans->position) * trans->rotation);
for (size_t i = 0; i < m_submittedDrawCalls.size(); i++) {
auto drawCall = m_submittedDrawCalls[i];
drawCall.material.prog->setFragmentDataLocations(
m_gBufferObject->getAttachmentLocations());
drawCall.material.prog->setUniformBlockBinding("bGlobalMatrices", 0);
drawCall.material.prog->use();
glm::mat4 viewMatrix = drawCall.transform;
drawCall.material.prog->setUniform("uViewMatrix", viewMatrix);
drawCall.material.prog->setUniform("uProjectionMatrix", projectioMatrix);
auto bunnyTexture = Texture2DFileManager::the()->get(
Texture2DCreator("clownfishBunny.png"));
drawCall.material.prog->setTexture("uTexture", bunnyTexture, 0);
drawCall.material.prog->setUniform("uModelMatrix", drawCall.transform);
drawCall.material.prog->setUniform("uViewProjectionMatrix",
projectionMatrix);
drawCall.geometry.vao->render();
}
// Deferred lighting
m_compositingBuffer->setClearColor(glm::vec4{0, 0, 0, 0});
m_compositingBuffer->bind();
m_compositingBuffer->clearBuffers();
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_BLEND);
m_deferredCombineProgram->use();
m_deferredCombineProgram->setTexture("uSamplerColor", m_gBufferTextures[0],
0);
m_deferredCombineProgram->setTexture("uSamplerNormal", m_gBufferTextures[1],
1);
m_deferredCombineProgram->setTexture("uSamplerDepth", m_gBufferTextures[2],
2);
m_deferredCombineProgram->setUniform("uNear", cam->near);
m_deferredCombineProgram->setUniform("uFar", cam->far);
m_deferredCombineProgram->setUniform("uViewProjectionInverseMatrix",
glm::inverse(projectionMatrix));
// attribute-less rendering:
VertexArrayObject vao;
vao.bind(); // 'empty' VAO -> no attributes are defined
struct Light {
glm::vec3 position;
glm::vec4 color;
};
std::vector<Light> lights = {
{{sin(totalTime) * 10, 10, cos(totalTime) * 10}, {0.1, 0.6, 0.1, 6}},
{{10, 10, 10}, {.5, .1, .1, 4}},
{trans->position, {1, 1, 1, 1}},
};
for (auto light : lights) {
m_deferredCombineProgram->setUniform("uLightPosition", light.position);
m_deferredCombineProgram->setUniform("uLightColor", light.color);
glDrawArrays(
GL_TRIANGLE_STRIP, 0,
4); // create 2 triangles (defined in shader) with no attributes
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_BLEND);
m_blitProgram->use();
m_blitProgram->setTexture(
"uSamplerColor", m_compositingBuffer->getColorAttachments()[0].texture,
0);
glDrawArrays(
GL_TRIANGLE_STRIP, 0,
4); // create 2 triangles (defined in shader) with no attributes
openGLCriticalError();
m_submittedDrawCalls.reset();
}
......
......@@ -67,19 +67,19 @@ int main(int argc, char *argv[]) {
// load a texture:
auto bunnyTexture = Texture2DFileManager::the()->get(Texture2DCreator("clownfishBunny.png"));
// look up all shader files starting with 'HelloWorld' and build a ShaderProgram from it:
auto normalsAsColorShader = ShaderProgramCreator("HelloWorld").attributeLocations(vaoCube->getAttributeLocations()).create();
normalsAsColorShader->use();
// look up all shader files starting with 'PBR' and build a ShaderProgram from it:
auto pbrShader = ShaderProgramCreator("PBR").attributeLocations(vaoCube->getAttributeLocations()).create();
pbrShader->use();
// set texture uniform and bind texture to the same texture unit:
normalsAsColorShader->setTexture("uTexture", bunnyTexture, 0);
pbrShader->setTexture("uTexture", bunnyTexture, 0);
// Create geometry objects that point to the previously initialized vaos
Geometry geom1 = { vaoBunny };
Geometry geom2 = { vaoCube };
// Create a material that uses the loaded shader program
Material mat = { normalsAsColorShader };
Material mat = { pbrShader };
// Create an entity in the scene graph
auto cube1 = sceneGraph.create();
......@@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
auto soundSource = cube2.assign<SoundSource>(testSound);
// Play that particular sound source
soundSource->play();
// soundSource->play();
// Create an entity that is used to position the camera in the scene
auto playerObj = sceneGraph.create();
......@@ -184,8 +184,6 @@ int main(int argc, char *argv[]) {
// Subscribe to the UI drawing event.
// This is called once per frame
events.subscribe<"DrawUI"_sh>([&soundSource]() {
static bool opened = true;
ImGui::ShowTestWindow(&opened);
ImGui::Begin("Sound Control", 0, ImGuiWindowFlags_::ImGuiWindowFlags_AlwaysAutoResize);
if (ImGui::Button("Pause Sound", glm::vec2(100, 20))) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment