mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-27 16:17:12 +03:00
Added Screen space reflections and Editor UI refactoring
This commit is contained in:
31
Editor/resources/Shaders/combine.shader
Normal file
31
Editor/resources/Shaders/combine.shader
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
189
Editor/resources/Shaders/ssr.shader
Normal file
189
Editor/resources/Shaders/ssr.shader
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user