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:
parent
6568cc7995
commit
a332579c80
|
|
@ -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
|
Nazara Engine - Graphics module
|
||||||
|
|
@ -37,6 +37,8 @@
|
||||||
#include <Nazara/Graphics/ColorBackground.hpp>
|
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||||
#include <Nazara/Graphics/Config.hpp>
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
#include <Nazara/Graphics/DeferredBloomPass.hpp>
|
#include <Nazara/Graphics/DeferredBloomPass.hpp>
|
||||||
|
#include <Nazara/Graphics/DeferredDOFPass.hpp>
|
||||||
|
#include <Nazara/Graphics/DeferredFinalPass.hpp>
|
||||||
#include <Nazara/Graphics/DeferredFogPass.hpp>
|
#include <Nazara/Graphics/DeferredFogPass.hpp>
|
||||||
#include <Nazara/Graphics/DeferredForwardPass.hpp>
|
#include <Nazara/Graphics/DeferredForwardPass.hpp>
|
||||||
#include <Nazara/Graphics/DeferredFXAAPass.hpp>
|
#include <Nazara/Graphics/DeferredFXAAPass.hpp>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ class NAZARA_API NzAbstractRenderTechnique : NzNonCopyable
|
||||||
NzAbstractRenderTechnique();
|
NzAbstractRenderTechnique();
|
||||||
virtual ~NzAbstractRenderTechnique();
|
virtual ~NzAbstractRenderTechnique();
|
||||||
|
|
||||||
virtual void Clear(const NzScene* scene) = 0;
|
virtual void Clear(const NzScene* scene) const = 0;
|
||||||
virtual bool Draw(const NzScene* scene) = 0;
|
virtual bool Draw(const NzScene* scene) const = 0;
|
||||||
|
|
||||||
virtual void EnableInstancing(bool instancing);
|
virtual void EnableInstancing(bool instancing);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -23,8 +23,6 @@ class NzStaticMesh;
|
||||||
|
|
||||||
class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourceListener
|
class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourceListener
|
||||||
{
|
{
|
||||||
friend class NzDeferredRenderTechnique;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NzDeferredRenderQueue(NzForwardRenderQueue* forwardQueue);
|
NzDeferredRenderQueue(NzForwardRenderQueue* forwardQueue);
|
||||||
~NzDeferredRenderQueue();
|
~NzDeferredRenderQueue();
|
||||||
|
|
@ -37,10 +35,6 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
|
||||||
|
|
||||||
void Clear(bool fully);
|
void Clear(bool fully);
|
||||||
|
|
||||||
private:
|
|
||||||
bool OnResourceDestroy(const NzResource* resource, int index) override;
|
|
||||||
void OnResourceReleased(const NzResource* resource, int index) override;
|
|
||||||
|
|
||||||
struct SkeletalData
|
struct SkeletalData
|
||||||
{
|
{
|
||||||
///TODO
|
///TODO
|
||||||
|
|
@ -84,6 +78,10 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
|
||||||
LightContainer pointLights;
|
LightContainer pointLights;
|
||||||
LightContainer spotLights;
|
LightContainer spotLights;
|
||||||
NzForwardRenderQueue* m_forwardQueue;
|
NzForwardRenderQueue* m_forwardQueue;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool OnResourceDestroy(const NzResource* resource, int index) override;
|
||||||
|
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_DEFERREDRENDERQUEUE_HPP
|
#endif // NAZARA_DEFERREDRENDERQUEUE_HPP
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,19 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
||||||
|
#include <Nazara/Graphics/DeferredRenderPass.hpp>
|
||||||
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
|
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
|
||||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||||
#include <Nazara/Renderer/RenderStates.hpp>
|
#include <Nazara/Renderer/RenderStates.hpp>
|
||||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
#include <Nazara/Renderer/ShaderProgram.hpp>
|
#include <Nazara/Renderer/ShaderProgram.hpp>
|
||||||
#include <Nazara/Renderer/Texture.hpp>
|
#include <Nazara/Renderer/Texture.hpp>
|
||||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||||
#include <Nazara/Utility/Mesh.hpp>
|
#include <Nazara/Utility/Mesh.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, public NzRenderTarget::Listener
|
class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, public NzRenderTarget::Listener
|
||||||
{
|
{
|
||||||
|
|
@ -25,61 +29,47 @@ class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, p
|
||||||
NzDeferredRenderTechnique();
|
NzDeferredRenderTechnique();
|
||||||
~NzDeferredRenderTechnique();
|
~NzDeferredRenderTechnique();
|
||||||
|
|
||||||
void Clear(const NzScene* scene);
|
void Clear(const NzScene* scene) const;
|
||||||
bool Draw(const NzScene* scene);
|
bool Draw(const NzScene* scene) const;
|
||||||
|
|
||||||
|
void EnablePass(nzRenderPassType renderPass, int position, bool enable);
|
||||||
|
|
||||||
|
NzRenderBuffer* GetDepthStencilBuffer() const;
|
||||||
NzTexture* GetGBuffer(unsigned int i) const;
|
NzTexture* GetGBuffer(unsigned int i) const;
|
||||||
|
NzRenderTexture* GetGBufferRTT() const;
|
||||||
|
const NzForwardRenderTechnique* GetForwardTechnique() const;
|
||||||
|
NzDeferredRenderPass* GetPass(nzRenderPassType renderPass, int position = 0);
|
||||||
NzAbstractRenderQueue* GetRenderQueue() override;
|
NzAbstractRenderQueue* GetRenderQueue() override;
|
||||||
nzRenderTechniqueType GetType() const override;
|
nzRenderTechniqueType GetType() const override;
|
||||||
|
NzRenderTexture* GetWorkRTT() const;
|
||||||
NzTexture* GetWorkTexture(unsigned int i) 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();
|
static bool IsSupported();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GeomPass(const NzScene* scene);
|
bool Resize(const NzVector2ui& dimensions) const;
|
||||||
void DirectionalLightPass(const NzScene* scene);
|
|
||||||
void PointLightPass(const NzScene* scene);
|
|
||||||
void SpotLightPass(const NzScene* scene);
|
|
||||||
bool UpdateTextures() 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
|
NzForwardRenderTechnique m_forwardTechnique; // Doit être initialisé avant la RenderQueue
|
||||||
NzDeferredRenderQueue m_renderQueue;
|
NzDeferredRenderQueue m_renderQueue;
|
||||||
NzMeshRef m_sphere;
|
mutable NzRenderBufferRef m_depthStencilBuffer;
|
||||||
NzStaticMesh* m_sphereMesh;
|
mutable NzRenderTexture m_GBufferRTT;
|
||||||
mutable NzRenderTexture m_bloomRTT;
|
mutable NzRenderTexture m_workRTT;
|
||||||
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 NzTextureRef m_GBuffer[4];
|
mutable NzTextureRef m_GBuffer[4];
|
||||||
mutable NzTextureRef m_ssaoTextureA;
|
mutable NzTextureRef m_workTextures[2];
|
||||||
mutable NzTextureRef m_ssaoTextureB;
|
mutable NzVector2ui m_GBufferSize;
|
||||||
mutable NzTextureRef m_ssaoNoiseTexture;
|
|
||||||
mutable NzTextureRef m_workTextureA;
|
|
||||||
mutable NzTextureRef m_workTextureB;
|
|
||||||
NzTextureSampler m_bilinearSampler;
|
|
||||||
NzTextureSampler m_pointSampler;
|
|
||||||
NzTextureSampler m_ssaoSampler;
|
|
||||||
NzVector2ui m_GBufferSize;
|
|
||||||
const NzRenderTarget* m_viewerTarget;
|
const NzRenderTarget* m_viewerTarget;
|
||||||
mutable bool m_texturesUpdated;
|
|
||||||
int m_gaussianBlurProgramFilterLocation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP
|
#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,21 @@ enum nzLightType
|
||||||
nzLightType_Max = nzLightType_Spot
|
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
|
enum nzRenderTechniqueType
|
||||||
{
|
{
|
||||||
nzRenderTechniqueType_AdvancedForward, // NzAdvancedForwardRenderTechnique
|
nzRenderTechniqueType_AdvancedForward, // NzAdvancedForwardRenderTechnique
|
||||||
|
|
|
||||||
|
|
@ -20,26 +20,26 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique
|
||||||
NzForwardRenderTechnique();
|
NzForwardRenderTechnique();
|
||||||
~NzForwardRenderTechnique();
|
~NzForwardRenderTechnique();
|
||||||
|
|
||||||
void Clear(const NzScene* scene);
|
void Clear(const NzScene* scene) const;
|
||||||
bool Draw(const NzScene* scene);
|
bool Draw(const NzScene* scene) const;
|
||||||
|
|
||||||
unsigned int GetMaxLightsPerObject() const;
|
unsigned int GetMaxLightPassPerObject() const;
|
||||||
NzAbstractRenderQueue* GetRenderQueue() override;
|
NzAbstractRenderQueue* GetRenderQueue() override;
|
||||||
nzRenderTechniqueType GetType() const override;
|
nzRenderTechniqueType GetType() const override;
|
||||||
|
|
||||||
void SetMaxLightsPerObject(unsigned int lightCount);
|
void SetMaxLightPassPerObject(unsigned int passCount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DrawOpaqueModels(const NzScene* scene);
|
void DrawOpaqueModels(const NzScene* scene) const;
|
||||||
void DrawSprites(const NzScene* scene);
|
void DrawSprites(const NzScene* scene) const;
|
||||||
void DrawTransparentModels(const NzScene* scene);
|
void DrawTransparentModels(const NzScene* scene) const;
|
||||||
|
|
||||||
NzForwardRenderQueue m_renderQueue;
|
mutable NzForwardRenderQueue m_renderQueue;
|
||||||
NzIndexBufferRef m_indexBuffer;
|
NzIndexBufferRef m_indexBuffer;
|
||||||
NzLightManager m_directionalLights;
|
mutable NzLightManager m_directionalLights;
|
||||||
NzLightManager m_lights;
|
mutable NzLightManager m_lights;
|
||||||
NzVertexBuffer m_spriteBuffer;
|
NzVertexBuffer m_spriteBuffer;
|
||||||
unsigned int m_maxLightsPerObject;
|
unsigned int m_maxLightPassPerObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP
|
#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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
|
|
@ -186,7 +186,8 @@ void NzForwardRenderQueue::AddSubMesh(const NzMaterial* material, const NzSubMes
|
||||||
unsigned int instanceCount = staticDataContainer.size() + 1;
|
unsigned int instanceCount = staticDataContainer.size() + 1;
|
||||||
|
|
||||||
// Avons-nous suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ?
|
// 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
|
enableInstancing = true; // Apparemment oui, activons l'instancing avec ce matériau
|
||||||
|
|
||||||
staticDataContainer.resize(instanceCount);
|
staticDataContainer.resize(instanceCount);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static NzIndexBuffer* s_indexBuffer = nullptr;
|
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;
|
unsigned int s_maxSprites = 8192;
|
||||||
|
|
||||||
NzIndexBuffer* BuildIndexBuffer()
|
NzIndexBuffer* BuildIndexBuffer()
|
||||||
|
|
@ -49,7 +49,7 @@ namespace
|
||||||
|
|
||||||
NzForwardRenderTechnique::NzForwardRenderTechnique() :
|
NzForwardRenderTechnique::NzForwardRenderTechnique() :
|
||||||
m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic),
|
m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic),
|
||||||
m_maxLightsPerObject(maxLightCount)
|
m_maxLightPassPerObject(3)
|
||||||
{
|
{
|
||||||
if (!s_indexBuffer)
|
if (!s_indexBuffer)
|
||||||
s_indexBuffer = BuildIndexBuffer();
|
s_indexBuffer = BuildIndexBuffer();
|
||||||
|
|
@ -63,7 +63,7 @@ NzForwardRenderTechnique::~NzForwardRenderTechnique()
|
||||||
s_indexBuffer = nullptr;
|
s_indexBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzForwardRenderTechnique::Clear(const NzScene* scene)
|
void NzForwardRenderTechnique::Clear(const NzScene* scene) const
|
||||||
{
|
{
|
||||||
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
|
NzRenderer::Enable(nzRendererParameter_DepthBuffer, true);
|
||||||
NzRenderer::Enable(nzRendererParameter_DepthWrite, true);
|
NzRenderer::Enable(nzRendererParameter_DepthWrite, true);
|
||||||
|
|
@ -74,7 +74,7 @@ void NzForwardRenderTechnique::Clear(const NzScene* scene)
|
||||||
background->Draw(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_directionalLights.SetLights(&m_renderQueue.directionalLights[0], m_renderQueue.directionalLights.size());
|
||||||
m_lights.SetLights(&m_renderQueue.lights[0], m_renderQueue.lights.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()
|
NzAbstractRenderQueue* NzForwardRenderTechnique::GetRenderQueue()
|
||||||
|
|
@ -156,26 +156,16 @@ nzRenderTechniqueType NzForwardRenderTechnique::GetType() const
|
||||||
return nzRenderTechniqueType_BasicForward;
|
return nzRenderTechniqueType_BasicForward;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzForwardRenderTechnique::SetMaxLightsPerObject(unsigned int lightCount)
|
void NzForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int passCount)
|
||||||
{
|
{
|
||||||
#if NAZARA_GRAPHICS_SAFE
|
m_maxLightPassPerObject = passCount;
|
||||||
if (lightCount > maxLightCount)
|
|
||||||
{
|
|
||||||
NazaraError("Light count is over maximum light count (" + NzString::Number(lightCount) + " > " + NzString::Number(lightCount) + ')');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_maxLightsPerObject = lightCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene)
|
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
{
|
{
|
||||||
NzAbstractViewer* viewer = scene->GetViewer();
|
NzAbstractViewer* viewer = scene->GetViewer();
|
||||||
const NzShaderProgram* lastProgram = nullptr;
|
const NzShaderProgram* lastProgram = nullptr;
|
||||||
|
|
||||||
unsigned int lightCount = 0;
|
|
||||||
|
|
||||||
for (auto& matIt : m_renderQueue.opaqueModels)
|
for (auto& matIt : m_renderQueue.opaqueModels)
|
||||||
{
|
{
|
||||||
bool& used = std::get<0>(matIt.second);
|
bool& used = std::get<0>(matIt.second);
|
||||||
|
|
@ -207,11 +197,6 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene)
|
||||||
// Position de la caméra
|
// Position de la caméra
|
||||||
program->SendVector(program->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
|
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;
|
lastProgram = program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -269,51 +254,110 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene)
|
||||||
|
|
||||||
unsigned int stride = instanceBuffer->GetStride();
|
unsigned int stride = instanceBuffer->GetStride();
|
||||||
|
|
||||||
const NzForwardRenderQueue::StaticData* data = &staticData[0];
|
// Avec l'instancing, impossible de sélectionner les lumières pour chaque objet
|
||||||
unsigned int instanceCount = staticData.size();
|
// Du coup, il n'est activé que pour les lumières directionnelles
|
||||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount();
|
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);
|
unsigned int renderedLightCount = std::min(lightCount, s_maxLightPerPass);
|
||||||
instanceCount -= renderedInstanceCount;
|
lightCount -= renderedLightCount;
|
||||||
|
|
||||||
NzBufferMapper<NzVertexBuffer> mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount);
|
if (pass == 1)
|
||||||
nzUInt8* ptr = reinterpret_cast<nzUInt8*>(mapper.GetPointer());
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < renderedInstanceCount; ++i)
|
|
||||||
{
|
{
|
||||||
std::memcpy(ptr, data->transformMatrix, sizeof(float)*16);
|
// 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
|
||||||
data++;
|
// (Autrement dit, sans blending)
|
||||||
ptr += stride;
|
// 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
|
else
|
||||||
{
|
{
|
||||||
unsigned int originalLightCount = lightCount;
|
|
||||||
for (const NzForwardRenderQueue::StaticData& data : staticData)
|
for (const NzForwardRenderQueue::StaticData& data : staticData)
|
||||||
{
|
{
|
||||||
// Calcul des lumières les plus proches
|
unsigned int directionalLightCount = m_directionalLights.GetLightCount();
|
||||||
if (lightCount < m_maxLightsPerObject && !m_lights.IsEmpty())
|
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));
|
unsigned int renderedLightCount = std::min(lightCount, s_maxLightPerPass);
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
lightCount -= renderedLightCount;
|
||||||
m_lights.GetResult(i)->Enable(program, lightCount++);
|
|
||||||
|
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)
|
NzRenderer::Enable(nzRendererParameter_Blend, false);
|
||||||
NzLight::Disable(program, i);
|
NzRenderer::SetDepthFunc(oldDepthFunc);
|
||||||
|
|
||||||
NzRenderer::SetMatrix(nzMatrixType_World, data.transformMatrix);
|
|
||||||
DrawFunc(primitiveMode, 0, indexCount);
|
|
||||||
|
|
||||||
lightCount = originalLightCount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
staticData.clear();
|
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();
|
NzAbstractViewer* viewer = scene->GetViewer();
|
||||||
const NzShaderProgram* lastProgram = nullptr;
|
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();
|
NzAbstractViewer* viewer = scene->GetViewer();
|
||||||
const NzShaderProgram* lastProgram = nullptr;
|
const NzShaderProgram* lastProgram = nullptr;
|
||||||
|
|
@ -474,14 +518,14 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene)
|
||||||
NzRenderer::SetVertexBuffer(vertexBuffer);
|
NzRenderer::SetVertexBuffer(vertexBuffer);
|
||||||
|
|
||||||
// Calcul des lumières les plus proches
|
// 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)
|
for (unsigned int i = 0; i < count; ++i)
|
||||||
m_lights.GetResult(i)->Enable(program, lightCount++);
|
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);
|
NzLight::Disable(program, i);
|
||||||
|
|
||||||
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
|
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,11 @@ void main()
|
||||||
{
|
{
|
||||||
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
|
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
|
||||||
vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0);
|
vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0);
|
||||||
if (gVec0.w == 0.0)
|
/* if (gVec0.w == 0.0)
|
||||||
{
|
{
|
||||||
RenderTarget0 = vec4(gVec0.xyz, 1.0);
|
RenderTarget0 = vec4(gVec0.xyz, 1.0);
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0);
|
vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0);
|
||||||
vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0);
|
vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -29,11 +29,11 @@ void main()
|
||||||
{
|
{
|
||||||
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
|
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
|
||||||
vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0);
|
vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0);
|
||||||
if (gVec0.w == 0.0)
|
/* if (gVec0.w == 0.0)
|
||||||
{
|
{
|
||||||
RenderTarget0 = vec4(gVec0.xyz, 1.0);
|
RenderTarget0 = vec4(gVec0.xyz, 1.0);
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0);
|
vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0);
|
||||||
vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0);
|
vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue