mirror of
https://github.com/antopilo/Nuake.git
synced 2026-01-01 05:48:14 +03:00
190 lines
6.0 KiB
GLSL
190 lines
6.0 KiB
GLSL
#shader vertex
|
|
#version 440 core
|
|
|
|
layout(location = 0) in vec3 VertexPosition;
|
|
layout(location = 1) in vec2 UVPosition;
|
|
|
|
out flat vec2 UV;
|
|
|
|
void main()
|
|
{
|
|
UV = UVPosition;
|
|
gl_Position = vec4(VertexPosition, 1.0f);
|
|
}
|
|
|
|
#shader fragment
|
|
#version 420 core
|
|
|
|
in vec2 UV;
|
|
out vec4 outColor;
|
|
|
|
uniform sampler2D textureFrame;
|
|
uniform sampler2D textureDepth;
|
|
uniform sampler2D textureNorm;
|
|
uniform sampler2D textureMetallic;
|
|
uniform sampler2D textureAlbedo;
|
|
|
|
uniform mat4 proj;
|
|
uniform mat4 invProj;
|
|
uniform mat4 view;
|
|
uniform mat4 invView;
|
|
|
|
uniform float rayStep = 0.2f;
|
|
uniform int iterationCount = 100;
|
|
uniform float distanceBias = 0.05f;
|
|
uniform bool enableSSR = true;
|
|
uniform int sampleCount = 4;
|
|
uniform bool isSamplingEnabled = true;
|
|
uniform bool isExponentialStepEnabled = false;
|
|
uniform bool isAdaptiveStepEnabled = true;
|
|
uniform bool isBinarySearchEnabled = true;
|
|
uniform bool debugDraw = false;
|
|
uniform float samplingCoefficient = 0.001f;
|
|
|
|
vec3 ReflectedVector;
|
|
float Metallic;
|
|
const float reflectionSpecularFalloffExponent = 5.0;
|
|
float random(vec2 uv) {
|
|
return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453123); //simple random function
|
|
}
|
|
|
|
vec3 generatePositionFromDepth(vec2 texturePos, float depth) {
|
|
vec4 ndc = vec4((texturePos - 0.5) * 2, depth, 1.f);
|
|
vec4 inversed = invProj * ndc;// going back from projected
|
|
inversed /= inversed.w;
|
|
return inversed.xyz;
|
|
}
|
|
|
|
vec2 generateProjectedPosition(vec3 pos) {
|
|
vec4 samplePosition = proj * vec4(pos, 1.f);
|
|
samplePosition.xy = (samplePosition.xy / samplePosition.w) * 0.5 + 0.5;
|
|
return samplePosition.xy;
|
|
}
|
|
|
|
vec3 SSR(vec3 position, vec3 reflection) {
|
|
vec3 step = rayStep * reflection;
|
|
vec3 marchingPosition = position + step;
|
|
float delta;
|
|
float depthFromScreen;
|
|
vec2 screenPosition;
|
|
|
|
int i = 0;
|
|
for (; i < iterationCount; i++) {
|
|
screenPosition = generateProjectedPosition(marchingPosition);
|
|
depthFromScreen = abs(generatePositionFromDepth(screenPosition, textureLod(textureDepth, screenPosition, 2).x).z);
|
|
delta = abs(marchingPosition.z) - depthFromScreen;
|
|
|
|
float depth = textureLod(textureDepth, screenPosition, 2).r;
|
|
if (depthFromScreen > 1000.0f)
|
|
{
|
|
vec2 dCoords = smoothstep(0.2, 0.6, abs(vec2(0.5, 0.5) - screenPosition.xy));
|
|
float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);
|
|
float ReflectionMultiplier = pow(Metallic, 3.0) *
|
|
screenEdgefactor *
|
|
-ReflectedVector.z;
|
|
return texture(textureFrame, screenPosition).xyz * ReflectionMultiplier;
|
|
}
|
|
if (abs(delta) < distanceBias) {
|
|
vec3 color = vec3(1);
|
|
if (debugDraw)
|
|
color = vec3(0.5 + sign(delta) / 2, 0.3, 0.5 - sign(delta) / 2);
|
|
vec2 dCoords = smoothstep(0.2, 0.6, abs(vec2(0.5, 0.5) - screenPosition.xy));
|
|
float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);
|
|
float ReflectionMultiplier = pow(Metallic, 3.0) *
|
|
screenEdgefactor *
|
|
-ReflectedVector.z;
|
|
|
|
return texture(textureFrame, screenPosition).xyz * color * clamp(ReflectionMultiplier, 0.0, 1.0);
|
|
}
|
|
if (isBinarySearchEnabled && delta > 0) {
|
|
break;
|
|
}
|
|
if (isAdaptiveStepEnabled) {
|
|
float directionSign = sign(abs(marchingPosition.z) - depthFromScreen);
|
|
//this is sort of adapting step, should prevent lining reflection by doing sort of iterative converging
|
|
//some implementation doing it by binary search, but I found this idea more cheaty and way easier to implement
|
|
step = step * (1.0 - rayStep * max(directionSign, 0.0));
|
|
marchingPosition += step * (-directionSign);
|
|
}
|
|
else {
|
|
marchingPosition += step;
|
|
}
|
|
if (isExponentialStepEnabled) {
|
|
step *= 1.05;
|
|
}
|
|
}
|
|
if (isBinarySearchEnabled) {
|
|
for (; i < iterationCount; i++) {
|
|
|
|
step *= 0.5;
|
|
marchingPosition = marchingPosition - step * sign(delta);
|
|
|
|
screenPosition = generateProjectedPosition(marchingPosition);
|
|
depthFromScreen = abs(generatePositionFromDepth(screenPosition, textureLod(textureDepth, screenPosition, 2).x).z);
|
|
delta = abs(marchingPosition.z) - depthFromScreen;
|
|
|
|
vec2 dCoords = smoothstep(0.2, 0.6, abs(vec2(0.5, 0.5) - screenPosition.xy));
|
|
float screenEdgefactor = clamp(1.0 - (dCoords.x + dCoords.y), 0.0, 1.0);
|
|
float ReflectionMultiplier = pow(Metallic, 3.0) * screenEdgefactor *
|
|
-ReflectedVector.z;
|
|
|
|
if (abs(delta) < distanceBias) {
|
|
return texture(textureFrame, screenPosition).xyz * clamp(ReflectionMultiplier, 0.0, 0.9);
|
|
}
|
|
}
|
|
}
|
|
|
|
return vec3(0, 0, 0);
|
|
}
|
|
|
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
|
{
|
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
|
}
|
|
|
|
void main() {
|
|
vec3 position = generatePositionFromDepth(UV, textureLod(textureDepth, UV, 2).x);
|
|
vec4 normal = view * vec4(texture(textureNorm, UV).xyz * 2.0 - 1.0, 0.0);
|
|
|
|
float metallic = texture(textureMetallic, UV).r;
|
|
Metallic = metallic;
|
|
vec3 albedo = texture(textureAlbedo, UV).rgb;
|
|
vec3 F0 = vec3(0.04);
|
|
F0 = mix(F0, albedo, metallic);
|
|
vec3 Fresnel = fresnelSchlick(max(dot(normalize(normal.rgb), normalize(position)), 0.0), F0);
|
|
|
|
if (!enableSSR || metallic < 0.01) {
|
|
discard;// outColor = mix(texture(textureFrame, UV), normal, 0.9);
|
|
}
|
|
else {
|
|
vec3 reflectionDirection = normalize(reflect(position, normalize(normal.xyz)));
|
|
|
|
ReflectedVector = reflectionDirection;
|
|
if (isSamplingEnabled) {
|
|
vec3 firstBasis = normalize(cross(vec3(0.f, 0.f, 1.f), reflectionDirection));
|
|
vec3 secondBasis = normalize(cross(reflectionDirection, firstBasis));
|
|
vec4 resultingColor = vec4(0.f);
|
|
for (int i = 0; i < sampleCount; i++) {
|
|
vec2 coeffs = vec2(random(UV + vec2(0, i)) + random(UV + vec2(i, 0))) * samplingCoefficient;
|
|
vec3 reflectionDirectionRandomized = reflectionDirection + firstBasis * coeffs.x + secondBasis * coeffs.y;
|
|
vec3 tempColor = SSR(position, normalize(reflectionDirectionRandomized));
|
|
|
|
resultingColor += vec4(tempColor, 1.0f);
|
|
}
|
|
|
|
|
|
if (resultingColor.w != 0)
|
|
resultingColor /= resultingColor.w;
|
|
|
|
outColor = vec4(resultingColor.xyz * Fresnel, 1.0) ;
|
|
|
|
}
|
|
else {
|
|
outColor = vec4(SSR(position, normalize(reflectionDirection)) * Fresnel, 1.0);
|
|
if (outColor.xyz == vec3(0.f)) {
|
|
outColor = texture(textureFrame, UV);
|
|
}
|
|
}
|
|
}
|
|
}
|