diff options
Diffstat (limited to 'apps/openmb/resources/shaders/textured_lit.frag')
| -rw-r--r-- | apps/openmb/resources/shaders/textured_lit.frag | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/apps/openmb/resources/shaders/textured_lit.frag b/apps/openmb/resources/shaders/textured_lit.frag new file mode 100644 index 0000000..58c71f7 --- /dev/null +++ b/apps/openmb/resources/shaders/textured_lit.frag @@ -0,0 +1,121 @@ +#version 330 core + +in vec2 vUV; +in vec3 vNormal; +in vec3 vFragPos; +in vec4 vFragPosLightSpace; +out vec4 FragColor; + +uniform sampler2D albedo; +uniform sampler2D normalMap; +uniform int normalEnabled; +uniform float normalStrength; +uniform vec3 tint; +uniform int radialEnabled; +uniform float radialInner; +uniform float radialOuter; + +struct DirectionalLight +{ + vec3 direction; + vec3 color; + float intensity; +}; + +uniform DirectionalLight dirLight; +uniform vec3 ambientColor = vec3(0.15, 0.15, 0.15); +uniform sampler2D shadowMap; +uniform float shadowBiasMin; +uniform float shadowBiasScale; +uniform int pcfRadius; +uniform sampler2D ssao; +uniform float aoStrength; +uniform float screenWidth; +uniform float screenHeight; + +// Fog +uniform vec3 cameraPos; +uniform vec3 fogColor; +uniform float fogDensity; // e.g. 0.02 +uniform float fogAmount; // 0..1 blend factor +float ShadowCalculation(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) +{ + + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + + projCoords = projCoords * 0.5 + 0.5; + + if (projCoords.z > 1.0) + return 0.0; + + + float currentDepth = projCoords.z; + + float bias = max(shadowBiasScale * (1.0 - max(dot(normal, lightDir), 0.0)), shadowBiasMin); + + + ivec2 texSize = textureSize(shadowMap, 0); + vec2 texelSize = 1.0 / vec2(texSize); + float vis = 0.0; + int samples = 0; + for (int x = -pcfRadius; x <= pcfRadius; ++x) + { + for (int y = -pcfRadius; y <= pcfRadius; ++y) + { + vec2 offset = vec2(x, y) * texelSize; + float depthSample = texture(shadowMap, projCoords.xy + offset).r; + // texture returns stored light-space depth. If our fragment's depth (minus bias) + // is less than or equal to the sampled depth, it's visible to the light. + vis += (currentDepth - bias <= depthSample) ? 1.0 : 0.0; + samples++; + } + } + float visibility = vis / float(samples); + float shadow = 1.0 - visibility; + return shadow; +} + +void main() +{ + vec4 tex = texture(albedo, vUV); + vec3 color = tex.rgb * tint; + float alpha = tex.a; + vec3 finalNormal = vec3(0.0, 0.0, 1.0); + if (normalEnabled == 1) + { + vec3 n = texture(normalMap, vUV).rgb; + n = n * 2.0 - 1.0; + finalNormal = normalize(vec3(n.x * normalStrength, n.y * normalStrength, 1.0)); + } + if (radialEnabled == 1) + { + float dist = distance(vUV, vec2(0.5, 0.5)); + float mask = 1.0 - smoothstep(radialInner, radialOuter, dist); + alpha *= mask; + } + + + vec3 N = normalize(finalNormal); + vec3 L = normalize(dirLight.direction); + float diff = max(dot(N, L), 0.0); + vec3 diffuse = dirLight.color * dirLight.intensity * diff; + + float shadow = ShadowCalculation(vFragPosLightSpace, N, L); + float shadowFactor = 1.0 - shadow * 0.9; + float ao = 1.0; + if (aoStrength > 0.0) + { + vec2 ssaoUV = gl_FragCoord.xy / vec2(screenWidth, screenHeight); + ao = texture(ssao, ssaoUV).r; + } + float aoFactor = mix(1.0, ao, aoStrength); + vec3 result = color * (ambientColor * aoFactor + diffuse * shadowFactor); + + // Compute fog based on distance from camera + float dist = length(vFragPos - cameraPos); + float fogFactor = 1.0 - exp(-fogDensity * dist); + fogFactor = clamp(fogFactor * fogAmount, 0.0, 1.0); + vec3 finalColor = mix(result, fogColor, fogFactor); + + FragColor = vec4(finalColor, alpha); +} |