[Bf-blender-cvs] [2632c13] viewport_experiments: SSAO shader.

Antony Riakiotakis noreply at git.blender.org
Mon Sep 15 16:12:16 CEST 2014


Commit: 2632c1308f37b0b12fecca9707c823148f839c38
Author: Antony Riakiotakis
Date:   Mon Sep 15 16:09:53 2014 +0200
Branches: viewport_experiments
https://developer.blender.org/rB2632c1308f37b0b12fecca9707c823148f839c38

SSAO shader.

This works by using the calculated view space normal and accumulating
coverage of a certain area by nearby pixels. There are two sliders to
control the effect:

* Scale controls the area around each pixel that the shader "collides"
against
* Darkening scales the occlusion effect.

The effect works, but due to the way the normals are calculated, the
normals are never smooth shaded (that would require a separate render
target to store them) and the edges or polygons can be too apparent.
This is not really fixable at the moment unless we move to deferred
pipeline.

The FX system is stll not well optimized and rendering does not always
work correctly, but it's good to have this out for people to play with.

===================================================================

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/gpu/shaders/gpu_shader_fx_frag.glsl
M	source/blender/makesdna/DNA_view3d_types.h
M	source/blender/makesrna/intern/rna_space.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index dce5749..e515240 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2869,13 +2869,17 @@ class VIEW3D_PT_view3d_shading(Panel):
         if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
             if obj and obj.mode == 'EDIT':
                 col.prop(view, "show_occlude_wire")
-            col.prop(view, "ssao")
             col.prop(view, "depth_of_field")
             if view.depth_of_field:
                 subcol = col.column(align=True)
                 subcol.prop(view, "dof_focal_distance")
                 subcol.prop(view, "dof_aperture")
                 subcol.prop(view, "dof_fstop")
+            col.prop(view, "ssao")
+            if view.ssao:
+                subcol = col.column(align=True)
+                subcol.prop(view, "ssao_scale")
+                subcol.prop(view, "ssao_darkening")
 
 
 class VIEW3D_PT_view3d_motion_tracking(Panel):
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 3283069..b79afea 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -3413,7 +3413,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
 #endif
 
 	/* framebuffer fx needed, we need to draw offscreen first */
-	if (v3d->shader_fx & V3D_FX_DEPTH_OF_FIELD) {
+	if (v3d->shader_fx) {
 		int w = BLI_rcti_size_x(&ar->winrct) + 1, h = BLI_rcti_size_y(&ar->winrct) + 1;
 		
 		char err_out[256];
@@ -3493,12 +3493,14 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
 		/* set up the shader */
 		fx_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD);
 		if (fx_shader) {
-			int screendim_uniform, color_uniform, depth_uniform, dof_uniform, blurred_uniform;
+			int screendim_uniform, color_uniform, depth_uniform, dof_uniform, blurred_uniform, ssao_uniform;
 			float fac = v3d->dof_fstop * v3d->dof_aperture;
-			float parameters[2] = {v3d->dof_aperture * fabs(fac / (v3d->dof_focal_distance - fac)), 
+			float dof_params[2] = {v3d->dof_aperture * fabs(fac / (v3d->dof_focal_distance - fac)), 
 								   v3d->dof_focal_distance};
+			float ssao_params[2] = {v3d->ssao_scale, v3d->ssao_darkening};
 
 			dof_uniform = GPU_shader_get_uniform(fx_shader, "dof_params");
+			ssao_uniform = GPU_shader_get_uniform(fx_shader, "ssao_params");
 			blurred_uniform = GPU_shader_get_uniform(fx_shader, "blurredcolorbuffer");
 			screendim_uniform = GPU_shader_get_uniform(fx_shader, "screendim");
 			color_uniform = GPU_shader_get_uniform(fx_shader, "colorbuffer");
@@ -3507,7 +3509,8 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
 			GPU_shader_bind(fx_shader);
 
 			GPU_shader_uniform_vector(fx_shader, screendim_uniform, 2, 1, screendim);
-			GPU_shader_uniform_vector(fx_shader, dof_uniform, 2, 1, parameters);
+			GPU_shader_uniform_vector(fx_shader, dof_uniform, 2, 1, dof_params);
+			GPU_shader_uniform_vector(fx_shader, ssao_uniform, 2, 1, ssao_params);
 
 			GPU_texture_bind(color_buffer, 0);
 			GPU_shader_uniform_texture(fx_shader, blurred_uniform, color_buffer);
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_frag.glsl
index 198eb45..7e95106 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_frag.glsl
@@ -11,19 +11,38 @@ uniform sampler2D depthbuffer;
 varying vec4 framecoords;
 
 // this includes focal distance in x and aperture size in y
-uniform vec2 dof_params; 
+uniform vec2 dof_params;
 
-#define NUM_SAMPLES 5
+/* ssao_params.x : pixel scale for the ssao radious */
+/* ssao_params.y : factor for the ssao darkening */
+uniform vec2 ssao_params;
 
-vec3 calculate_ss_normal(in vec4 viewposition)
+#define NUM_SAMPLES 8
+
+vec3 calculate_view_space_normal(in vec4 viewposition)
 {
     vec3 normal = cross(normalize(dFdx(viewposition.xyz)), 
                         normalize(dFdy(viewposition.xyz)));
     normalize(normal);
-    normal = normal * 0.5 + vec3(0.5);
     return normal;
 }
 
+vec4 calculate_view_space_position(in vec2 uvcoords)
+{
+    float depth = texture2D(depthbuffer, uvcoords).r;
+	
+    //First we need to calculate the view space distance from the shader inputs
+    //This will unfortunately depend on the precision of the depth buffer which is not linear
+    vec2 norm_scr = uvcoords * 2.0 - 1.0;
+    vec4 viewposition = vec4(norm_scr.x, norm_scr.y, depth, 1.0);
+
+    // convert to view space now
+    viewposition = gl_ProjectionMatrixInverse * viewposition;
+    viewposition = viewposition / viewposition.w;
+    
+    return viewposition;
+}
+
 float calculate_dof_coc(in vec4 viewposition, inout vec3 normal)
 {
     float dist = length(viewposition);
@@ -35,26 +54,40 @@ float calculate_dof_coc(in vec4 viewposition, inout vec3 normal)
 }
 
 
+float calculate_ssao_factor(in vec3 normal, in vec4 position)
+{
+    // divide by distance to camera to make the effect independent
+    vec2 offset = (ssao_params.x / position.z) * vec2(1.0/screendim.x, 1.0/screendim.y);
+    float factor = 0.0;
+    int x, y;
+    
+    for (x = 0; x < NUM_SAMPLES; x++) {
+        for (y = 0; y < NUM_SAMPLES; y++) {
+            vec4 pos_new = calculate_view_space_position(framecoords.xy + (vec2(x,y) - vec2(4.0)) * offset);
+            vec3 dir = vec3(pos_new.xyz) - vec3(position.xyz);
+            float len = length(dir);
+            factor += max(dot(dir, normal) * (1.0/(1.0 + len)), 0.0);
+        }
+    }
+
+    factor /= NUM_SAMPLES * NUM_SAMPLES;    
+    
+    return max(0.0, 1.0 - factor * ssao_params.y);
+}
+
 void main()
 {
     vec3 normal;
-    float depth = texture2D(depthbuffer, framecoords.xy).r;
-	
-    //First we need to calculate the view space distance from the shader inputs
-    //This will unfortunately depend on the precision of the depth buffer which is not linear
-    vec2 norm_scr = framecoords.xy * 2.0 - 1.0;
-    vec4 viewposition = vec4(norm_scr.x, norm_scr.y, depth, 1.0);
-    
-    // convert to view space now
-    viewposition = gl_ProjectionMatrixInverse * viewposition;
-    viewposition = viewposition / viewposition.w;
+    vec4 position = calculate_view_space_position(framecoords.xy);
     
-    normal = calculate_ss_normal(viewposition);
-    vec3 color = normal;
+    normal = calculate_view_space_normal(position);
+    //vec3 color = normal * 0.5 + vec3(0.5);
     
     // blend between blurred-non blurred images based on coc	
     //vec4 color = coc * texture2D(blurredcolorbuffer, framecoords.xy) +
     //       (1.0 - coc) * texture2D(colorbuffer, framecoords.xy);
     
+    vec4 color = texture2D(colorbuffer, framecoords.xy) *
+           calculate_ssao_factor(normal, position); 
     gl_FragColor = vec4(color.xyz, 1.0);
 }
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index f785901..cef93dd 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -220,6 +220,8 @@ typedef struct View3D {
 	float dof_focal_distance; /* focal distance for depth of field */
 	float dof_aperture;           /* aperture for dof lens (could use fstop as well) */
 	float dof_fstop;
+	float ssao_darkening;
+	float ssao_scale;
 	float pad4;
 	
 	void *properties_storage;		/* Nkey panel stores stuff here (runtime only!) */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 63f967d..414f437 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2180,20 +2180,30 @@ static void rna_def_space_view3d(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Depth Of Field", "Use depth of field on viewport using the values from active camera");
 	RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 	
-	prop = RNA_def_property(srna, "dof_focal_distance", PROP_FLOAT, PROP_UNIT_CAMERA);
+	prop = RNA_def_property(srna, "dof_focal_distance", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_ui_text(prop, "Focal distance", "Viewport dof focal distance");
 	RNA_def_property_range(prop, 0.0f, 100000.0f);
 	RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 
-	prop = RNA_def_property(srna, "dof_aperture", PROP_FLOAT, PROP_UNIT_CAMERA);
+	prop = RNA_def_property(srna, "dof_aperture", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_ui_text(prop, "Aperture", "Aperture for dof effect");
 	RNA_def_property_range(prop, 0.0f, 250.0f);
 	RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 
-	prop = RNA_def_property(srna, "dof_fstop", PROP_FLOAT, PROP_UNIT_CAMERA);
+	prop = RNA_def_property(srna, "dof_fstop", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_ui_text(prop, "FStop", "FStop for dof effect");
 	RNA_def_property_range(prop, 0.0f, 250.0f);
 	RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+	prop = RNA_def_property(srna, "ssao_darkening", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_ui_text(prop, "Darkening", "Darken the ssao effect");
+	RNA_def_property_range(prop, 0.0f, 250.0f);
+	RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+	prop = RNA_def_property(srna, "ssao_scale", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_ui_text(prop, "Scale", "Scale the SSAO search area");
+	RNA_def_property_range(prop, 0.0f, 100000.0f);
+	RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 	
 	prop = RNA_def_property(srna, "ssao", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "shader_fx", V3D_FX_SSAO);




More information about the Bf-blender-cvs mailing list