mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-04 11:35:06 +03:00
141 lines
4.0 KiB
GLSL
141 lines
4.0 KiB
GLSL
#shader vertex
|
|
#version 440 core
|
|
|
|
layout(location = 0) in vec3 VertexPosition;
|
|
layout(location = 1) in vec2 UVPosition;
|
|
|
|
out flat vec2 UV;
|
|
out mat4 InvView;
|
|
out mat4 InvProjection;
|
|
|
|
uniform mat4 u_View;
|
|
uniform mat4 u_Projection;
|
|
|
|
void main()
|
|
{
|
|
UV = UVPosition;
|
|
InvView = inverse(u_View);
|
|
InvProjection = inverse(u_Projection);
|
|
gl_Position = vec4(VertexPosition, 1.0f);
|
|
}
|
|
|
|
#shader fragment
|
|
#version 440 core
|
|
|
|
float ditherPattern[4][4] = { { 0.0f, 0.5f, 0.125f, 0.625f},
|
|
{ 0.75f, 0.22f, 0.875f, 0.375f},
|
|
{ 0.1875f, 0.6875f, 0.0625f, 0.5625},
|
|
{ 0.9375f, 0.4375f, 0.8125f, 0.3125} };
|
|
|
|
in mat4 InvView;
|
|
in mat4 InvProjection;
|
|
|
|
uniform sampler2D u_Depth;
|
|
|
|
uniform vec3 u_CamPosition;
|
|
uniform int u_StepCount;
|
|
uniform float u_FogAmount;
|
|
uniform float u_Exponant;
|
|
|
|
const int MAX_LIGHT = 20;
|
|
uniform int u_LightCount;
|
|
|
|
struct Light {
|
|
mat4 transform;
|
|
vec3 color;
|
|
vec3 direction;
|
|
sampler2D shadowmap;
|
|
float strength;
|
|
};
|
|
|
|
uniform Light u_Lights[MAX_LIGHT];
|
|
|
|
uniform sampler2D lightShadowmap;
|
|
in vec2 UV;
|
|
|
|
out vec4 FragColor;
|
|
const float PI = 3.141592653589793f;
|
|
|
|
// Mie scaterring approximated with Henyey-Greenstein phase function.
|
|
float ComputeScattering(float lightDotView)
|
|
{
|
|
float result = 1.0f - u_FogAmount ;
|
|
result /= (4.0f * PI * pow(1.0f + u_FogAmount * u_FogAmount - (1.0f * u_FogAmount) * lightDotView, 1.5f));
|
|
return result;
|
|
}
|
|
|
|
vec3 ComputeVolumetric(vec3 FragPos, Light light)
|
|
{
|
|
vec3 startPosition = u_CamPosition; // Camera Position
|
|
vec3 rayVector = FragPos - startPosition; // Ray Direction
|
|
|
|
float rayLength = length(rayVector); // Length of the raymarched
|
|
if(rayLength > 1000.0)
|
|
return vec3(0.0);
|
|
float stepLength = rayLength / u_StepCount; // Step length
|
|
vec3 rayDirection = rayVector / rayLength;
|
|
vec3 step = rayDirection * stepLength; // Normalized to step length direction
|
|
|
|
vec3 accumFog = vec3(0.0f, 0.0f, 0.0f); // accumulative color
|
|
|
|
// Raymarching
|
|
vec3 currentPosition = startPosition;
|
|
for (int i = 0; i < u_StepCount; i++)
|
|
{
|
|
vec4 fragPosLightSpace = light.transform * vec4(currentPosition, 1.0f);
|
|
// perform perspective divide
|
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
|
|
|
// transform to [0,1] range
|
|
projCoords = projCoords * 0.5 + 0.5;
|
|
|
|
float currentDepth = projCoords.z;
|
|
float closestDepth = texture(light.shadowmap, projCoords.xy).r;
|
|
if (closestDepth > currentDepth && closestDepth < 999)
|
|
{
|
|
//accumFog = vec3(light.color);
|
|
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).xxx * light.color);
|
|
//accumFog = vec3(projCoords.x, projCoords.y, 1.0);
|
|
|
|
}
|
|
currentPosition += step * ditherPattern[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4];
|
|
//accumFog = vec3(projCoords);
|
|
}
|
|
accumFog /= u_StepCount;
|
|
|
|
return accumFog;
|
|
}
|
|
|
|
// Converts depth to World space coords.
|
|
vec3 WorldPosFromDepth(float depth) {
|
|
float z = depth * 2.0 - 1.0;
|
|
|
|
vec4 clipSpacePosition = vec4(UV * 2.0 - 1.0, z, 1.0);
|
|
vec4 viewSpacePosition = InvProjection * clipSpacePosition;
|
|
|
|
// Perspective division
|
|
viewSpacePosition /= viewSpacePosition.w;
|
|
|
|
vec4 worldSpacePosition = InvView * viewSpacePosition;
|
|
|
|
return worldSpacePosition.xyz;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
float depth = texture(u_Depth, UV).r;
|
|
vec3 globalFragmentPosition = WorldPosFromDepth(depth);
|
|
|
|
vec3 fog = vec3(0, 0, 0);
|
|
for (int i = 0; i < u_LightCount; i++)
|
|
{
|
|
fog += ComputeVolumetric(globalFragmentPosition, u_Lights[i]) * u_Exponant;
|
|
}
|
|
|
|
FragColor = vec4(fog, 1.0);
|
|
//FragColor = vec4(mix(fog, ComputeVolumetric(globalFragmentPosition, u_Lights[0]), 0.9f), 0.01);
|
|
//FragColor = vec4(globalFragmentPosition * 10.0, 1.0f);
|
|
//FragColor = vec4(globalFragmentPosition.xyz * 100.0, 1.0f);
|
|
//FragColor = vec4(worldSpacePosition.x, worldSpacePosition.y, worldSpacePosition.z, 1);
|
|
//FragColor = vec4(ComputeVolumetric(globalFragmentPosition, u_Lights[0]), 1.0);
|
|
} |