Added Screen space reflections and Editor UI refactoring

This commit is contained in:
antopilo
2022-01-31 13:54:58 -05:00
parent e216686272
commit b273a2fb8a
78 changed files with 2454 additions and 946 deletions

View File

@@ -0,0 +1,31 @@
#shader vertex
#version 460 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 460 core
uniform sampler2D u_Source;
uniform sampler2D u_Source2;
in vec2 UV;
out vec4 FragColor;
void main()
{
vec4 a = texture(u_Source, UV);
vec4 b = texture(u_Source2, UV);
FragColor = vec4(vec3(a.rgb + b.rgb / 2.0), a.a * b.a);
}

View File

@@ -117,25 +117,51 @@ vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
}
float ShadowCalculation(Light light, vec3 FragPos, vec3 normal)
int GetCSMDepth(float depth, Light light)
{
// Get Depth
float depth = length(FragPos - u_EyePosition);
int shadowmap = 0;
int shadowmap = -1;
// Get CSM depth
for (int i = 0; i < 4; i++)
{
float CSMDepth = light.CascadeDepth[i];
if (depth < CSMDepth + 0.0001)
if (depth < CSMDepth + 0.0001f)
{
shadowmap = i;
break;
}
}
return shadowmap;
}
float SampleShadowMap(sampler2D shadowMap, vec2 coords, float compare)
{
return step(compare, texture(shadowMap, coords.xy).r);
}
float SampleShadowMapLinear(sampler2D shadowMap, vec2 coords, float compare, vec2 texelSize)
{
vec2 pixelPos = coords / texelSize + vec2(0.5);
vec2 fracPart = fract(pixelPos);
vec2 startTexel = (pixelPos - fracPart) * texelSize;
float blTexel = SampleShadowMap(shadowMap, startTexel, compare);
float brTexel = SampleShadowMap(shadowMap, startTexel + vec2(texelSize.x, 0.0), compare);
float tlTexel = SampleShadowMap(shadowMap, startTexel + vec2(0.0, texelSize.y), compare);
float trTexel = SampleShadowMap(shadowMap, startTexel + texelSize, compare);
float mixA = mix(blTexel, tlTexel, fracPart.y);
float mixB = mix(brTexel, trTexel, fracPart.y);
return mix(mixA, mixB, fracPart.x);
}
float ShadowCalculation(Light light, vec3 FragPos, vec3 normal)
{
// Get Depth
float depth = length(FragPos - u_EyePosition);
int shadowmap = GetCSMDepth(depth, light);
if (shadowmap == -1)
return 1.0;
@@ -149,18 +175,40 @@ float ShadowCalculation(Light light, vec3 FragPos, vec3 normal)
// get depth of current fragment from light's perspective
float currentDepth = projCoords.z;
// check whether current frag pos is in shadow
float bias = max(0.005 * (1.0 - dot(normal, light.Direction)), 0.0005);
float shadow = 0.0;
float bias = max(0.005 * (1.0 - dot(normal, light.Direction)), 0.0005);
//float pcfDepth = texture(ShadowMaps[shadowmap], vec3(projCoords.xy, currentDepth), bias);
float pcfDepth = texture(ShadowMaps[shadowmap], projCoords.xy).r;
return currentDepth - bias > pcfDepth ? 1.0 : 0.0;
if (shadowmap <= 3)
{
const float NUM_SAMPLES = 4.f;
const float SAMPLES_START = (NUM_SAMPLES - 1.0f) / 2.0f;
const float NUM_SAMPLES_SQUARED = NUM_SAMPLES * NUM_SAMPLES;
vec2 texelSize = 1.0 / vec2(2048, 2048);
float result = 0.0f;
for (float y = -SAMPLES_START; y <= SAMPLES_START; y += 1.0f)
{
for (float x = -SAMPLES_START; x <= SAMPLES_START; x += 1.0f)
{
vec2 coordsOffset = vec2(x, y) * texelSize;
result += SampleShadowMapLinear(ShadowMaps[shadowmap], projCoords.xy + coordsOffset, currentDepth - bias, texelSize);
}
}
return result / NUM_SAMPLES_SQUARED;
}
else
{
return SampleShadowMap(ShadowMaps[shadowmap], projCoords.xy, currentDepth - bias);
}
}
void main()
{
vec3 worldPos = WorldPosFromDepth(texture(m_Depth, UV).r);
if (texture(m_Depth, UV).r == 1)
{
FragColor = vec4(0, 0, 0, 0);
@@ -202,7 +250,7 @@ void main()
vec3 radiance = Lights[i].Color * attenuation ;
if (Lights[i].Type == 0) {
radiance *= 1.0f - shadow;
radiance *= shadow;
}
// Cook-Torrance BRDF
@@ -235,5 +283,18 @@ void main()
vec3 ambient = (kD * albedo) * ao;
vec3 color = ambient + Lo;
// Display CSM splits..
/*float depth = length(worldPos - u_EyePosition);
int cascade = GetCSMDepth(depth, Lights[0]);
if (cascade == 0)
color *= vec3(1.0, 0.0, 0.0);
if (cascade == 1)
color *= vec3(0.0, 1.0, 0.0);
if (cascade == 2)
color *= vec3(0.0, 0.0, 1.0);
if (cascade == 3)
color *= vec3(0.0, 1.0, 1.0);
*/
FragColor = vec4(color, 1.0);
}

View File

@@ -25,7 +25,6 @@ void main()
discard;
vec4 finalColor = u_Color;
finalColor.a = (sin(u_Time * 4.0) + 1.0) / 4.0 + 0.1;
FragColor = finalColor;
}

View File

@@ -17,8 +17,15 @@ out vec2 UV;
void main()
{
vec3 N = normalize((u_Model * vec4(Normal, 0.0f)).xyz);
//mat3 normalMatrix = transpose(inverse(mat3(u_Model)));
//vec3 T = normalize(normalMatrix * Tangent);
//vec3 N = normalize(normalMatrix * Normal);
//T = normalize(T - dot(T, N) * N);
//vec3 B = cross(N, T);
vec3 T = normalize((u_Model * vec4(Tangent, 0.0f)).xyz);
vec3 N = normalize((u_Model * vec4(Normal, 0.0f)).xyz);
vec3 B = normalize((u_Model * vec4(Bitangent, 0.0f)).xyz);
TBN = mat3(T, B, N);
@@ -68,10 +75,8 @@ void main()
if (u_HasNormal == 1)
normal = texture(m_Normal, UV).rgb;
normal = normal * 2.0 - 1.0;
normal = TBN * normalize(normal);
gNormal = vec4(normal, 1.0) / 2.0 + 0.5;
gNormal = vec4(normal / 2.0 + 0.5, 1.0);
// Albedo
gAlbedo = vec4(m_AlbedoColor, 1.0);

View File

@@ -1,5 +1,6 @@
#shader vertex
#version 460 core
layout(location = 0) in vec3 VertexPosition;
layout(location = 1) in vec2 UVPosition;
layout(location = 2) in vec3 Normal;

View File

@@ -0,0 +1,189 @@
#shader vertex
#version 460 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 = 3.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 (abs(delta) < distanceBias || depthFromScreen > 1000.0f) {
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, 0.9);
}
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);
}
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));
if(tempColor != vec3(0))
resultingColor += vec4(tempColor, 1.0f);
}
if(resultingColor.w != 0)
resultingColor /= resultingColor.w;
if (resultingColor.xyz == vec3(0.0f))
{
outColor = vec4(1, 0, 0, 0);
return;
}
outColor = vec4(resultingColor.xyz * Fresnel, metallic) ;
}
else {
outColor = vec4(SSR(position, normalize(reflectionDirection)) * Fresnel, metallic);
if (outColor.xyz == vec3(0.f)) {
outColor = texture(textureFrame, UV);
}
}
}
}

View File

@@ -37,11 +37,12 @@ struct Light {
mat4 transform;
vec3 color;
vec3 direction;
sampler2D shadowmap;
int shadowmap;
};
uniform Light u_Lights[MAX_LIGHT];
uniform sampler2D lightShadowmap;
in vec2 UV;
out vec4 FragColor;
@@ -57,7 +58,8 @@ float ComputeScattering(float lightDotView)
vec3 ComputeVolumetric(vec3 FragPos, Light light)
{
vec3 rayVector = FragPos - u_CamPosition; // Ray Direction
vec3 startPosition = u_CamPosition; // Camera Position
vec3 rayVector = FragPos - startPosition; // Ray Direction
float rayLength = length(rayVector); // Length of the raymarched
@@ -68,7 +70,7 @@ vec3 ComputeVolumetric(vec3 FragPos, Light light)
vec3 accumFog = vec3(0.0f, 0.0f, 0.0f); // accumulative color
// Raymarching
vec3 currentPosition = u_CamPosition;
vec3 currentPosition = startPosition;
for (int i = 0; i < u_StepCount; i++)
{
vec4 fragPosLightSpace = light.transform * vec4(currentPosition, 1.0f);
@@ -78,7 +80,7 @@ vec3 ComputeVolumetric(vec3 FragPos, Light light)
projCoords = projCoords * 0.5 + 0.5;
float currentDepth = projCoords.z;
float closestDepth = texture(light.shadowmap, projCoords.xy).r;
float closestDepth = texture(lightShadowmap, projCoords.xy).r;
if (closestDepth > currentDepth)
accumFog += (ComputeScattering(dot(rayDirection, normalize(light.direction))).xxx * light.color);
@@ -110,11 +112,10 @@ void main()
vec3 globalFragmentPosition = WorldPosFromDepth(depth);
vec3 fog = vec3(0, 0, 0);
for (int i = 0; i < u_LightCount; i++)
{
fog += ComputeVolumetric(globalFragmentPosition, u_Lights[i]);
}
FragColor = vec4(mix(fog, vec3(depth), 0.01), 1.0);
FragColor = vec4(mix(fog, ComputeVolumetric(globalFragmentPosition, u_Lights[0]), 0.9f), 1.0);
}