Files
squidout/src/game/Core/Renderer.cpp
T

720 lines
27 KiB
C++
Executable File

/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/Renderer.h"
void dd::Renderer::Initialize()
{
// Initialize GLFW
if (!glfwInit()) {
LOG_ERROR("GLFW: Initialization failed");
exit(EXIT_FAILURE);
}
// Create a window
GLFWmonitor* monitor = nullptr;
if (m_Fullscreen) {
monitor = glfwGetPrimaryMonitor();
}
glfwWindowHint(GLFW_SAMPLES, 8);
m_Window = glfwCreateWindow(m_Resolution.Width, m_Resolution.Height, "daydream", monitor, nullptr);
if (!m_Window) {
LOG_ERROR("GLFW: Failed to create window");
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(m_Window);
// GL version info
glGetIntegerv(GL_MAJOR_VERSION, &m_GLVersion[0]);
glGetIntegerv(GL_MINOR_VERSION, &m_GLVersion[1]);
m_GLVendor = (GLchar*)glGetString(GL_VENDOR);
std::stringstream ss;
ss << m_GLVendor << " OpenGL " << m_GLVersion[0] << "." << m_GLVersion[1];
#ifdef DEBUG
ss << " DEBUG";
#endif
LOG_INFO(ss.str().c_str());
glfwSetWindowTitle(m_Window, ss.str().c_str());
// Initialize GLEW
if (glewInit() != GLEW_OK) {
LOG_ERROR("GLEW: Initialization failed");
exit(EXIT_FAILURE);
}
// Create default camera
m_DefaultCamera = std::unique_ptr<dd::Camera>(new dd::Camera((float)m_Resolution.Width / m_Resolution.Height, 45.f, 0.01f, 5000.f));
m_DefaultCamera->SetPosition(glm::vec3(0, 0, 0));
if (m_Camera == nullptr) {
m_Camera = m_DefaultCamera.get();
}
glfwSwapInterval(m_VSYNC);
LoadShaders();
CreateBuffers();
m_CurrentScreenBuffer = m_TFinal;
}
void dd::Renderer::LoadShaders()
{
/*
Deferred rendering
*/
// Pass #1: Fill G-buffers
m_SpDeferred1 = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/1/");
m_SpDeferred1->BindFragDataLocation(0, "GDiffuse");
m_SpDeferred1->BindFragDataLocation(1, "GPosition");
m_SpDeferred1->BindFragDataLocation(2, "GNormal");
m_SpDeferred1->BindFragDataLocation(3, "GSpecular");
m_SpDeferred1->Link();
// Pass #2: Lighting
m_SpDeferred2 = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/2/");
//glBindFragDataLocation(m_SPDeferred2, 0, "FragmentLighting");
m_SpDeferred2->Link();
//Water Pass
m_SpWater = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/water/");
m_SpWater->Link();
m_SpWater2 = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/water2/");
m_SpWater2->Link();
// Pass #3: Combining into final image
m_SpDeferred3 = ResourceManager::Load<ShaderProgram>("Shaders/Deferred/3/");
m_SpDeferred3->Link();
/*
Forward rendering
*/
m_SpForward = ResourceManager::Load<ShaderProgram>("Shaders/Forward/");
m_SpForward->Link();
/*
Screen draw
*/
m_SpScreen = ResourceManager::Load<ShaderProgram>("Shaders/Screen/");
m_SpScreen->Link();
}
void dd::Renderer::CreateBuffers()
{
//TODO: Make the most common cases of texture create and FBO create into a function so it's not so cluttered in here.
m_ScreenQuad = CreateQuad();
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");
m_StandardNormal = ResourceManager::Load<Texture>("Textures/Core/NeutralNormalMap.png");
m_StandardSpecular = ResourceManager::Load<Texture>("Textures/Core/NeutralSpecularMap.png");
//m_WhiteSphereTexture = ResourceManager::Load<Texture>("Textures/Test/Water.png");
m_WhiteSphereTexture = ResourceManager::Load<Texture>("Textures/Particles/FadeBall.png");
glGenRenderbuffers(1, &m_RbDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_RbDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Resolution.Width, m_Resolution.Height);
// Generate G-buffer textures
glGenTextures(1, &m_GDiffuse);
glBindTexture(GL_TEXTURE_2D, m_GDiffuse);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &m_GPosition);
glBindTexture(GL_TEXTURE_2D, m_GPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, m_Resolution.Width, m_Resolution.Height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &m_GNormal);
glBindTexture(GL_TEXTURE_2D, m_GNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, m_Resolution.Width, m_Resolution.Height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &m_GSpecular);
glBindTexture(GL_TEXTURE_2D, m_GSpecular);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenTextures(1, &m_Gwater);
glBindTexture(GL_TEXTURE_2D, m_Gwater);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Create first pass framebuffer
glGenFramebuffers(1, &m_FbDeferred1);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred1);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_RbDepthBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_GDiffuse, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_GPosition, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, m_GNormal, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, m_GSpecular, 0);
GLenum firstPassDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
glDrawBuffers(4, firstPassDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_FbDeferred1 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
// Generate lighting texture
glGenTextures(1, &m_TLighting);
glBindTexture(GL_TEXTURE_2D, m_TLighting);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Create second pass framebuffer
glGenFramebuffers(1, &m_FbDeferred2);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred2);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TLighting, 0);
GLenum secondPassDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, secondPassDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_FbDeferred2 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
//Fill Water Texture
glGenTextures(1, &m_Gwater);
glBindTexture(GL_TEXTURE_2D, m_Gwater);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Fill water pass
glGenFramebuffers(1, &m_FbWater);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbWater);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_Gwater, 0);
GLenum waterPassDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, waterPassDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_FbDeferred2 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
//water Blur texture
glGenTextures(1, &m_BWater);
glBindTexture(GL_TEXTURE_2D, m_BWater);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Fill waterBlur pass
glGenFramebuffers(1, &m_FbWaterBlur);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbWaterBlur);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_BWater, 0);
GLenum waterBlurDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, waterBlurDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_FbDeferred2 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
//water Blur texture2
glGenTextures(1, &m_BWater2);
glBindTexture(GL_TEXTURE_2D, m_BWater2);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_RbDepthBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Fill waterBlur pass2
glGenFramebuffers(1, &m_FbWaterBlur2);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbWaterBlur2);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_BWater2, 0);
GLenum waterBlur2DrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, waterBlur2DrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_FbDeferred2 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
// Generate final deferred texture
glGenTextures(1, &m_TFinal);
glBindTexture(GL_TEXTURE_2D, m_TFinal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Resolution.Width, m_Resolution.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Create third pass framebuffer
glGenFramebuffers(1, &m_FbDeferred3);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred3);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_RbDepthBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TFinal, 0);
GLenum thirdPassDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, thirdPassDrawBuffers);
if (GLenum fbStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("m_FbDeferred3 incomplete: 0x%x\n", fbStatus);
exit(EXIT_FAILURE);
}
}
void dd::Renderer::Draw(RenderQueueCollection& rq)
{
rq.Forward.Jobs.sort(dd::Renderer::DepthSort);
DrawDeferred(rq.Deferred, rq.Lights);
DrawForward(rq.Forward, rq.Lights);
DrawGUI(rq.GUI);
// Finally: Draw the deferred+forward combined texture to the screen
glDisable(GL_CULL_FACE);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
m_SpScreen->Bind();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_CurrentScreenBuffer);
glBindVertexArray(m_ScreenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(m_Window);
DebugKeys();
}
void dd::Renderer::DrawDeferred(RenderQueue &objects, RenderQueue &lights)
{
// Pass #1: Fill G-buffers
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred1);
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_SpDeferred1->Bind();
DrawScene(objects, *m_SpDeferred1);
// Pass #2: Lighting
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glDepthMask(GL_FALSE);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred2);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
m_SpDeferred2->Bind();
DrawLightSpheres(lights);
// Pass #3: Combine into final deferred image
glCullFace(GL_BACK);
glDisable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred3);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
m_SpDeferred3->Bind();
glUniform3fv(glGetUniformLocation(*m_SpDeferred3, "La"), 1, glm::value_ptr(glm::vec3(0.5f)));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_GDiffuse);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_TLighting);
glBindVertexArray(m_ScreenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
void dd::Renderer::DrawForward(RenderQueue &objects, RenderQueue &lights)
{
// Forward-render semi-transparent objects on top of the current framebuffer
glDisable(GL_CULL_FACE);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred3);
// glClearColor(1, 0.9, 0.8f, 1);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_SpForward->Bind();
DrawScene(objects, *m_SpForward);
//WaterPass
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbWater);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
m_SpWater->Bind();
DrawWater(objects);
}
void dd::Renderer::PlaceCamera(glm::vec3 position)
{
m_DefaultCamera->SetPosition(position);
}
void dd::Renderer::DrawScene(RenderQueue &objects, ShaderProgram &program)
{
GLuint shaderProgramHandle = program;
glm::mat4 viewMatrix = m_Camera->ViewMatrix();
glm::mat4 PV = m_Camera->ProjectionMatrix() * viewMatrix;
glm::mat4 MVP;
for (auto &job : objects) {
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if (modelJob) {
glm::mat4 modelMatrix = modelJob->ModelMatrix;
MVP = PV * modelMatrix;
glUniform4fv(glGetUniformLocation(shaderProgramHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightPosition"), 1, glm::value_ptr(glm::vec3(0.f,0.f,-9.f)));
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightSpecular"), 1, glm::value_ptr(glm::vec3(1.f)));
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightDiffuse"), 1, glm::value_ptr(glm::vec3(1.f)));
glUniform1f(glGetUniformLocation(shaderProgramHandle, "LightRadius"), 40.0f);
glUniform1f(glGetUniformLocation(shaderProgramHandle, "MaterialShininess"), modelJob->Shininess);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture);
if (modelJob->NormalTexture != 0) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, modelJob->NormalTexture);
} else {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, *m_StandardNormal);
}
if (modelJob->SpecularTexture != 0) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, modelJob->SpecularTexture);
} else {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, *m_StandardSpecular);
}
if (modelJob->Skeleton != nullptr) {
auto animation = modelJob->Skeleton->GetAnimation(modelJob->AnimationName);
if (animation != nullptr) {
std::vector<glm::mat4> frameBones = modelJob->Skeleton->GetFrameBones(
*animation,
modelJob->AnimationTime,
modelJob->NoRootMotion
);
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
} else {
LOG_WARNING("Tried to play unknown animation \"%s\"", modelJob->AnimationName.c_str());
}
}
glBindVertexArray(modelJob->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
continue;
}
auto spriteJob = std::dynamic_pointer_cast<SpriteJob>(job);
if (spriteJob)
{
glm::mat4 modelMatrix = spriteJob->ModelMatrix;
MVP = PV * modelMatrix;
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniform4fv(glGetUniformLocation(shaderProgramHandle, "Color"), 1, glm::value_ptr(spriteJob->Color));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, spriteJob->DiffuseTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, spriteJob->NormalTexture);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, spriteJob->SpecularTexture);
glBindVertexArray(m_UnitQuad->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_UnitQuad->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, m_UnitQuad->m_Indices.size(), GL_UNSIGNED_INT, 0, 0);
continue;
}
}
}
void dd::Renderer::DrawLightSpheres(RenderQueue &lights)
{
GLuint shaderProgramHandle = *m_SpDeferred2;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_GPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_GNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, m_GSpecular);
glm::mat4 projectionMatrix = m_Camera->ProjectionMatrix();
glm::mat4 viewMatrix = m_Camera->ViewMatrix();
glm::mat4 PV = projectionMatrix * viewMatrix;
glm::mat4 MVP;
for (auto &job : lights) {
auto pointLightJob = std::dynamic_pointer_cast<PointLightJob>(job);
if (pointLightJob) {
glm::mat4 modelMatrix = glm::translate(pointLightJob->Position) * glm::scale(glm::vec3(pointLightJob->Radius * 2.f));
MVP = PV * modelMatrix;
glUniform2fv(glGetUniformLocation(shaderProgramHandle, "ViewportSize"), 1, glm::value_ptr(glm::vec2(m_Resolution.Width, m_Resolution.Height)));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightPosition"), 1, glm::value_ptr(pointLightJob->Position));
glUniform1f(glGetUniformLocation(shaderProgramHandle, "LightRadius"), pointLightJob->Radius);
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightDiffuse"), 1, glm::value_ptr(pointLightJob->DiffuseColor));
glUniform3fv(glGetUniformLocation(shaderProgramHandle, "LightSpecular"), 1, glm::value_ptr(pointLightJob->SpecularColor));
glBindVertexArray(m_UnitSphere->VAO);
glDrawArrays(GL_TRIANGLES, 0, m_UnitSphere->m_Vertices.size());
}
}
}
void dd::Renderer::DrawWater(RenderQueue &rq)
{
GLuint shaderProgramHandle = *m_SpWater;
glm::mat4 projectionMatrix = m_Camera->ProjectionMatrix();
glm::mat4 viewMatrix = m_Camera->ViewMatrix();
glm::mat4 PV = projectionMatrix * viewMatrix;
glm::mat4 MVP;
for ( auto &job : rq ) {
auto waterJob = std::dynamic_pointer_cast<WaterParticleJob>(job);
if (waterJob) {
glm::mat4 modelMatrix = waterJob->ModelMatrix;
MVP = PV * modelMatrix;
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "M"), 1, GL_FALSE,
glm::value_ptr(modelMatrix));
glUniformMatrix4fv(glGetUniformLocation(shaderProgramHandle, "V"), 1, GL_FALSE,
glm::value_ptr(viewMatrix));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, *m_WhiteSphereTexture);
glBindVertexArray(m_UnitQuad->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_UnitQuad->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, m_UnitQuad->m_Indices.size(), GL_UNSIGNED_INT, 0, 0);
}
}
//blur1
shaderProgramHandle = *m_SpWater2;
glDisable(GL_CULL_FACE);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbWaterBlur);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
m_SpWater2->Bind();
//TODO: Add this in water particle component. Blurradius
float radius = ResourceManager::Load<ConfigFile>("Config.ini")->GetValue<float>("Water.Radius", 0.2f);
radius *= 35;
glUniform2fv(glGetUniformLocation(shaderProgramHandle, "dir"), 1, glm::value_ptr(glm::vec2(1.0f, 0.0f)));
glUniform1f(glGetUniformLocation(shaderProgramHandle, "res"), m_Resolution.Width);
glUniform1f(glGetUniformLocation(shaderProgramHandle, "radius"), radius);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_Gwater);
glBindVertexArray(m_ScreenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
//blur2
shaderProgramHandle = *m_SpWater2;
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred3);
m_SpWater2->Bind();
glUniform2fv(glGetUniformLocation(shaderProgramHandle, "dir"), 1, glm::value_ptr(glm::vec2(0.0f, 1.0f)));
glUniform1f(glGetUniformLocation(shaderProgramHandle, "res"), m_Resolution.Height);
glUniform1f(glGetUniformLocation(shaderProgramHandle, "radius"), radius);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_BWater);
glBindVertexArray(m_ScreenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
GLuint dd::Renderer::CreateQuad()
{
float quadVertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
float quadTexCoords[] =
{
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
GLuint vbo[2], vao;
glGenBuffers(2, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 3 * 6 * sizeof(float), quadVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, 2 * 6 * sizeof(float), quadTexCoords, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return vao;
}
void dd::Renderer::DebugKeys()
{
if (glfwGetKey(m_Window, GLFW_KEY_F1)) {
m_CurrentScreenBuffer = m_TFinal;
}
if (glfwGetKey(m_Window, GLFW_KEY_F2)) {
m_CurrentScreenBuffer = m_GDiffuse;
}
if (glfwGetKey(m_Window, GLFW_KEY_F3)) {
m_CurrentScreenBuffer = m_GPosition;
}
if (glfwGetKey(m_Window, GLFW_KEY_F4)) {
m_CurrentScreenBuffer = m_GNormal;
}
if (glfwGetKey(m_Window, GLFW_KEY_F5)) {
m_CurrentScreenBuffer = m_GSpecular;
}
if (glfwGetKey(m_Window, GLFW_KEY_F6)) {
m_CurrentScreenBuffer = m_TLighting;
}
if (glfwGetKey(m_Window, GLFW_KEY_F7)) {
m_CurrentScreenBuffer = m_Gwater;
}
if (glfwGetKey(m_Window, GLFW_KEY_F8)) {
m_CurrentScreenBuffer = m_BWater;
}
}
void dd::Renderer::DrawGUI(dd::RenderQueue& rq)
{
glBindFramebuffer(GL_FRAMEBUFFER, m_FbDeferred3);
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
//glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
m_SpScreen->Bind();
glm::mat4 MVP;
for (auto &job : rq) {
auto frameJob = std::dynamic_pointer_cast<FrameJob>(job);
if (frameJob) {
FrameJob jobCopy = *(frameJob.get());
glm::mat4 viewMatrix = glm::mat4(1); //frameJob->ViewMatrix;
glm::mat4 PV = glm::mat4(1); //frameJob->ProjectionMatrix * viewMatrix;
glm::mat4 modelMatrix = glm::mat4(1); //frameJob->ModelMatrix;
MVP = PV * modelMatrix;
glUniformMatrix4fv(glGetUniformLocation(*m_SpScreen, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glUniformMatrix4fv(glGetUniformLocation(*m_SpScreen, "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix));
glUniformMatrix4fv(glGetUniformLocation(*m_SpScreen, "V"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniform4fv(glGetUniformLocation(*m_SpScreen, "Color"), 1, glm::value_ptr(frameJob->Color));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, frameJob->DiffuseTexture);
//glActiveTexture(GL_TEXTURE1);
//glBindTexture(GL_TEXTURE_2D, frameJob->NormalTexture);
//glActiveTexture(GL_TEXTURE2);
//glBindTexture(GL_TEXTURE_2D, frameJob->SpecularTexture);
Rectangle& vp = frameJob->Viewport;
glViewport(vp.X, m_Resolution.Height - vp.Y - vp.Height, vp.Width, vp.Height);
Rectangle& sc = frameJob->Scissor;
if (sc == Rectangle()) {
glDisable(GL_SCISSOR_TEST);
} else {
glEnable(GL_SCISSOR_TEST);
glScissor(sc.X, m_Resolution.Height - sc.Y - sc.Height, sc.Width, sc.Height);
}
glBindVertexArray(m_ScreenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
continue;
}
}
glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, m_Resolution.Width, m_Resolution.Height);
}