Big UberShader update

-Added GRAPHICS_MAX_LIGHTPERPASS macro
-Added glGetActiveUniform OpenGL function
-Added (Uber)ShaderLibrary
-Added (Uber)ShaderName parameter to models
-Changed uniform system
-Fixed Node copying
-Moved Material class to Graphics module
-Optimized lights
-Remade Shader class
-Renamed Node::Invalidate to Node::InvalidateNode
-Renamed ShaderProgram to Shader


Former-commit-id: 15f0cad52969e91a2442e7d750ba2dc412f3549d
This commit is contained in:
Lynix
2014-02-21 19:27:39 +01:00
parent 4ee2ceaef0
commit 86bdab9055
147 changed files with 2693 additions and 4135 deletions

View File

@@ -2,6 +2,10 @@
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#ifndef NAZARA_RENDERER_OPENGL
#define NAZARA_RENDERER_OPENGL // Nécessaire pour inclure les headers OpenGL
#endif
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Graphics/AbstractBackground.hpp>
@@ -16,12 +20,14 @@
#include <Nazara/Graphics/DeferredPhongLightingPass.hpp>
#include <Nazara/Graphics/Drawable.hpp>
#include <Nazara/Graphics/Light.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/Sprite.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Material.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/ShaderProgramManager.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/ShaderLibrary.hpp>
#include <Nazara/Renderer/ShaderStage.hpp>
#include <limits>
#include <memory>
#include <random>
@@ -43,6 +49,37 @@ namespace
};
static_assert(sizeof(RenderPassPriority)/sizeof(unsigned int) == nzRenderPassType_Max+1, "Render pass priority array is incomplete");
inline NzShader* RegisterDeferredShader(const NzString& name, const nzUInt8* fragmentSource, unsigned int fragmentSourceLength, const NzShaderStage& vertexStage, NzString* err)
{
NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled);
std::unique_ptr<NzShader> shader(new NzShader);
shader->SetPersistent(false);
if (!shader->Create())
{
err->Set("Failed to create shader");
return nullptr;
}
if (!shader->AttachStageFromSource(nzShaderStage_Fragment, reinterpret_cast<const char*>(fragmentSource), fragmentSourceLength))
{
err->Set("Failed to attach fragment stage");
return nullptr;
}
shader->AttachStage(nzShaderStage_Vertex, vertexStage);
if (!shader->Link())
{
err->Set("Failed to link shader");
return nullptr;
}
NzShaderLibrary::Register(name, shader.get());
return shader.release();
}
}
NzDeferredRenderTechnique::NzDeferredRenderTechnique() :
@@ -67,7 +104,6 @@ m_GBufferSize(0U)
try
{
NzErrorFlags errFlags(nzErrorFlag_ThrowException);
std::unique_ptr<NzDeferredRenderPass> smartPtr; // Nous évite un leak en cas d'exception
ResetPass(nzRenderPassType_Final, 0);
ResetPass(nzRenderPassType_Geometry, 0);
@@ -343,14 +379,186 @@ void NzDeferredRenderTechnique::SetPass(nzRenderPassType relativeTo, int positio
m_passes[relativeTo].erase(position);
}
bool NzDeferredRenderTechnique::Initialize()
{
const nzUInt8 fragmentSource_BloomBright[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/BloomBright.frag.h>
};
const nzUInt8 fragmentSource_BloomFinal[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/BloomFinal.frag.h>
};
const nzUInt8 fragmentSource_DirectionalLight[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/DirectionalLight.frag.h>
};
const nzUInt8 fragmentSource_FXAA[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/FXAA.frag.h>
};
const nzUInt8 fragmentSource_GBufferClear[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/GBufferClear.frag.h>
};
const nzUInt8 fragmentSource_GaussianBlur[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/GaussianBlur.frag.h>
};
const nzUInt8 fragmentSource_PointSpotLight[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/PointSpotLight.frag.h>
};
const char vertexSource_Basic[] =
"#version 140\n"
"in vec3 VertexPosition;\n"
"uniform mat4 WorldViewProjMatrix;\n"
"void main()\n"
"{\n"
"gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n"
"}\n";
const char vertexSource_PostProcess[] =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(VertexPosition, 1.0);"
"}\n";
NzShaderStage basicVertexStage(nzShaderStage_Vertex);
if (!basicVertexStage.IsValid())
{
NazaraError("Failed to create basic vertex shader");
return false;
}
basicVertexStage.SetSource(vertexSource_Basic, sizeof(vertexSource_Basic));
if (!basicVertexStage.Compile())
{
NazaraError("Failed to compile basic vertex shader");
return false;
}
NzShaderStage ppVertexStage(nzShaderStage_Vertex);
if (!ppVertexStage.IsValid())
{
NazaraError("Failed to create vertex shader");
return false;
}
ppVertexStage.SetSource(vertexSource_PostProcess, sizeof(vertexSource_PostProcess));
if (!ppVertexStage.Compile())
{
NazaraError("Failed to compile vertex shader");
return false;
}
NzString error;
NzShader* shader;
// Shaders critiques (Nécessaires pour le Deferred Shading minimal)
shader = RegisterDeferredShader("DeferredGBufferClear", fragmentSource_GBufferClear, sizeof(fragmentSource_GBufferClear), ppVertexStage, &error);
if (!shader)
{
NazaraError("Failed to register critical shader: " + error);
return false;
}
shader = RegisterDeferredShader("DeferredDirectionnalLight", fragmentSource_DirectionalLight, sizeof(fragmentSource_DirectionalLight), ppVertexStage, &error);
if (!shader)
{
NazaraError("Failed to register critical shader: " + error);
return false;
}
shader->SendInteger(shader->GetUniformLocation("GBuffer0"), 0);
shader->SendInteger(shader->GetUniformLocation("GBuffer1"), 1);
shader->SendInteger(shader->GetUniformLocation("GBuffer2"), 2);
shader = RegisterDeferredShader("DeferredPointSpotLight", fragmentSource_PointSpotLight, sizeof(fragmentSource_PointSpotLight), basicVertexStage, &error);
if (!shader)
{
NazaraError("Failed to register critical shader: " + error);
return false;
}
shader->SendInteger(shader->GetUniformLocation("GBuffer0"), 0);
shader->SendInteger(shader->GetUniformLocation("GBuffer1"), 1);
shader->SendInteger(shader->GetUniformLocation("GBuffer2"), 2);
// Shaders optionnels (S'ils ne sont pas présents, le rendu minimal sera quand même assuré)
shader = RegisterDeferredShader("DeferredBloomBright", fragmentSource_BloomBright, sizeof(fragmentSource_BloomBright), ppVertexStage, &error);
if (shader)
shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0);
else
{
NazaraWarning("Failed to register bloom (bright pass) shader, certain features will not work: " + error);
}
shader = RegisterDeferredShader("DeferredBloomFinal", fragmentSource_BloomFinal, sizeof(fragmentSource_BloomFinal), ppVertexStage, &error);
if (shader)
{
shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0);
shader->SendInteger(shader->GetUniformLocation("BloomTexture"), 1);
}
else
{
NazaraWarning("Failed to register bloom (final pass) shader, certain features will not work: " + error);
}
shader = RegisterDeferredShader("DeferredFXAA", fragmentSource_FXAA, sizeof(fragmentSource_FXAA), ppVertexStage, &error);
if (shader)
shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0);
else
{
NazaraWarning("Failed to register FXAA shader, certain features will not work: " + error);
}
shader = RegisterDeferredShader("DeferredGaussianBlur", fragmentSource_GaussianBlur, sizeof(fragmentSource_GaussianBlur), ppVertexStage, &error);
if (shader)
shader->SendInteger(shader->GetUniformLocation("ColorTexture"), 0);
else
{
NazaraWarning("Failed to register gaussian blur shader, certain features will not work: " + error);
}
return true;
}
bool NzDeferredRenderTechnique::IsSupported()
{
// On ne va pas s'embêter à écrire un Deferred Renderer qui ne passe pas par le MRT, ce serait lent et inutile (OpenGL 2 garanti cette fonctionnalité en plus)
return NzRenderer::HasCapability(nzRendererCap_RenderTexture) &&
return NzOpenGL::GetGLSLVersion() >= 140 && // On ne va pas s'embêter non plus avec le mode de compatibilité
NzRenderer::HasCapability(nzRendererCap_RenderTexture) &&
NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets) &&
NzRenderer::GetMaxColorAttachments() >= 4 &&
NzRenderer::GetMaxRenderTargets() >= 4 &&
NzTexture::IsFormatSupported(nzPixelFormat_RGBA32F);
NzRenderer::GetMaxRenderTargets() >= 4;
}
void NzDeferredRenderTechnique::Uninitialize()
{
NzShaderLibrary::Unregister("DeferredGBufferClear");
NzShaderLibrary::Unregister("DeferredDirectionnalLight");
NzShaderLibrary::Unregister("DeferredPointSpotLight");
NzShaderLibrary::Unregister("DeferredBloomBright");
NzShaderLibrary::Unregister("DeferredBloomFinal");
NzShaderLibrary::Unregister("DeferredFXAA");
NzShaderLibrary::Unregister("DeferredGaussianBlur");
}
bool NzDeferredRenderTechnique::Resize(const NzVector2ui& dimensions) const