Skip to content

Commit

Permalink
Merge pull request JuliaPlots#97 from ffreyer/SSAO
Browse files Browse the repository at this point in the history
SSAO
  • Loading branch information
SimonDanisch authored May 17, 2020
2 parents 4216ce5 + 7668c54 commit 5df183e
Show file tree
Hide file tree
Showing 17 changed files with 367 additions and 116 deletions.
2 changes: 1 addition & 1 deletion src/GLAbstraction/GLTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ function RenderObject(
# but in some cases we want a Texture, sometimes a GLBuffer or TextureBuffer
data[k] = gl_convert(targets[k], v)
else
k in (:indices, :visible, :fxaa) && continue
k in (:indices, :visible, :fxaa, :ssao) && continue
# structs are treated differently, since they have to be composed into their fields
if isa_gl_struct(v)
merge!(data, gl_convert_struct(v, k))
Expand Down
2 changes: 2 additions & 0 deletions src/GLMakie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ using Base: RefValue
import Base: push!, isopen, show
using Base.Iterators: repeated, drop

using LinearAlgebra

for name in names(AbstractPlotting)
@eval import AbstractPlotting: $(name)
end
Expand Down
10 changes: 10 additions & 0 deletions src/GLVisualize/assets/shader/fragment_output.frag
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@

layout(location=0) out vec4 fragment_color;
layout(location=1) out uvec2 fragment_groupid;
layout(location=2) out vec4 fragment_position;
layout(location=3) out vec3 fragment_normal;

in vec4 o_view_pos;
in vec3 o_normal;

void write2framebuffer(vec4 color, uvec2 id){
if(color.a <= 0.0)
discard;
// For FXAA & SSAO
fragment_color = color;
// For plot/sprite picking
fragment_groupid = id;
// For SSAO
fragment_position = o_view_pos;
fragment_normal = o_normal;
}
2 changes: 1 addition & 1 deletion src/GLVisualize/assets/shader/particles.vert
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ vec4 _color(sampler2D color, Nothing intensity, Nothing color_map, Nothing color
return vec4(0);
}

void render(vec4 vertices, vec3 normal, mat4 view, mat4 projection, vec3 lightposition);
void render(vec4 position_world, vec3 normal, mat4 view, mat4 projection, vec3 lightposition);


vec2 get_uv(Nothing x){return vec2(0.0);}
Expand Down
90 changes: 90 additions & 0 deletions src/GLVisualize/assets/shader/postprocessing/SSAO.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{{GLSL_VERSION}}

// SSAO
uniform sampler2D position_buffer;
uniform sampler2D normal_buffer;
uniform sampler2D noise;
uniform vec3 kernel[{{N_samples}}];
uniform vec2 noise_scale;
uniform mat4 projection;

// bias/epsilon for depth check
uniform float bias;
// max range for depth check
uniform float radius;


in vec2 frag_uv;
out float o_occlusion;


void main(void)
{
vec3 view_pos = texture(position_buffer, frag_uv).xyz;
vec3 normal = texture(normal_buffer, frag_uv).xyz;

// The normal buffer gets cleared every frame. (also position, color etc)
// If normal == vec3(1) then there is no geometry at this fragment.
// Therefore skip SSAO calculation
if (normal != vec3(1)) {
vec3 rand_vec = vec3(texture(noise, frag_uv * noise_scale).xy, 0.0);
vec3 tangent = normalize(rand_vec - normal * dot(rand_vec, normal));
vec3 bitangent = cross(normal, tangent);
mat3 TBN = mat3(tangent, bitangent, normal);

float occlusion = 0.0;
for (int i = 0; i < {{N_samples}}; ++i) {
// random offset in view space
vec3 sample_view_offset = TBN * kernel[i] * radius;

/*
We want to get the uv (screen) coordinate of position + offset in
view space. Usually this would be:
clip_coordinate = projection * view_coordinate
clip_coordinate /= clip_coordinate.w
screen_coordinate = 0.5 * clip_coordinate + 0.5
But Makie allows multiple scenes, which each have their own
coordinate system. This means it is possible that multiple
regions of the screen (different scenes) refer to the same view
position. To differentiate between them we must calculate the
screen space coordinate using frag_uv and an offset derived from
the view space offset.
Instead of
clip_coord = projection * (view_pos + view_offset)
clip_coord /= clip_coord.w
screen_coordinate = 0.5 * clip_coord + 0.5
we essentially calculate
clip_offset = projection * view_offset
clip_offset /= (projection * (view_pos + view_offset)).w
clip_position = frag_uv - 0.5
clip_position *= (projection * view_pos).w
clip_position /= (projection * (view_pos + view_offset)).w
screen_coordinate = clip_position + 0.5 * clip_offset+ 0.5
*/

vec4 sample_frag_pos = vec4(
(projection * vec4(sample_view_offset, 1.0)).xyz,
(projection * vec4(view_pos + sample_view_offset, 1.0)).w
);
float sample_clip_pos_w = sample_frag_pos.w;
float clip_pos_w = (projection * vec4(view_pos, 1.0)).w;
sample_frag_pos.xyz /= sample_frag_pos.w;
sample_frag_pos.xyz = sample_frag_pos.xyz * 0.5 + 0.5;
sample_frag_pos.xy += (frag_uv - 0.5) * clip_pos_w / sample_clip_pos_w;


float sample_depth = texture(position_buffer, sample_frag_pos.xy).z;
float range_check = smoothstep(0.0, 1.0, radius / abs(view_pos.z - sample_depth));
occlusion += (sample_depth >= sample_view_offset.z + view_pos.z + bias ? 1.0 : 0.0) * range_check;
}
occlusion = 1.0 - (occlusion / {{N_samples}});
o_occlusion = occlusion;
} else {
o_occlusion = 1.0;
}
}
38 changes: 38 additions & 0 deletions src/GLVisualize/assets/shader/postprocessing/SSAO_blur.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{{GLSL_VERSION}}

uniform sampler2D occlusion;
uniform sampler2D color_texture;
uniform usampler2D ids;
uniform vec2 inv_texel_size;
// Settings/Attributes
uniform int blur_range;

in vec2 frag_uv;
out vec4 fragment_color;

void main(void)
{
// occlusion blur
float blurred_occlusion = 0.0;
uvec2 id0 = texture(ids, frag_uv).xy;
float weight = 0;

for (int x = -blur_range; x <= blur_range; ++x){
for (int y = -blur_range; y <= blur_range; ++y){
vec2 offset = vec2(float(x), float(y)) * inv_texel_size;
// The id check makes it so that the blur acts per object.
// Without this, a high (low) occlusion from one object can bleed
// into the low (high) occlusion of another, giving an unwanted
// shine effect.
uvec2 id = texture(ids, frag_uv + offset).xy;
if (id0 == id) {
blurred_occlusion += texture(occlusion, frag_uv + offset).r;
weight += 1;
}
}
}
blurred_occlusion = blurred_occlusion / weight;
fragment_color = texture(color_texture, frag_uv) * blurred_occlusion;
// Display occlusion instead:
// fragment_color = vec4(vec3(blurred_occlusion), 1.0);
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,7 @@ in vec2 frag_uv;

out vec4 fragment_color;


void main(void)
{
// fragment_color = texture(color_texture, frag_uv);
Expand Down
4 changes: 2 additions & 2 deletions src/GLVisualize/assets/shader/standard.vert
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ in vec3 normals;

uniform vec3 lightposition;
uniform mat4 projection, view, model;
void render(vec4 vertices, vec3 normals, mat4 viewmodel, mat4 projection, vec3 lightposition);
void render(vec4 position_world, vec3 normal, mat4 view, mat4 projection, vec3 lightposition);

uniform uint objectid;
flat out uvec2 o_id;
Expand All @@ -30,5 +30,5 @@ void main()
o_uv = vec2(1.0 - tex_uv.y, tex_uv.x);
o_color = to_color(vertex_color);
vec3 v = to_3d(vertices);
render(model * vec4(v, 1), (model * vec4(normals, 0)).xyz, view, projection, lightposition);
render(model * vec4(v, 1), normals, view, projection, lightposition);
}
4 changes: 2 additions & 2 deletions src/GLVisualize/assets/shader/surface.vert
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ uniform vec3 scale;

uniform mat4 view, model, projection;

void render(vec4 vertices, vec3 normal, mat4 viewmodel, mat4 projection, vec3 lightposition);
void render(vec4 position_world, vec3 normal, mat4 view, mat4 projection, vec3 lightposition);
ivec2 ind2sub(ivec2 dim, int linearindex);
vec2 linear_index(ivec2 dims, int index);
vec2 linear_index(ivec2 dims, int index, vec2 offset);
Expand Down Expand Up @@ -100,5 +100,5 @@ void main()
o_id = uvec2(objectid, index1D+1);
o_uv = index01;
vec3 normalvec = {{normal_calc}};
render(model * vec4(pos, 1), (model * vec4(normalvec, 0)).xyz, view, projection, lightposition);
render(model * vec4(pos, 1), normalvec, view, projection, lightposition);
}
26 changes: 14 additions & 12 deletions src/GLVisualize/assets/shader/util.vert
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ struct Grid3D{
vec3 stop;
ivec3 dims;
};
struct Light{
vec3 diffuse;
vec3 specular;
vec3 ambient;
vec3 position;
};

// stretch is
vec3 stretch(vec3 val, vec3 from, vec3 to){
Expand Down Expand Up @@ -225,24 +219,32 @@ vec4 _color(Nothing color, float intensity, sampler1D color_map, vec2 color_norm



out vec4 o_view_pos;
out vec3 o_normal;
out vec3 o_lightdir;
out vec3 o_camdir;
// transpose(inv(view * model))
// Transformation for vectors (rather than points)
uniform mat3 normalmatrix;
uniform vec3 lightposition;
uniform vec3 eyeposition;


void render(vec4 position_world, vec3 normal, mat4 view, mat4 projection, vec3 lightposition)
{
// normal in world space
// TODO move transpose inverse calculation to cpu
o_normal = normal;
o_normal = normalmatrix * normal;
// position in view space (as seen from camera)
o_view_pos = view * position_world;
// position in clip space (w/ depth)
gl_Position = projection * o_view_pos;
// direction to light
o_lightdir = normalize(lightposition - position_world.xyz);
o_lightdir = normalize(view*vec4(lightposition, 1.0) - o_view_pos).xyz;
// direction to camera
o_camdir = normalize(eyeposition - position_world.xyz);
// screen space coordinates of the vertex
gl_Position = projection * view * position_world;
// This is equivalent to
// normalize(view*vec4(eyeposition, 1.0) - o_view_pos).xyz
// (by definition `view * eyeposition = 0`)
o_camdir = normalize(-o_view_pos).xyz;
}

//
Expand Down
8 changes: 7 additions & 1 deletion src/drawing_primitives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function cached_robj!(robj_func, screen, scene, x::AbstractPlot)
robj = get!(screen.cache, objectid(x)) do

filtered = filter(x.attributes) do (k, v)
!(k in (:transformation, :tickranges, :ticklabels, :raw))
!(k in (:transformation, :tickranges, :ticklabels, :raw, :SSAO))
end

gl_attributes = Dict{Symbol, Any}(map(filtered) do key_value
Expand Down Expand Up @@ -69,6 +69,12 @@ function cached_robj!(robj_func, screen, scene, x::AbstractPlot)
for key in (:pixel_space, :view, :projection, :resolution, :eyeposition, :projectionview)
robj[key] = getfield(scene.camera, key)
end
if !haskey(gl_attributes, :normalmatrix)
robj[:normalmatrix] = map(robj[:view], robj[:model]) do v, m
Mat3f0(transpose(inv(v[1:3, 1:3] * m[1:3, 1:3])))
end
end
!haskey(gl_attributes, :ssao) && (robj[:ssao] = Node(false))
screen.cache2plot[robj.id] = x
robj
end
Expand Down
Loading

0 comments on commit 5df183e

Please sign in to comment.