Skip to content

Commit

Permalink
#149 Improve SSR Shader
Browse files Browse the repository at this point in the history
  • Loading branch information
ducphamhong committed Jun 6, 2022
1 parent 72d59ac commit 0dd0cac
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 124 deletions.
76 changes: 42 additions & 34 deletions Assets/BuiltIn/Shader/SSR/GLSL/LibSSR.glsl
Original file line number Diff line number Diff line change
@@ -1,63 +1,71 @@
#define RAY_LENGTH 32.0
// References
// https://github.com/MonkeyFirst/Urho3D_SSR_Shader/blob/master/bin/CoreData/Shaders/GLSL/SSR.glsl
vec2 binarySearch(vec3 dir, vec3 rayPosition)
{
vec4 projectedCoord;

for(int i = 16; i > 0; --i)
{
projectedCoord = uProjection * vec4(rayPosition.xyz, 1.0);
projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
projectedCoord.xy = 0.5 * projectedCoord.xy + vec2(0.5, 0.5);

vec4 testPosition = texture(uTexPosition, projectedCoord.xy);
float dDepth = rayPosition.z - testPosition.w;

dir *= 0.5;
if(dDepth > 0.0)
rayPosition -= dir;
else
rayPosition += dir;
}

return projectedCoord.xy;
}

vec3 SSR(const vec3 baseColor, const vec3 position, const vec3 reflection, const float roughness)
{
vec3 SSR(const vec3 baseColor, const vec4 position, const vec3 reflection, const float roughness)
{
vec4 projectedCoord;

vec3 beginPosition;
vec3 endPosition;
// convert to view space
vec3 rayPosition = (uView * vec4(position.xyz, 1.0)).xyz;
vec3 viewReflection = normalize((uView * vec4(reflection, 0.0)).xyz);

vec3 rayPosition = position;
vec4 viewPosition;

vec3 dir = reflection * RAY_LENGTH;
// step 0.5m
vec3 dir = viewReflection * 0.5;

float mipLevel = roughness * 5.0;
vec2 ssrUV;

// ray test
for (int i = 32; i > 0; --i)
{
// begin ray
beginPosition = rayPosition;

// end ray
endPosition = rayPosition + dir;

// mid ray
rayPosition += dir * 0.5;
rayPosition += dir;

// convert 3d position to 2d texture coord
projectedCoord = uViewProjection * vec4(rayPosition.xyz, 1.0);
projectedCoord = uProjection * vec4(rayPosition.xyz, 1.0);
projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
projectedCoord.xy = 0.5 * projectedCoord.xy + vec2(0.5, 0.5);
ssrUV = 0.5 * projectedCoord.xy + vec2(0.5, 0.5);

vec3 testPosition = texture(uTexPosition, projectedCoord.xy).xyz;
vec4 testPosition = texture(uTexPosition, ssrUV);

vec3 d1 = testPosition - beginPosition;
float lengthSQ1 = d1.x*d1.x + d1.y*d1.y + d1.z*d1.z;

vec3 d2 = testPosition - endPosition;
float lengthSQ2 = d2.x*d2.x + d2.y*d2.y + d2.z*d2.z;

// beginPosition is nearer
if (lengthSQ1 < lengthSQ2)
float depthDiff = rayPosition.z - testPosition.w;
if(depthDiff >= 0.0)
{
rayPosition = beginPosition;
ssrUV = binarySearch(dir, rayPosition);
break;
}

// binary search test
dir *= 0.5;
}

// z clip when camera look down
float z = (uView * vec4(reflection, 0.0)).z;
z = clamp(z, 0.0, 1.0);

// convert 3d position to 2d texture coord
vec3 color = textureLod(uTexLastFrame, projectedCoord.xy, 0).rgb;
vec3 color = textureLod(uTexLastFrame, ssrUV, mipLevel).rgb;

// edge factor
vec2 dCoords = smoothstep(vec2(0.0, 0.0), vec2(0.5, 0.5), abs(vec2(0.5, 0.5) - projectedCoord.xy));
vec2 dCoords = smoothstep(vec2(0.0, 0.0), vec2(0.5, 0.5), abs(vec2(0.5, 0.5) - ssrUV));
float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);

return mix(baseColor * 0.8, color, screenEdgefactor * z);
Expand Down
85 changes: 49 additions & 36 deletions Assets/BuiltIn/Shader/SSR/HLSL/LibSSR.hlsl
Original file line number Diff line number Diff line change
@@ -1,65 +1,78 @@
#define RAY_LENGTH 32.0
// References
// https://github.com/MonkeyFirst/Urho3D_SSR_Shader/blob/master/bin/CoreData/Shaders/GLSL/SSR.glsl

float3 SSR(const float3 baseColor, const float3 position, const float3 reflection, const float roughness)
float2 binarySearch(float3 dir, float3 rayPosition)
{
float4 projectedCoord;

[unroll]
for(int i = 16; i > 0; --i)
{
projectedCoord = mul(float4(rayPosition.xyz, 1.0), uProjection);
projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
projectedCoord.xy = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);

float4 testPosition = uTexPosition.Sample(uTexPositionSampler, projectedCoord.xy);
float dDepth = rayPosition.z - testPosition.w;

dir *= 0.5;
if(dDepth > 0.0)
rayPosition -= dir;
else
rayPosition += dir;
}

return projectedCoord.xy;
}

float3 SSR(const float3 baseColor, const float4 position, const float3 reflection, const float roughness)
{
float4 projectedCoord;

float3 beginPosition;
float3 endPosition;
// convert to view space
float3 rayPosition = mul(float4(position.xyz, 1.0), uView).xyz;
float3 viewReflection = normalize(mul(float4(reflection, 0.0), uView).xyz);

float3 rayPosition = position;
float4 viewPosition;

float3 dir = reflection * RAY_LENGTH;
// step 0.5m
float3 dir = viewReflection * 0.5;

float mipLevel = roughness * 5.0;

// ray test
float2 ssrUV;

// RayMarch test
[unroll]
for (int i = 32; i > 0; --i)
{
// begin ray
beginPosition = rayPosition;
rayPosition += dir;

// end ray
endPosition = rayPosition + dir;

// mid ray
rayPosition += dir * 0.5;

// convert 3d position to 2d texture coord
projectedCoord = mul(float4(rayPosition.xyz, 1.0), uViewProjection);
// convert 3d position to 2d texture coord
projectedCoord = mul(float4(rayPosition.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;
ssrUV = float2(0.5, -0.5) * projectedCoord.xy + float2(0.5, 0.5);
float4 testPosition = uTexPosition.Sample(uTexPositionSampler, ssrUV);

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)
float depthDiff = rayPosition.z - testPosition.w;
if(depthDiff >= 0.0)
{
rayPosition = beginPosition;
ssrUV = binarySearch(dir, rayPosition);
break;
}

// binary search test
dir *= 0.5;
}

// z clip when camera look down
float z = mul(float4(reflection, 0.0), uView).z;
z = clamp(z, 0.0, 1.0);

// convert 3d position to 2d texture coord
float3 color = uTexLastFrame.SampleLevel(uTexLastFrameSampler, projectedCoord.xy, 0).rgb;
float3 color = uTexLastFrame.SampleLevel(uTexLastFrameSampler, ssrUV, 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));
float2 dCoords = smoothstep(float2(0.0, 0.0), float2(0.5, 0.5), abs(float2(0.5, 0.5) - ssrUV));
float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);

return lerp(baseColor * 0.8, color, screenEdgefactor * z);

// test
// return float3(screenEdgefactor * z, screenEdgefactor * z, screenEdgefactor * z);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ vec3 SG(
const vec3 baseColor,
const float spec,
const float gloss,
const vec3 position,
const vec4 position,
const vec3 worldViewDir,
const vec3 worldLightDir,
const vec3 worldNormal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ vec3 SG(
const vec3 baseColor,
const float spec,
const float gloss,
const vec3 position,
const vec4 position,
const vec3 worldViewDir,
const vec3 worldLightDir,
const vec3 worldNormal,
Expand Down Expand Up @@ -155,7 +155,7 @@ void main(void)
albedo,
data.r,
data.g,
position,
posdepth,
viewDir,
uLightDirection.xyz,
normal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ uniform mat4 uShadowMatrix[3];
#if defined(ENABLE_SSR)
uniform mat4 uViewProjection;
uniform mat4 uView;
uniform mat4 uProjection;
#endif

in vec2 varTexCoord0;
Expand Down Expand Up @@ -82,7 +83,7 @@ void main(void)
albedo,
data.r,
data.g,
position,
posdepth,
viewDir,
uLightDirection.xyz,
normal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ uniform vec3 uShadowDistance;
uniform mat4 uShadowMatrix[3];
uniform mat4 uViewProjection;
uniform mat4 uView;
uniform mat4 uProjection;
in vec2 varTexCoord0;
out vec4 FragColor;
vec2 rand(vec2 co){
Expand Down Expand Up @@ -73,38 +74,50 @@ float solveMetallic(vec3 diffuse, vec3 specular, float oneMinusSpecularStrength)
float D = b * b - 4.0 * a * c;
return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
}
vec3 SSR(const vec3 baseColor, const vec3 position, const vec3 reflection, const float roughness)
vec2 binarySearch(vec3 dir, vec3 rayPosition)
{
vec4 projectedCoord;
vec3 beginPosition;
vec3 endPosition;
vec3 rayPosition = position;
vec4 viewPosition;
vec3 dir = reflection * 32.0;
for(int i = 16; i > 0; --i)
{
projectedCoord = uProjection * vec4(rayPosition.xyz, 1.0);
projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
projectedCoord.xy = 0.5 * projectedCoord.xy + vec2(0.5, 0.5);
vec4 testPosition = texture(uTexPosition, projectedCoord.xy);
float dDepth = rayPosition.z - testPosition.w;
dir *= 0.5;
if(dDepth > 0.0)
rayPosition -= dir;
else
rayPosition += dir;
}
return projectedCoord.xy;
}
vec3 SSR(const vec3 baseColor, const vec4 position, const vec3 reflection, const float roughness)
{
vec4 projectedCoord;
vec3 rayPosition = (uView * vec4(position.xyz, 1.0)).xyz;
vec3 viewReflection = normalize((uView * vec4(reflection, 0.0)).xyz);
vec3 dir = viewReflection * 0.5;
float mipLevel = roughness * 5.0;
vec2 ssrUV;
for (int i = 32; i > 0; --i)
{
beginPosition = rayPosition;
endPosition = rayPosition + dir;
rayPosition += dir * 0.5;
projectedCoord = uViewProjection * vec4(rayPosition.xyz, 1.0);
rayPosition += dir;
projectedCoord = uProjection * vec4(rayPosition.xyz, 1.0);
projectedCoord.xy = projectedCoord.xy / projectedCoord.w;
projectedCoord.xy = 0.5 * projectedCoord.xy + vec2(0.5, 0.5);
vec3 testPosition = texture(uTexPosition, projectedCoord.xy).xyz;
vec3 d1 = testPosition - beginPosition;
float lengthSQ1 = d1.x*d1.x + d1.y*d1.y + d1.z*d1.z;
vec3 d2 = testPosition - endPosition;
float lengthSQ2 = d2.x*d2.x + d2.y*d2.y + d2.z*d2.z;
if (lengthSQ1 < lengthSQ2)
ssrUV = 0.5 * projectedCoord.xy + vec2(0.5, 0.5);
vec4 testPosition = texture(uTexPosition, ssrUV);
float depthDiff = rayPosition.z - testPosition.w;
if(depthDiff >= 0.0)
{
rayPosition = beginPosition;
ssrUV = binarySearch(dir, rayPosition);
break;
}
dir *= 0.5;
}
float z = (uView * vec4(reflection, 0.0)).z;
z = clamp(z, 0.0, 1.0);
vec3 color = textureLod(uTexLastFrame, projectedCoord.xy, 0).rgb;
vec2 dCoords = smoothstep(vec2(0.0, 0.0), vec2(0.5, 0.5), abs(vec2(0.5, 0.5) - projectedCoord.xy));
vec3 color = textureLod(uTexLastFrame, ssrUV, mipLevel).rgb;
vec2 dCoords = smoothstep(vec2(0.0, 0.0), vec2(0.5, 0.5), abs(vec2(0.5, 0.5) - ssrUV));
float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);
return mix(baseColor * 0.8, color, screenEdgefactor * z);
}
Expand All @@ -122,7 +135,7 @@ vec3 SG(
const vec3 baseColor,
const float spec,
const float gloss,
const vec3 position,
const vec4 position,
const vec3 worldViewDir,
const vec3 worldLightDir,
const vec3 worldNormal,
Expand Down Expand Up @@ -188,7 +201,7 @@ void main(void)
albedo,
data.r,
data.g,
position,
posdepth,
viewDir,
uLightDirection.xyz,
normal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ float3 SG(
const float3 baseColor,
const float spec,
const float gloss,
const float3 position,
const float4 position,
const float3 worldViewDir,
const float3 worldLightDir,
const float3 worldNormal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ float3 SG(
const float3 baseColor,
const float spec,
const float gloss,
const float3 position,
const float4 position,
const float3 worldViewDir,
const float3 worldLightDir,
const float3 worldNormal,
Expand Down Expand Up @@ -166,7 +166,7 @@ float4 main(PS_INPUT input) : SV_TARGET
albedo,
data.r,
data.g,
position,
posdepth,
viewDir,
uLightDirection.xyz,
normal,
Expand Down
Loading

0 comments on commit 0dd0cac

Please sign in to comment.