Deferred Shading update

-Deferred Shading now use a dynamics pass system
-Forward Shading is now capable of rendering more than three lights
(Multipass)


Former-commit-id: 74ed0b998d72aa9eb3bd2aab938a75985ebb2bf6
This commit is contained in:
Lynix 2013-12-28 10:22:03 +01:00
parent 6568cc7995
commit a332579c80
31 changed files with 2431 additions and 1354 deletions

View File

@ -1,4 +1,4 @@
// This file was automatically generated on 20 Dec 2013 at 20:02:16
// This file was automatically generated on 27 Dec 2013 at 22:07:53
/*
Nazara Engine - Graphics module
@ -37,6 +37,8 @@
#include <Nazara/Graphics/ColorBackground.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/DeferredBloomPass.hpp>
#include <Nazara/Graphics/DeferredDOFPass.hpp>
#include <Nazara/Graphics/DeferredFinalPass.hpp>
#include <Nazara/Graphics/DeferredFogPass.hpp>
#include <Nazara/Graphics/DeferredForwardPass.hpp>
#include <Nazara/Graphics/DeferredFXAAPass.hpp>

View File

@ -22,8 +22,8 @@ class NAZARA_API NzAbstractRenderTechnique : NzNonCopyable
NzAbstractRenderTechnique();
virtual ~NzAbstractRenderTechnique();
virtual void Clear(const NzScene* scene) = 0;
virtual bool Draw(const NzScene* scene) = 0;
virtual void Clear(const NzScene* scene) const = 0;
virtual bool Draw(const NzScene* scene) const = 0;
virtual void EnableInstancing(bool instancing);

View File

@ -0,0 +1,54 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDBLOOMPASS_HPP
#define NAZARA_DEFERREDBLOOMPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
class NAZARA_API NzDeferredBloomPass : public NzDeferredRenderPass
{
public:
NzDeferredBloomPass();
virtual ~NzDeferredBloomPass();
unsigned int GetBlurPassCount() const;
float GetBrightLuminance() const;
float GetBrightMiddleGrey() const;
float GetBrightThreshold() const;
NzTexture* GetTexture(unsigned int i) const;
bool Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
bool Resize(const NzVector2ui& dimensions);
void SetBlurPassCount(unsigned int passCount);
void SetBrightLuminance(float luminance);
void SetBrightMiddleGrey(float middleGrey);
void SetBrightThreshold(float threshold);
protected:
NzRenderStates m_bloomStates;
NzRenderTexture m_bloomRTT;
NzShaderProgramRef m_bloomBrightProgram;
NzShaderProgramRef m_bloomFinalProgram;
NzShaderProgramRef m_gaussianBlurProgram;
NzTextureRef m_bloomTextures[2];
NzTextureSampler m_bilinearSampler;
mutable bool m_uniformUpdated;
float m_brightLuminance;
float m_brightMiddleGrey;
float m_brightThreshold;
int m_gaussianBlurProgramFilterLocation;
unsigned int m_blurPassCount;
};
#endif // NAZARA_DEFERREDBLOOMPASS_HPP

View File

@ -0,0 +1,38 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDDOFPASS_HPP
#define NAZARA_DEFERREDDOFPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
class NAZARA_API NzDeferredDOFPass : public NzDeferredRenderPass
{
public:
NzDeferredDOFPass();
virtual ~NzDeferredDOFPass();
bool Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
bool Resize(const NzVector2ui& dimensions);
protected:
NzRenderTexture m_dofRTT;
NzRenderStates m_states;
NzShaderProgramRef m_blurProgram;
NzShaderProgramRef m_dofProgram;
NzTextureRef m_dofTextures[2];
NzTextureSampler m_bilinearSampler;
NzTextureSampler m_pointSampler;
int m_blurProgramFilterLocation;
};
#endif // NAZARA_DEFERREDDOFPASS_HPP

View File

@ -0,0 +1,30 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDFXAAPASS_HPP
#define NAZARA_DEFERREDFXAAPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
class NAZARA_API NzDeferredFXAAPass : public NzDeferredRenderPass
{
public:
NzDeferredFXAAPass();
virtual ~NzDeferredFXAAPass();
bool Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
protected:
NzRenderStates m_states;
NzShaderProgramRef m_fxaaProgram;
NzTextureSampler m_pointSampler;
};
#endif // NAZARA_DEFERREDFXAAPASS_HPP

View File

@ -0,0 +1,30 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDFINALPASS_HPP
#define NAZARA_DEFERREDFINALPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
class NAZARA_API NzDeferredFinalPass : public NzDeferredRenderPass
{
public:
NzDeferredFinalPass();
virtual ~NzDeferredFinalPass();
bool Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
protected:
NzRenderStates m_states;
NzShaderProgramRef m_program;
NzTextureSampler m_pointSampler;
};
#endif // NAZARA_DEFERREDFINALPASS_HPP

View File

@ -0,0 +1,30 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDFOGPASS_HPP
#define NAZARA_DEFERREDFOGPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
class NAZARA_API NzDeferredFogPass : public NzDeferredRenderPass
{
public:
NzDeferredFogPass();
virtual ~NzDeferredFogPass();
bool Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
protected:
NzRenderStates m_states;
NzShaderProgramRef m_program;
NzTextureSampler m_pointSampler;
};
#endif // NAZARA_DEFERREDFOGPASS_HPP

View File

@ -0,0 +1,28 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDFORWARDPASS_HPP
#define NAZARA_DEFERREDFORWARDPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
class NzForwardRenderTechnique;
class NAZARA_API NzDeferredForwardPass : public NzDeferredRenderPass
{
public:
NzDeferredForwardPass();
virtual ~NzDeferredForwardPass();
void Initialize(NzDeferredRenderTechnique* technique);
bool Process(const NzScene* scene, unsigned int workTexture, unsigned sceneTexture) const;
protected:
const NzForwardRenderTechnique* m_forwardTechnique;
};
#endif // NAZARA_DEFERREDFORWARDPASS_HPP

View File

@ -0,0 +1,29 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDGEOMETRYPASS_HPP
#define NAZARA_DEFERREDGEOMETRYPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
class NAZARA_API NzDeferredGeometryPass : public NzDeferredRenderPass
{
public:
NzDeferredGeometryPass();
virtual ~NzDeferredGeometryPass();
bool Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
bool Resize(const NzVector2ui& dimensions);
protected:
NzRenderStates m_clearStates;
NzShaderProgramRef m_clearProgram;
};
#endif // NAZARA_DEFERREDGEOMETRYPASS_HPP

View File

@ -0,0 +1,42 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDPHONGLIGHTINGPASS_HPP
#define NAZARA_DEFERREDPHONGLIGHTINGPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
#include <Nazara/Utility/Mesh.hpp>
class NzStaticMesh;
class NAZARA_API NzDeferredPhongLightingPass : public NzDeferredRenderPass
{
public:
NzDeferredPhongLightingPass();
virtual ~NzDeferredPhongLightingPass();
void EnableLightMeshesDrawing(bool enable);
bool IsLightMeshesDrawingEnabled() const;
bool Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
protected:
NzMeshRef m_cone;
NzMeshRef m_sphere;
NzShaderProgramRef m_directionalLightProgram;
NzShaderProgramRef m_pointLightProgram;
NzShaderProgramRef m_spotLightProgram;
NzTextureSampler m_pointSampler;
NzStaticMesh* m_coneMesh;
NzStaticMesh* m_sphereMesh;
bool m_lightMeshesDrawing;
};
#endif // NAZARA_DEFERREDPHONGLIGHTINGPASS_HPP

View File

@ -0,0 +1,52 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDRENDERPASS_HPP
#define NAZARA_DEFERREDRENDERPASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Math/Vector2.hpp>
class NzDeferredRenderTechnique;
class NzDeferredRenderQueue;
class NzRenderBuffer;
class NzRenderTexture;
class NzScene;
class NzTexture;
class NAZARA_API NzDeferredRenderPass
{
friend NzDeferredRenderTechnique;
public:
NzDeferredRenderPass();
virtual ~NzDeferredRenderPass();
void Enable(bool enable);
virtual void Initialize(NzDeferredRenderTechnique* technique);
bool IsEnabled() const;
virtual bool Process(const NzScene* scene, unsigned int workTexture, unsigned sceneTexture) const = 0;
virtual bool Resize(const NzVector2ui& GBufferSize);
protected:
NzVector2ui m_dimensions;
NzDeferredRenderTechnique* m_deferredTechnique;
NzDeferredRenderQueue* m_renderQueue;
NzRenderBuffer* m_depthStencilBuffer;
NzRenderTexture* m_GBufferRTT;
NzRenderTexture* m_workRTT;
NzTexture* m_GBuffer[4];
NzTexture* m_workTextures[2];
private:
bool m_enabled;
};
#endif // NAZARA_DEFERREDRENDERPASS_HPP

View File

@ -23,8 +23,6 @@ class NzStaticMesh;
class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourceListener
{
friend class NzDeferredRenderTechnique;
public:
NzDeferredRenderQueue(NzForwardRenderQueue* forwardQueue);
~NzDeferredRenderQueue();
@ -37,10 +35,6 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
void Clear(bool fully);
private:
bool OnResourceDestroy(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
struct SkeletalData
{
///TODO
@ -84,6 +78,10 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
LightContainer pointLights;
LightContainer spotLights;
NzForwardRenderQueue* m_forwardQueue;
private:
bool OnResourceDestroy(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
};
#endif // NAZARA_DEFERREDRENDERQUEUE_HPP

View File

@ -9,15 +9,19 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Renderer/RenderBuffer.hpp>
#include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Renderer/ShaderProgram.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Renderer/TextureSampler.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <map>
#include <memory>
class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, public NzRenderTarget::Listener
{
@ -25,61 +29,47 @@ class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, p
NzDeferredRenderTechnique();
~NzDeferredRenderTechnique();
void Clear(const NzScene* scene);
bool Draw(const NzScene* scene);
void Clear(const NzScene* scene) const;
bool Draw(const NzScene* scene) const;
void EnablePass(nzRenderPassType renderPass, int position, bool enable);
NzRenderBuffer* GetDepthStencilBuffer() const;
NzTexture* GetGBuffer(unsigned int i) const;
NzRenderTexture* GetGBufferRTT() const;
const NzForwardRenderTechnique* GetForwardTechnique() const;
NzDeferredRenderPass* GetPass(nzRenderPassType renderPass, int position = 0);
NzAbstractRenderQueue* GetRenderQueue() override;
nzRenderTechniqueType GetType() const override;
NzRenderTexture* GetWorkRTT() const;
NzTexture* GetWorkTexture(unsigned int i) const;
bool IsPassEnabled(nzRenderPassType renderPass, int position);
NzDeferredRenderPass* ResetPass(nzRenderPassType renderPass, int position);
void SetPass(nzRenderPassType relativeTo, int position, NzDeferredRenderPass* pass);
static bool IsSupported();
private:
void GeomPass(const NzScene* scene);
void DirectionalLightPass(const NzScene* scene);
void PointLightPass(const NzScene* scene);
void SpotLightPass(const NzScene* scene);
bool UpdateTextures() const;
bool Resize(const NzVector2ui& dimensions) const;
struct RenderPassComparator
{
bool operator()(nzRenderPassType pass1, nzRenderPassType pass2);
};
std::map<nzRenderPassType, std::map<int, std::unique_ptr<NzDeferredRenderPass>>, RenderPassComparator> m_passes;
NzForwardRenderTechnique m_forwardTechnique; // Doit être initialisé avant la RenderQueue
NzDeferredRenderQueue m_renderQueue;
NzMeshRef m_sphere;
NzStaticMesh* m_sphereMesh;
mutable NzRenderTexture m_bloomRTT;
mutable NzRenderTexture m_dofRTT;
mutable NzRenderTexture m_geometryRTT;
mutable NzRenderTexture m_ssaoRTT;
NzRenderStates m_clearStates;
NzShaderProgramRef m_aaProgram;
NzShaderProgramRef m_blitProgram;
NzShaderProgramRef m_bloomBrightProgram;
NzShaderProgramRef m_bloomFinalProgram;
NzShaderProgramRef m_clearProgram;
NzShaderProgramRef m_directionalLightProgram;
NzShaderProgramRef m_depthOfFieldProgram;
NzShaderProgramRef m_gaussianBlurProgram;
NzShaderProgramRef m_pointLightProgram;
NzShaderProgramRef m_ssaoProgram;
NzShaderProgramRef m_ssaoFinalProgram;
NzShaderProgramRef m_spotLightProgram;
mutable NzTextureRef m_bloomTextureA;
mutable NzTextureRef m_bloomTextureB;
mutable NzTextureRef m_dofTextureA;
mutable NzTextureRef m_dofTextureB;
mutable NzRenderBufferRef m_depthStencilBuffer;
mutable NzRenderTexture m_GBufferRTT;
mutable NzRenderTexture m_workRTT;
mutable NzTextureRef m_GBuffer[4];
mutable NzTextureRef m_ssaoTextureA;
mutable NzTextureRef m_ssaoTextureB;
mutable NzTextureRef m_ssaoNoiseTexture;
mutable NzTextureRef m_workTextureA;
mutable NzTextureRef m_workTextureB;
NzTextureSampler m_bilinearSampler;
NzTextureSampler m_pointSampler;
NzTextureSampler m_ssaoSampler;
NzVector2ui m_GBufferSize;
mutable NzTextureRef m_workTextures[2];
mutable NzVector2ui m_GBufferSize;
const NzRenderTarget* m_viewerTarget;
mutable bool m_texturesUpdated;
int m_gaussianBlurProgramFilterLocation;
};
#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP

View File

@ -26,6 +26,21 @@ enum nzLightType
nzLightType_Max = nzLightType_Spot
};
enum nzRenderPassType
{
nzRenderPassType_AA,
nzRenderPassType_Bloom,
nzRenderPassType_DOF,
nzRenderPassType_Final,
nzRenderPassType_Fog,
nzRenderPassType_Forward,
nzRenderPassType_Lighting,
nzRenderPassType_Geometry,
nzRenderPassType_SSAO,
nzRenderPassType_Max = nzRenderPassType_SSAO
};
enum nzRenderTechniqueType
{
nzRenderTechniqueType_AdvancedForward, // NzAdvancedForwardRenderTechnique

View File

@ -20,26 +20,26 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique
NzForwardRenderTechnique();
~NzForwardRenderTechnique();
void Clear(const NzScene* scene);
bool Draw(const NzScene* scene);
void Clear(const NzScene* scene) const;
bool Draw(const NzScene* scene) const;
unsigned int GetMaxLightsPerObject() const;
unsigned int GetMaxLightPassPerObject() const;
NzAbstractRenderQueue* GetRenderQueue() override;
nzRenderTechniqueType GetType() const override;
void SetMaxLightsPerObject(unsigned int lightCount);
void SetMaxLightPassPerObject(unsigned int passCount);
private:
void DrawOpaqueModels(const NzScene* scene);
void DrawSprites(const NzScene* scene);
void DrawTransparentModels(const NzScene* scene);
void DrawOpaqueModels(const NzScene* scene) const;
void DrawSprites(const NzScene* scene) const;
void DrawTransparentModels(const NzScene* scene) const;
NzForwardRenderQueue m_renderQueue;
mutable NzForwardRenderQueue m_renderQueue;
NzIndexBufferRef m_indexBuffer;
NzLightManager m_directionalLights;
NzLightManager m_lights;
mutable NzLightManager m_directionalLights;
mutable NzLightManager m_lights;
NzVertexBuffer m_spriteBuffer;
unsigned int m_maxLightsPerObject;
unsigned int m_maxLightPassPerObject;
};
#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP

View File

@ -0,0 +1,309 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredBloomPass.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
namespace
{
NzShaderProgram* BuildBloomBrightProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/BloomBright.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
program->SendInteger(program->GetUniformLocation("ColorTexture"), 0);
return program.release();
}
NzShaderProgram* BuildBloomFinalProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/BloomFinal.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
program->SendInteger(program->GetUniformLocation("ColorTexture"), 0);
program->SendInteger(program->GetUniformLocation("BloomTexture"), 1);
return program.release();
}
NzShaderProgram* BuildGaussianBlurProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/GaussianBlur.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
program->SendInteger(program->GetUniformLocation("ColorTexture"), 0);
return program.release();
}
}
NzDeferredBloomPass::NzDeferredBloomPass() :
m_uniformUpdated(false),
m_brightLuminance(0.8),
m_brightMiddleGrey(0.5),
m_brightThreshold(0.8),
m_blurPassCount(5)
{
m_bilinearSampler.SetAnisotropyLevel(1);
m_bilinearSampler.SetFilterMode(nzSamplerFilter_Bilinear);
m_bilinearSampler.SetWrapMode(nzSamplerWrap_Clamp);
m_bloomBrightProgram = BuildBloomBrightProgram();
m_bloomBrightProgram->SendInteger(m_bloomBrightProgram->GetUniformLocation("ColorTexture"), 0);
m_bloomFinalProgram = BuildBloomFinalProgram();
m_bloomFinalProgram->SendInteger(m_bloomBrightProgram->GetUniformLocation("BloomTexture"), 1);
m_bloomFinalProgram->SendInteger(m_bloomBrightProgram->GetUniformLocation("ColorTexture"), 0);
m_bloomStates.parameters[nzRendererParameter_DepthBuffer] = false;
for (unsigned int i = 0; i < 2; ++i)
{
m_bloomTextures[i] = new NzTexture;
m_bloomTextures[i]->SetPersistent(false);
}
m_gaussianBlurProgram = BuildGaussianBlurProgram();
m_gaussianBlurProgramFilterLocation = m_gaussianBlurProgram->GetUniformLocation("Filter");
}
NzDeferredBloomPass::~NzDeferredBloomPass() = default;
unsigned int NzDeferredBloomPass::GetBlurPassCount() const
{
return m_blurPassCount;
}
float NzDeferredBloomPass::GetBrightLuminance() const
{
return m_brightLuminance;
}
float NzDeferredBloomPass::GetBrightMiddleGrey() const
{
return m_brightMiddleGrey;
}
float NzDeferredBloomPass::GetBrightThreshold() const
{
return m_brightThreshold;
}
NzTexture* NzDeferredBloomPass::GetTexture(unsigned int i) const
{
#if NAZARA_GRAPHICS_SAFE
if (i >= 2)
{
NazaraError("Texture index out of range (" + NzString::Number(i) + " >= 2)");
return nullptr;
}
#endif
return m_bloomTextures[i];
}
bool NzDeferredBloomPass::Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
{
NazaraUnused(scene);
NzRenderer::SetRenderStates(m_bloomStates);
NzRenderer::SetTextureSampler(0, m_bilinearSampler);
NzRenderer::SetTextureSampler(1, m_bilinearSampler);
m_workRTT->SetColorTarget(firstWorkTexture);
NzRenderer::SetTarget(m_workRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzRenderer::SetShaderProgram(m_bloomBrightProgram);
if (!m_uniformUpdated)
{
m_bloomBrightProgram->SendFloat(m_bloomBrightProgram->GetUniformLocation("BrightLuminance"), m_brightLuminance);
m_bloomBrightProgram->SendFloat(m_bloomBrightProgram->GetUniformLocation("BrightMiddleGrey"), m_brightMiddleGrey);
m_bloomBrightProgram->SendFloat(m_bloomBrightProgram->GetUniformLocation("BrightThreshold"), m_brightThreshold);
m_uniformUpdated = true;
}
NzRenderer::SetTexture(0, m_workTextures[secondWorkTexture]);
NzRenderer::DrawFullscreenQuad();
NzRenderer::SetTarget(&m_bloomRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x/8, m_dimensions.y/8));
NzRenderer::SetShaderProgram(m_gaussianBlurProgram);
for (unsigned int i = 0; i < m_blurPassCount; ++i)
{
m_bloomRTT.SetColorTarget(0); // bloomTextureA
m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(1.f, 0.f));
NzRenderer::SetTexture(0, (i == 0) ? m_workTextures[firstWorkTexture] : static_cast<const NzTexture*>(m_bloomTextures[1]));
NzRenderer::DrawFullscreenQuad();
m_bloomRTT.SetColorTarget(1); // bloomTextureB
m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(0.f, 1.f));
NzRenderer::SetTexture(0, m_bloomTextures[0]);
NzRenderer::DrawFullscreenQuad();
}
m_workRTT->SetColorTarget(firstWorkTexture);
NzRenderer::SetTarget(m_workRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzRenderer::SetShaderProgram(m_bloomFinalProgram);
NzRenderer::SetTexture(0, m_bloomTextures[1]);
NzRenderer::SetTexture(1, m_workTextures[secondWorkTexture]);
NzRenderer::DrawFullscreenQuad();
return true;
}
bool NzDeferredBloomPass::Resize(const NzVector2ui& dimensions)
{
NzDeferredRenderPass::Resize(dimensions);
m_bloomRTT.Create(true);
for (unsigned int i = 0; i < 2; ++i)
{
m_bloomTextures[i]->Create(nzImageType_2D, nzPixelFormat_RGBA8, dimensions.x/8, dimensions.y/8);
m_bloomRTT.AttachTexture(nzAttachmentPoint_Color, i, m_bloomTextures[i]);
}
m_bloomRTT.Unlock();
if (!m_bloomRTT.IsComplete())
{
NazaraError("Incomplete RTT");
return false;
}
return true;
}
void NzDeferredBloomPass::SetBlurPassCount(unsigned int passCount)
{
m_blurPassCount = passCount; // N'est pas une uniforme
}
void NzDeferredBloomPass::SetBrightLuminance(float luminance)
{
m_brightLuminance = luminance;
m_uniformUpdated = false;
}
void NzDeferredBloomPass::SetBrightMiddleGrey(float middleGrey)
{
m_brightMiddleGrey = middleGrey;
m_uniformUpdated = false;
}
void NzDeferredBloomPass::SetBrightThreshold(float threshold)
{
m_brightThreshold = threshold;
m_uniformUpdated = false;
}

View File

@ -0,0 +1,224 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredDOFPass.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/Scene.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
namespace
{
// http://digitalerr0r.wordpress.com/2009/05/16/xna-shader-programming-tutorial-20-depth-of-field/
NzShaderProgram* BuildDepthOfFieldProgram()
{
const char* fragmentSource =
"#version 140\n"
"out vec4 RenderTarget0;\n"
"uniform sampler2D BlurTexture;\n"
"uniform sampler2D ColorTexture;\n"
"uniform sampler2D GBuffer1;\n"
"uniform vec2 InvTargetSize;" "\n"
"float Distance = 30.0;\n"
"float Range = 10.0;\n"
"float Near = 0.1;\n"
"float Far = (1000.0) / (1000.0 - 0.1);\n"
//"float Far = 50.0;\n"
"void main()\n"
"{\n"
"vec2 texCoord = gl_FragCoord.xy * InvTargetSize;\n"
"// Get our original pixel from ColorMap\n"
"vec3 color = textureLod(ColorTexture, texCoord, 0.0).rgb;\n"
"// Get our bloom pixel from bloom texture\n"
"vec3 blur = textureLod(BlurTexture, texCoord, 0.0).rgb;\n"
"float depth = textureLod(GBuffer1, texCoord, 0.0).w;\n"
"depth = (2.0 * 0.1) / (1000.0 + 0.1 - depth * (1000.0 - 0.1));"
"depth = 1.0 - depth;\n"
"float fSceneZ = ( -Near * Far ) / ( depth - Far);\n"
"float blurFactor = clamp(abs(fSceneZ - Distance)/Range, 0.0, 1.0);\n"
"RenderTarget0 = vec4(mix(color, blur, blurFactor), 1.0);\n"
"}\n";
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, fragmentSource))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
return program.release();
}
NzShaderProgram* BuildGaussianBlurProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/GaussianBlur.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
return program.release();
}
}
NzDeferredDOFPass::NzDeferredDOFPass()
{
m_blurProgram = BuildGaussianBlurProgram();
m_blurProgram->SendInteger(m_blurProgram->GetUniformLocation("ColorTexture"), 0);
m_blurProgramFilterLocation = m_blurProgram->GetUniformLocation("Filer");
m_dofProgram = BuildDepthOfFieldProgram();
m_dofProgram->SendInteger(m_dofProgram->GetUniformLocation("ColorTexture"), 0);
m_dofProgram->SendInteger(m_dofProgram->GetUniformLocation("BlurTexture"), 1);
m_dofProgram->SendInteger(m_dofProgram->GetUniformLocation("GBuffer1"), 2);
for (unsigned int i = 0; i < 2; ++i)
{
m_dofTextures[i] = new NzTexture;
m_dofTextures[i]->SetPersistent(false);
}
m_bilinearSampler.SetAnisotropyLevel(1);
m_bilinearSampler.SetFilterMode(nzSamplerFilter_Bilinear);
m_bilinearSampler.SetWrapMode(nzSamplerWrap_Clamp);
m_pointSampler.SetAnisotropyLevel(1);
m_pointSampler.SetFilterMode(nzSamplerFilter_Nearest);
m_pointSampler.SetWrapMode(nzSamplerWrap_Clamp);
m_states.parameters[nzRendererParameter_DepthBuffer] = false;
}
NzDeferredDOFPass::~NzDeferredDOFPass() = default;
bool NzDeferredDOFPass::Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
{
NzRenderer::SetTextureSampler(0, m_pointSampler);
NzRenderer::SetTextureSampler(1, m_bilinearSampler);
NzRenderer::SetTextureSampler(2, m_pointSampler);
NzRenderer::SetTarget(&m_dofRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x/4, m_dimensions.y/4));
NzRenderer::SetShaderProgram(m_blurProgram);
const unsigned int dofBlurPass = 2;
for (unsigned int i = 0; i < dofBlurPass; ++i)
{
m_dofRTT.SetColorTarget(0); // dofTextureA
m_blurProgram->SendVector(m_blurProgramFilterLocation, NzVector2f(1.f, 0.f));
NzRenderer::SetTexture(0, (i == 0) ? m_workTextures[secondWorkTexture] : static_cast<const NzTexture*>(m_dofTextures[1]));
NzRenderer::DrawFullscreenQuad();
m_dofRTT.SetColorTarget(1); // dofTextureB
m_blurProgram->SendVector(m_blurProgramFilterLocation, NzVector2f(0.f, 1.f));
NzRenderer::SetTexture(0, m_dofTextures[0]);
NzRenderer::DrawFullscreenQuad();
}
m_workRTT->SetColorTarget(firstWorkTexture);
NzRenderer::SetTarget(m_workRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzRenderer::SetShaderProgram(m_dofProgram);
NzRenderer::SetTexture(0, m_workTextures[secondWorkTexture]);
NzRenderer::SetTexture(1, m_dofTextures[1]);
NzRenderer::SetTexture(2, m_GBuffer[1]);
NzRenderer::DrawFullscreenQuad();
return true;
}
bool NzDeferredDOFPass::Resize(const NzVector2ui& dimensions)
{
NzDeferredRenderPass::Resize(dimensions);
m_dofRTT.Create(true);
for (unsigned int i = 0; i < 2; ++i)
{
m_dofTextures[i]->Create(nzImageType_2D, nzPixelFormat_RGBA8, dimensions.x/4, dimensions.y/4);
m_dofRTT.AttachTexture(nzAttachmentPoint_Color, i, m_dofTextures[i]);
}
m_dofRTT.Unlock();
if (!m_dofRTT.IsComplete())
{
NazaraError("Incomplete RTT");
return false;
}
return true;
}

View File

@ -0,0 +1,84 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredFXAAPass.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
namespace
{
NzShaderProgram* BuildFXAAProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/FXAA.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
return program.release();
}
}
NzDeferredFXAAPass::NzDeferredFXAAPass()
{
m_fxaaProgram = BuildFXAAProgram();
m_fxaaProgram->SendInteger(m_fxaaProgram->GetUniformLocation("ColorTexture"), 0);
m_pointSampler.SetAnisotropyLevel(1);
m_pointSampler.SetFilterMode(nzSamplerFilter_Nearest);
m_pointSampler.SetWrapMode(nzSamplerWrap_Clamp);
m_states.parameters[nzRendererParameter_DepthBuffer] = false;
}
NzDeferredFXAAPass::~NzDeferredFXAAPass() = default;
bool NzDeferredFXAAPass::Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
{
NazaraUnused(scene);
m_workRTT->SetColorTarget(firstWorkTexture);
NzRenderer::SetTarget(m_workRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzRenderer::SetRenderStates(m_states);
NzRenderer::SetShaderProgram(m_fxaaProgram);
NzRenderer::SetTexture(0, m_workTextures[secondWorkTexture]);
NzRenderer::SetTextureSampler(0, m_pointSampler);
NzRenderer::DrawFullscreenQuad();
return true;
}

View File

@ -0,0 +1,85 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredFinalPass.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/Scene.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
namespace
{
NzShaderProgram* BuildBlitProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/Blit.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
return program.release();
}
}
NzDeferredFinalPass::NzDeferredFinalPass()
{
m_program = BuildBlitProgram();
m_program->SendInteger(m_program->GetUniformLocation("ColorTexture"), 0);
m_pointSampler.SetAnisotropyLevel(1);
m_pointSampler.SetFilterMode(nzSamplerFilter_Nearest);
m_pointSampler.SetWrapMode(nzSamplerWrap_Clamp);
m_states.parameters[nzRendererParameter_DepthBuffer] = false;
}
NzDeferredFinalPass::~NzDeferredFinalPass() = default;
bool NzDeferredFinalPass::Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
{
NazaraUnused(firstWorkTexture);
scene->GetViewer()->ApplyView();
NzRenderer::SetRenderStates(m_states);
NzRenderer::SetShaderProgram(m_program);
NzRenderer::SetTexture(0, m_workTextures[secondWorkTexture]);
NzRenderer::SetTextureSampler(0, m_pointSampler);
NzRenderer::DrawFullscreenQuad();
return false;
}

View File

@ -0,0 +1,138 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredFogPass.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/Scene.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
namespace
{
NzShaderProgram* BuildFogProgram()
{
/*const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/FXAA.frag.h>
};*/
const char* fragmentSource =
"#version 140\n"
"out vec4 RenderTarget0;\n"
"uniform sampler2D ColorTexture;\n"
"uniform sampler2D NormalBuffer;\n"
"uniform mat4 InvViewProjMatrix;\n"
"uniform vec2 InvTargetSize;\n"
"uniform vec3 EyePosition;\n"
"float n = 0.1;"
"float f = 1000.0;"
"void main()\n"
"{"
"vec2 texCoord = gl_FragCoord.xy * InvTargetSize;\n"
"\t" "vec3 color = texture(ColorTexture, texCoord).xyz;\n"
"vec4 gVec1 = textureLod(NormalBuffer, texCoord, 0.0);\n"
"float depth = gVec1.w*2.0 - 1.0;\n"
"float linearDepth = (2 * n) / (f + n - depth * (f - n));"
"vec3 viewSpace = vec3(texCoord*2.0 - 1.0, depth);\n"
"vec4 worldPos = InvViewProjMatrix * vec4(viewSpace, 1.0);\n"
"worldPos.xyz /= worldPos.w;\n"
/*"float lumThreshold = 0.1;"
"float lumMultipler = 2.0;"
//"float lumFactor = max(dot(color, vec3(0.299, 0.587, 0.114)) - lumThreshold, 0.0) / (1.0-lumThreshold);"
"float fogFactor = (1.0 - clamp(worldPos.y-2.0, 0.0, 1.0)) - lumFactor*lumMultipler;"
"fogFactor += (1.0 - clamp(EyePosition.y-2.5, 0.0, 1.0));"
"fogFactor = clamp(fogFactor, 0.0, 1.0);"*/
"float lumThreshold = 0.8;"
"float lumMultipler = 2.0;"
"float luminosity = dot(color, vec3(0.299, 0.587, 0.114));"
"float lumFactor = max(luminosity - lumThreshold, 0.0) / (1.0-lumThreshold);"
"vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
"vec2 fogrange = vec2(0, 50);\n"
"float fogeffect = clamp( 1.0 - (fogrange.y - linearDepth*0.5*f) / (fogrange.y - fogrange.x) , 0.0, 1.0 ) * fogColor.w;\n"
"fogeffect = max(fogeffect-lumFactor, 0.0);"
//fogeffect*=(1.0 - int(depth));
"\t" "vec3 fragmentColor = color*(1.0-fogeffect) + fogColor.rgb * fogeffect;\n"
"\t" "RenderTarget0 = vec4(fragmentColor, 1.0);\n"
"}";
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, fragmentSource/*NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))*/))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
return program.release();
}
}
NzDeferredFogPass::NzDeferredFogPass()
{
m_program = BuildFogProgram();
m_program->SendInteger(m_program->GetUniformLocation("ColorTexture"), 0);
m_program->SendInteger(m_program->GetUniformLocation("NormalBuffer"), 1);
m_pointSampler.SetAnisotropyLevel(1);
m_pointSampler.SetFilterMode(nzSamplerFilter_Nearest);
m_pointSampler.SetWrapMode(nzSamplerWrap_Clamp);
m_states.parameters[nzRendererParameter_DepthBuffer] = false;
}
NzDeferredFogPass::~NzDeferredFogPass() = default;
bool NzDeferredFogPass::Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
{
m_workRTT->SetColorTarget(firstWorkTexture);
NzRenderer::SetTarget(m_workRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzRenderer::SetShaderProgram(m_program);
m_program->SendVector(m_program->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition());
NzRenderer::SetRenderStates(m_states);
NzRenderer::SetTexture(0, m_workTextures[secondWorkTexture]);
NzRenderer::SetTexture(1, m_GBuffer[1]);
NzRenderer::SetTextureSampler(0, m_pointSampler);
NzRenderer::SetTextureSampler(1, m_pointSampler);
NzRenderer::DrawFullscreenQuad();
return true;
}

View File

@ -0,0 +1,45 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredForwardPass.hpp>
#include <Nazara/Graphics/AbstractBackground.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Graphics/Scene.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Graphics/Debug.hpp>
NzDeferredForwardPass::NzDeferredForwardPass() = default;
NzDeferredForwardPass::~NzDeferredForwardPass() = default;
void NzDeferredForwardPass::Initialize(NzDeferredRenderTechnique* technique)
{
NzDeferredRenderPass::Initialize(technique);
m_forwardTechnique = technique->GetForwardTechnique();
}
bool NzDeferredForwardPass::Process(const NzScene* scene, unsigned int workTexture, unsigned sceneTexture) const
{
NazaraUnused(workTexture);
m_workRTT->SetColorTarget(sceneTexture);
NzRenderer::SetTarget(m_workRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzAbstractBackground* background = scene->GetBackground();
if (background)
background->Draw(scene);
NzAbstractViewer* viewer = scene->GetViewer();
NzRenderer::SetMatrix(nzMatrixType_Projection, viewer->GetProjectionMatrix());
NzRenderer::SetMatrix(nzMatrixType_View, viewer->GetViewMatrix());
m_forwardTechnique->Draw(scene);
return false;
}

View File

@ -0,0 +1,303 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredGeometryPass.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
#include <Nazara/Graphics/Scene.hpp>
#include <Nazara/Renderer/Material.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Utility/BufferMapper.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Utility/VertexStruct.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
namespace
{
NzShaderProgram* BuildClearProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/ClearGBuffer.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec2 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 0.0, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
return program.release();
}
}
NzDeferredGeometryPass::NzDeferredGeometryPass()
{
m_clearProgram = BuildClearProgram();
m_clearStates.parameters[nzRendererParameter_DepthBuffer] = true;
m_clearStates.parameters[nzRendererParameter_FaceCulling] = true;
m_clearStates.parameters[nzRendererParameter_StencilTest] = true;
m_clearStates.depthFunc = nzRendererComparison_Always;
m_clearStates.frontFace.stencilCompare = nzRendererComparison_Always;
m_clearStates.frontFace.stencilPass = nzStencilOperation_Zero;
}
NzDeferredGeometryPass::~NzDeferredGeometryPass() = default;
bool NzDeferredGeometryPass::Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
{
NazaraUnused(firstWorkTexture);
NazaraUnused(secondWorkTexture);
NzAbstractViewer* viewer = scene->GetViewer();
bool instancingEnabled = m_deferredTechnique->IsInstancingEnabled();
m_GBufferRTT->SetColorTargets({0, 1, 2}); // G-Buffer
NzRenderer::SetTarget(m_GBufferRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzRenderer::SetRenderStates(m_clearStates);
NzRenderer::SetShaderProgram(m_clearProgram);
NzRenderer::DrawFullscreenQuad();
NzRenderer::SetMatrix(nzMatrixType_Projection, viewer->GetProjectionMatrix());
NzRenderer::SetMatrix(nzMatrixType_View, viewer->GetViewMatrix());
const NzShaderProgram* lastProgram = nullptr;
for (auto& matIt : m_renderQueue->opaqueModels)
{
bool& used = std::get<0>(matIt.second);
if (used)
{
bool& renderQueueInstancing = std::get<1>(matIt.second);
NzDeferredRenderQueue::BatchedSkeletalMeshContainer& skeletalContainer = std::get<2>(matIt.second);
NzDeferredRenderQueue::BatchedStaticMeshContainer& staticContainer = std::get<3>(matIt.second);
if (!skeletalContainer.empty() || !staticContainer.empty())
{
const NzMaterial* material = matIt.first;
// Nous utilisons de l'instancing que lorsqu'aucune lumière (autre que directionnelle) n'est active
// Ceci car l'instancing n'est pas compatible avec la recherche des lumières les plus proches
// (Le deferred shading n'a pas ce problème)
bool useInstancing = instancingEnabled && renderQueueInstancing;
// On commence par récupérer le programme du matériau
nzUInt32 flags = nzShaderFlags_Deferred;
if (useInstancing)
flags |= nzShaderFlags_Instancing;
const NzShaderProgram* program = material->GetShaderProgram(nzShaderTarget_Model, flags);
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
if (program != lastProgram)
{
NzRenderer::SetShaderProgram(program);
// Couleur ambiante de la scène
program->SendColor(program->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
// Position de la caméra
program->SendVector(program->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
lastProgram = program;
}
material->Apply(program);
// Meshs squelettiques
/*if (!skeletalContainer.empty())
{
NzRenderer::SetVertexBuffer(m_skinningBuffer); // Vertex buffer commun
for (auto& subMeshIt : container)
{
///TODO
}
}*/
// Meshs statiques
for (auto& subMeshIt : staticContainer)
{
const NzStaticMesh* mesh = subMeshIt.first;
std::vector<NzDeferredRenderQueue::StaticData>& staticData = subMeshIt.second;
if (!staticData.empty())
{
const NzIndexBuffer* indexBuffer = mesh->GetIndexBuffer();
const NzVertexBuffer* vertexBuffer = mesh->GetVertexBuffer();
// Gestion du draw call avant la boucle de rendu
std::function<void(nzPrimitiveMode, unsigned int, unsigned int)> DrawFunc;
std::function<void(unsigned int, nzPrimitiveMode, unsigned int, unsigned int)> InstancedDrawFunc;
unsigned int indexCount;
if (indexBuffer)
{
DrawFunc = NzRenderer::DrawIndexedPrimitives;
InstancedDrawFunc = NzRenderer::DrawIndexedPrimitivesInstanced;
indexCount = indexBuffer->GetIndexCount();
}
else
{
DrawFunc = NzRenderer::DrawPrimitives;
InstancedDrawFunc = NzRenderer::DrawPrimitivesInstanced;
indexCount = vertexBuffer->GetVertexCount();
}
NzRenderer::SetIndexBuffer(indexBuffer);
NzRenderer::SetVertexBuffer(vertexBuffer);
nzPrimitiveMode primitiveMode = mesh->GetPrimitiveMode();
if (useInstancing)
{
NzVertexBuffer* instanceBuffer = NzRenderer::GetInstanceBuffer();
instanceBuffer->SetVertexDeclaration(NzVertexDeclaration::Get(nzVertexLayout_Matrix4));
unsigned int stride = instanceBuffer->GetStride();
const NzDeferredRenderQueue::StaticData* data = &staticData[0];
unsigned int instanceCount = staticData.size();
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Le nombre de sommets maximum avec la déclaration donnée plus hautg
while (instanceCount > 0)
{
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
instanceCount -= renderedInstanceCount;
NzBufferMapper<NzVertexBuffer> mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount);
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(mapper.GetPointer());
for (unsigned int i = 0; i < renderedInstanceCount; ++i)
{
std::memcpy(ptr, data->transformMatrix, sizeof(float)*16);
data++;
ptr += stride;
}
mapper.Unmap();
InstancedDrawFunc(renderedInstanceCount, primitiveMode, 0, indexCount);
}
}
else
{
for (const NzDeferredRenderQueue::StaticData& data : staticData)
{
NzRenderer::SetMatrix(nzMatrixType_World, data.transformMatrix);
DrawFunc(primitiveMode, 0, indexCount);
}
}
staticData.clear();
}
}
}
// Et on remet à zéro les données
renderQueueInstancing = false;
used = false;
}
}
return false; // On ne fait que remplir le G-Buffer, les work texture ne sont pas affectées
}
bool NzDeferredGeometryPass::Resize(const NzVector2ui& dimensions)
{
NzDeferredRenderPass::Resize(dimensions);
/*
G-Buffer:
Texture0: Diffuse Color + Flags
Texture1: Normal map + Depth
Texture2: Specular value + Shininess
Texture3: N/A
*/
try
{
NzErrorFlags errFlags(nzErrorFlag_ThrowException);
unsigned int width = dimensions.x;
unsigned int height = dimensions.y;
m_depthStencilBuffer->Create(nzPixelFormat_Depth24Stencil8, width, height);
m_GBuffer[0]->Create(nzImageType_2D, nzPixelFormat_RGBA8, width, height);
m_GBuffer[1]->Create(nzImageType_2D, nzPixelFormat_RGBA32F, width, height);
m_GBuffer[2]->Create(nzImageType_2D, nzPixelFormat_RGBA8, width, height);
m_GBufferRTT->Create(true);
// Texture 0 : Diffuse Color + Flags
m_GBufferRTT->AttachTexture(nzAttachmentPoint_Color, 0, m_GBuffer[0]);
// Texture 1 : Normal map + Depth
m_GBufferRTT->AttachTexture(nzAttachmentPoint_Color, 1, m_GBuffer[1]);
// Texture 2 : Specular value + Shininess
m_GBufferRTT->AttachTexture(nzAttachmentPoint_Color, 2, m_GBuffer[2]);
// Texture 3 : Emission map ?
m_GBufferRTT->AttachBuffer(nzAttachmentPoint_DepthStencil, 0, m_deferredTechnique->GetDepthStencilBuffer());
m_GBufferRTT->Unlock();
m_workRTT->Create(true);
for (unsigned int i = 0; i < 2; ++i)
{
m_workTextures[i]->Create(nzImageType_2D, nzPixelFormat_RGBA8, width, height);
m_workRTT->AttachTexture(nzAttachmentPoint_Color, i, m_workTextures[i]);
}
m_workRTT->AttachBuffer(nzAttachmentPoint_DepthStencil, 0, m_depthStencilBuffer);
m_workRTT->Unlock();
if (!m_workRTT->IsComplete() || !m_GBufferRTT->IsComplete())
{
NazaraError("Incomplete RTT");
return false;
}
return true;
}
catch (const std::exception& e)
{
NazaraError("Failed to create G-Buffer RTT");
return false;
}
}

View File

@ -0,0 +1,421 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredPhongLightingPass.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
#include <Nazara/Graphics/Light.hpp>
#include <Nazara/Graphics/Scene.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Renderer/ShaderProgramManager.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <memory>
#include <Nazara/Renderer/OpenGL.hpp> // Supprimer
#include <Nazara/Graphics/Debug.hpp>
namespace
{
NzShaderProgram* BuildDirectionalLightProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/DirectionalLight.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec2 VertexPosition;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = vec4(VertexPosition, 0.0, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
program->SendInteger(program->GetUniformLocation("GBuffer0"), 0);
program->SendInteger(program->GetUniformLocation("GBuffer1"), 1);
program->SendInteger(program->GetUniformLocation("GBuffer2"), 2);
return program.release();
}
NzShaderProgram* BuildPointLightProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"uniform mat4 WorldViewProjMatrix;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
program->SendInteger(program->GetUniformLocation("GBuffer0"), 0);
program->SendInteger(program->GetUniformLocation("GBuffer1"), 1);
program->SendInteger(program->GetUniformLocation("GBuffer2"), 2);
return program.release();
}
NzShaderProgram* BuildSpotLightProgram()
{
const nzUInt8 fragmentSource[] = {
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag.h>
};
const char* vertexSource =
"#version 140\n"
"in vec3 VertexPosition;\n"
"uniform mat4 WorldViewProjMatrix;\n"
"void main()\n"
"{\n"
"\t" "gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);" "\n"
"}\n";
///TODO: Remplacer ça par des ShaderNode
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
program->SetPersistent(false);
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
{
NazaraError("Failed to load fragment shader");
return nullptr;
}
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
{
NazaraError("Failed to load vertex shader");
return nullptr;
}
if (!program->Compile())
{
NazaraError("Failed to compile program");
return nullptr;
}
program->SendInteger(program->GetUniformLocation("GBuffer0"), 0);
program->SendInteger(program->GetUniformLocation("GBuffer1"), 1);
program->SendInteger(program->GetUniformLocation("GBuffer2"), 2);
return program.release();
}
}
NzDeferredPhongLightingPass::NzDeferredPhongLightingPass() :
m_lightMeshesDrawing(false)
{
m_directionalLightProgram = BuildDirectionalLightProgram();
m_pointLightProgram = BuildPointLightProgram();
m_spotLightProgram = BuildSpotLightProgram();
m_pointSampler.SetAnisotropyLevel(1);
m_pointSampler.SetFilterMode(nzSamplerFilter_Nearest);
m_pointSampler.SetWrapMode(nzSamplerWrap_Clamp);
m_cone = new NzMesh;
m_cone->SetPersistent(false);
m_cone->CreateStatic();
m_coneMesh = static_cast<NzStaticMesh*>(m_cone->BuildSubMesh(NzPrimitive::Cone(1.f, 1.f, 16, NzMatrix4f::Rotate(NzEulerAnglesf(90.f, 0.f, 0.f)))));
m_sphere = new NzMesh;
m_sphere->SetPersistent(false);
m_sphere->CreateStatic();
m_sphereMesh = static_cast<NzStaticMesh*>(m_sphere->BuildSubMesh(NzPrimitive::IcoSphere(1.f, 1)));
}
NzDeferredPhongLightingPass::~NzDeferredPhongLightingPass() = default;
void NzDeferredPhongLightingPass::EnableLightMeshesDrawing(bool enable)
{
m_lightMeshesDrawing = enable;
}
bool NzDeferredPhongLightingPass::IsLightMeshesDrawingEnabled() const
{
return m_lightMeshesDrawing;
}
bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
{
NazaraUnused(secondWorkTexture);
m_workRTT->SetColorTarget(firstWorkTexture);
NzRenderer::SetTarget(m_workRTT);
NzRenderer::SetViewport(NzRecti(0, 0, m_dimensions.x, m_dimensions.y));
NzRenderer::SetTexture(0, m_GBuffer[0]);
NzRenderer::SetTextureSampler(0, m_pointSampler);
NzRenderer::SetTexture(1, m_GBuffer[1]);
NzRenderer::SetTextureSampler(1, m_pointSampler);
NzRenderer::SetTexture(2, m_GBuffer[2]);
NzRenderer::SetTextureSampler(2, m_pointSampler);
NzRenderer::SetClearColor(NzColor::Black);
NzRenderer::Clear(nzRendererClear_Color);
NzRenderStates lightStates;
lightStates.dstBlend = nzBlendFunc_One;
lightStates.srcBlend = nzBlendFunc_One;
lightStates.parameters[nzRendererParameter_Blend] = true;
lightStates.parameters[nzRendererParameter_DepthBuffer] = false;
lightStates.parameters[nzRendererParameter_DepthWrite] = false;
// Directional lights
if (!m_renderQueue->directionalLights.empty())
{
NzRenderer::SetRenderStates(lightStates);
NzRenderer::SetShaderProgram(m_directionalLightProgram);
m_directionalLightProgram->SendColor(m_directionalLightProgram->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
m_directionalLightProgram->SendVector(m_directionalLightProgram->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition());
for (const NzLight* light : m_renderQueue->directionalLights)
{
light->Enable(m_directionalLightProgram, 0);
NzRenderer::DrawFullscreenQuad();
}
}
// Point lights/Spot lights
if (!m_renderQueue->pointLights.empty() || !m_renderQueue->spotLights.empty())
{
// http://www.altdevblogaday.com/2011/08/08/stencil-buffer-optimisation-for-deferred-lights/
lightStates.parameters[nzRendererParameter_StencilTest] = true;
lightStates.faceCulling = nzFaceSide_Front;
lightStates.backFace.stencilMask = 0xFF;
lightStates.backFace.stencilReference = 0;
lightStates.backFace.stencilFail = nzStencilOperation_Keep;
lightStates.backFace.stencilPass = nzStencilOperation_Keep;
lightStates.backFace.stencilZFail = nzStencilOperation_Invert;
lightStates.frontFace.stencilMask = 0xFF;
lightStates.frontFace.stencilReference = 0;
lightStates.frontFace.stencilFail = nzStencilOperation_Keep;
lightStates.frontFace.stencilPass = nzStencilOperation_Keep;
lightStates.frontFace.stencilZFail = nzStencilOperation_Invert;
NzRenderer::SetRenderStates(lightStates);
if (!m_renderQueue->pointLights.empty())
{
NzRenderer::SetShaderProgram(m_pointLightProgram);
m_pointLightProgram->SendColor(m_pointLightProgram->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
m_pointLightProgram->SendVector(m_pointLightProgram->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition());
const NzIndexBuffer* indexBuffer = m_sphereMesh->GetIndexBuffer();
NzRenderer::SetIndexBuffer(indexBuffer);
NzRenderer::SetVertexBuffer(m_sphereMesh->GetVertexBuffer());
NzMatrix4f lightMatrix;
lightMatrix.MakeIdentity();
for (const NzLight* light : m_renderQueue->pointLights)
{
light->Enable(m_pointLightProgram, 0);
lightMatrix.SetScale(NzVector3f(light->GetRadius()*1.1f)); // Pour corriger les imperfections liées à la sphère
lightMatrix.SetTranslation(light->GetPosition());
NzRenderer::SetMatrix(nzMatrixType_World, lightMatrix);
// Rendu de la sphère dans le stencil buffer
NzRenderer::Enable(nzRendererParameter_ColorWrite, false);
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
NzRenderer::SetStencilCompareFunction(nzRendererComparison_Always);
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
// Rendu de la sphère comme zone d'effet
NzRenderer::Enable(nzRendererParameter_ColorWrite, true);
NzRenderer::Enable(nzRendererParameter_DepthBuffer, false);
NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
NzRenderer::SetStencilCompareFunction(nzRendererComparison_NotEqual, nzFaceSide_Back);
NzRenderer::SetStencilPassOperation(nzStencilOperation_Zero, nzFaceSide_Back);
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
}
if (m_lightMeshesDrawing)
{
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
NzRenderer::Enable(nzRendererParameter_DepthWrite, true);
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
NzRenderer::Enable(nzRendererParameter_StencilTest, false);
NzRenderer::SetFaceFilling(nzFaceFilling_Line);
NzShaderProgramManagerParams params;
params.flags = nzShaderFlags_None;
params.target = nzShaderTarget_Model;
params.model.alphaMapping = false;
params.model.alphaTest = false;
params.model.diffuseMapping = false;
params.model.emissiveMapping = false;
params.model.lighting = false;
params.model.normalMapping = false;
params.model.parallaxMapping = false;
params.model.specularMapping = false;
const NzShaderProgram* program = NzShaderProgramManager::Get(params);
NzRenderer::SetShaderProgram(program);
for (const NzLight* light : m_renderQueue->pointLights)
{
lightMatrix.SetScale(NzVector3f(light->GetRadius()*1.1f)); // Pour corriger les imperfections liées à la sphère
lightMatrix.SetTranslation(light->GetPosition());
NzRenderer::SetMatrix(nzMatrixType_World, lightMatrix);
program->SendColor(program->GetUniformLocation(nzShaderUniform_MaterialDiffuse), light->GetColor());
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
}
NzRenderer::Enable(nzRendererParameter_DepthBuffer, false);
NzRenderer::Enable(nzRendererParameter_DepthWrite, false);
NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
NzRenderer::Enable(nzRendererParameter_StencilTest, true);
NzRenderer::SetFaceFilling(nzFaceFilling_Fill);
}
}
if (!m_renderQueue->spotLights.empty())
{
NzRenderer::SetShaderProgram(m_spotLightProgram);
m_spotLightProgram->SendColor(m_spotLightProgram->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
m_spotLightProgram->SendVector(m_spotLightProgram->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition());
const NzIndexBuffer* indexBuffer = m_coneMesh->GetIndexBuffer();
NzRenderer::SetIndexBuffer(indexBuffer);
NzRenderer::SetVertexBuffer(m_coneMesh->GetVertexBuffer());
NzMatrix4f lightMatrix;
lightMatrix.MakeIdentity();
for (const NzLight* light : m_renderQueue->spotLights)
{
light->Enable(m_spotLightProgram, 0);
float radius = light->GetRadius()*std::tan(NzDegreeToRadian(light->GetOuterAngle()))*1.1f;
lightMatrix.MakeTransform(light->GetPosition(), light->GetRotation(), NzVector3f(radius, radius, light->GetRadius()));
NzRenderer::SetMatrix(nzMatrixType_World, lightMatrix);
// Rendu de la sphère dans le stencil buffer
NzRenderer::Enable(nzRendererParameter_ColorWrite, false);
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
NzRenderer::SetStencilCompareFunction(nzRendererComparison_Always);
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
// Rendu de la sphère comme zone d'effet
NzRenderer::Enable(nzRendererParameter_ColorWrite, true);
NzRenderer::Enable(nzRendererParameter_DepthBuffer, false);
NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
NzRenderer::SetFaceCulling(nzFaceSide_Front);
NzRenderer::SetStencilCompareFunction(nzRendererComparison_NotEqual, nzFaceSide_Back);
NzRenderer::SetStencilPassOperation(nzStencilOperation_Zero, nzFaceSide_Back);
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
}
if (m_lightMeshesDrawing)
{
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
NzRenderer::Enable(nzRendererParameter_DepthWrite, true);
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
NzRenderer::Enable(nzRendererParameter_StencilTest, false);
NzRenderer::SetFaceFilling(nzFaceFilling_Line);
NzShaderProgramManagerParams params;
params.flags = nzShaderFlags_None;
params.target = nzShaderTarget_Model;
params.model.alphaMapping = false;
params.model.alphaTest = false;
params.model.diffuseMapping = false;
params.model.emissiveMapping = false;
params.model.lighting = false;
params.model.normalMapping = false;
params.model.parallaxMapping = false;
params.model.specularMapping = false;
const NzShaderProgram* program = NzShaderProgramManager::Get(params);
NzRenderer::SetShaderProgram(program);
for (const NzLight* light : m_renderQueue->spotLights)
{
float baseRadius = light->GetRadius()*std::tan(NzDegreeToRadian(light->GetOuterAngle()))*1.1f;
lightMatrix.MakeTransform(light->GetPosition(), light->GetRotation(), NzVector3f(baseRadius, baseRadius, light->GetRadius()));
NzRenderer::SetMatrix(nzMatrixType_World, lightMatrix);
program->SendColor(program->GetUniformLocation(nzShaderUniform_MaterialDiffuse), light->GetColor());
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
}
NzRenderer::Enable(nzRendererParameter_DepthBuffer, false);
NzRenderer::Enable(nzRendererParameter_DepthWrite, false);
NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
NzRenderer::Enable(nzRendererParameter_StencilTest, true);
NzRenderer::SetFaceFilling(nzFaceFilling_Fill);
}
}
NzRenderer::Enable(nzRendererParameter_StencilTest, false);
}
return true;
}

View File

@ -0,0 +1,48 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
#include <Nazara/Graphics/Debug.hpp>
NzDeferredRenderPass::NzDeferredRenderPass() :
m_enabled(true)
{
}
NzDeferredRenderPass::~NzDeferredRenderPass() = default;
void NzDeferredRenderPass::Enable(bool enable)
{
m_enabled = enable;
}
void NzDeferredRenderPass::Initialize(NzDeferredRenderTechnique* technique)
{
m_deferredTechnique = technique;
m_renderQueue = static_cast<NzDeferredRenderQueue*>(technique->GetRenderQueue());
m_depthStencilBuffer = technique->GetDepthStencilBuffer();
m_GBufferRTT = technique->GetGBufferRTT();
for (unsigned int i = 0; i < 3; ++i)
m_GBuffer[i] = technique->GetGBuffer(i);
m_workRTT = technique->GetWorkRTT();
for (unsigned int i = 0; i < 2; ++i)
m_workTextures[i] = technique->GetWorkTexture(i);
}
bool NzDeferredRenderPass::IsEnabled() const
{
return m_enabled;
}
bool NzDeferredRenderPass::Resize(const NzVector2ui& dimensions)
{
m_dimensions = dimensions;
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -186,7 +186,8 @@ void NzForwardRenderQueue::AddSubMesh(const NzMaterial* material, const NzSubMes
unsigned int instanceCount = staticDataContainer.size() + 1;
// Avons-nous suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ?
if (instanceCount >= NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT)
unsigned int tumasoublie = NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT;
if (instanceCount >= 10)
enableInstancing = true; // Apparemment oui, activons l'instancing avec ce matériau
staticDataContainer.resize(instanceCount);

View File

@ -21,7 +21,7 @@
namespace
{
static NzIndexBuffer* s_indexBuffer = nullptr;
unsigned int maxLightCount = 3; ///TODO: Constante sur le nombre maximum de lumières
unsigned int s_maxLightPerPass = 3; ///TODO: Constante sur le nombre maximum de lumières
unsigned int s_maxSprites = 8192;
NzIndexBuffer* BuildIndexBuffer()
@ -49,7 +49,7 @@ namespace
NzForwardRenderTechnique::NzForwardRenderTechnique() :
m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic),
m_maxLightsPerObject(maxLightCount)
m_maxLightPassPerObject(3)
{
if (!s_indexBuffer)
s_indexBuffer = BuildIndexBuffer();
@ -63,7 +63,7 @@ NzForwardRenderTechnique::~NzForwardRenderTechnique()
s_indexBuffer = nullptr;
}
void NzForwardRenderTechnique::Clear(const NzScene* scene)
void NzForwardRenderTechnique::Clear(const NzScene* scene) const
{
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
NzRenderer::Enable(nzRendererParameter_DepthWrite, true);
@ -74,7 +74,7 @@ void NzForwardRenderTechnique::Clear(const NzScene* scene)
background->Draw(scene);
}
bool NzForwardRenderTechnique::Draw(const NzScene* scene)
bool NzForwardRenderTechnique::Draw(const NzScene* scene) const
{
m_directionalLights.SetLights(&m_renderQueue.directionalLights[0], m_renderQueue.directionalLights.size());
m_lights.SetLights(&m_renderQueue.lights[0], m_renderQueue.lights.size());
@ -141,9 +141,9 @@ bool NzForwardRenderTechnique::Draw(const NzScene* scene)
}*/
}
unsigned int NzForwardRenderTechnique::GetMaxLightsPerObject() const
unsigned int NzForwardRenderTechnique::GetMaxLightPassPerObject() const
{
return m_maxLightsPerObject;
return m_maxLightPassPerObject;
}
NzAbstractRenderQueue* NzForwardRenderTechnique::GetRenderQueue()
@ -156,26 +156,16 @@ nzRenderTechniqueType NzForwardRenderTechnique::GetType() const
return nzRenderTechniqueType_BasicForward;
}
void NzForwardRenderTechnique::SetMaxLightsPerObject(unsigned int lightCount)
void NzForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int passCount)
{
#if NAZARA_GRAPHICS_SAFE
if (lightCount > maxLightCount)
{
NazaraError("Light count is over maximum light count (" + NzString::Number(lightCount) + " > " + NzString::Number(lightCount) + ')');
return;
}
#endif
m_maxLightsPerObject = lightCount;
m_maxLightPassPerObject = passCount;
}
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene)
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
const NzShaderProgram* lastProgram = nullptr;
unsigned int lightCount = 0;
for (auto& matIt : m_renderQueue.opaqueModels)
{
bool& used = std::get<0>(matIt.second);
@ -207,11 +197,6 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene)
// Position de la caméra
program->SendVector(program->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
lightCount = std::min(m_directionalLights.GetLightCount(), 3U);
for (unsigned int i = 0; i < lightCount; ++i)
m_directionalLights.GetLight(i)->Enable(program, i);
lastProgram = program;
}
@ -269,51 +254,110 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene)
unsigned int stride = instanceBuffer->GetStride();
const NzForwardRenderQueue::StaticData* data = &staticData[0];
unsigned int instanceCount = staticData.size();
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount();
// Avec l'instancing, impossible de sélectionner les lumières pour chaque objet
// Du coup, il n'est activé que pour les lumières directionnelles
unsigned int lightCount = m_directionalLights.GetLightCount();
unsigned int lightIndex = 0;
nzRendererComparison oldDepthFunc = NzRenderer::GetDepthFunc();
while (instanceCount > 0)
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/s_maxLightPerPass + 1;
for (unsigned int pass = 0; pass < passCount; ++pass)
{
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
instanceCount -= renderedInstanceCount;
unsigned int renderedLightCount = std::min(lightCount, s_maxLightPerPass);
lightCount -= renderedLightCount;
NzBufferMapper<NzVertexBuffer> mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount);
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(mapper.GetPointer());
for (unsigned int i = 0; i < renderedInstanceCount; ++i)
if (pass == 1)
{
std::memcpy(ptr, data->transformMatrix, sizeof(float)*16);
data++;
ptr += stride;
// Pour additionner le résultat des calculs de lumière
// Aucune chance d'interférer avec les paramètres du matériau car nous ne rendons que les objets opaques
// (Autrement dit, sans blending)
// Quant à la fonction de profondeur, elle ne doit être appliquée que la première fois
NzRenderer::Enable(nzRendererParameter_Blend, true);
NzRenderer::SetBlendFunc(nzBlendFunc_One, nzBlendFunc_One);
NzRenderer::SetDepthFunc(nzRendererComparison_Equal);
}
mapper.Unmap();
for (unsigned int i = 0; i < renderedLightCount; ++i)
m_directionalLights.GetLight(lightIndex++)->Enable(program, i);
InstancedDrawFunc(renderedInstanceCount, primitiveMode, 0, indexCount);
for (unsigned int i = renderedLightCount; i < s_maxLightPerPass; ++i)
NzLight::Disable(program, i);
const NzForwardRenderQueue::StaticData* data = &staticData[0];
unsigned int instanceCount = staticData.size();
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount();
while (instanceCount > 0)
{
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
instanceCount -= renderedInstanceCount;
NzBufferMapper<NzVertexBuffer> mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount);
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(mapper.GetPointer());
for (unsigned int i = 0; i < renderedInstanceCount; ++i)
{
std::memcpy(ptr, data->transformMatrix, sizeof(float)*16);
data++;
ptr += stride;
}
mapper.Unmap();
InstancedDrawFunc(renderedInstanceCount, primitiveMode, 0, indexCount);
}
}
NzRenderer::Enable(nzRendererParameter_Blend, false);
NzRenderer::SetDepthFunc(oldDepthFunc);
}
else
{
unsigned int originalLightCount = lightCount;
for (const NzForwardRenderQueue::StaticData& data : staticData)
{
// Calcul des lumières les plus proches
if (lightCount < m_maxLightsPerObject && !m_lights.IsEmpty())
unsigned int directionalLightCount = m_directionalLights.GetLightCount();
unsigned int otherLightCount = m_lights.ComputeClosestLights(data.transformMatrix.GetTranslation() + boundingSphere.GetPosition(), boundingSphere.radius, m_maxLightPassPerObject*s_maxLightPerPass - directionalLightCount);
unsigned int lightCount = directionalLightCount + otherLightCount;
NzRenderer::SetMatrix(nzMatrixType_World, data.transformMatrix);
unsigned int directionalLightIndex = 0;
unsigned int otherLightIndex = 0;
nzRendererComparison oldDepthFunc = NzRenderer::GetDepthFunc();
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/s_maxLightPerPass + 1;
for (unsigned int pass = 0; pass < passCount; ++pass)
{
unsigned int count = std::min(m_maxLightsPerObject-lightCount, m_lights.ComputeClosestLights(data.transformMatrix.GetTranslation() + boundingSphere.GetPosition(), boundingSphere.radius, maxLightCount));
for (unsigned int i = 0; i < count; ++i)
m_lights.GetResult(i)->Enable(program, lightCount++);
unsigned int renderedLightCount = std::min(lightCount, s_maxLightPerPass);
lightCount -= renderedLightCount;
if (pass == 1)
{
// Pour additionner le résultat des calculs de lumière
// Aucune chance d'interférer avec les paramètres du matériau car nous ne rendons que les objets opaques
// (Autrement dit, sans blending)
// Quant à la fonction de profondeur, elle ne doit être appliquée que la première fois
NzRenderer::Enable(nzRendererParameter_Blend, true);
NzRenderer::SetBlendFunc(nzBlendFunc_One, nzBlendFunc_One);
NzRenderer::SetDepthFunc(nzRendererComparison_Equal);
}
for (unsigned int i = 0; i < renderedLightCount; ++i)
{
if (directionalLightIndex >= directionalLightCount)
m_lights.GetResult(otherLightIndex++)->Enable(program, i);
else
m_directionalLights.GetLight(directionalLightIndex++)->Enable(program, i);
}
for (unsigned int i = renderedLightCount; i < s_maxLightPerPass; ++i)
NzLight::Disable(program, i);
DrawFunc(primitiveMode, 0, indexCount);
}
for (unsigned int i = lightCount; i < maxLightCount; ++i)
NzLight::Disable(program, i);
NzRenderer::SetMatrix(nzMatrixType_World, data.transformMatrix);
DrawFunc(primitiveMode, 0, indexCount);
lightCount = originalLightCount;
NzRenderer::Enable(nzRendererParameter_Blend, false);
NzRenderer::SetDepthFunc(oldDepthFunc);
}
}
staticData.clear();
@ -328,7 +372,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene)
}
}
void NzForwardRenderTechnique::DrawSprites(const NzScene* scene)
void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
const NzShaderProgram* lastProgram = nullptr;
@ -408,7 +452,7 @@ void NzForwardRenderTechnique::DrawSprites(const NzScene* scene)
}
}
void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene)
void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
const NzShaderProgram* lastProgram = nullptr;
@ -474,14 +518,14 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene)
NzRenderer::SetVertexBuffer(vertexBuffer);
// Calcul des lumières les plus proches
if (lightCount < m_maxLightsPerObject && !m_lights.IsEmpty())
if (lightCount < s_maxLightPerPass && !m_lights.IsEmpty())
{
unsigned int count = std::min(m_maxLightsPerObject-lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + staticModel.boundingSphere.GetPosition(), staticModel.boundingSphere.radius, maxLightCount));
unsigned int count = std::min(s_maxLightPerPass - lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + staticModel.boundingSphere.GetPosition(), staticModel.boundingSphere.radius, s_maxLightPerPass));
for (unsigned int i = 0; i < count; ++i)
m_lights.GetResult(i)->Enable(program, lightCount++);
}
for (unsigned int i = lightCount; i < maxLightCount; ++i)
for (unsigned int i = lightCount; i < s_maxLightPerPass; ++i)
NzLight::Disable(program, i);
NzRenderer::SetMatrix(nzMatrixType_World, matrix);

View File

@ -29,11 +29,11 @@ void main()
{
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0);
if (gVec0.w == 0.0)
/* if (gVec0.w == 0.0)
{
RenderTarget0 = vec4(gVec0.xyz, 1.0);
return;
}
}*/
vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0);
vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0);

File diff suppressed because one or more lines are too long

View File

@ -29,11 +29,11 @@ void main()
{
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0);
if (gVec0.w == 0.0)
/* if (gVec0.w == 0.0)
{
RenderTarget0 = vec4(gVec0.xyz, 1.0);
return;
}
}*/
vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0);
vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0);

File diff suppressed because one or more lines are too long