Pulled SSAO out into its own shader to support running at a lower-than-native framebuffer resolution (defaults at half-resolution [SHRenderSSAOResolutionScale=.5] ). This doesn't improve the slow ssao/shadow softening, however, as that bit remains unchanged.

This commit is contained in:
Shyotl
2013-12-13 02:19:57 -06:00
parent 78e3d61b98
commit 7da8b012e6
13 changed files with 445 additions and 207 deletions

View File

@@ -32,6 +32,7 @@ out vec4 frag_color;
//class 2 -- shadows and SSAO
uniform sampler2DRect diffuseRect;
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
uniform sampler2DShadow shadowMap0;
@@ -40,16 +41,12 @@ uniform sampler2DShadow shadowMap2;
uniform sampler2DShadow shadowMap3;
uniform sampler2DShadow shadowMap4;
uniform sampler2DShadow shadowMap5;
uniform sampler2D noiseMap;
//uniform sampler2D noiseMap;
// Inputs
uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform float ssao_radius;
uniform float ssao_max_radius;
uniform float ssao_factor;
uniform float ssao_factor_inv;
VARYING vec2 vary_fragcoord;
@@ -66,6 +63,8 @@ uniform float shadow_offset;
uniform float spot_shadow_bias;
uniform float spot_shadow_offset;
uniform float downsampled_depth_scale;
vec2 encode_normal(vec3 n)
{
float f = sqrt(8 * n.z + 8);
@@ -96,61 +95,6 @@ vec4 getPosition(vec2 pos_screen)
return pos;
}
vec2 getKern(int i)
{
vec2 kern[8];
// exponentially (^2) distant occlusion samples spread around origin
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
return kern[i];
}
//calculate decreases in ambient lighting when crowded out (SSAO)
float calcAmbientOcclusion(vec4 pos, vec3 norm)
{
vec2 pos_screen = vary_fragcoord.xy;
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
// We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
float points = 1.0;
float angle_hidden = 0.0;
// use a kernel scale that diminishes with distance.
// a scale of less than 32 is just wasting good samples, though.
float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
for (int i = 0; i < 8; i++)
{
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
vec3 samppos_world = getPosition(samppos_screen).xyz;
vec3 diff = samppos_world - pos.xyz;
if (diff.z < ssao_factor && diff.z != 0.0)
{
float dist = length(diff);
float angrel = max(0.0, dot(norm.xyz, diff/dist));
float distrel = 1.0/(1.0+dist*dist);
float samplehidden = min(angrel, distrel);
angle_hidden += (samplehidden);
points += 1.0;
}
}
angle_hidden /= points;
float rtn = (1.0 - angle_hidden);
return (rtn * rtn);
}
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
{
stc.xyz /= stc.w;
@@ -301,7 +245,7 @@ void main()
}
frag_color[0] = shadow;
frag_color[1] = calcAmbientOcclusion(pos, norm);
frag_color[1] = texture2DRect(diffuseRect,vary_fragcoord*downsampled_depth_scale);
spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);