-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #161 from erikstrand/ssao
Add an SSAO example
- Loading branch information
Showing
8 changed files
with
200,524 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#version 330 core | ||
|
||
#if defined VERTEX_SHADER | ||
|
||
in vec3 in_position; | ||
in vec2 in_texcoord_0; | ||
|
||
out vec2 texcoord; | ||
|
||
void main() { | ||
gl_Position = vec4(in_position, 1.0); | ||
texcoord = in_texcoord_0; | ||
} | ||
|
||
#elif defined FRAGMENT_SHADER | ||
|
||
uniform sampler2D input_texture; | ||
|
||
in vec2 texcoord; | ||
|
||
layout(location=0) out float blurred_texture; | ||
|
||
void main() { | ||
vec2 texel_size = 1.0 / vec2(textureSize(input_texture, 0)); | ||
float result = 0.0; | ||
const int h = 2; | ||
uint n_samples = 0u; | ||
for (int x = -h; x <= h; ++x) { | ||
for (int y = -h; y <= h; ++y) { | ||
vec2 offset = vec2(float(x), float(y)) * texel_size; | ||
float sample = texture(input_texture, texcoord + offset).x; | ||
if (sample != 0.0) { | ||
result += sample; | ||
++n_samples; | ||
} | ||
} | ||
} | ||
blurred_texture = result / float(n_samples); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#version 330 | ||
|
||
#if defined VERTEX_SHADER | ||
|
||
uniform mat4 mvp; | ||
|
||
in vec3 in_position; | ||
in vec3 in_normal; | ||
|
||
out vec3 pos; | ||
out vec3 normal; | ||
|
||
void main() { | ||
gl_Position = mvp * vec4(in_position, 1.0);; | ||
pos = in_position; | ||
normal = in_normal; | ||
} | ||
|
||
#elif defined FRAGMENT_SHADER | ||
|
||
uniform mat4 m_camera; | ||
|
||
in vec3 pos; | ||
in vec3 normal; | ||
|
||
layout(location=0) out float g_view_z; | ||
layout(location=1) out vec3 g_normal; | ||
|
||
void main() { | ||
// Rotate into view space, and record the z component. | ||
g_view_z = -(m_camera * vec4(pos, 1.0)).z; | ||
g_normal = normalize(normal); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#version 330 | ||
|
||
#if defined VERTEX_SHADER | ||
|
||
uniform mat4 m_camera_inverse; | ||
uniform mat4 m_projection_inverse; | ||
uniform vec3 v_camera_pos; | ||
|
||
in vec3 in_position; | ||
in vec2 in_texcoord_0; | ||
|
||
out vec3 view_ray; | ||
out vec2 texcoord; | ||
|
||
void main() { | ||
gl_Position = vec4(in_position, 1.0); | ||
|
||
// Convert in_position from clip space to view space. | ||
vec4 pos = m_projection_inverse * vec4(in_position, 1.0); | ||
// Normalize its z value. | ||
pos.xy /= -pos.z; | ||
pos.z = -1.0; | ||
pos.w = 1.0; | ||
// Convert to world space. | ||
pos = m_camera_inverse * pos; | ||
view_ray = pos.xyz - v_camera_pos; | ||
|
||
texcoord = in_texcoord_0; | ||
} | ||
|
||
#elif defined FRAGMENT_SHADER | ||
|
||
uniform vec3 light_pos; | ||
uniform vec3 camera_pos; | ||
uniform vec3 base_color; | ||
uniform vec4 material_properties; | ||
uniform int render_mode; | ||
|
||
uniform sampler2D g_view_z; | ||
uniform sampler2D g_normal; | ||
uniform sampler2D ssao_occlusion; | ||
|
||
in vec3 view_ray; | ||
in vec2 texcoord; | ||
|
||
layout(location=0) out vec4 frag_color; | ||
|
||
void main() { | ||
// Ignore background fragments. | ||
float view_z = texture(g_view_z, texcoord).x; | ||
if (view_z == 0.0) { | ||
discard; | ||
} | ||
|
||
// Load/compute the position and normal vectors (in world space). | ||
vec3 position = camera_pos + view_z * view_ray; | ||
vec3 normal = texture(g_normal, texcoord).xyz; | ||
|
||
// Compute lighting. | ||
float ambient_magnitude = material_properties.x; | ||
float diffuse_magnitude = material_properties.y; | ||
float specular_magnitude = material_properties.z; | ||
float specular_exponent = material_properties.w; | ||
float occlusion; | ||
if (render_mode != 1) { | ||
occlusion = texture(ssao_occlusion, texcoord).x; | ||
} else { | ||
occlusion = 1.0; | ||
} | ||
vec3 light_dir = normalize(light_pos - position); | ||
vec3 reflection_dir = reflect(-light_dir, normal); | ||
float ambient = ambient_magnitude * occlusion; | ||
float diffuse = diffuse_magnitude * max(dot(light_dir, normal), 0.0); | ||
float specular = specular_magnitude * pow(max(dot(light_dir, normal), 0.0), specular_exponent); | ||
float luminosity = ambient + diffuse + specular; | ||
vec3 color = luminosity * base_color; | ||
if (render_mode == 2) { | ||
color = vec3(occlusion); | ||
} | ||
frag_color = vec4(color, 1.0); | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#version 330 | ||
|
||
#if defined VERTEX_SHADER | ||
|
||
uniform mat4 m_camera_inverse; | ||
uniform mat4 m_projection_inverse; | ||
uniform vec3 v_camera_pos; | ||
|
||
in vec3 in_position; | ||
in vec2 in_texcoord_0; | ||
|
||
out vec3 view_ray; | ||
out vec2 texcoord; | ||
|
||
void main() { | ||
gl_Position = vec4(in_position, 1.0); | ||
|
||
// Convert in_position from clip space to view space. | ||
vec4 pos = m_projection_inverse * vec4(in_position, 1.0); | ||
// Normalize its z value. | ||
pos.xy /= -pos.z; | ||
pos.z = -1.0; | ||
pos.w = 1.0; | ||
// Convert to world space. | ||
pos = m_camera_inverse * pos; | ||
view_ray = pos.xyz - v_camera_pos; | ||
|
||
texcoord = in_texcoord_0; | ||
} | ||
|
||
#elif defined FRAGMENT_SHADER | ||
|
||
const int n_samples = 64; | ||
|
||
uniform vec3 f_camera_pos; | ||
uniform mat4 mvp; | ||
uniform vec3 samples[n_samples]; | ||
uniform float z_offset; | ||
|
||
uniform sampler2D g_view_z; | ||
uniform sampler2D g_norm; | ||
uniform sampler2D noise; | ||
|
||
in vec3 view_ray; | ||
in vec2 texcoord; | ||
|
||
layout(location=0) out float occlusion; | ||
|
||
void main() { | ||
// Ignore background fragments. | ||
float f_view_z = texture(g_view_z, texcoord).x; | ||
if (f_view_z == 0.0) { | ||
discard; | ||
} | ||
|
||
// Load/compute the position and normal vectors (in world coordinates). | ||
vec3 f_pos = f_camera_pos + f_view_z * view_ray; | ||
vec3 f_norm = texture(g_norm, texcoord).xyz; | ||
|
||
// Compute the rotation matrix that takes us from tangent space to world space. | ||
// Note that the x and y axes in tangent space aren't aligned with the texture coordinates or | ||
// anything -- they are intentionally randomized to decorrelate our samples in nearby pixels. | ||
const int noise_size = 32; | ||
vec2 noise_pos = (1.0 / float(noise_size)) * vec2( | ||
float(mod(gl_FragCoord.x, noise_size)), | ||
float(mod(gl_FragCoord.y, noise_size)) | ||
); | ||
vec3 random_vec = normalize(texture(noise, noise_pos).xyz); | ||
vec3 tangent_x = normalize(random_vec - f_norm * dot(random_vec, f_norm)); | ||
vec3 tangent_y = cross(f_norm, tangent_x); | ||
mat3 tan_to_world = mat3(tangent_x, tangent_y, f_norm); | ||
|
||
// Measure occlusion. | ||
occlusion = 0.0; | ||
for (int i = 0; i < n_samples; ++i) { | ||
// Compute the sample position in world coordinates. | ||
vec3 sample_offset = tan_to_world * samples[i]; | ||
vec4 sample_pos = vec4(f_pos + sample_offset, 1.0); | ||
|
||
// Convert to clip space, then scale the relevant coordinates to the range [0, 1]. | ||
sample_pos = mvp * sample_pos; | ||
sample_pos.xyz /= sample_pos.w; | ||
sample_pos.xy = 0.5 * sample_pos.xy + 0.5; | ||
|
||
// Read the actual depth at the sample point. | ||
float actual_view_z = texture(g_view_z, sample_pos.xy).x; | ||
|
||
// If the actual depth is less than the depth of the sample point, the sample is occluded. | ||
occlusion += (actual_view_z != 0.0 && actual_view_z + z_offset < f_view_z) ? 1.0 : 0.0; | ||
} | ||
occlusion = 1.0 - (1.0 / float(n_samples)) * occlusion; | ||
} | ||
|
||
#endif |
Oops, something went wrong.