feat: basic shadow map + renderdoc labels
This commit is contained in:
@@ -35,6 +35,10 @@ vec4 sampleTextureCubeLinear(uint texID, vec3 p) {
|
||||
return texture(nonuniformEXT(samplerCube(textureCubes[texID], samplers[LINEAR_SAMPLER_ID])), p);
|
||||
}
|
||||
|
||||
float sampleTexture2DShadow(uint texID, vec3 p) {
|
||||
return texture(nonuniformEXT(sampler2DShadow(textures[texID], samplers[SHADOW_SAMPLER_ID])), p);
|
||||
}
|
||||
|
||||
float sampleTextureArrayShadow(uint texID, vec4 p) {
|
||||
return texture(nonuniformEXT(sampler2DArrayShadow(textureArrays[texID], samplers[SHADOW_SAMPLER_ID])), p);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ float calculateSpotAttenuation(Light light, vec3 l)
|
||||
}
|
||||
|
||||
vec3 calculateLight(Light light, vec3 fragPos, vec3 n, vec3 v,
|
||||
vec3 diffuseColor, float roughness, float metallic, vec3 f0)
|
||||
vec3 diffuseColor, float roughness, float metallic, vec3 f0, float occlusion)
|
||||
{
|
||||
vec3 l;
|
||||
float attenuation = 1.0;
|
||||
@@ -80,7 +80,7 @@ vec3 calculateLight(Light light, vec3 fragPos, vec3 n, vec3 v,
|
||||
vec3 kd = (vec3(1.0) - F) * (1.0 - metallic);
|
||||
vec3 diffuse = kd * diffuseColor / PI;
|
||||
|
||||
return (diffuse + specular) * light.color * light.intensity * attenuation * NoL;
|
||||
return (diffuse + specular) * light.color * light.intensity * attenuation * NoL * occlusion;
|
||||
}
|
||||
|
||||
// blue -> green -> red, used to visualise how many lights a tile has
|
||||
|
||||
@@ -27,7 +27,8 @@ struct Light {
|
||||
|
||||
float spotInnerCos;
|
||||
float spotOuterCos;
|
||||
vec2 padding;
|
||||
uint castShadows;
|
||||
float padding;
|
||||
};
|
||||
|
||||
layout (buffer_reference, std430) readonly buffer LightsBuffer {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "scene_data.glsl"
|
||||
#include "mesh_pcs.glsl"
|
||||
#include "lighting.glsl"
|
||||
#include "shadows.glsl"
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUV;
|
||||
@@ -69,8 +70,17 @@ void main()
|
||||
uint lightIndex = pcs.sceneData.tileLightIndices.data[tileOffset + 1 + i];
|
||||
Light light = pcs.sceneData.lights.data[lightIndex];
|
||||
|
||||
float occlusion = 1.0;
|
||||
if (light.castShadows != 0) {
|
||||
occlusion = calculateDirectionalShadow(
|
||||
fragPos, n,
|
||||
pcs.sceneData.lightViewProj,
|
||||
pcs.sceneData.shadowMapId,
|
||||
pcs.sceneData.shadowNormalOffset);
|
||||
}
|
||||
|
||||
fragColor += calculateLight(light, fragPos, n, v,
|
||||
diffuseColor, roughness, metallic, f0);
|
||||
diffuseColor, roughness, metallic, f0, occlusion);
|
||||
}
|
||||
|
||||
// emissive
|
||||
|
||||
@@ -33,7 +33,12 @@ layout (buffer_reference, scalar) readonly buffer SceneDataBuffer {
|
||||
uint numLights;
|
||||
uint tileCountX;
|
||||
uint debugLightHeatmap;
|
||||
|
||||
// directional shadows
|
||||
uint shadowMapId;
|
||||
float shadowNormalOffset;
|
||||
uint padding;
|
||||
mat4 lightViewProj;
|
||||
} sceneDataBuffer;
|
||||
|
||||
#endif // SCENE_DATA_GLSL
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#version 460
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
#include "mesh_pcs.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
Vertex v = pcs.vertexBuffer.vertices[gl_VertexIndex];
|
||||
|
||||
gl_Position = pcs.sceneData.lightViewProj * pcs.transform * vec4(v.position, 1.0f);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef SHADOWS_GLSL
|
||||
#define SHADOWS_GLSL
|
||||
|
||||
// expects bindless.glsl to be included before this file (it has no include guard)
|
||||
|
||||
// Returns 1.0 when fully lit, 0.0 when fully in shadow
|
||||
float calculateDirectionalShadow(vec3 fragPos, vec3 n, mat4 lightViewProj, uint shadowMapID, float normalOffset)
|
||||
{
|
||||
// pushing the sample point along the normal hides most of the shadow acne
|
||||
vec4 lightClip = lightViewProj * vec4(fragPos + n * normalOffset, 1.0);
|
||||
vec3 lightNDC = lightClip.xyz / lightClip.w;
|
||||
vec2 uv = lightNDC.xy * 0.5 + 0.5;
|
||||
|
||||
// outside the shadow map counts as lit
|
||||
if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0))) || lightNDC.z > 1.0) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
vec2 texelSize = 1.0 / vec2(textureSize(sampler2DShadow(textures[shadowMapID], samplers[SHADOW_SAMPLER_ID]), 0));
|
||||
|
||||
// 3x3 PCF, every tap is already bilinearly filtered by the compare sampler
|
||||
float shadowed = 0.0;
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
shadowed += sampleTexture2DShadow(shadowMapID, vec3(uv + vec2(x, y) * texelSize, lightNDC.z));
|
||||
}
|
||||
}
|
||||
|
||||
// the shadow sampler compares with GREATER_OR_EQUAL (it was set up for reversed Z),
|
||||
// with regular depth that returns 1 when the fragment is behind the occluder
|
||||
return 1.0 - shadowed / 9.0;
|
||||
}
|
||||
|
||||
#endif // SHADOWS_GLSL
|
||||
Reference in New Issue
Block a user