From a332579c80104d3f24f4c626c7f6304909902b19 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 28 Dec 2013 10:22:03 +0100 Subject: [PATCH] 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 --- include/Nazara/Graphics.hpp | 4 +- .../Graphics/AbstractRenderTechnique.hpp | 4 +- include/Nazara/Graphics/DeferredBloomPass.hpp | 54 + include/Nazara/Graphics/DeferredDOFPass.hpp | 38 + include/Nazara/Graphics/DeferredFXAAPass.hpp | 30 + include/Nazara/Graphics/DeferredFinalPass.hpp | 30 + include/Nazara/Graphics/DeferredFogPass.hpp | 30 + .../Nazara/Graphics/DeferredForwardPass.hpp | 28 + .../Nazara/Graphics/DeferredGeometryPass.hpp | 29 + .../Graphics/DeferredPhongLightingPass.hpp | 42 + .../Nazara/Graphics/DeferredRenderPass.hpp | 52 + .../Nazara/Graphics/DeferredRenderQueue.hpp | 10 +- .../Graphics/DeferredRenderTechnique.hpp | 72 +- include/Nazara/Graphics/Enums.hpp | 15 + .../Graphics/ForwardRenderTechnique.hpp | 22 +- src/Nazara/Graphics/DeferredBloomPass.cpp | 309 ++++ src/Nazara/Graphics/DeferredDOFPass.cpp | 224 +++ src/Nazara/Graphics/DeferredFXAAPass.cpp | 84 + src/Nazara/Graphics/DeferredFinalPass.cpp | 85 + src/Nazara/Graphics/DeferredFogPass.cpp | 138 ++ src/Nazara/Graphics/DeferredForwardPass.cpp | 45 + src/Nazara/Graphics/DeferredGeometryPass.cpp | 303 ++++ .../Graphics/DeferredPhongLightingPass.cpp | 421 +++++ src/Nazara/Graphics/DeferredRenderPass.cpp | 48 + .../Graphics/DeferredRenderTechnique.cpp | 1493 +++-------------- src/Nazara/Graphics/ForwardRenderQueue.cpp | 3 +- .../Graphics/ForwardRenderTechnique.cpp | 160 +- .../DeferredShading/Shaders/PointLight.frag | 4 +- .../DeferredShading/Shaders/PointLight.frag.h | 2 +- .../DeferredShading/Shaders/SpotLight.frag | 4 +- .../DeferredShading/Shaders/SpotLight.frag.h | 2 +- 31 files changed, 2431 insertions(+), 1354 deletions(-) create mode 100644 include/Nazara/Graphics/DeferredBloomPass.hpp create mode 100644 include/Nazara/Graphics/DeferredDOFPass.hpp create mode 100644 include/Nazara/Graphics/DeferredFXAAPass.hpp create mode 100644 include/Nazara/Graphics/DeferredFinalPass.hpp create mode 100644 include/Nazara/Graphics/DeferredFogPass.hpp create mode 100644 include/Nazara/Graphics/DeferredForwardPass.hpp create mode 100644 include/Nazara/Graphics/DeferredGeometryPass.hpp create mode 100644 include/Nazara/Graphics/DeferredPhongLightingPass.hpp create mode 100644 include/Nazara/Graphics/DeferredRenderPass.hpp create mode 100644 src/Nazara/Graphics/DeferredBloomPass.cpp create mode 100644 src/Nazara/Graphics/DeferredDOFPass.cpp create mode 100644 src/Nazara/Graphics/DeferredFXAAPass.cpp create mode 100644 src/Nazara/Graphics/DeferredFinalPass.cpp create mode 100644 src/Nazara/Graphics/DeferredFogPass.cpp create mode 100644 src/Nazara/Graphics/DeferredForwardPass.cpp create mode 100644 src/Nazara/Graphics/DeferredGeometryPass.cpp create mode 100644 src/Nazara/Graphics/DeferredPhongLightingPass.cpp create mode 100644 src/Nazara/Graphics/DeferredRenderPass.cpp diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 81ec3a609..b835f5d26 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -1,4 +1,4 @@ -// This file was automatically generated on 20 Dec 2013 at 20:02:16 +// This file was automatically generated on 27 Dec 2013 at 22:07:53 /* Nazara Engine - Graphics module @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/include/Nazara/Graphics/AbstractRenderTechnique.hpp b/include/Nazara/Graphics/AbstractRenderTechnique.hpp index cb93fec7c..ae6df79db 100644 --- a/include/Nazara/Graphics/AbstractRenderTechnique.hpp +++ b/include/Nazara/Graphics/AbstractRenderTechnique.hpp @@ -22,8 +22,8 @@ class NAZARA_API NzAbstractRenderTechnique : NzNonCopyable NzAbstractRenderTechnique(); virtual ~NzAbstractRenderTechnique(); - virtual void Clear(const NzScene* scene) = 0; - virtual bool Draw(const NzScene* scene) = 0; + virtual void Clear(const NzScene* scene) const = 0; + virtual bool Draw(const NzScene* scene) const = 0; virtual void EnableInstancing(bool instancing); diff --git a/include/Nazara/Graphics/DeferredBloomPass.hpp b/include/Nazara/Graphics/DeferredBloomPass.hpp new file mode 100644 index 000000000..b0dbaf579 --- /dev/null +++ b/include/Nazara/Graphics/DeferredBloomPass.hpp @@ -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 +#include +#include +#include +#include +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredDOFPass.hpp b/include/Nazara/Graphics/DeferredDOFPass.hpp new file mode 100644 index 000000000..8b7881bb4 --- /dev/null +++ b/include/Nazara/Graphics/DeferredDOFPass.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 +#include +#include +#include +#include +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredFXAAPass.hpp b/include/Nazara/Graphics/DeferredFXAAPass.hpp new file mode 100644 index 000000000..da088eb5e --- /dev/null +++ b/include/Nazara/Graphics/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_DEFERREDFXAAPASS_HPP +#define NAZARA_DEFERREDFXAAPASS_HPP + +#include +#include +#include +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredFinalPass.hpp b/include/Nazara/Graphics/DeferredFinalPass.hpp new file mode 100644 index 000000000..7e737db1e --- /dev/null +++ b/include/Nazara/Graphics/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_DEFERREDFINALPASS_HPP +#define NAZARA_DEFERREDFINALPASS_HPP + +#include +#include +#include +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredFogPass.hpp b/include/Nazara/Graphics/DeferredFogPass.hpp new file mode 100644 index 000000000..8c187ac97 --- /dev/null +++ b/include/Nazara/Graphics/DeferredFogPass.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 +#include +#include +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredForwardPass.hpp b/include/Nazara/Graphics/DeferredForwardPass.hpp new file mode 100644 index 000000000..049d776a7 --- /dev/null +++ b/include/Nazara/Graphics/DeferredForwardPass.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 +#include + +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 diff --git a/include/Nazara/Graphics/DeferredGeometryPass.hpp b/include/Nazara/Graphics/DeferredGeometryPass.hpp new file mode 100644 index 000000000..50ce71343 --- /dev/null +++ b/include/Nazara/Graphics/DeferredGeometryPass.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 +#include +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredPhongLightingPass.hpp b/include/Nazara/Graphics/DeferredPhongLightingPass.hpp new file mode 100644 index 000000000..e61d8808b --- /dev/null +++ b/include/Nazara/Graphics/DeferredPhongLightingPass.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 +#include +#include +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredRenderPass.hpp b/include/Nazara/Graphics/DeferredRenderPass.hpp new file mode 100644 index 000000000..4fa0cb189 --- /dev/null +++ b/include/Nazara/Graphics/DeferredRenderPass.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 +#include +#include + +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 diff --git a/include/Nazara/Graphics/DeferredRenderQueue.hpp b/include/Nazara/Graphics/DeferredRenderQueue.hpp index 5e6efb111..5333fca5e 100644 --- a/include/Nazara/Graphics/DeferredRenderQueue.hpp +++ b/include/Nazara/Graphics/DeferredRenderQueue.hpp @@ -23,8 +23,6 @@ class NzStaticMesh; class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourceListener { - friend class NzDeferredRenderTechnique; - public: NzDeferredRenderQueue(NzForwardRenderQueue* forwardQueue); ~NzDeferredRenderQueue(); @@ -37,10 +35,6 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc void Clear(bool fully); - private: - bool OnResourceDestroy(const NzResource* resource, int index) override; - void OnResourceReleased(const NzResource* resource, int index) override; - struct SkeletalData { ///TODO @@ -84,6 +78,10 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc LightContainer pointLights; LightContainer spotLights; NzForwardRenderQueue* m_forwardQueue; + + private: + bool OnResourceDestroy(const NzResource* resource, int index) override; + void OnResourceReleased(const NzResource* resource, int index) override; }; #endif // NAZARA_DEFERREDRENDERQUEUE_HPP diff --git a/include/Nazara/Graphics/DeferredRenderTechnique.hpp b/include/Nazara/Graphics/DeferredRenderTechnique.hpp index 1b55db4bc..a844989a1 100644 --- a/include/Nazara/Graphics/DeferredRenderTechnique.hpp +++ b/include/Nazara/Graphics/DeferredRenderTechnique.hpp @@ -9,15 +9,19 @@ #include #include +#include #include #include #include +#include #include #include #include #include #include #include +#include +#include class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, public NzRenderTarget::Listener { @@ -25,61 +29,47 @@ class NAZARA_API NzDeferredRenderTechnique : public NzAbstractRenderTechnique, p NzDeferredRenderTechnique(); ~NzDeferredRenderTechnique(); - void Clear(const NzScene* scene); - bool Draw(const NzScene* scene); + void Clear(const NzScene* scene) const; + bool Draw(const NzScene* scene) const; + void EnablePass(nzRenderPassType renderPass, int position, bool enable); + + NzRenderBuffer* GetDepthStencilBuffer() const; NzTexture* GetGBuffer(unsigned int i) const; + NzRenderTexture* GetGBufferRTT() const; + const NzForwardRenderTechnique* GetForwardTechnique() const; + NzDeferredRenderPass* GetPass(nzRenderPassType renderPass, int position = 0); NzAbstractRenderQueue* GetRenderQueue() override; nzRenderTechniqueType GetType() const override; + NzRenderTexture* GetWorkRTT() const; NzTexture* GetWorkTexture(unsigned int i) const; + bool IsPassEnabled(nzRenderPassType renderPass, int position); + + NzDeferredRenderPass* ResetPass(nzRenderPassType renderPass, int position); + + void SetPass(nzRenderPassType relativeTo, int position, NzDeferredRenderPass* pass); + static bool IsSupported(); private: - void GeomPass(const NzScene* scene); - void DirectionalLightPass(const NzScene* scene); - void PointLightPass(const NzScene* scene); - void SpotLightPass(const NzScene* scene); - bool UpdateTextures() const; + bool Resize(const NzVector2ui& dimensions) const; + struct RenderPassComparator + { + bool operator()(nzRenderPassType pass1, nzRenderPassType pass2); + }; + + std::map>, RenderPassComparator> m_passes; NzForwardRenderTechnique m_forwardTechnique; // Doit être initialisé avant la RenderQueue NzDeferredRenderQueue m_renderQueue; - NzMeshRef m_sphere; - NzStaticMesh* m_sphereMesh; - mutable NzRenderTexture m_bloomRTT; - mutable NzRenderTexture m_dofRTT; - mutable NzRenderTexture m_geometryRTT; - mutable NzRenderTexture m_ssaoRTT; - NzRenderStates m_clearStates; - NzShaderProgramRef m_aaProgram; - NzShaderProgramRef m_blitProgram; - NzShaderProgramRef m_bloomBrightProgram; - NzShaderProgramRef m_bloomFinalProgram; - NzShaderProgramRef m_clearProgram; - NzShaderProgramRef m_directionalLightProgram; - NzShaderProgramRef m_depthOfFieldProgram; - NzShaderProgramRef m_gaussianBlurProgram; - NzShaderProgramRef m_pointLightProgram; - NzShaderProgramRef m_ssaoProgram; - NzShaderProgramRef m_ssaoFinalProgram; - NzShaderProgramRef m_spotLightProgram; - mutable NzTextureRef m_bloomTextureA; - mutable NzTextureRef m_bloomTextureB; - mutable NzTextureRef m_dofTextureA; - mutable NzTextureRef m_dofTextureB; + mutable NzRenderBufferRef m_depthStencilBuffer; + mutable NzRenderTexture m_GBufferRTT; + mutable NzRenderTexture m_workRTT; mutable NzTextureRef m_GBuffer[4]; - mutable NzTextureRef m_ssaoTextureA; - mutable NzTextureRef m_ssaoTextureB; - mutable NzTextureRef m_ssaoNoiseTexture; - mutable NzTextureRef m_workTextureA; - mutable NzTextureRef m_workTextureB; - NzTextureSampler m_bilinearSampler; - NzTextureSampler m_pointSampler; - NzTextureSampler m_ssaoSampler; - NzVector2ui m_GBufferSize; + mutable NzTextureRef m_workTextures[2]; + mutable NzVector2ui m_GBufferSize; const NzRenderTarget* m_viewerTarget; - mutable bool m_texturesUpdated; - int m_gaussianBlurProgramFilterLocation; }; #endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index f7b89bb70..f64ff374d 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -26,6 +26,21 @@ enum nzLightType nzLightType_Max = nzLightType_Spot }; +enum nzRenderPassType +{ + nzRenderPassType_AA, + nzRenderPassType_Bloom, + nzRenderPassType_DOF, + nzRenderPassType_Final, + nzRenderPassType_Fog, + nzRenderPassType_Forward, + nzRenderPassType_Lighting, + nzRenderPassType_Geometry, + nzRenderPassType_SSAO, + + nzRenderPassType_Max = nzRenderPassType_SSAO +}; + enum nzRenderTechniqueType { nzRenderTechniqueType_AdvancedForward, // NzAdvancedForwardRenderTechnique diff --git a/include/Nazara/Graphics/ForwardRenderTechnique.hpp b/include/Nazara/Graphics/ForwardRenderTechnique.hpp index a0d5d98bd..7e1d6754b 100644 --- a/include/Nazara/Graphics/ForwardRenderTechnique.hpp +++ b/include/Nazara/Graphics/ForwardRenderTechnique.hpp @@ -20,26 +20,26 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique NzForwardRenderTechnique(); ~NzForwardRenderTechnique(); - void Clear(const NzScene* scene); - bool Draw(const NzScene* scene); + void Clear(const NzScene* scene) const; + bool Draw(const NzScene* scene) const; - unsigned int GetMaxLightsPerObject() const; + unsigned int GetMaxLightPassPerObject() const; NzAbstractRenderQueue* GetRenderQueue() override; nzRenderTechniqueType GetType() const override; - void SetMaxLightsPerObject(unsigned int lightCount); + void SetMaxLightPassPerObject(unsigned int passCount); private: - void DrawOpaqueModels(const NzScene* scene); - void DrawSprites(const NzScene* scene); - void DrawTransparentModels(const NzScene* scene); + void DrawOpaqueModels(const NzScene* scene) const; + void DrawSprites(const NzScene* scene) const; + void DrawTransparentModels(const NzScene* scene) const; - NzForwardRenderQueue m_renderQueue; + mutable NzForwardRenderQueue m_renderQueue; NzIndexBufferRef m_indexBuffer; - NzLightManager m_directionalLights; - NzLightManager m_lights; + mutable NzLightManager m_directionalLights; + mutable NzLightManager m_lights; NzVertexBuffer m_spriteBuffer; - unsigned int m_maxLightsPerObject; + unsigned int m_maxLightPassPerObject; }; #endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP diff --git a/src/Nazara/Graphics/DeferredBloomPass.cpp b/src/Nazara/Graphics/DeferredBloomPass.cpp new file mode 100644 index 000000000..e8415d78b --- /dev/null +++ b/src/Nazara/Graphics/DeferredBloomPass.cpp @@ -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 +#include +#include +#include + +namespace +{ + NzShaderProgram* BuildBloomBrightProgram() + { + const nzUInt8 fragmentSource[] = { + #include + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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 + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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 + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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(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; +} diff --git a/src/Nazara/Graphics/DeferredDOFPass.cpp b/src/Nazara/Graphics/DeferredDOFPass.cpp new file mode 100644 index 000000000..5861c30fb --- /dev/null +++ b/src/Nazara/Graphics/DeferredDOFPass.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +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 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 + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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(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; +} diff --git a/src/Nazara/Graphics/DeferredFXAAPass.cpp b/src/Nazara/Graphics/DeferredFXAAPass.cpp new file mode 100644 index 000000000..86b87823f --- /dev/null +++ b/src/Nazara/Graphics/DeferredFXAAPass.cpp @@ -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 +#include +#include +#include +#include + +namespace +{ + NzShaderProgram* BuildFXAAProgram() + { + const nzUInt8 fragmentSource[] = { + #include + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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; +} diff --git a/src/Nazara/Graphics/DeferredFinalPass.cpp b/src/Nazara/Graphics/DeferredFinalPass.cpp new file mode 100644 index 000000000..261cb6176 --- /dev/null +++ b/src/Nazara/Graphics/DeferredFinalPass.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +namespace +{ + NzShaderProgram* BuildBlitProgram() + { + const nzUInt8 fragmentSource[] = { + #include + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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; +} diff --git a/src/Nazara/Graphics/DeferredFogPass.cpp b/src/Nazara/Graphics/DeferredFogPass.cpp new file mode 100644 index 000000000..9199885d8 --- /dev/null +++ b/src/Nazara/Graphics/DeferredFogPass.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +namespace +{ + NzShaderProgram* BuildFogProgram() + { + /*const nzUInt8 fragmentSource[] = { + #include + };*/ + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, fragmentSource/*NzString(reinterpret_cast(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; +} diff --git a/src/Nazara/Graphics/DeferredForwardPass.cpp b/src/Nazara/Graphics/DeferredForwardPass.cpp new file mode 100644 index 000000000..cd07f931c --- /dev/null +++ b/src/Nazara/Graphics/DeferredForwardPass.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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; +} + diff --git a/src/Nazara/Graphics/DeferredGeometryPass.cpp b/src/Nazara/Graphics/DeferredGeometryPass.cpp new file mode 100644 index 000000000..b9cbb675d --- /dev/null +++ b/src/Nazara/Graphics/DeferredGeometryPass.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + NzShaderProgram* BuildClearProgram() + { + const nzUInt8 fragmentSource[] = { + #include + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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& 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 DrawFunc; + std::function 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 mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount); + nzUInt8* ptr = reinterpret_cast(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; + } +} diff --git a/src/Nazara/Graphics/DeferredPhongLightingPass.cpp b/src/Nazara/Graphics/DeferredPhongLightingPass.cpp new file mode 100644 index 000000000..db3fa5b58 --- /dev/null +++ b/src/Nazara/Graphics/DeferredPhongLightingPass.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // Supprimer +#include + +namespace +{ + NzShaderProgram* BuildDirectionalLightProgram() + { + const nzUInt8 fragmentSource[] = { + #include + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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 + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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 + }; + + 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); + program->SetPersistent(false); + + if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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(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(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; +} + diff --git a/src/Nazara/Graphics/DeferredRenderPass.cpp b/src/Nazara/Graphics/DeferredRenderPass.cpp new file mode 100644 index 000000000..91e9b5f64 --- /dev/null +++ b/src/Nazara/Graphics/DeferredRenderPass.cpp @@ -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 +#include +#include +#include + +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(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; +} diff --git a/src/Nazara/Graphics/DeferredRenderTechnique.cpp b/src/Nazara/Graphics/DeferredRenderTechnique.cpp index 9e38a9678..00999e0c0 100644 --- a/src/Nazara/Graphics/DeferredRenderTechnique.cpp +++ b/src/Nazara/Graphics/DeferredRenderTechnique.cpp @@ -6,6 +6,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -14,9 +22,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -24,958 +29,178 @@ namespace { - NzShaderProgram* BuildClearProgram() + unsigned int RenderPassPriority[] = { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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(); - } - - NzShaderProgram* BuildDirectionalLightProgram() - { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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 - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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 - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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* BuildBloomBrightProgram() - { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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* BuildGaussianBlurProgram() - { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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 - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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* BuildAAProgram() - { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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("GBuffer1"), 0); - program->SendInteger(program->GetUniformLocation("NoiseTexture"), 1); - - return program.release(); - } - - NzShaderProgram* BuildSSAOProgram() - { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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("GBuffer1"), 0); - program->SendInteger(program->GetUniformLocation("NoiseTexture"), 1); - - return program.release(); - } - - NzShaderProgram* BuildSSAOFinalProgram() - { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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("SSAOTexture"), 1); - - return program.release(); - } - - // 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 = 100.0;\n" - "float Near = 0.1;\n" - "float Far = (5000.0) / (5000.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) / (5000.0 + 0.1 - depth * (5000.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 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; - } - - program->SendInteger(program->GetUniformLocation("ColorTexture"), 0); - program->SendInteger(program->GetUniformLocation("BlurTexture"), 1); - program->SendInteger(program->GetUniformLocation("GBuffer1"), 2); - - return program.release(); - } - - NzShaderProgram* BuildBlitProgram() - { - const nzUInt8 fragmentSource[] = { - #include - }; - - 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 program(new NzShaderProgram(nzShaderLanguage_GLSL)); - program->SetPersistent(false); - - if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast(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(); - } + 6, // nzRenderPassType_AA + 4, // nzRenderPassType_Bloom + 7, // nzRenderPassType_DOF + 0xFF, // nzRenderPassType_Final + 5, // nzRenderPassType_Fog + 2, // nzRenderPassType_Forward + 1, // nzRenderPassType_Lighting + 0, // nzRenderPassType_Geometry + 3, // nzRenderPassType_SSAO + }; + + static_assert(sizeof(RenderPassPriority)/sizeof(unsigned int) == nzRenderPassType_Max+1, "Render pass priority array is incomplete"); } NzDeferredRenderTechnique::NzDeferredRenderTechnique() : m_renderQueue(static_cast(m_forwardTechnique.GetRenderQueue())), -m_GBufferSize(0, 0), -m_texturesUpdated(false) +m_GBufferSize(0U) { - m_aaProgram = BuildAAProgram(); + m_depthStencilBuffer = new NzRenderBuffer; + m_depthStencilBuffer->SetPersistent(false); - m_blitProgram = BuildBlitProgram(); - - m_bloomBrightProgram = BuildBloomBrightProgram(); - m_bloomFinalProgram = BuildBloomFinalProgram(); - - 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; - - m_gaussianBlurProgram = BuildGaussianBlurProgram(); - m_gaussianBlurProgramFilterLocation = m_gaussianBlurProgram->GetUniformLocation("Filter"); - - m_directionalLightProgram = BuildDirectionalLightProgram(); - m_pointLightProgram = BuildPointLightProgram(); - m_spotLightProgram = BuildSpotLightProgram(); - - m_depthOfFieldProgram = BuildDepthOfFieldProgram(); - - 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_ssaoSampler.SetAnisotropyLevel(1); - m_ssaoSampler.SetFilterMode(nzSamplerFilter_Nearest); - m_ssaoSampler.SetWrapMode(nzSamplerWrap_Repeat); - - /*const unsigned int kernelSize = 16; - - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_real_distribution dis(-1.f, 1.f); - std::uniform_real_distribution dis2(0.f, 1.f); - - std::vector kernel(kernelSize); - for (unsigned int i = 0; i < kernelSize; ++i) + for (unsigned int i = 0; i < 2; ++i) { - kernel[i].Set(dis(gen), dis(gen), dis2(gen)); - kernel[i].Normalize(); - - float scale = static_cast(i) / kernelSize; - kernel[i] *= NzLerp(0.1f, 1.0f, scale * scale); + m_workTextures[i] = new NzTexture; + m_workTextures[i]->SetPersistent(false); } - int noiseDataSize = 4 * 4; - - std::vector noiseData(noiseDataSize*2); - for (int i = 0; i < noiseDataSize; ++i) - { - NzVector2f vec(dis(gen), dis(gen)); - vec.Normalize(); - - noiseData[i*2 + 0] = static_cast((vec.x*0.5f + 0.5f) * 0xFF); - noiseData[i*2 + 1] = static_cast((vec.y*0.5f + 0.5f) * 0xFF); - } - - m_ssaoNoiseTexture = new NzTexture; - m_ssaoNoiseTexture->SetPersistent(false); - m_ssaoNoiseTexture->Create(nzImageType_2D, nzPixelFormat_RG8, 4, 4); - m_ssaoNoiseTexture->Update(&noiseData[0]);*/ - - const nzUInt8 noiseTexture[] = { - #include - }; - - m_ssaoNoiseTexture = new NzTexture; - m_ssaoNoiseTexture->SetPersistent(false); - m_ssaoNoiseTexture->LoadFromMemory(noiseTexture, sizeof(noiseTexture)); - - m_ssaoProgram = BuildSSAOProgram(); - m_ssaoProgram->SendInteger(m_ssaoProgram->GetUniformLocation("NoiseTextureSize"), m_ssaoNoiseTexture->GetWidth()); - //m_ssaoProgram->SendInteger(m_ssaoProgram->GetUniformLocation("ssaoKernelSize"), kernelSize); - //m_ssaoProgram->SendVectorArray(m_ssaoProgram->GetUniformLocation("ssaoKernelOffsets"), &kernel[0], kernelSize); - - m_ssaoFinalProgram = BuildSSAOFinalProgram(); - - m_sphere = new NzMesh; - m_sphere->SetPersistent(false); - m_sphere->CreateStatic(); - m_sphereMesh = static_cast(m_sphere->BuildSubMesh(NzPrimitive::IcoSphere(1.f, 1))); - - m_bloomTextureA = new NzTexture; - m_bloomTextureA->SetPersistent(false); - - m_bloomTextureB = new NzTexture; - m_bloomTextureB->SetPersistent(false); - - m_dofTextureA = new NzTexture; - m_dofTextureA->SetPersistent(false); - - m_dofTextureB = new NzTexture; - m_dofTextureB->SetPersistent(false); - - m_ssaoTextureA = new NzTexture; - m_ssaoTextureA->SetPersistent(false); - - m_ssaoTextureB = new NzTexture; - m_ssaoTextureB->SetPersistent(false); - - m_workTextureA = new NzTexture; - m_workTextureA->SetPersistent(false); - - m_workTextureB = new NzTexture; - m_workTextureB->SetPersistent(false); - for (unsigned int i = 0; i < 3; ++i) { m_GBuffer[i] = new NzTexture; m_GBuffer[i]->SetPersistent(false); } + + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException); + std::unique_ptr smartPtr; // Nous évite un leak en cas d'exception + + ResetPass(nzRenderPassType_Final, 0); + ResetPass(nzRenderPassType_Geometry, 0); + ResetPass(nzRenderPassType_Lighting, 0); + } + catch (const std::exception& e) + { + NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled); + + NazaraError("Failed to add geometry and/or phong lighting pass"); + throw; + } + + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException); + ResetPass(nzRenderPassType_AA, 0); + } + catch (const std::exception& e) + { + NazaraWarning("Failed to add FXAA pass"); + } + + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException); + ResetPass(nzRenderPassType_Bloom, 0); + } + catch (const std::exception& e) + { + NazaraWarning("Failed to add bloom pass"); + } + + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException); + + NzDeferredRenderPass* dofPass = ResetPass(nzRenderPassType_DOF, 0); + dofPass->Enable(false); + } + catch (const std::exception& e) + { + NazaraWarning("Failed to add DOF pass"); + } + + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException); + + NzDeferredRenderPass* fogPass = ResetPass(nzRenderPassType_Fog, 0); + fogPass->Enable(false); + } + catch (const std::exception& e) + { + NazaraWarning("Failed to add fog pass"); + } + + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException); + ResetPass(nzRenderPassType_Forward, 0); + } + catch (const std::exception& e) + { + NazaraWarning("Failed to add forward pass"); + } + + try + { + NzErrorFlags errFlags(nzErrorFlag_ThrowException); + ResetPass(nzRenderPassType_SSAO, 0); + } + catch (const std::exception& e) + { + NazaraWarning("Failed to add SSAO pass"); + } } -NzDeferredRenderTechnique::~NzDeferredRenderTechnique() -{ -} +NzDeferredRenderTechnique::~NzDeferredRenderTechnique() = default; -void NzDeferredRenderTechnique::Clear(const NzScene* scene) +void NzDeferredRenderTechnique::Clear(const NzScene* scene) const { NazaraUnused(scene); } -bool NzDeferredRenderTechnique::Draw(const NzScene* scene) +bool NzDeferredRenderTechnique::Draw(const NzScene* scene) const { - NzAbstractViewer* viewer = scene->GetViewer(); - NzRecti viewerViewport = NzRenderer::GetViewport(); + NzRecti viewerViewport = scene->GetViewer()->GetViewport(); - if (static_cast(viewerViewport.width) != m_GBufferSize.x || static_cast(viewerViewport.height) != m_GBufferSize.y) + NzVector2ui viewportDimensions(viewerViewport.width, viewerViewport.height); + if (viewportDimensions != m_GBufferSize) { - m_GBufferSize.Set(viewerViewport.width, viewerViewport.height); - m_texturesUpdated = false; + if (!Resize(viewportDimensions)) + { + NazaraError("Failed to update RTT"); + return false; + } } - if (!m_texturesUpdated && !UpdateTextures()) + unsigned int sceneTexture = 0; + unsigned int workTexture = 1; + for (auto& passIt : m_passes) { - NazaraError("Failed to update RTT"); - return false; + for (auto& passIt2 : passIt.second) + { + const NzDeferredRenderPass* pass = passIt2.second.get(); + if (pass->IsEnabled()) + { + if (pass->Process(scene, workTexture, sceneTexture)) + std::swap(workTexture, sceneTexture); + } + } } - NzRenderer::SetTarget(&m_geometryRTT); - NzRenderer::SetViewport(NzRecti(0, 0, m_GBufferSize.x, m_GBufferSize.y)); - - /****************************Passe géométrique****************************/ - m_geometryRTT.SetColorTargets({0, 1, 2}); // G-Buffer - - NzRenderer::SetRenderStates(m_clearStates); - NzRenderer::SetShaderProgram(m_clearProgram); - NzRenderer::DrawFullscreenQuad(); - - NzRenderer::SetMatrix(nzMatrixType_Projection, viewer->GetProjectionMatrix()); - NzRenderer::SetMatrix(nzMatrixType_View, viewer->GetViewMatrix()); - - GeomPass(scene); - - /****************************Passe d'éclairage****************************/ - m_geometryRTT.SetColorTarget(4); // workTextureA - - 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] = true; - lightStates.parameters[nzRendererParameter_DepthWrite] = false; - - // Directional lights - if (!m_renderQueue.directionalLights.empty()) - { - NzRenderer::SetRenderStates(lightStates); - DirectionalLightPass(scene); - } - - // 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()) - PointLightPass(scene); - - if (!m_renderQueue.spotLights.empty()) - SpotLightPass(scene); - - NzRenderer::Enable(nzRendererParameter_StencilTest, false); - } - - /******************************Passe forward******************************/ - NzAbstractBackground* background = scene->GetBackground(); - if (background) - background->Draw(scene); - - NzRenderer::SetMatrix(nzMatrixType_Projection, viewer->GetProjectionMatrix()); - NzRenderer::SetMatrix(nzMatrixType_View, viewer->GetViewMatrix()); - - m_forwardTechnique.Draw(scene); - - NzRenderStates states; - states.parameters[nzRendererParameter_DepthBuffer] = false; - - NzRenderer::SetRenderStates(states); - - /****************************SSAO***************************/ -/* NzRenderer::SetShaderProgram(m_ssaoProgram); - - NzRenderer::SetTarget(&m_ssaoRTT); - NzRenderer::SetViewport(NzRecti(0, 0, m_GBufferSize.x/4, m_GBufferSize.y/4)); - - m_ssaoRTT.SetColorTarget(0); // ssaoTextureA - - NzRenderer::SetTexture(0, m_GBuffer[1]); - NzRenderer::SetTexture(1, m_ssaoNoiseTexture); - NzRenderer::SetTextureSampler(0, m_pointSampler); - NzRenderer::SetTextureSampler(1, m_ssaoSampler); - NzRenderer::DrawFullscreenQuad(); - - NzRenderer::SetShaderProgram(m_gaussianBlurProgram); - - const unsigned int ssaoBlurPass = 2; - for (unsigned int i = 0; i < ssaoBlurPass; ++i) - { - m_ssaoRTT.SetColorTarget(1); // ssaoTextureB - - m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(1.f, 0.f)); - - NzRenderer::SetTexture(0, m_ssaoTextureA); - NzRenderer::DrawFullscreenQuad(); - - m_ssaoRTT.SetColorTarget(0); // ssaoTextureA - - m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(0.f, 1.f)); - - NzRenderer::SetTexture(0, m_ssaoTextureB); - NzRenderer::DrawFullscreenQuad(); - } - - NzRenderer::SetTarget(&m_geometryRTT); - NzRenderer::SetViewport(NzRecti(0, 0, m_GBufferSize.x, m_GBufferSize.y)); - m_geometryRTT.SetColorTarget(5); // workTextureB - - NzRenderer::SetShaderProgram(m_ssaoFinalProgram); - NzRenderer::SetTexture(0, m_workTextureA); - NzRenderer::SetTexture(1, m_ssaoTextureA); - NzRenderer::SetTextureSampler(0, m_pointSampler); - NzRenderer::SetTextureSampler(1, m_bilinearSampler); - NzRenderer::DrawFullscreenQuad(); -*/ - /****************************AA***************************/ - NzRenderer::SetShaderProgram(m_aaProgram); - - m_geometryRTT.SetColorTarget(5); // workTextureB - - NzRenderer::SetTexture(0, m_workTextureA); - NzRenderer::SetTextureSampler(0, m_pointSampler); - NzRenderer::DrawFullscreenQuad(); - - /****************************Bloom***************************/ - NzRenderer::SetTextureSampler(0, m_bilinearSampler); - NzRenderer::SetTextureSampler(1, m_bilinearSampler); - - m_geometryRTT.SetColorTarget(4); // workTextureA - - NzRenderer::SetShaderProgram(m_bloomBrightProgram); - - NzRenderer::SetTexture(0, m_workTextureB); - NzRenderer::DrawFullscreenQuad(); - - NzRenderer::SetTarget(&m_bloomRTT); - NzRenderer::SetViewport(NzRecti(0, 0, m_GBufferSize.x/8, m_GBufferSize.y/8)); - - NzRenderer::SetShaderProgram(m_gaussianBlurProgram); - - const unsigned int bloomBlurPass = 5; - for (unsigned int i = 0; i < bloomBlurPass; ++i) - { - m_bloomRTT.SetColorTarget(0); // bloomTextureA - - m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(1.f, 0.f)); - - NzRenderer::SetTexture(0, (i == 0) ? m_workTextureA : m_bloomTextureB); - NzRenderer::DrawFullscreenQuad(); - - m_bloomRTT.SetColorTarget(1); // bloomTextureB - - m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(0.f, 1.f)); - - NzRenderer::SetTexture(0, m_bloomTextureA); - NzRenderer::DrawFullscreenQuad(); - } - - NzRenderer::SetTarget(&m_geometryRTT); - NzRenderer::SetViewport(NzRecti(0, 0, m_GBufferSize.x, m_GBufferSize.y)); - m_geometryRTT.SetColorTarget(5); // workTextureB - - NzRenderer::SetShaderProgram(m_bloomFinalProgram); - NzRenderer::SetTexture(0, m_workTextureB); - NzRenderer::SetTexture(1, m_bloomTextureB); - NzRenderer::DrawFullscreenQuad(); - - /****************************Depth-of-Field***************************/ -/* 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_GBufferSize.x/4, m_GBufferSize.y/4)); - - NzRenderer::SetShaderProgram(m_gaussianBlurProgram); - - const unsigned int dofBlurPass = 2; - for (unsigned int i = 0; i < dofBlurPass; ++i) - { - m_dofRTT.SetColorTarget(0); // dofTextureA - - m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(1.f, 0.f)); - - NzRenderer::SetTexture(0, (i == 0) ? m_workTextureA : m_dofTextureB); - NzRenderer::DrawFullscreenQuad(); - - m_dofRTT.SetColorTarget(1); // dofTextureB - - m_gaussianBlurProgram->SendVector(m_gaussianBlurProgramFilterLocation, NzVector2f(0.f, 1.f)); - - NzRenderer::SetTexture(0, m_dofTextureA); - NzRenderer::DrawFullscreenQuad(); - } - - NzRenderer::SetTarget(&m_geometryRTT); - NzRenderer::SetViewport(NzRecti(0, 0, m_GBufferSize.x, m_GBufferSize.y)); - m_geometryRTT.SetColorTarget(5); // workTextureB - - NzRenderer::SetShaderProgram(m_depthOfFieldProgram); - NzRenderer::SetTexture(0, m_workTextureA); - NzRenderer::SetTexture(1, m_dofTextureB); - NzRenderer::SetTexture(2, m_GBuffer[1]); - NzRenderer::DrawFullscreenQuad();*/ - - /*******************************Passe finale******************************/ - scene->GetViewer()->ApplyView(); - - NzRenderer::SetRenderStates(states); - NzRenderer::SetShaderProgram(m_blitProgram); - NzRenderer::SetTexture(0, m_workTextureB); - NzRenderer::SetTextureSampler(0, m_pointSampler); - - NzRenderer::DrawFullscreenQuad(); - return true; } +void NzDeferredRenderTechnique::EnablePass(nzRenderPassType renderPass, int position, bool enable) +{ + auto it = m_passes.find(renderPass); + if (it != m_passes.end()) + { + auto it2 = it->second.find(position); + if (it2 != it->second.end()) + it2->second->Enable(enable); + } +} + +NzRenderBuffer* NzDeferredRenderTechnique::GetDepthStencilBuffer() const +{ + return m_depthStencilBuffer; +} + NzTexture* NzDeferredRenderTechnique::GetGBuffer(unsigned int i) const { #if NAZARA_GRAPHICS_SAFE @@ -989,6 +214,29 @@ NzTexture* NzDeferredRenderTechnique::GetGBuffer(unsigned int i) const return m_GBuffer[i]; } +NzRenderTexture* NzDeferredRenderTechnique::GetGBufferRTT() const +{ + return &m_GBufferRTT; +} + +const NzForwardRenderTechnique* NzDeferredRenderTechnique::GetForwardTechnique() const +{ + return &m_forwardTechnique; +} + +NzDeferredRenderPass* NzDeferredRenderTechnique::GetPass(nzRenderPassType renderPass, int position) +{ + auto it = m_passes.find(renderPass); + if (it != m_passes.end()) + { + auto it2 = it->second.find(position); + if (it2 != it->second.end()) + return it2->second.get(); + } + + return nullptr; +} + NzAbstractRenderQueue* NzDeferredRenderTechnique::GetRenderQueue() { return &m_renderQueue; @@ -999,18 +247,100 @@ nzRenderTechniqueType NzDeferredRenderTechnique::GetType() const return nzRenderTechniqueType_DeferredShading; } +NzRenderTexture* NzDeferredRenderTechnique::GetWorkRTT() const +{ + return &m_workRTT; +} + NzTexture* NzDeferredRenderTechnique::GetWorkTexture(unsigned int i) const { #if NAZARA_GRAPHICS_SAFE if (i >= 2) { - NazaraError("GBuffer texture index out of range (" + NzString::Number(i) + " >= 3)"); + NazaraError("Work texture index out of range (" + NzString::Number(i) + " >= 2)"); return nullptr; } #endif - return (i == 0) ? m_workTextureA : m_workTextureB; + return m_workTextures[i]; +} +bool NzDeferredRenderTechnique::IsPassEnabled(nzRenderPassType renderPass, int position) +{ + auto it = m_passes.find(renderPass); + if (it != m_passes.end()) + { + auto it2 = it->second.find(position); + if (it2 != it->second.end()) + return it2->second->IsEnabled(); + } + + return false; +} + +NzDeferredRenderPass* NzDeferredRenderTechnique::ResetPass(nzRenderPassType renderPass, int position) +{ + std::unique_ptr smartPtr; // Nous évite un leak en cas d'exception + + switch (renderPass) + { + case nzRenderPassType_AA: + smartPtr.reset(new NzDeferredFXAAPass); + break; + + case nzRenderPassType_Bloom: + smartPtr.reset(new NzDeferredBloomPass); + break; + + case nzRenderPassType_DOF: + smartPtr.reset(new NzDeferredDOFPass); + break; + + case nzRenderPassType_Final: + smartPtr.reset(new NzDeferredFinalPass); + break; + + case nzRenderPassType_Fog: + smartPtr.reset(new NzDeferredFogPass); + break; + + case nzRenderPassType_Forward: + smartPtr.reset(new NzDeferredForwardPass); + break; + + case nzRenderPassType_Geometry: + smartPtr.reset(new NzDeferredGeometryPass); + break; + + case nzRenderPassType_Lighting: + smartPtr.reset(new NzDeferredPhongLightingPass); + break; + + case nzRenderPassType_SSAO: + //smartPtr.reset(new NzDeferredSSAOPass); + break; + } + + NzDeferredRenderPass* oldPass = GetPass(renderPass, position); + if (oldPass && !oldPass->IsEnabled()) + smartPtr->Enable(false); + + SetPass(renderPass, position, smartPtr.get()); + return smartPtr.release(); +} + +void NzDeferredRenderTechnique::SetPass(nzRenderPassType relativeTo, int position, NzDeferredRenderPass* pass) +{ + if (pass) + { + pass->Initialize(this); + if (m_GBufferSize != NzVector2ui(0U)) + pass->Resize(m_GBufferSize); + + m_passes[relativeTo][position].reset(pass); + } + else + m_passes[relativeTo].erase(position); } bool NzDeferredRenderTechnique::IsSupported() @@ -1018,320 +348,22 @@ bool NzDeferredRenderTechnique::IsSupported() // On ne va pas s'embêter à écrire un Deferred Renderer qui ne passe pas par le MRT, ce serait lent et inutile (OpenGL 2 garanti cette fonctionnalité en plus) return NzRenderer::HasCapability(nzRendererCap_RenderTexture) && NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets) && - NzRenderer::GetMaxColorAttachments() >= 6 && //FIXME: Repasser à quatre + NzRenderer::GetMaxColorAttachments() >= 4 && NzRenderer::GetMaxRenderTargets() >= 4 && NzTexture::IsFormatSupported(nzPixelFormat_RGBA32F); } -void NzDeferredRenderTechnique::GeomPass(const NzScene* scene) +bool NzDeferredRenderTechnique::Resize(const NzVector2ui& dimensions) const { - NzAbstractViewer* viewer = scene->GetViewer(); - 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 instancing = m_instancingEnabled && renderQueueInstancing; - - // On commence par récupérer le programme du matériau - nzUInt32 flags = nzShaderFlags_Deferred; - if (instancing) - 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& 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 DrawFunc; - std::function 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 (instancing) - { - 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(); - - while (instanceCount > 0) - { - unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount); - instanceCount -= renderedInstanceCount; - - NzBufferMapper mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount); - nzUInt8* ptr = reinterpret_cast(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; - } - } -} - -void NzDeferredRenderTechnique::DirectionalLightPass(const NzScene* scene) -{ - 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(); - } -} - -void NzDeferredRenderTechnique::PointLightPass(const NzScene* scene) -{ - 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)); - 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::SetFaceCulling(nzFaceSide_Front); - NzRenderer::SetStencilCompareFunction(nzRendererComparison_NotEqual, nzFaceSide_Back); - NzRenderer::SetStencilPassOperation(nzStencilOperation_Zero, nzFaceSide_Back); - - NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); - } -} - -void NzDeferredRenderTechnique::SpotLightPass(const NzScene* scene) -{ - 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_sphereMesh->GetIndexBuffer(); - NzRenderer::SetIndexBuffer(indexBuffer); - NzRenderer::SetVertexBuffer(m_sphereMesh->GetVertexBuffer()); - - for (const NzLight* light : m_renderQueue.spotLights) - { - light->Enable(m_spotLightProgram, 0); - NzMatrix4f lightMatrix; - lightMatrix.MakeIdentity(); - lightMatrix.SetScale(NzVector3f(light->GetRadius()*1.1f)); - 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::SetFaceCulling(nzFaceSide_Front); - NzRenderer::SetStencilCompareFunction(nzRendererComparison_NotEqual, nzFaceSide_Back); - NzRenderer::SetStencilPassOperation(nzStencilOperation_Zero, nzFaceSide_Back); - - NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount()); - } -} - -bool NzDeferredRenderTechnique::UpdateTextures() const -{ - /* - 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 = m_GBufferSize.x; - unsigned int height = m_GBufferSize.y; + for (auto& passIt : m_passes) + for (auto& passIt2 : passIt.second) + passIt2.second->Resize(dimensions); - 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_bloomTextureA->Create(nzImageType_2D, nzPixelFormat_RGBA8, width/8, height/8); - m_bloomTextureB->Create(nzImageType_2D, nzPixelFormat_RGBA8, width/8, height/8); - m_dofTextureA->Create(nzImageType_2D, nzPixelFormat_RGB8, width/4, height/4); - m_dofTextureB->Create(nzImageType_2D, nzPixelFormat_RGB8, width/4, height/4); - m_ssaoTextureA->Create(nzImageType_2D, nzPixelFormat_R8, width/4, height/4); - m_ssaoTextureB->Create(nzImageType_2D, nzPixelFormat_R8, width/4, height/4); - m_workTextureA->Create(nzImageType_2D, nzPixelFormat_RGBA8, width, height); - m_workTextureB->Create(nzImageType_2D, nzPixelFormat_RGBA8, width, height); - - m_geometryRTT.Create(true); - - // Texture 0 : Diffuse Color + Flags - m_geometryRTT.AttachTexture(nzAttachmentPoint_Color, 0, m_GBuffer[0]); - - // Texture 1 : Normal map + Depth - m_geometryRTT.AttachTexture(nzAttachmentPoint_Color, 1, m_GBuffer[1]); - - // Texture 2 : Specular value + Shininess - m_geometryRTT.AttachTexture(nzAttachmentPoint_Color, 2, m_GBuffer[2]); - - // Texture 3 : Emission map ? - - // Texture 4 : Target A - m_geometryRTT.AttachTexture(nzAttachmentPoint_Color, 4, m_workTextureA); - - // Texture 5 : Target B - m_geometryRTT.AttachTexture(nzAttachmentPoint_Color, 5, m_workTextureB); - - // Depth/stencil buffer - m_geometryRTT.AttachBuffer(nzAttachmentPoint_DepthStencil, 0, nzPixelFormat_Depth24Stencil8, width, height); - - m_geometryRTT.Unlock(); - - m_bloomRTT.Create(true); - m_bloomRTT.AttachTexture(nzAttachmentPoint_Color, 0, m_bloomTextureA); - m_bloomRTT.AttachTexture(nzAttachmentPoint_Color, 1, m_bloomTextureB); - m_bloomRTT.Unlock(); - - m_dofRTT.Create(true); - m_dofRTT.AttachTexture(nzAttachmentPoint_Color, 0, m_dofTextureA); - m_dofRTT.AttachTexture(nzAttachmentPoint_Color, 1, m_dofTextureB); - m_dofRTT.Unlock(); - - m_ssaoRTT.Create(true); - m_ssaoRTT.AttachTexture(nzAttachmentPoint_Color, 0, m_ssaoTextureA); - m_ssaoRTT.AttachTexture(nzAttachmentPoint_Color, 1, m_ssaoTextureB); - m_ssaoRTT.Unlock(); - - if (!m_bloomRTT.IsComplete() || !m_dofRTT.IsComplete() || !m_geometryRTT.IsComplete() || !m_ssaoRTT.IsComplete()) - { - NazaraError("Incomplete RTT"); - return false; - } - - m_texturesUpdated = true; + m_GBufferSize = dimensions; return true; } @@ -1341,3 +373,8 @@ bool NzDeferredRenderTechnique::UpdateTextures() const return false; } } + +bool NzDeferredRenderTechnique::RenderPassComparator::operator()(nzRenderPassType pass1, nzRenderPassType pass2) +{ + return RenderPassPriority[pass1] < RenderPassPriority[pass2]; +} diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index eeecc6ed4..3746e2a87 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -186,7 +186,8 @@ void NzForwardRenderQueue::AddSubMesh(const NzMaterial* material, const NzSubMes unsigned int instanceCount = staticDataContainer.size() + 1; // Avons-nous suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ? - if (instanceCount >= NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT) + unsigned int tumasoublie = NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT; + if (instanceCount >= 10) enableInstancing = true; // Apparemment oui, activons l'instancing avec ce matériau staticDataContainer.resize(instanceCount); diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 41c34f492..d8102ac98 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -21,7 +21,7 @@ namespace { static NzIndexBuffer* s_indexBuffer = nullptr; - unsigned int maxLightCount = 3; ///TODO: Constante sur le nombre maximum de lumières + unsigned int s_maxLightPerPass = 3; ///TODO: Constante sur le nombre maximum de lumières unsigned int s_maxSprites = 8192; NzIndexBuffer* BuildIndexBuffer() @@ -49,7 +49,7 @@ namespace NzForwardRenderTechnique::NzForwardRenderTechnique() : m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic), -m_maxLightsPerObject(maxLightCount) +m_maxLightPassPerObject(3) { if (!s_indexBuffer) s_indexBuffer = BuildIndexBuffer(); @@ -63,7 +63,7 @@ NzForwardRenderTechnique::~NzForwardRenderTechnique() s_indexBuffer = nullptr; } -void NzForwardRenderTechnique::Clear(const NzScene* scene) +void NzForwardRenderTechnique::Clear(const NzScene* scene) const { NzRenderer::Enable(nzRendererParameter_DepthBuffer, true); NzRenderer::Enable(nzRendererParameter_DepthWrite, true); @@ -74,7 +74,7 @@ void NzForwardRenderTechnique::Clear(const NzScene* scene) background->Draw(scene); } -bool NzForwardRenderTechnique::Draw(const NzScene* scene) +bool NzForwardRenderTechnique::Draw(const NzScene* scene) const { m_directionalLights.SetLights(&m_renderQueue.directionalLights[0], m_renderQueue.directionalLights.size()); m_lights.SetLights(&m_renderQueue.lights[0], m_renderQueue.lights.size()); @@ -141,9 +141,9 @@ bool NzForwardRenderTechnique::Draw(const NzScene* scene) }*/ } -unsigned int NzForwardRenderTechnique::GetMaxLightsPerObject() const +unsigned int NzForwardRenderTechnique::GetMaxLightPassPerObject() const { - return m_maxLightsPerObject; + return m_maxLightPassPerObject; } NzAbstractRenderQueue* NzForwardRenderTechnique::GetRenderQueue() @@ -156,26 +156,16 @@ nzRenderTechniqueType NzForwardRenderTechnique::GetType() const return nzRenderTechniqueType_BasicForward; } -void NzForwardRenderTechnique::SetMaxLightsPerObject(unsigned int lightCount) +void NzForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int passCount) { - #if NAZARA_GRAPHICS_SAFE - if (lightCount > maxLightCount) - { - NazaraError("Light count is over maximum light count (" + NzString::Number(lightCount) + " > " + NzString::Number(lightCount) + ')'); - return; - } - #endif - - m_maxLightsPerObject = lightCount; + m_maxLightPassPerObject = passCount; } -void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) +void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); const NzShaderProgram* lastProgram = nullptr; - unsigned int lightCount = 0; - for (auto& matIt : m_renderQueue.opaqueModels) { bool& used = std::get<0>(matIt.second); @@ -207,11 +197,6 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) // Position de la caméra program->SendVector(program->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition()); - // On envoie les lumières directionnelles s'il y a (Les mêmes pour tous) - lightCount = std::min(m_directionalLights.GetLightCount(), 3U); - for (unsigned int i = 0; i < lightCount; ++i) - m_directionalLights.GetLight(i)->Enable(program, i); - lastProgram = program; } @@ -269,51 +254,110 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) unsigned int stride = instanceBuffer->GetStride(); - const NzForwardRenderQueue::StaticData* data = &staticData[0]; - unsigned int instanceCount = staticData.size(); - unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); + // Avec l'instancing, impossible de sélectionner les lumières pour chaque objet + // Du coup, il n'est activé que pour les lumières directionnelles + unsigned int lightCount = m_directionalLights.GetLightCount(); + unsigned int lightIndex = 0; + nzRendererComparison oldDepthFunc = NzRenderer::GetDepthFunc(); - while (instanceCount > 0) + unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/s_maxLightPerPass + 1; + for (unsigned int pass = 0; pass < passCount; ++pass) { - unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount); - instanceCount -= renderedInstanceCount; + unsigned int renderedLightCount = std::min(lightCount, s_maxLightPerPass); + lightCount -= renderedLightCount; - NzBufferMapper mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount); - nzUInt8* ptr = reinterpret_cast(mapper.GetPointer()); - - for (unsigned int i = 0; i < renderedInstanceCount; ++i) + if (pass == 1) { - std::memcpy(ptr, data->transformMatrix, sizeof(float)*16); - - data++; - ptr += stride; + // Pour additionner le résultat des calculs de lumière + // Aucune chance d'interférer avec les paramètres du matériau car nous ne rendons que les objets opaques + // (Autrement dit, sans blending) + // Quant à la fonction de profondeur, elle ne doit être appliquée que la première fois + NzRenderer::Enable(nzRendererParameter_Blend, true); + NzRenderer::SetBlendFunc(nzBlendFunc_One, nzBlendFunc_One); + NzRenderer::SetDepthFunc(nzRendererComparison_Equal); } - mapper.Unmap(); + for (unsigned int i = 0; i < renderedLightCount; ++i) + m_directionalLights.GetLight(lightIndex++)->Enable(program, i); - InstancedDrawFunc(renderedInstanceCount, primitiveMode, 0, indexCount); + for (unsigned int i = renderedLightCount; i < s_maxLightPerPass; ++i) + NzLight::Disable(program, i); + + const NzForwardRenderQueue::StaticData* data = &staticData[0]; + unsigned int instanceCount = staticData.size(); + unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); + + while (instanceCount > 0) + { + unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount); + instanceCount -= renderedInstanceCount; + + NzBufferMapper mapper(instanceBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedInstanceCount); + nzUInt8* ptr = reinterpret_cast(mapper.GetPointer()); + + for (unsigned int i = 0; i < renderedInstanceCount; ++i) + { + std::memcpy(ptr, data->transformMatrix, sizeof(float)*16); + + data++; + ptr += stride; + } + + mapper.Unmap(); + + InstancedDrawFunc(renderedInstanceCount, primitiveMode, 0, indexCount); + } } + + NzRenderer::Enable(nzRendererParameter_Blend, false); + NzRenderer::SetDepthFunc(oldDepthFunc); } else { - unsigned int originalLightCount = lightCount; for (const NzForwardRenderQueue::StaticData& data : staticData) { - // Calcul des lumières les plus proches - if (lightCount < m_maxLightsPerObject && !m_lights.IsEmpty()) + unsigned int directionalLightCount = m_directionalLights.GetLightCount(); + unsigned int otherLightCount = m_lights.ComputeClosestLights(data.transformMatrix.GetTranslation() + boundingSphere.GetPosition(), boundingSphere.radius, m_maxLightPassPerObject*s_maxLightPerPass - directionalLightCount); + unsigned int lightCount = directionalLightCount + otherLightCount; + + NzRenderer::SetMatrix(nzMatrixType_World, data.transformMatrix); + unsigned int directionalLightIndex = 0; + unsigned int otherLightIndex = 0; + nzRendererComparison oldDepthFunc = NzRenderer::GetDepthFunc(); + + unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/s_maxLightPerPass + 1; + for (unsigned int pass = 0; pass < passCount; ++pass) { - unsigned int count = std::min(m_maxLightsPerObject-lightCount, m_lights.ComputeClosestLights(data.transformMatrix.GetTranslation() + boundingSphere.GetPosition(), boundingSphere.radius, maxLightCount)); - for (unsigned int i = 0; i < count; ++i) - m_lights.GetResult(i)->Enable(program, lightCount++); + unsigned int renderedLightCount = std::min(lightCount, s_maxLightPerPass); + lightCount -= renderedLightCount; + + if (pass == 1) + { + // Pour additionner le résultat des calculs de lumière + // Aucune chance d'interférer avec les paramètres du matériau car nous ne rendons que les objets opaques + // (Autrement dit, sans blending) + // Quant à la fonction de profondeur, elle ne doit être appliquée que la première fois + NzRenderer::Enable(nzRendererParameter_Blend, true); + NzRenderer::SetBlendFunc(nzBlendFunc_One, nzBlendFunc_One); + NzRenderer::SetDepthFunc(nzRendererComparison_Equal); + } + + for (unsigned int i = 0; i < renderedLightCount; ++i) + { + if (directionalLightIndex >= directionalLightCount) + m_lights.GetResult(otherLightIndex++)->Enable(program, i); + else + m_directionalLights.GetLight(directionalLightIndex++)->Enable(program, i); + } + + for (unsigned int i = renderedLightCount; i < s_maxLightPerPass; ++i) + NzLight::Disable(program, i); + + DrawFunc(primitiveMode, 0, indexCount); } - for (unsigned int i = lightCount; i < maxLightCount; ++i) - NzLight::Disable(program, i); - - NzRenderer::SetMatrix(nzMatrixType_World, data.transformMatrix); - DrawFunc(primitiveMode, 0, indexCount); - - lightCount = originalLightCount; + NzRenderer::Enable(nzRendererParameter_Blend, false); + NzRenderer::SetDepthFunc(oldDepthFunc); } } staticData.clear(); @@ -328,7 +372,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) } } -void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) +void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); const NzShaderProgram* lastProgram = nullptr; @@ -408,7 +452,7 @@ void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) } } -void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) +void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const { NzAbstractViewer* viewer = scene->GetViewer(); const NzShaderProgram* lastProgram = nullptr; @@ -474,14 +518,14 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) NzRenderer::SetVertexBuffer(vertexBuffer); // Calcul des lumières les plus proches - if (lightCount < m_maxLightsPerObject && !m_lights.IsEmpty()) + if (lightCount < s_maxLightPerPass && !m_lights.IsEmpty()) { - unsigned int count = std::min(m_maxLightsPerObject-lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + staticModel.boundingSphere.GetPosition(), staticModel.boundingSphere.radius, maxLightCount)); + unsigned int count = std::min(s_maxLightPerPass - lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + staticModel.boundingSphere.GetPosition(), staticModel.boundingSphere.radius, s_maxLightPerPass)); for (unsigned int i = 0; i < count; ++i) m_lights.GetResult(i)->Enable(program, lightCount++); } - for (unsigned int i = lightCount; i < maxLightCount; ++i) + for (unsigned int i = lightCount; i < s_maxLightPerPass; ++i) NzLight::Disable(program, i); NzRenderer::SetMatrix(nzMatrixType_World, matrix); diff --git a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag index e7aa5d043..372b421a5 100644 --- a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag +++ b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag @@ -29,11 +29,11 @@ void main() { vec2 texCoord = gl_FragCoord.xy * InvTargetSize; vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0); - if (gVec0.w == 0.0) +/* if (gVec0.w == 0.0) { RenderTarget0 = vec4(gVec0.xyz, 1.0); return; - } + }*/ vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0); vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0); diff --git a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag.h b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag.h index de8e63c78..ae8c7784c 100644 --- a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag.h +++ b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag.h @@ -1 +1 @@ -35,118,101,114,115,105,111,110,32,49,52,48,13,10,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,97,109,98,105,101,110,116,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,49,93,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,48,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,49,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,50,59,13,10,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,9,118,101,99,52,32,103,86,101,99,48,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,48,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,9,105,102,32,40,103,86,101,99,48,46,119,32,61,61,32,48,46,48,41,13,10,9,123,13,10,9,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,103,86,101,99,48,46,120,121,122,44,32,49,46,48,41,59,13,10,9,9,114,101,116,117,114,110,59,13,10,9,125,13,10,13,10,9,118,101,99,52,32,103,86,101,99,49,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,49,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,9,118,101,99,52,32,103,86,101,99,50,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,50,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,103,86,101,99,48,46,120,121,122,59,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,103,86,101,99,49,46,120,121,122,42,50,46,48,32,45,32,49,46,48,59,13,10,9,118,101,99,51,32,115,112,101,99,117,108,97,114,67,111,108,111,114,32,61,32,103,86,101,99,50,46,120,121,122,59,13,10,9,102,108,111,97,116,32,100,101,112,116,104,32,61,32,103,86,101,99,49,46,119,42,50,46,48,32,45,32,49,46,48,59,13,10,9,102,108,111,97,116,32,115,104,105,110,105,110,101,115,115,32,61,32,40,103,86,101,99,50,46,119,32,61,61,32,48,46,48,41,32,63,32,48,46,48,32,58,32,101,120,112,50,40,103,86,101,99,50,46,119,42,49,48,46,53,41,59,13,10,13,10,9,118,101,99,51,32,118,105,101,119,83,112,97,99,101,32,61,32,118,101,99,51,40,116,101,120,67,111,111,114,100,42,50,46,48,32,45,32,49,46,48,44,32,100,101,112,116,104,41,59,13,10,13,10,9,118,101,99,52,32,119,111,114,108,100,80,111,115,32,61,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,105,101,119,83,112,97,99,101,44,32,49,46,48,41,59,13,10,9,119,111,114,108,100,80,111,115,46,120,121,122,32,47,61,32,119,111,114,108,100,80,111,115,46,119,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,59,13,10,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,13,10,13,10,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,47,47,32,65,109,98,105,101,110,116,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,118,101,99,51,40,49,46,48,41,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,47,47,32,68,105,102,102,117,115,101,13,10,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,105,102,32,40,115,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,41,59,13,10,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,115,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,115,112,101,99,117,108,97,114,67,111,108,111,114,59,13,10,13,10,9,118,101,99,51,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,32,42,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,102,114,97,103,109,101,110,116,67,111,108,111,114,44,32,49,46,48,41,59,13,10,125, \ No newline at end of file +35,118,101,114,115,105,111,110,32,49,52,48,13,10,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,97,109,98,105,101,110,116,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,49,93,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,48,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,49,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,50,59,13,10,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,9,118,101,99,52,32,103,86,101,99,48,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,48,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,47,42,9,105,102,32,40,103,86,101,99,48,46,119,32,61,61,32,48,46,48,41,13,10,9,123,13,10,9,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,103,86,101,99,48,46,120,121,122,44,32,49,46,48,41,59,13,10,9,9,114,101,116,117,114,110,59,13,10,9,125,42,47,13,10,13,10,9,118,101,99,52,32,103,86,101,99,49,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,49,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,9,118,101,99,52,32,103,86,101,99,50,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,50,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,103,86,101,99,48,46,120,121,122,59,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,103,86,101,99,49,46,120,121,122,42,50,46,48,32,45,32,49,46,48,59,13,10,9,118,101,99,51,32,115,112,101,99,117,108,97,114,67,111,108,111,114,32,61,32,103,86,101,99,50,46,120,121,122,59,13,10,9,102,108,111,97,116,32,100,101,112,116,104,32,61,32,103,86,101,99,49,46,119,42,50,46,48,32,45,32,49,46,48,59,13,10,9,102,108,111,97,116,32,115,104,105,110,105,110,101,115,115,32,61,32,40,103,86,101,99,50,46,119,32,61,61,32,48,46,48,41,32,63,32,48,46,48,32,58,32,101,120,112,50,40,103,86,101,99,50,46,119,42,49,48,46,53,41,59,13,10,13,10,9,118,101,99,51,32,118,105,101,119,83,112,97,99,101,32,61,32,118,101,99,51,40,116,101,120,67,111,111,114,100,42,50,46,48,32,45,32,49,46,48,44,32,100,101,112,116,104,41,59,13,10,13,10,9,118,101,99,52,32,119,111,114,108,100,80,111,115,32,61,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,105,101,119,83,112,97,99,101,44,32,49,46,48,41,59,13,10,9,119,111,114,108,100,80,111,115,46,120,121,122,32,47,61,32,119,111,114,108,100,80,111,115,46,119,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,59,13,10,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,13,10,13,10,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,47,47,32,65,109,98,105,101,110,116,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,118,101,99,51,40,49,46,48,41,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,47,47,32,68,105,102,102,117,115,101,13,10,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,105,102,32,40,115,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,41,59,13,10,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,115,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,115,112,101,99,117,108,97,114,67,111,108,111,114,59,13,10,13,10,9,118,101,99,51,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,32,42,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,102,114,97,103,109,101,110,116,67,111,108,111,114,44,32,49,46,48,41,59,13,10,125, \ No newline at end of file diff --git a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag index ffc7cc57f..dc9fdbc27 100644 --- a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag +++ b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag @@ -29,11 +29,11 @@ void main() { vec2 texCoord = gl_FragCoord.xy * InvTargetSize; vec4 gVec0 = textureLod(GBuffer0, texCoord, 0.0); - if (gVec0.w == 0.0) +/* if (gVec0.w == 0.0) { RenderTarget0 = vec4(gVec0.xyz, 1.0); return; - } + }*/ vec4 gVec1 = textureLod(GBuffer1, texCoord, 0.0); vec4 gVec2 = textureLod(GBuffer2, texCoord, 0.0); diff --git a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag.h b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag.h index 8967be414..acaa928f5 100644 --- a/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag.h +++ b/src/Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag.h @@ -1 +1 @@ -35,118,101,114,115,105,111,110,32,49,52,48,13,10,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,97,109,98,105,101,110,116,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,49,93,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,48,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,49,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,50,59,13,10,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,9,118,101,99,52,32,103,86,101,99,48,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,48,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,9,105,102,32,40,103,86,101,99,48,46,119,32,61,61,32,48,46,48,41,13,10,9,123,13,10,9,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,103,86,101,99,48,46,120,121,122,44,32,49,46,48,41,59,13,10,9,9,114,101,116,117,114,110,59,13,10,9,125,13,10,13,10,9,118,101,99,52,32,103,86,101,99,49,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,49,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,9,118,101,99,52,32,103,86,101,99,50,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,50,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,103,86,101,99,48,46,120,121,122,59,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,103,86,101,99,49,46,120,121,122,42,50,46,48,32,45,32,49,46,48,59,13,10,9,118,101,99,51,32,115,112,101,99,117,108,97,114,67,111,108,111,114,32,61,32,103,86,101,99,50,46,120,121,122,59,13,10,9,102,108,111,97,116,32,100,101,112,116,104,32,61,32,103,86,101,99,49,46,119,42,50,46,48,32,45,32,49,46,48,59,13,10,9,102,108,111,97,116,32,115,104,105,110,105,110,101,115,115,32,61,32,40,103,86,101,99,50,46,119,32,61,61,32,48,46,48,41,32,63,32,48,46,48,32,58,32,101,120,112,50,40,103,86,101,99,50,46,119,42,49,48,46,53,41,59,13,10,13,10,9,118,101,99,51,32,118,105,101,119,83,112,97,99,101,32,61,32,118,101,99,51,40,116,101,120,67,111,111,114,100,42,50,46,48,32,45,32,49,46,48,44,32,100,101,112,116,104,41,59,13,10,13,10,9,118,101,99,52,32,119,111,114,108,100,80,111,115,32,61,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,105,101,119,83,112,97,99,101,44,32,49,46,48,41,59,13,10,9,119,111,114,108,100,80,111,115,46,120,121,122,32,47,61,32,119,111,114,108,100,80,111,115,46,119,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,59,13,10,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,13,10,13,10,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,47,47,32,65,109,98,105,101,110,116,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,118,101,99,51,40,49,46,48,41,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,47,47,32,68,105,102,102,117,115,101,13,10,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,105,102,32,40,115,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,41,59,13,10,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,115,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,115,112,101,99,117,108,97,114,67,111,108,111,114,59,13,10,13,10,9,118,101,99,51,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,32,42,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,102,114,97,103,109,101,110,116,67,111,108,111,114,44,32,49,46,48,41,59,13,10,125, \ No newline at end of file +35,118,101,114,115,105,111,110,32,49,52,48,13,10,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,115,116,114,117,99,116,32,76,105,103,104,116,13,10,123,13,10,9,105,110,116,32,116,121,112,101,59,13,10,9,118,101,99,52,32,97,109,98,105,101,110,116,59,13,10,9,118,101,99,52,32,99,111,108,111,114,59,13,10,9,118,101,99,50,32,102,97,99,116,111,114,115,59,13,10,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,49,59,13,10,9,118,101,99,52,32,112,97,114,97,109,101,116,101,114,115,50,59,13,10,9,118,101,99,50,32,112,97,114,97,109,101,116,101,114,115,51,59,13,10,125,59,13,10,13,10,117,110,105,102,111,114,109,32,118,101,99,51,32,69,121,101,80,111,115,105,116,105,111,110,59,13,10,117,110,105,102,111,114,109,32,76,105,103,104,116,32,76,105,103,104,116,115,91,49,93,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,48,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,49,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,71,66,117,102,102,101,114,50,59,13,10,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,83,99,101,110,101,65,109,98,105,101,110,116,59,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,9,118,101,99,52,32,103,86,101,99,48,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,48,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,47,42,9,105,102,32,40,103,86,101,99,48,46,119,32,61,61,32,48,46,48,41,13,10,9,123,13,10,9,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,103,86,101,99,48,46,120,121,122,44,32,49,46,48,41,59,13,10,9,9,114,101,116,117,114,110,59,13,10,9,125,42,47,13,10,13,10,9,118,101,99,52,32,103,86,101,99,49,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,49,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,9,118,101,99,52,32,103,86,101,99,50,32,61,32,116,101,120,116,117,114,101,76,111,100,40,71,66,117,102,102,101,114,50,44,32,116,101,120,67,111,111,114,100,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,100,105,102,102,117,115,101,67,111,108,111,114,32,61,32,103,86,101,99,48,46,120,121,122,59,13,10,9,118,101,99,51,32,110,111,114,109,97,108,32,61,32,103,86,101,99,49,46,120,121,122,42,50,46,48,32,45,32,49,46,48,59,13,10,9,118,101,99,51,32,115,112,101,99,117,108,97,114,67,111,108,111,114,32,61,32,103,86,101,99,50,46,120,121,122,59,13,10,9,102,108,111,97,116,32,100,101,112,116,104,32,61,32,103,86,101,99,49,46,119,42,50,46,48,32,45,32,49,46,48,59,13,10,9,102,108,111,97,116,32,115,104,105,110,105,110,101,115,115,32,61,32,40,103,86,101,99,50,46,119,32,61,61,32,48,46,48,41,32,63,32,48,46,48,32,58,32,101,120,112,50,40,103,86,101,99,50,46,119,42,49,48,46,53,41,59,13,10,13,10,9,118,101,99,51,32,118,105,101,119,83,112,97,99,101,32,61,32,118,101,99,51,40,116,101,120,67,111,111,114,100,42,50,46,48,32,45,32,49,46,48,44,32,100,101,112,116,104,41,59,13,10,13,10,9,118,101,99,52,32,119,111,114,108,100,80,111,115,32,61,32,73,110,118,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,118,105,101,119,83,112,97,99,101,44,32,49,46,48,41,59,13,10,9,119,111,114,108,100,80,111,115,46,120,121,122,32,47,61,32,119,111,114,108,100,80,111,115,46,119,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,114,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,120,121,122,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,59,13,10,9,102,108,111,97,116,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,32,61,32,108,101,110,103,116,104,40,108,105,103,104,116,68,105,114,41,59,13,10,9,108,105,103,104,116,68,105,114,32,47,61,32,108,105,103,104,116,68,105,114,76,101,110,103,116,104,59,13,10,13,10,9,102,108,111,97,116,32,97,116,116,32,61,32,109,97,120,40,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,49,46,119,32,45,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,50,46,119,42,108,105,103,104,116,68,105,114,76,101,110,103,116,104,44,32,48,46,48,41,59,13,10,13,10,9,47,47,32,65,109,98,105,101,110,116,13,10,9,118,101,99,51,32,108,105,103,104,116,65,109,98,105,101,110,116,32,61,32,97,116,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,120,32,42,32,40,118,101,99,51,40,49,46,48,41,32,43,32,83,99,101,110,101,65,109,98,105,101,110,116,46,114,103,98,41,59,13,10,13,10,9,47,47,32,77,111,100,105,102,105,99,97,116,105,111,110,32,100,101,32,108,39,97,116,116,195,169,110,117,97,116,105,111,110,32,112,111,117,114,32,103,195,169,114,101,114,32,108,101,32,115,112,111,116,13,10,9,102,108,111,97,116,32,99,117,114,65,110,103,108,101,32,61,32,100,111,116,40,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,50,46,120,121,122,44,32,45,108,105,103,104,116,68,105,114,41,59,13,10,9,102,108,111,97,116,32,111,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,51,46,121,59,13,10,9,102,108,111,97,116,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,32,61,32,76,105,103,104,116,115,91,48,93,46,112,97,114,97,109,101,116,101,114,115,51,46,120,32,45,32,111,117,116,101,114,65,110,103,108,101,59,13,10,9,97,116,116,32,42,61,32,109,97,120,40,40,99,117,114,65,110,103,108,101,32,45,32,111,117,116,101,114,65,110,103,108,101,41,32,47,32,105,110,110,101,114,77,105,110,117,115,79,117,116,101,114,65,110,103,108,101,44,32,48,46,48,41,59,13,10,13,10,9,47,47,32,68,105,102,102,117,115,101,13,10,9,102,108,111,97,116,32,108,97,109,98,101,114,116,32,61,32,109,97,120,40,100,111,116,40,110,111,114,109,97,108,44,32,108,105,103,104,116,68,105,114,41,44,32,48,46,48,41,59,13,10,13,10,9,118,101,99,51,32,108,105,103,104,116,68,105,102,102,117,115,101,32,61,32,97,116,116,32,42,32,108,97,109,98,101,114,116,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,32,42,32,76,105,103,104,116,115,91,48,93,46,102,97,99,116,111,114,115,46,121,59,13,10,13,10,9,47,47,32,83,112,101,99,117,108,97,114,13,10,9,118,101,99,51,32,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,118,101,99,51,40,48,46,48,41,59,13,10,9,105,102,32,40,115,104,105,110,105,110,101,115,115,32,62,32,48,46,48,41,13,10,9,123,13,10,9,9,118,101,99,51,32,101,121,101,86,101,99,32,61,32,110,111,114,109,97,108,105,122,101,40,69,121,101,80,111,115,105,116,105,111,110,32,45,32,119,111,114,108,100,80,111,115,46,120,121,122,41,59,13,10,9,9,118,101,99,51,32,114,101,102,108,101,99,116,105,111,110,32,61,32,114,101,102,108,101,99,116,40,45,108,105,103,104,116,68,105,114,44,32,110,111,114,109,97,108,41,59,13,10,9,9,102,108,111,97,116,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,109,97,120,40,100,111,116,40,114,101,102,108,101,99,116,105,111,110,44,32,101,121,101,86,101,99,41,44,32,48,46,48,41,59,13,10,9,9,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,61,32,112,111,119,40,115,112,101,99,117,108,97,114,70,97,99,116,111,114,44,32,115,104,105,110,105,110,101,115,115,41,59,13,10,13,10,9,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,61,32,97,116,116,32,42,32,115,112,101,99,117,108,97,114,70,97,99,116,111,114,32,42,32,76,105,103,104,116,115,91,48,93,46,99,111,108,111,114,46,114,103,98,59,13,10,9,125,13,10,13,10,9,108,105,103,104,116,83,112,101,99,117,108,97,114,32,42,61,32,115,112,101,99,117,108,97,114,67,111,108,111,114,59,13,10,13,10,9,118,101,99,51,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,100,105,102,102,117,115,101,67,111,108,111,114,32,42,32,40,108,105,103,104,116,65,109,98,105,101,110,116,32,43,32,108,105,103,104,116,68,105,102,102,117,115,101,32,43,32,108,105,103,104,116,83,112,101,99,117,108,97,114,41,59,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,118,101,99,52,40,102,114,97,103,109,101,110,116,67,111,108,111,114,44,32,49,46,48,41,59,13,10,125, \ No newline at end of file