Reunited Deferred Point Shader and Spot Shader
Former-commit-id: 0a77f57d8af98387690748102f6cdcea5d5514ed
This commit is contained in:
parent
16578e728f
commit
cbce6e6e64
|
|
@ -31,12 +31,13 @@ class NAZARA_API NzDeferredPhongLightingPass : public NzDeferredRenderPass
|
|||
NzMeshRef m_cone;
|
||||
NzMeshRef m_sphere;
|
||||
NzShaderProgramRef m_directionalLightProgram;
|
||||
NzShaderProgramRef m_pointLightProgram;
|
||||
NzShaderProgramRef m_spotLightProgram;
|
||||
NzShaderProgramRef m_pointSpotLightProgram;
|
||||
NzTextureSampler m_pointSampler;
|
||||
NzStaticMesh* m_coneMesh;
|
||||
NzStaticMesh* m_sphereMesh;
|
||||
bool m_lightMeshesDrawing;
|
||||
int m_pointSpotLightProgramDiscardLocation;
|
||||
int m_pointSpotLightProgramSpotLightLocation;
|
||||
};
|
||||
|
||||
#endif // NAZARA_DEFERREDPHONGLIGHTINGPASS_HPP
|
||||
|
|
|
|||
|
|
@ -62,57 +62,10 @@ namespace
|
|||
return program.release();
|
||||
}
|
||||
|
||||
NzShaderProgram* BuildPointLightProgram()
|
||||
NzShaderProgram* BuildPointSpotLightProgram()
|
||||
{
|
||||
const nzUInt8 fragmentSource[] = {
|
||||
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/PointLight.frag.h>
|
||||
};
|
||||
|
||||
const char* vertexSource =
|
||||
"#version 140\n"
|
||||
|
||||
"in vec3 VertexPosition;\n"
|
||||
|
||||
"uniform mat4 WorldViewProjMatrix;\n"
|
||||
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"\t" "gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);" "\n"
|
||||
"}\n";
|
||||
|
||||
///TODO: Remplacer ça par des ShaderNode
|
||||
std::unique_ptr<NzShaderProgram> program(new NzShaderProgram(nzShaderLanguage_GLSL));
|
||||
program->SetPersistent(false);
|
||||
|
||||
if (!program->LoadShader(nzShaderType_Fragment, NzString(reinterpret_cast<const char*>(fragmentSource), sizeof(fragmentSource))))
|
||||
{
|
||||
NazaraError("Failed to load fragment shader");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!program->LoadShader(nzShaderType_Vertex, vertexSource))
|
||||
{
|
||||
NazaraError("Failed to load vertex shader");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!program->Compile())
|
||||
{
|
||||
NazaraError("Failed to compile program");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
program->SendInteger(program->GetUniformLocation("GBuffer0"), 0);
|
||||
program->SendInteger(program->GetUniformLocation("GBuffer1"), 1);
|
||||
program->SendInteger(program->GetUniformLocation("GBuffer2"), 2);
|
||||
|
||||
return program.release();
|
||||
}
|
||||
|
||||
NzShaderProgram* BuildSpotLightProgram()
|
||||
{
|
||||
const nzUInt8 fragmentSource[] = {
|
||||
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/SpotLight.frag.h>
|
||||
#include <Nazara/Graphics/Resources/DeferredShading/Shaders/PointSpotLight.frag.h>
|
||||
};
|
||||
|
||||
const char* vertexSource =
|
||||
|
|
@ -161,8 +114,10 @@ NzDeferredPhongLightingPass::NzDeferredPhongLightingPass() :
|
|||
m_lightMeshesDrawing(false)
|
||||
{
|
||||
m_directionalLightProgram = BuildDirectionalLightProgram();
|
||||
m_pointLightProgram = BuildPointLightProgram();
|
||||
m_spotLightProgram = BuildSpotLightProgram();
|
||||
m_pointSpotLightProgram = BuildPointSpotLightProgram();
|
||||
|
||||
m_pointSpotLightProgramDiscardLocation = m_pointSpotLightProgram->GetUniformLocation("Discard");
|
||||
m_pointSpotLightProgramSpotLightLocation = m_pointSpotLightProgram->GetUniformLocation("SpotLight");
|
||||
|
||||
m_pointSampler.SetAnisotropyLevel(1);
|
||||
m_pointSampler.SetFilterMode(nzSamplerFilter_Nearest);
|
||||
|
|
@ -252,21 +207,23 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir
|
|||
|
||||
NzRenderer::SetRenderStates(lightStates);
|
||||
|
||||
NzRenderer::SetShaderProgram(m_pointSpotLightProgram);
|
||||
m_pointSpotLightProgram->SendColor(m_pointSpotLightProgram->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
|
||||
m_pointSpotLightProgram->SendVector(m_pointSpotLightProgram->GetUniformLocation(nzShaderUniform_EyePosition), scene->GetViewer()->GetEyePosition());
|
||||
|
||||
NzMatrix4f lightMatrix;
|
||||
lightMatrix.MakeIdentity();
|
||||
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());
|
||||
m_pointSpotLightProgram->SendBoolean(m_pointSpotLightProgramSpotLightLocation, false);
|
||||
|
||||
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);
|
||||
light->Enable(m_pointSpotLightProgram, 0);
|
||||
lightMatrix.SetScale(NzVector3f(light->GetRadius()*1.1f)); // Pour corriger les imperfections liées à la sphère
|
||||
lightMatrix.SetTranslation(light->GetPosition());
|
||||
|
||||
|
|
@ -278,6 +235,8 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir
|
|||
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
|
||||
NzRenderer::SetStencilCompareFunction(nzRendererComparison_Always);
|
||||
|
||||
m_pointSpotLightProgram->SendBoolean(m_pointSpotLightProgramDiscardLocation, true);
|
||||
|
||||
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
|
||||
|
||||
// Rendu de la sphère comme zone d'effet
|
||||
|
|
@ -287,6 +246,8 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir
|
|||
NzRenderer::SetStencilCompareFunction(nzRendererComparison_NotEqual, nzFaceSide_Back);
|
||||
NzRenderer::SetStencilPassOperation(nzStencilOperation_Zero, nzFaceSide_Back);
|
||||
|
||||
m_pointSpotLightProgram->SendBoolean(m_pointSpotLightProgramDiscardLocation, false);
|
||||
|
||||
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
|
||||
}
|
||||
|
||||
|
|
@ -334,19 +295,15 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir
|
|||
|
||||
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());
|
||||
m_pointSpotLightProgram->SendBoolean(m_pointSpotLightProgramSpotLightLocation, true);
|
||||
|
||||
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);
|
||||
light->Enable(m_pointSpotLightProgram, 0);
|
||||
float radius = light->GetRadius()*std::tan(NzDegreeToRadian(light->GetOuterAngle()))*1.1f;
|
||||
lightMatrix.MakeTransform(light->GetPosition(), light->GetRotation(), NzVector3f(radius, radius, light->GetRadius()));
|
||||
|
||||
|
|
@ -358,6 +315,8 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir
|
|||
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
|
||||
NzRenderer::SetStencilCompareFunction(nzRendererComparison_Always);
|
||||
|
||||
m_pointSpotLightProgram->SendBoolean(m_pointSpotLightProgramDiscardLocation, true);
|
||||
|
||||
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
|
||||
|
||||
// Rendu de la sphère comme zone d'effet
|
||||
|
|
@ -368,6 +327,8 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir
|
|||
NzRenderer::SetStencilCompareFunction(nzRendererComparison_NotEqual, nzFaceSide_Back);
|
||||
NzRenderer::SetStencilPassOperation(nzStencilOperation_Zero, nzFaceSide_Back);
|
||||
|
||||
m_pointSpotLightProgram->SendBoolean(m_pointSpotLightProgramDiscardLocation, false);
|
||||
|
||||
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
|
||||
}
|
||||
|
||||
|
|
@ -418,4 +379,3 @@ bool NzDeferredPhongLightingPass::Process(const NzScene* scene, unsigned int fir
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ void NzLight::Enable(const NzShaderProgram* program, unsigned int lightUnit) con
|
|||
|
||||
Point
|
||||
-P1: vec3 position + float attenuation
|
||||
-P2: float invRadius
|
||||
-P2: vec3 NON-USED + float invRadius
|
||||
|
||||
Spot
|
||||
-P1: vec3 position + float attenuation
|
||||
|
|
@ -112,7 +112,7 @@ void NzLight::Enable(const NzShaderProgram* program, unsigned int lightUnit) con
|
|||
|
||||
case nzLightType_Point:
|
||||
program->SendVector(parameters1Location, NzVector4f(m_derivedPosition, m_attenuation));
|
||||
program->SendVector(parameters2Location, NzVector4f(1.f/m_radius, 0.f, 0.f, 0.f));
|
||||
program->SendVector(parameters2Location, NzVector4f(0.f, 0.f, 0.f, 1.f/m_radius));
|
||||
break;
|
||||
|
||||
case nzLightType_Spot:
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
#version 140
|
||||
|
||||
out vec4 RenderTarget0;
|
||||
|
||||
struct Light
|
||||
{
|
||||
int type;
|
||||
vec4 ambient;
|
||||
vec4 color;
|
||||
vec2 factors;
|
||||
|
||||
vec4 parameters1;
|
||||
vec4 parameters2;
|
||||
vec2 parameters3;
|
||||
};
|
||||
|
||||
uniform vec3 EyePosition;
|
||||
uniform Light Lights[1];
|
||||
|
||||
uniform sampler2D GBuffer0;
|
||||
uniform sampler2D GBuffer1;
|
||||
uniform sampler2D GBuffer2;
|
||||
|
||||
uniform mat4 InvViewProjMatrix;
|
||||
uniform vec2 InvTargetSize;
|
||||
uniform vec4 SceneAmbient;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
|
||||
vec4 gVec0 = textureLod(GBuffer0, texCoord, 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);
|
||||
|
||||
vec3 diffuseColor = gVec0.xyz;
|
||||
vec3 normal = gVec1.xyz*2.0 - 1.0;
|
||||
vec3 specularColor = gVec2.xyz;
|
||||
float depth = gVec1.w*2.0 - 1.0;
|
||||
float shininess = (gVec2.w == 0.0) ? 0.0 : exp2(gVec2.w*10.5);
|
||||
|
||||
vec3 viewSpace = vec3(texCoord*2.0 - 1.0, depth);
|
||||
|
||||
vec4 worldPos = InvViewProjMatrix * vec4(viewSpace, 1.0);
|
||||
worldPos.xyz /= worldPos.w;
|
||||
|
||||
vec3 lightDir = Lights[0].parameters1.xyz - worldPos.xyz;
|
||||
float lightDirLength = length(lightDir);
|
||||
lightDir /= lightDirLength;
|
||||
|
||||
float att = max(Lights[0].parameters1.w - Lights[0].parameters2.x*lightDirLength, 0.0);
|
||||
|
||||
// Ambient
|
||||
vec3 lightAmbient = att * Lights[0].color.rgb * Lights[0].factors.x * (vec3(1.0) + SceneAmbient.rgb);
|
||||
|
||||
// Diffuse
|
||||
float lambert = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
vec3 lightDiffuse = att * lambert * Lights[0].color.rgb * Lights[0].factors.y;
|
||||
|
||||
// Specular
|
||||
vec3 lightSpecular = vec3(0.0);
|
||||
if (shininess > 0.0)
|
||||
{
|
||||
vec3 eyeVec = normalize(EyePosition - worldPos.xyz);
|
||||
vec3 reflection = reflect(-lightDir, normal);
|
||||
float specularFactor = max(dot(reflection, eyeVec), 0.0);
|
||||
specularFactor = pow(specularFactor, shininess);
|
||||
|
||||
lightSpecular = att * specularFactor * Lights[0].color.rgb;
|
||||
}
|
||||
|
||||
lightSpecular *= specularColor;
|
||||
|
||||
vec3 fragmentColor = diffuseColor * (lightAmbient + lightDiffuse + lightSpecular);
|
||||
RenderTarget0 = vec4(fragmentColor, 1.0);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -25,15 +25,21 @@ uniform mat4 InvViewProjMatrix;
|
|||
uniform vec2 InvTargetSize;
|
||||
uniform vec4 SceneAmbient;
|
||||
|
||||
uniform bool Discard = false;
|
||||
uniform bool SpotLight;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (Discard)
|
||||
return;
|
||||
|
||||
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);
|
||||
|
|
@ -58,12 +64,15 @@ void main()
|
|||
// Ambient
|
||||
vec3 lightAmbient = att * Lights[0].color.rgb * Lights[0].factors.x * (vec3(1.0) + SceneAmbient.rgb);
|
||||
|
||||
// Modification de l'atténuation pour gérer le spot
|
||||
float curAngle = dot(Lights[0].parameters2.xyz, -lightDir);
|
||||
float outerAngle = Lights[0].parameters3.y;
|
||||
float innerMinusOuterAngle = Lights[0].parameters3.x - outerAngle;
|
||||
att *= max((curAngle - outerAngle) / innerMinusOuterAngle, 0.0);
|
||||
|
||||
if (SpotLight)
|
||||
{
|
||||
// Modification de l'atténuation pour gérer le spot
|
||||
float curAngle = dot(Lights[0].parameters2.xyz, -lightDir);
|
||||
float outerAngle = Lights[0].parameters3.y;
|
||||
float innerMinusOuterAngle = Lights[0].parameters3.x - outerAngle;
|
||||
att *= max((curAngle - outerAngle) / innerMinusOuterAngle, 0.0);
|
||||
}
|
||||
|
||||
// Diffuse
|
||||
float lambert = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue