This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
Antonis Ryakiotakis 590efaacb8 Potential fix for T43987, ambient occlusion different between offscreen
and on screen rendering.

Aaaaah, the beauty of driver implementations of OpenGL!

Turns out the problem here is that drivers calculate df/dy differently
in some cases (probably because OpenGL counts y reverse to how the
window system does, so drivers can get confused).

Fixed this for the ATI case based on info we have so far, there's also
the Intel case which will be handled separately (missing info on Intel's
renderer string etc).

Unfortunately we can't really fix this for the general case so we'll
have to haldle cases as they come in our tracker and by adding silly
string comparisons in our GPU initialization module <sigh>.
2015-03-30 14:14:52 +02:00

95 lines
3.1 KiB
GLSL

// color buffer
uniform sampler2D colorbuffer;
// jitter texture for ssao
uniform sampler2D jitter_tex;
// concentric sample texture for ssao
uniform sampler1D ssao_concentric_tex;
// depth buffer
uniform sampler2D depthbuffer;
// coordinates on framebuffer in normalized (0.0-1.0) uv space
varying vec4 uvcoordsvar;
/* ssao_params.x : pixel scale for the ssao radious */
/* ssao_params.y : factor for the ssao darkening */
uniform vec4 ssao_params;
uniform vec4 ssao_sample_params;
uniform vec4 ssao_color;
/* store the view space vectors for the corners of the view frustum here.
* It helps to quickly reconstruct view space vectors by using uv coordinates,
* see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
uniform vec4 viewvecs[3];
vec3 calculate_view_space_normal(in vec3 viewposition)
{
vec3 normal = cross(normalize(dFdx(viewposition)),
ssao_params.w * normalize(dFdy(viewposition)));
normalize(normal);
return normal;
}
float calculate_ssao_factor(float depth)
{
/* take the normalized ray direction here */
vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.zw).rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
/* occlusion is zero in full depth */
if (depth == 1.0)
return 0.0;
vec3 position = get_view_space_from_depth(uvcoordsvar.xy, viewvecs[0].xyz, viewvecs[1].xyz, depth);
vec3 normal = calculate_view_space_normal(position);
// find the offset in screen space by multiplying a point in camera space at the depth of the point by the projection matrix.
vec2 offset;
float homcoord = gl_ProjectionMatrix[2][3] * position.z + gl_ProjectionMatrix[3][3];
offset.x = gl_ProjectionMatrix[0][0] * ssao_params.x / homcoord;
offset.y = gl_ProjectionMatrix[1][1] * ssao_params.x / homcoord;
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
float factor = 0.0;
int x;
int num_samples = int(ssao_sample_params.x);
for (x = 0; x < num_samples; x++) {
vec2 dir_sample = texture1D(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
/* rotate with random direction to get jittered result */
vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
vec2 uvcoords = uvcoordsvar.xy + dir_jittered * offset;
if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
continue;
float depth_new = texture2D(depthbuffer, uvcoords).r;
if (depth_new != 1.0) {
vec3 pos_new = get_view_space_from_depth(uvcoords, viewvecs[0].xyz, viewvecs[1].xyz, depth_new);
vec3 dir = pos_new - position;
float len = length(dir);
float f = dot(dir, normal);
/* use minor bias here to avoid self shadowing */
if (f > 0.05 * len + 0.0001)
factor += f * 1.0/(len * (1.0 + len * len * ssao_params.z));
}
}
factor /= ssao_sample_params.x;
return clamp(factor * ssao_params.y, 0.0, 1.0);
}
void main()
{
float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
vec4 scene_col = texture2D(colorbuffer, uvcoordsvar.xy);
vec3 final_color = mix(scene_col.rgb, ssao_color.rgb, calculate_ssao_factor(depth));
gl_FragColor = vec4(final_color.rgb, scene_col.a);
}