diff --git a/Assets/BuiltIn/Shader/SSR/HLSL/LibSSR.hlsl b/Assets/BuiltIn/Shader/SSR/HLSL/LibSSR.hlsl
new file mode 100644
index 000000000..fbaf8c7fd
--- /dev/null
+++ b/Assets/BuiltIn/Shader/SSR/HLSL/LibSSR.hlsl
@@ -0,0 +1,80 @@
+#define LENGTH 20.0
+
+float3 SSR(const float3 position, const float3 reflection, const float roughness)
+{
+ float4 projectedCoord;
+
+ float3 beginPosition;
+ float3 endPosition;
+
+ float3 rayPosition = position;
+ float4 viewPosition;
+
+ float3 dir = reflection * LENGTH;
+
+ float mipLevel = roughness * 7.0;
+
+ // base color
+ // convert 3d position to 2d texture coord
+ viewPosition = mul(float4(position, 1.0), uView);
+ projectedCoord = mul(float4(viewPosition.xyz, 1.0), uProjection);
+ projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
+ projectedCoord.xy = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);
+
+ // default reflect color is from position
+ float3 baseColor = uTexLastFrame.SampleLevel(uTexLastFrameSampler, projectedCoord.xy, mipLevel).rgb;
+
+ // ray test
+ for (int i = 6; i >= 0; --i)
+ {
+ // begin ray
+ beginPosition = rayPosition;
+
+ // end ray
+ endPosition = rayPosition + dir;
+
+ // mid ray
+ rayPosition += dir * 0.5;
+
+ // convert 3d position to 2d texture coord
+ viewPosition = mul(float4(rayPosition, 1.0), uView);
+ projectedCoord = mul(float4(viewPosition.xyz, 1.0), uProjection);
+ projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
+ projectedCoord.xy = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);
+
+ float3 testPosition = uTexPosition.Sample(uTexPositionSampler, projectedCoord.xy).xyz;
+
+ float3 d1 = testPosition - beginPosition;
+ float lengthSQ1 = d1.x*d1.x + d1.y*d1.y + d1.z*d1.z;
+
+ float3 d2 = testPosition - endPosition;
+ float lengthSQ2 = d2.x*d2.x + d2.y*d2.y + d2.z*d2.z;
+
+ // beginPosition is nearer
+ if (lengthSQ1 < lengthSQ2)
+ {
+ rayPosition = beginPosition;
+ }
+
+ // binary search test
+ dir *= 0.5;
+ }
+
+ float z = mul(float4(reflection, 0.0), uView).z;
+ z = clamp(z, 0.0, 1.0);
+
+ // convert 3d position to 2d texture coord
+ viewPosition = mul(float4(rayPosition, 1.0), uView);
+ projectedCoord = mul(float4(viewPosition.xyz, 1.0), uProjection);
+ projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
+ projectedCoord.xy = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);
+
+ // default reflect color is from position
+ float3 color = uTexLastFrame.SampleLevel(uTexLastFrameSampler, projectedCoord.xy, mipLevel).rgb;
+
+ // edge factor
+ float2 dCoords = smoothstep(float2(0.0, 0.0), float2(0.5, 0.5), abs(float2(0.5, 0.5) - projectedCoord.xy));
+ float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);
+
+ return lerp(baseColor * 0.7, color, screenEdgefactor * z);
+}
\ No newline at end of file
diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/LibSG.hlsl b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/LibSG.hlsl
index e5beb5fec..3c053b53e 100644
--- a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/LibSG.hlsl
+++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/LibSG.hlsl
@@ -1,12 +1,16 @@
static const float PI = 3.1415926;
#include "LibSolverMetallic.hlsl"
+#if defined(ENABLE_SSR)
+#include "../../../SSR/HLSL/LibSSR.hlsl"
+#endif
#include "../../../PostProcessing/HLSL/LibToneMapping.hlsl"
float3 SG(
const float3 baseColor,
const float spec,
const float gloss,
+ const float3 position,
const float3 worldViewDir,
const float3 worldLightDir,
const float3 worldNormal,
@@ -55,7 +59,10 @@ float3 SG(
color += indirectColor * diffuseColor * indirectMultiplier / PI;
// IBL reflection
- // ...
+#if defined(ENABLE_SSR)
+ float3 reflection = -normalize(reflect(worldViewDir, worldNormal));
+ color = color + sRGB(SSR(position, reflection, roughness)) * metallic * specularColor;
+#endif
return color;
}
\ No newline at end of file
diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.d.hlsl b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.d.hlsl
index 9881e9493..35d7bb116 100644
--- a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.d.hlsl
+++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.d.hlsl
@@ -82,6 +82,7 @@ float4 main(PS_INPUT input) : SV_TARGET
albedo,
data.r,
data.g,
+ position,
viewDir,
uLightDirection.xyz,
normal,
diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.hlsl b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.hlsl
index 67e293298..b2dec2635 100644
--- a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.hlsl
+++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightBakeFS.hlsl
@@ -92,6 +92,7 @@ float3 SG(
const float3 baseColor,
const float spec,
const float gloss,
+ const float3 position,
const float3 worldViewDir,
const float3 worldLightDir,
const float3 worldNormal,
@@ -160,6 +161,7 @@ float4 main(PS_INPUT input) : SV_TARGET
albedo,
data.r,
data.g,
+ position,
viewDir,
uLightDirection.xyz,
normal,
diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.d.hlsl b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.d.hlsl
index a623afb58..a7e9788fd 100644
--- a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.d.hlsl
+++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.d.hlsl
@@ -36,8 +36,12 @@ cbuffer cbPerFrame
float3 uLightMultiplier;
float3 uShadowDistance;
float4x4 uShadowMatrix[3];
+ float4x4 uProjection;
+ float4x4 uView;
};
+#define ENABLE_SSR
+
#include "LibShadow.hlsl"
#include "LibSG.hlsl"
@@ -72,6 +76,7 @@ float4 main(PS_INPUT input) : SV_TARGET
albedo,
data.r,
data.g,
+ position,
viewDir,
uLightDirection.xyz,
normal,
diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.hlsl b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.hlsl
index bd158e596..714278044 100644
--- a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.hlsl
+++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/HLSL/SGDirectionalLightFS.hlsl
@@ -28,6 +28,8 @@ cbuffer cbPerFrame
float3 uLightMultiplier;
float3 uShadowDistance;
float4x4 uShadowMatrix[3];
+ float4x4 uProjection;
+ float4x4 uView;
};
float texture2DCompare(float3 uv, float compare) {
float depth = uShadowMap.SampleLevel(uShadowMapSampler, uv, 0).r;
@@ -80,6 +82,51 @@ float solveMetallic(float3 diffuse, float3 specular, float oneMinusSpecularStren
float D = b * b - 4.0 * a * c;
return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
}
+float3 SSR(const float3 position, const float3 reflection, const float roughness)
+{
+ float4 projectedCoord;
+ float3 beginPosition;
+ float3 endPosition;
+ float3 rayPosition = position;
+ float4 viewPosition;
+ float3 dir = reflection * 20.0;
+ float mipLevel = roughness * 7.0;
+ viewPosition = mul(float4(position, 1.0), uView);
+ projectedCoord = mul(float4(viewPosition.xyz, 1.0), uProjection);
+ projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
+ projectedCoord.xy = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);
+ float3 baseColor = uTexLastFrame.SampleLevel(uTexLastFrameSampler, projectedCoord.xy, mipLevel).rgb;
+ for (int i = 6; i >= 0; --i)
+ {
+ beginPosition = rayPosition;
+ endPosition = rayPosition + dir;
+ rayPosition += dir * 0.5;
+ viewPosition = mul(float4(rayPosition, 1.0), uView);
+ projectedCoord = mul(float4(viewPosition.xyz, 1.0), uProjection);
+ projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
+ projectedCoord.xy = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);
+ float3 testPosition = uTexPosition.Sample(uTexPositionSampler, projectedCoord.xy).xyz;
+ float3 d1 = testPosition - beginPosition;
+ float lengthSQ1 = d1.x*d1.x + d1.y*d1.y + d1.z*d1.z;
+ float3 d2 = testPosition - endPosition;
+ float lengthSQ2 = d2.x*d2.x + d2.y*d2.y + d2.z*d2.z;
+ if (lengthSQ1 < lengthSQ2)
+ {
+ rayPosition = beginPosition;
+ }
+ dir *= 0.5;
+ }
+ float z = mul(float4(reflection, 0.0), uView).z;
+ z = clamp(z, 0.0, 1.0);
+ viewPosition = mul(float4(rayPosition, 1.0), uView);
+ projectedCoord = mul(float4(viewPosition.xyz, 1.0), uProjection);
+ projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
+ projectedCoord.xy = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);
+ float3 color = uTexLastFrame.SampleLevel(uTexLastFrameSampler, projectedCoord.xy, mipLevel).rgb;
+ float2 dCoords = smoothstep(float2(0.0, 0.0), float2(0.5, 0.5), abs(float2(0.5, 0.5) - projectedCoord.xy));
+ float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);
+ return lerp(baseColor * 0.7, color, screenEdgefactor * z);
+}
static const float gamma = 2.2;
static const float invGamma = 1.0 / 2.2;
float3 sRGB(float3 color)
@@ -94,6 +141,7 @@ float3 SG(
const float3 baseColor,
const float spec,
const float gloss,
+ const float3 position,
const float3 worldViewDir,
const float3 worldLightDir,
const float3 worldNormal,
@@ -126,6 +174,8 @@ float3 SG(
float3 directionalLight = NdotL * directionLightColor * visibility;
float3 color = (directionalLight * directMultiplier + pointLightColor * lightMultiplier) * diffuseColor + specular * specularColor * visibility + light.a * specularColor;
color += indirectColor * diffuseColor * indirectMultiplier / PI;
+ float3 reflection = -normalize(reflect(worldViewDir, worldNormal));
+ color = color + sRGB(SSR(position, reflection, roughness)) * metallic * specularColor;
return color;
}
float4 main(PS_INPUT input) : SV_TARGET
@@ -152,6 +202,7 @@ float4 main(PS_INPUT input) : SV_TARGET
albedo,
data.r,
data.g,
+ position,
viewDir,
uLightDirection.xyz,
normal,
diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/SGDirectionalLight.xml b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/SGDirectionalLight.xml
index 13278d746..656270c9f 100644
--- a/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/SGDirectionalLight.xml
+++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Lighting/SGDirectionalLight.xml
@@ -19,6 +19,8 @@
+
+
diff --git a/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp b/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp
index d704391f0..3c8054d30 100644
--- a/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp
+++ b/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp
@@ -33,6 +33,7 @@ This file is part of the "Skylicht Engine".
#include "ShaderCallback/CShaderShadow.h"
#include "ShaderCallback/CShaderSH.h"
#include "ShaderCallback/CShaderParticle.h"
+#include "ShaderCallback/CShaderDeferred.h"
namespace Skylicht
{
@@ -50,6 +51,7 @@ namespace Skylicht
addCallback();
addCallback();
addCallback();
+ addCallback();
}
CShader::~CShader()
@@ -1052,21 +1054,13 @@ namespace Skylicht
{
}
break;
- case DEFERRED_VIEW:
- {
- }
- break;
- case DEFERRED_PROJECTION:
- {
- }
- break;
+ */
case CUSTOM_VALUE:
{
// todo
// set params in callback
}
break;
- */
default:
return false;
}
diff --git a/Projects/Skylicht/Engine/Source/Material/Shader/ShaderCallback/CShaderDeferred.cpp b/Projects/Skylicht/Engine/Source/Material/Shader/ShaderCallback/CShaderDeferred.cpp
new file mode 100644
index 000000000..6dec3d11b
--- /dev/null
+++ b/Projects/Skylicht/Engine/Source/Material/Shader/ShaderCallback/CShaderDeferred.cpp
@@ -0,0 +1,67 @@
+/*
+!@
+MIT License
+
+Copyright (c) 2020 Skylicht Technology CO., LTD
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+This file is part of the "Skylicht Engine".
+https://github.com/skylicht-lab/skylicht-engine
+!#
+*/
+
+#include "pch.h"
+#include "CShaderDeferred.h"
+
+namespace Skylicht
+{
+ core::matrix4 CShaderDeferred::s_projection;
+ core::matrix4 CShaderDeferred::s_view;
+
+ CShaderDeferred::CShaderDeferred()
+ {
+
+ }
+
+ CShaderDeferred::~CShaderDeferred()
+ {
+
+ }
+
+ void CShaderDeferred::OnSetConstants(CShader *shader, SUniform *uniform, IMaterialRenderer* matRender, bool vertexShader)
+ {
+ switch (uniform->Type)
+ {
+ case DEFERRED_VIEW:
+ {
+ if (vertexShader == true)
+ matRender->setShaderVariable(uniform->UniformShaderID, s_view.pointer(), uniform->SizeOfUniform, video::EST_VERTEX_SHADER);
+ else
+ matRender->setShaderVariable(uniform->UniformShaderID, s_view.pointer(), uniform->SizeOfUniform, video::EST_PIXEL_SHADER);
+ }
+ break;
+ case DEFERRED_PROJECTION:
+ {
+ if (vertexShader == true)
+ matRender->setShaderVariable(uniform->UniformShaderID, s_projection.pointer(), uniform->SizeOfUniform, video::EST_VERTEX_SHADER);
+ else
+ matRender->setShaderVariable(uniform->UniformShaderID, s_projection.pointer(), uniform->SizeOfUniform, video::EST_PIXEL_SHADER);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Projects/Skylicht/Engine/Source/Material/Shader/ShaderCallback/CShaderDeferred.h b/Projects/Skylicht/Engine/Source/Material/Shader/ShaderCallback/CShaderDeferred.h
new file mode 100644
index 000000000..0a62093c6
--- /dev/null
+++ b/Projects/Skylicht/Engine/Source/Material/Shader/ShaderCallback/CShaderDeferred.h
@@ -0,0 +1,55 @@
+/*
+!@
+MIT License
+
+Copyright (c) 2020 Skylicht Technology CO., LTD
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+This file is part of the "Skylicht Engine".
+https://github.com/skylicht-lab/skylicht-engine
+!#
+*/
+
+#pragma once
+
+#include "Material/Shader/CShader.h"
+
+namespace Skylicht
+{
+ class CShaderDeferred : public IShaderCallback
+ {
+ protected:
+ static core::matrix4 s_projection;
+ static core::matrix4 s_view;
+
+ public:
+ CShaderDeferred();
+
+ virtual ~CShaderDeferred();
+
+ virtual void OnSetConstants(CShader *shader, SUniform *uniform, IMaterialRenderer* matRender, bool vertexShader);
+
+ public:
+ static void setProjection(const core::matrix4& mat)
+ {
+ s_projection = mat;
+ }
+
+ static void setView(const core::matrix4& mat)
+ {
+ s_view = mat;
+ }
+ };
+}
\ No newline at end of file
diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp b/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp
index e14674a41..1d0cc9e1a 100644
--- a/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp
+++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp
@@ -30,6 +30,7 @@ This file is part of the "Skylicht Engine".
#include "Material/Shader/CShaderManager.h"
#include "Material/Shader/ShaderCallback/CShaderShadow.h"
#include "Material/Shader/ShaderCallback/CShaderLighting.h"
+#include "Material/Shader/ShaderCallback/CShaderDeferred.h"
#include "Lighting/CLightCullingSystem.h"
#include "Lighting/CPointLight.h"
#include "IndirectLighting/CIndirectLightingData.h"
@@ -338,6 +339,10 @@ namespace Skylicht
entityManager->setCamera(camera);
entityManager->setRenderPipeline(this);
+ // save projection/view for advance shader SSR
+ CShaderDeferred::setProjection(driver->getTransform(video::ETS_PROJECTION));
+ CShaderDeferred::setView(m_viewMatrix = driver->getTransform(video::ETS_VIEW));
+
// STEP 01:
// draw baked indirect lighting
m_isIndirectPass = true;
@@ -465,7 +470,11 @@ namespace Skylicht
// ssr (last frame)
if (m_postProcessor != NULL)
+ {
m_directionalLightPass.TextureLayer[7].Texture = m_postProcessor->getLastFrameBuffer();
+ m_directionalLightPass.TextureLayer[7].TextureWrapU = ETC_CLAMP_TO_BORDER;
+ m_directionalLightPass.TextureLayer[7].TextureWrapV = ETC_CLAMP_TO_BORDER;
+ }
beginRender2D(renderW, renderH);
diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CPostProcessorRP.cpp b/Projects/Skylicht/Engine/Source/RenderPipeline/CPostProcessorRP.cpp
index 7af8a6737..b93f9d801 100644
--- a/Projects/Skylicht/Engine/Source/RenderPipeline/CPostProcessorRP.cpp
+++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CPostProcessorRP.cpp
@@ -106,7 +106,12 @@ namespace Skylicht
}
if (m_screenSpaceReflection)
+ {
m_lastFrameBuffer = driver->addRenderTargetTexture(m_size, "last_frame", ECF_A8R8G8B8);
+
+ driver->setRenderTarget(m_lastFrameBuffer, true, false);
+ driver->setRenderTarget(NULL);
+ }
else
m_lastFrameBuffer = NULL;
}
diff --git a/Samples/Sponza/Source/CViewInit.cpp b/Samples/Sponza/Source/CViewInit.cpp
index 1ffbe1618..83eac5101 100644
--- a/Samples/Sponza/Source/CViewInit.cpp
+++ b/Samples/Sponza/Source/CViewInit.cpp
@@ -231,7 +231,7 @@ void CViewInit::initProbes()
probes.push_back(probe);
}
- CLightProbeRender::showProbe(true);
+ CLightProbeRender::showProbe(false);
context->setProbes(probes);
}