Viewport compositing - first code
authorAntony Riakiotakis <kalast@gmail.com>
Thu, 12 Feb 2015 17:54:41 +0000 (18:54 +0100)
committerAntony Riakiotakis <kalast@gmail.com>
Thu, 12 Feb 2015 17:54:41 +0000 (18:54 +0100)
This commit introduces a few ready made effects for the 3D viewport
and OpenGL rendering.

Included effects are Depth of Field, accessible from camera view
and screen space ambient occlusion. Those effects can be turned on and
tweaked from the shading panel in the 3D viewport.

Off screen rendering will use the settings of the current camera.

WIP documentation can be found here:

http://wiki.blender.org/index.php/User:Psy-Fi/Framebuffer_Post-processing

36 files changed:
SConstruct
release/scripts/startup/bl_ui/properties_data_camera.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/CMakeLists.txt
source/blender/blenkernel/BKE_camera.h
source/blender/blenkernel/BKE_screen.h
source/blender/blenkernel/intern/camera.c
source/blender/blenkernel/intern/screen.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/include/ED_view3d.h
source/blender/editors/render/render_opengl.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/GPU_compositing.h [new file with mode: 0644]
source/blender/gpu/GPU_extensions.h
source/blender/gpu/SConscript
source/blender/gpu/intern/gpu_codegen.c
source/blender/gpu/intern/gpu_compositing.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_fx_lib.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_fx_vert.glsl [new file with mode: 0644]
source/blender/makesdna/DNA_camera_types.h
source/blender/makesdna/DNA_gpu_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/intern/rna_camera.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_space.c

index 7de9f2c243c20ffd3763bcf6ac626573957625cc..225b532c8a0ec4f7ad81848533e9363f15ecc932 100644 (file)
@@ -761,6 +761,11 @@ if B.targets != ['cudakernels']:
     data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex_world.glsl")
     data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
     data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
+    data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl")
+    data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl")
+    data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl")
+    data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_lib.glsl")
+    data_to_c_simple("source/blender/gpu/shaders/gpu_shader_fx_vert.glsl")
     data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")
 
     # --- blender ---
index 0b0b9b6690ddf0683e64418aff6fd430afc08cb2..7fc2c2ec084e9ffc99b926780a6c5f5116163e88 100644 (file)
@@ -177,6 +177,7 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
         layout = self.layout
 
         cam = context.camera
+        dof_options = cam.gpu_dof
 
         layout.label(text="Focus:")
 
@@ -187,6 +188,7 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
 
         col.active = cam.dof_object is None
         col.prop(cam, "dof_distance", text="Distance")
+        col.prop(dof_options, "fstop", text="GPU fstop")
 
 
 class DATA_PT_camera_display(CameraButtonsPanel, Panel):
index d2c95715a7ec04613b0cd86e213ff76c98513169..b5bd13781f7dc90c362c41f03cf2841f54345df4 100644 (file)
@@ -2929,8 +2929,26 @@ class VIEW3D_PT_view3d_shading(Panel):
                 col.prop(view, "show_textured_shadeless")
 
         col.prop(view, "show_backface_culling")
-        if obj and obj.mode == 'EDIT' and view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
-            col.prop(view, "show_occlude_wire")
+
+        if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}:
+            if obj and obj.mode == 'EDIT':
+                col.prop(view, "show_occlude_wire")
+
+            fx_settings = view.fx_settings
+
+            sub = col.column()
+            sub.active = view.region_3d.view_perspective == 'CAMERA'
+            sub.prop(fx_settings, "use_dof")
+
+            col.prop(fx_settings, "use_ssao", text="Ambient Occlusion")
+            if fx_settings.use_ssao:
+                ssao_settings = fx_settings.ssao
+                subcol = col.column(align=True)
+                subcol.prop(ssao_settings, "factor")
+                subcol.prop(ssao_settings, "distance_max")
+                subcol.prop(ssao_settings, "attenuation")
+                subcol.prop(ssao_settings, "samples")
+                subcol.prop(ssao_settings, "color")
 
 
 class VIEW3D_PT_view3d_motion_tracking(Panel):
index 1cc232a8ed6ce34b36ca4a52f4cb9234c3e01643..d87d5dfc2cce7abf0ebf010e7971d900efb497fd 100644 (file)
@@ -46,6 +46,7 @@ set(SRC_DNA_INC
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_freestyle_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_genfile.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_types.h
+       ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_group_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ipo_types.h
index 26d4986d93e77204ddebf0323555e3ab05d1f791..77296920ee2a790f6af02c30ba4c0cf14578d296 100644 (file)
@@ -46,6 +46,7 @@ struct RenderData;
 struct Scene;
 struct rctf;
 struct View3D;
+struct GPUFXSettings;
 
 /* Camera Datablock */
 
@@ -122,6 +123,8 @@ bool BKE_camera_view_frame_fit_to_scene(struct Scene *scene, struct View3D *v3d,
 bool BKE_camera_view_frame_fit_to_coords(struct Scene *scene, float (*cos)[3], int num_cos,
                                          struct Object *camera_ob, float r_co[3], float *r_scale);
 
+void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings);
+
 #ifdef __cplusplus
 }
 #endif
index 3eb6ba7b6faf677c155d6ed9b40946a5c4d6965c..29590c52b23531c4f19b081fa8bbdded9edc6d36 100644 (file)
@@ -52,6 +52,7 @@ struct wmKeyConfig;
 struct wmNotifier;
 struct wmWindow;
 struct wmWindowManager;
+struct GPUFXSettings;
 
 #include "BLI_compiler_attrs.h"
 
@@ -294,6 +295,7 @@ void BKE_screen_view3d_scene_sync(struct bScreen *sc);
 void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene);
 void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i);
 void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i);
+void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings);
 
 /* zoom factor conversion */
 float BKE_screen_view3d_zoom_to_fac(float camzoom);
index e424823d8dc585ec7699bf1486f5349236c35fe5..e1d771dad65d26a89ba8265c37c21a639e8cb1f8 100644 (file)
@@ -49,6 +49,8 @@
 #include "BKE_main.h"
 #include "BKE_screen.h"
 
+#include "GPU_compositing.h"
+
 /****************************** Camera Datablock *****************************/
 
 void *BKE_camera_add(Main *bmain, const char *name)
@@ -66,7 +68,9 @@ void *BKE_camera_add(Main *bmain, const char *name)
        cam->ortho_scale = 6.0;
        cam->flag |= CAM_SHOWPASSEPARTOUT;
        cam->passepartalpha = 0.5f;
-       
+
+       GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
+
        return cam;
 }
 
@@ -686,3 +690,18 @@ bool BKE_camera_view_frame_fit_to_coords(
        return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
 }
 
+void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings)
+{
+       if (camera->type == OB_CAMERA) {
+               Camera *cam = camera->data;
+               r_fx_settings->dof = &cam->gpu_dof;
+               r_fx_settings->dof->focal_length = cam->lens;
+               r_fx_settings->dof->sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
+               if (cam->dof_ob) {
+                       r_fx_settings->dof->focus_distance = len_v3v3(cam->dof_ob->obmat[3], camera->obmat[3]);
+               }
+               else {
+                       r_fx_settings->dof->focus_distance = cam->YF_dofdist;
+               }
+       }
+}
index c9dba38b713e238655f893a3913bc67eacdf9d67..a6ac4551f4a09071141605737066e874de3a13f5 100644 (file)
@@ -39,6 +39,8 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "GPU_compositing.h"
+
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
@@ -598,3 +600,26 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac)
 {
        return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f);
 }
+
+void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
+{
+       /* currently we use DOF from the camera _only_,
+        * so we never allocate this, only copy from the Camera */
+#if 0
+       if ((fx_settings->dof == NULL) &&
+           (fx_settings->fx_flag & GPU_FX_FLAG_DOF))
+       {
+               GPUDOFSettings *fx_dof;
+               fx_dof = fx_settings->dof = MEM_callocN(sizeof(GPUDOFSettings), __func__);
+       }
+#endif
+
+       if ((fx_settings->ssao == NULL) &&
+           (fx_settings->fx_flag & GPU_FX_FLAG_SSAO))
+       {
+               GPUSSAOSettings *fx_ssao;
+               fx_ssao = fx_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__);
+
+               GPU_fx_compositor_init_ssao_settings(fx_ssao);
+       }
+}
index 66fbca395a8a14f7073741519c71609c195631bc..204a7af69eff15f88e6c95df5ef2badb8d405ea2 100644 (file)
@@ -6421,6 +6421,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
                                rv3d->render_engine = NULL;
                                rv3d->sms = NULL;
                                rv3d->smooth_timer = NULL;
+                               rv3d->compositor = NULL;
                        }
                }
        }
@@ -6528,7 +6529,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
                /* add local view3d too */
                else if (sa->spacetype == SPACE_VIEW3D)
                        blo_do_versions_view3d_split_250(sa->spacedata.first, &sa->regionbase);
-               
+
                /* incase we set above */
                sa->butspacetype = sa->spacetype;
 
@@ -6575,6 +6576,11 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
                                /* render can be quite heavy, set to solid on load */
                                if (v3d->drawtype == OB_RENDER)
                                        v3d->drawtype = OB_SOLID;
+
+                               if (v3d->fx_settings.dof)
+                                       v3d->fx_settings.dof = newdataadr(fd, v3d->fx_settings.dof);
+                               if (v3d->fx_settings.ssao)
+                                       v3d->fx_settings.ssao = newdataadr(fd, v3d->fx_settings.ssao);
                                
                                blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
                        }
index 572566df6a2e76a1b428cccd321939038a92bb3a..23bf291b981212ee6117dce013a1e98a1fc40d8e 100644 (file)
@@ -35,6 +35,7 @@
 #define DNA_DEPRECATED_ALLOW
 
 #include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
 #include "DNA_cloth_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_sdna_types.h"
@@ -562,6 +563,16 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                        }
                        FOREACH_NODETREE_END
                }
+
+               if (!DNA_struct_elem_find(fd->filesdna, "Camera", "GPUDOFSettings", "gpu_dof")) {
+                       Camera *ca;
+                       for (ca = main->camera.first; ca; ca = ca->id.next) {
+                               ca->gpu_dof.fstop = 128.0f;
+                               ca->gpu_dof.focal_length = 1.0f;
+                               ca->gpu_dof.focus_distance = 1.0f;
+                               ca->gpu_dof.sensor = 1.0f;
+                       }
+               }
        }
 
        if (!MAIN_VERSION_ATLEAST(main, 273, 7)) {
index 6031400684c091d2b45acb71f1034df12a3f5e04..308ab448fcd84771f37b893d143f05694f17c265 100644 (file)
@@ -2682,6 +2682,11 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                        for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next)
                                                writestruct(wd, DATA, "BGpic", 1, bgpic);
                                        if (v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
+
+                                       if (v3d->fx_settings.ssao)
+                                               writestruct(wd, DATA, "GPUSSAOSettings", 1, v3d->fx_settings.ssao);
+                                       if (v3d->fx_settings.dof)
+                                               writestruct(wd, DATA, "GPUDOFSettings", 1, v3d->fx_settings.dof);
                                }
                                else if (sl->spacetype==SPACE_IPO) {
                                        SpaceIpo *sipo= (SpaceIpo *)sl;
index b62d99601177ce8767f680afcd2a2dca49bee676..e6434a19952e2774434683666b5a68452e0bc8ba 100644 (file)
@@ -61,6 +61,10 @@ struct rcti;
 struct wmOperator;
 struct wmOperatorType;
 struct wmWindow;
+struct GPUFX;
+struct GPUOffScreen;
+struct GPUFXSettings;
+enum eGPUFXFlags;
 
 /* for derivedmesh drawing callbacks, for view3d_select, .... */
 typedef struct ViewContext {
@@ -303,8 +307,11 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active);
 
 bool ED_view3d_context_activate(struct bContext *C);
 void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d);
-void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
-                              int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky);
+void ED_view3d_draw_offscreen(
+        struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
+        float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp,
+        struct GPUOffScreen *ofs,
+        struct GPUFX *fx, struct GPUFXSettings *fx_settings);
 
 struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
                                              bool draw_background, int alpha_mode, char err_out[256]);
index fc6ff4eb0c0c58f351491225433933f1af9f7d19..402e72db217dbfc2ed8b052fd706a3c1c8ebfc61 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_camera_types.h"
 #include "BLI_math.h"
 #include "BLI_math_color_blend.h"
 #include "BLI_blenlib.h"
@@ -42,6 +43,7 @@
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
 
+#include "BKE_camera.h"
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_image.h"
@@ -68,6 +70,7 @@
 
 #include "GPU_extensions.h"
 #include "GPU_glew.h"
+#include "GPU_compositing.h"
 
 
 #include "render_intern.h"
@@ -92,6 +95,7 @@ typedef struct OGLRender {
        ImageUser iuser;
 
        GPUOffScreen *ofs;
+       GPUFX *fx;
        int sizex, sizey;
        int write_still;
 
@@ -180,7 +184,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                        int i;
                        unsigned char *gp_rect;
 
-                       GPU_offscreen_bind(oglrender->ofs);
+                       GPU_offscreen_bind(oglrender->ofs, true);
 
                        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -200,22 +204,27 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                                rgba_uchar_to_float(col_src, &gp_rect[i]);
                                blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src);
                        }
-                       GPU_offscreen_unbind(oglrender->ofs);
+                       GPU_offscreen_unbind(oglrender->ofs, true);
 
                        MEM_freeN(gp_rect);
                }
        }
        else if (view_context) {
+               bool is_persp;
+               /* full copy */
+               GPUFXSettings fx_settings = v3d->fx_settings;
+
                ED_view3d_draw_offscreen_init(scene, v3d);
 
-               GPU_offscreen_bind(oglrender->ofs); /* bind */
+               GPU_offscreen_bind(oglrender->ofs, true); /* bind */
 
                /* render 3d view */
                if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
                        /*int is_ortho = scene->r.mode & R_ORTHO;*/
                        camera = v3d->camera;
                        RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat);
-                       
+                       is_persp = true;
+                       BKE_camera_to_gpu_dof(camera, &fx_settings);
                }
                else {
                        rctf viewplane;
@@ -224,12 +233,17 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                        bool is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
                        if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
                        else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+
+                       is_persp = !is_ortho;
                }
 
                rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
 
                if ((scene->r.mode & R_OSA) == 0) {
-                       ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
+                       ED_view3d_draw_offscreen(
+                               scene, v3d, ar, sizex, sizey, NULL, winmat,
+                               draw_bgpic, draw_sky, is_persp,
+                               oglrender->ofs, oglrender->fx, &fx_settings);
                        GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
                }
                else {
@@ -242,7 +256,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                        BLI_jitter_init(jit_ofs, scene->r.osa);
 
                        /* first sample buffer, also initializes 'rv3d->persmat' */
-                       ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky);
+                       ED_view3d_draw_offscreen(
+                               scene, v3d, ar, sizex, sizey, NULL, winmat,
+                               draw_bgpic, draw_sky, is_persp,
+                               oglrender->ofs, oglrender->fx, &fx_settings);
                        GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
 
                        for (i = 0; i < sizex * sizey * 4; i++)
@@ -255,7 +272,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                                                    (jit_ofs[j][0] * 2.0f) / sizex,
                                                    (jit_ofs[j][1] * 2.0f) / sizey);
 
-                               ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky);
+                               ED_view3d_draw_offscreen(
+                                       scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
+                                       draw_bgpic, draw_sky, is_persp,
+                                       oglrender->ofs, oglrender->fx, &fx_settings);
                                GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
 
                                for (i = 0; i < sizex * sizey * 4; i++)
@@ -268,7 +288,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                        MEM_freeN(accum_buffer);
                }
 
-               GPU_offscreen_unbind(oglrender->ofs); /* unbind */
+               GPU_offscreen_unbind(oglrender->ofs, true); /* unbind */
        }
        else {
                /* shouldnt suddenly give errors mid-render but possible */
@@ -448,6 +468,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
                 * running notifiers again will overwrite */
                oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal;
 
+               if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) {
+                       oglrender->fx = GPU_fx_compositor_create();
+               }
        }
 
        /* create render */
@@ -497,6 +520,9 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
 
        WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
 
+       if (oglrender->fx)
+               GPU_fx_compositor_destroy(oglrender->fx);
+
        GPU_offscreen_free(oglrender->ofs);
 
        oglrender->scene->customdata_mask_modal = 0;
index 6ac2f426ed778b51e6d8543dcbb525e63b5f4af5..01a70d36edaefa100cbc4de112a6179bf467b6de 100644 (file)
@@ -7392,7 +7392,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) {
                        if (ob->type == OB_MESH) {
                                if (dt < OB_SOLID) {
-                                       zbufoff = 1;
+                                       zbufoff = true;
                                        dt = OB_SOLID;
                                }
 
index 25085368dac540447d3a24241eed3e0da86bc8dd..ff212a1d74e2ba9a5962d89fed535a9402fcca32 100644 (file)
@@ -56,6 +56,7 @@
 
 #include "GPU_extensions.h"
 #include "GPU_material.h"
+#include "GPU_compositing.h"
 
 #include "BIF_gl.h"
 
@@ -418,6 +419,11 @@ static void view3d_free(SpaceLink *sl)
                BKE_previewimg_free(&vd->defmaterial->preview);
                MEM_freeN(vd->defmaterial);
        }
+
+               if (vd->fx_settings.ssao)
+                       MEM_freeN(vd->fx_settings.ssao);
+               if (vd->fx_settings.dof)
+                       MEM_freeN(vd->fx_settings.dof);
 }
 
 
@@ -459,7 +465,11 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
        }
 
        v3dn->properties_storage = NULL;
-       
+       if (v3dn->fx_settings.dof)
+               v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
+       if (v3dn->fx_settings.ssao)
+               v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao);
+
        return (SpaceLink *)v3dn;
 }
 
@@ -559,6 +569,11 @@ static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
                GPU_offscreen_free(rv3d->gpuoffscreen);
                rv3d->gpuoffscreen = NULL;
        }
+       
+       if (rv3d->compositor) {
+               GPU_fx_compositor_destroy(rv3d->compositor);
+               rv3d->compositor = NULL;
+       }
 }
 
 static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
@@ -713,6 +728,9 @@ static void view3d_main_area_free(ARegion *ar)
                if (rv3d->gpuoffscreen) {
                        GPU_offscreen_free(rv3d->gpuoffscreen);
                }
+               if (rv3d->compositor) {
+                       GPU_fx_compositor_destroy(rv3d->compositor);
+               }
 
                MEM_freeN(rv3d);
                ar->regiondata = NULL;
@@ -736,6 +754,7 @@ static void *view3d_main_area_duplicate(void *poin)
                new->render_engine = NULL;
                new->sms = NULL;
                new->smooth_timer = NULL;
+               new->compositor = NULL;
                
                return new;
        }
index 929929c7dd06a723bce81a347f62c9c7b9e6e4de..94d0ffcc9eecc13e2221a9128ddef99a642100b9 100644 (file)
@@ -94,6 +94,7 @@
 #include "GPU_draw.h"
 #include "GPU_material.h"
 #include "GPU_extensions.h"
+#include "GPU_compositing.h"
 
 #include "view3d_intern.h"  /* own include */
 
@@ -1374,7 +1375,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
        }
 
        if (rv3d->gpuoffscreen)
-               GPU_offscreen_bind(rv3d->gpuoffscreen);
+               GPU_offscreen_bind(rv3d->gpuoffscreen, true);
        else
                glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
 
@@ -1397,7 +1398,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
                draw_object_backbufsel(scene, v3d, rv3d, base->object);
        
        if (rv3d->gpuoffscreen)
-               GPU_offscreen_unbind(rv3d->gpuoffscreen);
+               GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
        else
                ar->swap = 0; /* mark invalid backbuf for wm draw */
 
@@ -1423,10 +1424,10 @@ void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int form
        RegionView3D *rv3d = ar->regiondata;
 
        if (rv3d->gpuoffscreen) {
-               GPU_offscreen_bind(rv3d->gpuoffscreen);
+               GPU_offscreen_bind(rv3d->gpuoffscreen, true);
                glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
                glReadPixels(x, y, w, h, format, type, data);
-               GPU_offscreen_unbind(rv3d->gpuoffscreen);
+               GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
        }
        else {
                glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
@@ -2532,7 +2533,10 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
                invert_m4_m4(rv3d.persinv, rv3d.viewinv);
 
                /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
-               ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, false, false);
+               ED_view3d_draw_offscreen(
+                           scene, v3d, &ar, winsize, winsize, viewmat, winmat,
+                           false, false, true,
+                           NULL, NULL, NULL);
                GPU_lamp_shadow_buffer_unbind(shadow->lamp);
                
                v3d->drawtype = drawtype;
@@ -3049,13 +3053,18 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool
 /* ED_view3d_draw_offscreen_init should be called before this to initialize
  * stuff like shadow buffers
  */
-void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
-                              float viewmat[4][4], float winmat[4][4],
-                              bool do_bgpic, bool do_sky)
+void ED_view3d_draw_offscreen(
+        Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
+        float viewmat[4][4], float winmat[4][4],
+        bool do_bgpic, bool do_sky, bool is_persp,
+        GPUOffScreen *ofs,
+        GPUFX *fx, GPUFXSettings *fx_settings)
 {
        struct bThemeState theme_state;
        int bwinx, bwiny;
        rcti brect;
+       bool do_compositing = false;
+       RegionView3D *rv3d = ar->regiondata;
 
        glPushMatrix();
 
@@ -3082,9 +3091,15 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
                 * warning! can be slow so only free animated images - campbell */
                GPU_free_images_anim();
        }
-       /* setup view matrices */
+
+       /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
        view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
-       
+
+       /* framebuffer fx needed, we need to draw offscreen first */
+       if (v3d->fx_settings.fx_flag && fx) {
+               do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
+       }
+
        /* clear opengl buffers */
        if (do_sky) {
                view3d_main_area_clear(scene, v3d, ar, true);
@@ -3097,6 +3112,13 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
        /* main drawing call */
        view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true);
 
+       /* post process */
+       if (do_compositing) {
+               if (!winmat)
+                       is_persp = rv3d->is_persp;
+               GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
+       }
+
        if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
                /* draw grease-pencil stuff */
                ED_region_pixelspace(ar);
@@ -3131,7 +3153,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
        ImBuf *ibuf;
        GPUOffScreen *ofs;
        bool draw_sky = (alpha_mode == R_ADDSKY);
-       
+
        /* state changes make normal drawing go weird otherwise */
        glPushAttrib(GL_LIGHTING_BIT);
 
@@ -3144,11 +3166,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
 
        ED_view3d_draw_offscreen_init(scene, v3d);
 
-       GPU_offscreen_bind(ofs);
+       GPU_offscreen_bind(ofs, true);
 
        /* render 3d view */
        if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
                CameraParams params;
+               GPUFXSettings fx_settings = {0};
+               Object *camera = v3d->camera;
 
                BKE_camera_params_init(&params);
                /* fallback for non camera objects */
@@ -3158,10 +3182,18 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
                BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
                BKE_camera_params_compute_matrix(&params);
 
-               ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, draw_sky);
+               BKE_camera_to_gpu_dof(camera, &fx_settings);
+
+               ED_view3d_draw_offscreen(
+                       scene, v3d, ar, sizex, sizey, NULL, params.winmat,
+                       draw_background, draw_sky, !params.is_ortho,
+                       ofs, NULL, &fx_settings);
        }
        else {
-               ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, draw_sky);
+               ED_view3d_draw_offscreen(
+                       scene, v3d, ar, sizex, sizey, NULL, NULL,
+                       draw_background, draw_sky, true,
+                       ofs, NULL, NULL);
        }
 
        /* read in pixels & stamp */
@@ -3173,7 +3205,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
                GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
 
        /* unbind */
-       GPU_offscreen_unbind(ofs);
+       GPU_offscreen_unbind(ofs, true);
        GPU_offscreen_free(ofs);
 
        glPopAttrib();
@@ -3451,13 +3483,15 @@ static void update_lods(Scene *scene, float camera_pos[3])
 }
 #endif
 
-
 static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
                                           ARegion *ar, const char **grid_unit)
 {
        RegionView3D *rv3d = ar->regiondata;
        unsigned int lay_used = v3d->lay_used;
-
+       
+       /* post processing */
+       bool do_compositing = false;
+       
        /* shadow buffers, before we setup matrices */
        if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
                gpu_update_lamps_shadows(scene, v3d);
@@ -3481,6 +3515,22 @@ 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->fx_settings.fx_flag) {
+               GPUFXSettings fx_settings;
+               BKE_screen_gpu_fx_validate(&v3d->fx_settings);
+               fx_settings = v3d->fx_settings;
+               if (!rv3d->compositor)
+                       rv3d->compositor = GPU_fx_compositor_create();
+               
+               if (rv3d->persp == RV3D_CAMOB && v3d->camera)
+                       BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
+               else {
+                       fx_settings.dof = NULL;
+               }
+               do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
+       }
+       
        /* clear the background */
        view3d_main_area_clear(scene, v3d, ar, false);
 
@@ -3492,6 +3542,11 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
        /* main drawing call */
        view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false);
 
+       /* post process */
+       if (do_compositing) {
+               GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
+       }
+       
        /* Disable back anti-aliasing */
        if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
                glDisable(GL_MULTISAMPLE_ARB);
index 361c247767fbbe3028bacf06b57755a4dd8ef93a..7e32105a9164c4a75ba027edaab8e2cbf70242de 100644 (file)
@@ -54,6 +54,21 @@ set(SRC
        intern/gpu_material.c
        intern/gpu_simple_shader.c
        intern/gpu_select.c
+       intern/gpu_compositing.c
+
+       shaders/gpu_shader_fx_lib.glsl
+       shaders/gpu_shader_fx_ssao_frag.glsl
+       shaders/gpu_shader_fx_dof_frag.glsl
+       shaders/gpu_shader_fx_dof_vert.glsl
+       shaders/gpu_shader_fx_vert.glsl
+       shaders/gpu_shader_material.glsl
+       shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+       shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+       shaders/gpu_shader_simple_frag.glsl
+       shaders/gpu_shader_simple_vert.glsl
+       shaders/gpu_shader_vertex.glsl
+       shaders/gpu_shader_vsm_store_frag.glsl
+       shaders/gpu_shader_vsm_store_vert.glsl
 
        GPU_buffers.h
        GPU_draw.h
@@ -63,6 +78,7 @@ set(SRC
        GPU_material.h
        GPU_simple_shader.h
        GPU_select.h
+       GPU_compositing.h
        intern/gpu_codegen.h
        intern/gpu_extensions_private.h
 )
@@ -76,6 +92,11 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC)
 
 if(WITH_GAMEENGINE)
        add_definitions(-DWITH_GAMEENGINE)
diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h
new file mode 100644 (file)
index 0000000..796341d
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_compositing.h
+ *  \ingroup gpu
+ */
+
+#ifndef __GPU_COMPOSITING_H__
+#define __GPU_COMPOSITING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* opaque handle for framebuffer compositing effects (defined in gpu_compositing.c )*/
+typedef struct GPUFX GPUFX;
+struct GPUDOFSettings;
+struct GPUSSAOSettings;
+struct GPUOffScreen;
+struct GPUFXSettings;
+struct RegionView3D;
+struct rcti;
+struct Scene;
+struct View3D;
+enum eGPUFXFlags;
+
+/**** Public API *****/
+
+typedef enum GPUFXShaderEffect {
+       /* Screen space ambient occlusion shader */
+       GPU_SHADER_FX_SSAO           = 1,
+
+       /* depth of field passes. Yep, quite a complex effect */
+       GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2,
+       GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO = 3,
+       GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4,
+       GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5,
+       GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6,
+} GPUFXShaderEffect;
+
+/* keep in synch with enum above! */
+#define MAX_FX_SHADERS 11
+
+/* generate a new FX compositor */
+GPUFX *GPU_fx_compositor_create(void);
+
+/* destroy a text compositor */
+void GPU_fx_compositor_destroy(GPUFX *fx);
+
+/* initialize a framebuffer with size taken from the viewport */
+bool GPU_fx_compositor_initialize_passes(
+        GPUFX *fx, const struct rcti *rect, const struct rcti *scissor_rect,
+        const struct GPUFXSettings *fx_settings);
+
+/* do compositing on the fx passes that have been initialized */
+bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs);
+
+void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
+void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __GPU_COMPOSITING_H__
index bb0cf2dd2b90ab94f93aca222989a52642325257..739d45663f8dc239b6f1d7bd0fd28cd11326b6a7 100644 (file)
@@ -107,11 +107,19 @@ int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
  *  - if created with from_blender, will not free the texture
  */
 
+typedef enum GPUHDRType {
+       GPU_HDR_NONE =       0,
+       GPU_HDR_HALF_FLOAT = 1,
+       GPU_HDR_FULL_FLOAT = (1 << 1),
+} GPUHDRType;
+
 GPUTexture *GPU_texture_create_1D(int w, float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, GPUHDRType hdr, char err_out[256]);
 GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels);
 GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
 GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_1D_procedural(int w, float *pixels, char err_out[256]);
 GPUTexture *GPU_texture_from_blender(struct Image *ima,
        struct ImageUser *iuser, bool is_data, double time, int mipmap);
 GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
@@ -126,6 +134,8 @@ void GPU_texture_ref(GPUTexture *tex);
 void GPU_texture_bind(GPUTexture *tex, int number);
 void GPU_texture_unbind(GPUTexture *tex);
 
+void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter);
+
 GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
 
 int GPU_texture_target(GPUTexture *tex);
@@ -145,11 +155,13 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
 GPUFrameBuffer *GPU_framebuffer_create(void);
 int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
 void GPU_framebuffer_texture_detach(GPUTexture *tex);
-void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot);
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
 void GPU_framebuffer_free(GPUFrameBuffer *fb);
 bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
 
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
+
 void GPU_framebuffer_restore(void);
 void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
 
@@ -159,8 +171,8 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
 
 GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]);
 void GPU_offscreen_free(GPUOffScreen *ofs);
-void GPU_offscreen_bind(GPUOffScreen *ofs);
-void GPU_offscreen_unbind(GPUOffScreen *ofs);
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
 void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
 int GPU_offscreen_width(GPUOffScreen *ofs);
 int GPU_offscreen_height(GPUOffScreen *ofs);
@@ -177,7 +189,7 @@ void GPU_shader_unbind(void);
 
 int GPU_shader_get_uniform(GPUShader *shader, const char *name);
 void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
-       int arraysize, float *value);
+       int arraysize, const float *value);
 void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
 void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
 
@@ -190,6 +202,8 @@ typedef enum GPUBuiltinShader {
 } GPUBuiltinShader;
 
 GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
+
 void GPU_shader_free_builtin_shaders(void);
 
 /* Vertex attributes for shaders */
index e44a99286a898c0161c98a3854de124b1a29ae98..158cfb67dda3358f3575aa3cc8a4355e936ee75f 100644 (file)
@@ -65,6 +65,11 @@ import os
 sources.extend((
     os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"),
     os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"),
+    os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),
+    os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_frag.glsl.c"),
+    os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_vert.glsl.c"),
+    os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_lib.glsl.c"),
+    os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_vert.glsl.c"),
     os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"),
     os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"),
     os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"),
index 97064f43f5d5b5b0b2dab66e0070a53cf3fb7603..9e4d0d5f82303bc97af77ea9c760371c0caa49be 100644 (file)
@@ -972,7 +972,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
                input->textype = type;
 
                //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
-               input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
+               input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
                input->textarget = GL_TEXTURE_2D;
 
                MEM_freeN(link->ptr1);
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
new file mode 100644 (file)
index 0000000..b423c14
--- /dev/null
@@ -0,0 +1,863 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_compositing.c
+ *  \ingroup gpu
+ *
+ * System that manages framebuffer compositing.
+ */
+
+#include "BLI_sys_types.h"
+#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+
+#include "BLI_rand.h"
+#include "BLI_listbase.h"
+
+#include "DNA_vec_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_gpu_types.h"
+
+#include "GPU_extensions.h"
+#include "GPU_compositing.h"
+
+#include "GL/glew.h"
+
+#include "MEM_guardedalloc.h"
+
+static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
+static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
+
+struct GPUFX {
+       /* we borrow the term gbuffer from deferred rendering however this is just a regular
+        * depth/color framebuffer. Could be extended later though */
+       GPUFrameBuffer *gbuffer;
+
+       /* texture bound to the first color attachment of the gbuffer */
+       GPUTexture *color_buffer;
+
+       /* second texture used for ping-pong compositing */
+       GPUTexture *color_buffer_sec;
+
+       /* all those buffers below have to coexist. Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
+       int dof_downsampled_w;
+       int dof_downsampled_h;
+
+       /* texture used for near coc and color blurring calculation */
+       GPUTexture *dof_near_coc_buffer;
+       /* blurred near coc buffer. */
+       GPUTexture *dof_near_coc_blurred_buffer;
+       /* final near coc buffer. */
+       GPUTexture *dof_near_coc_final_buffer;
+
+       /* half size blur buffer */
+       GPUTexture *dof_half_downsampled;
+       /* high quality dof texture downsamplers. 6 levels means 64 pixels wide */
+       GPUTexture *dof_nearfar_coc[6];
+       GPUTexture *dof_near_blur;
+       GPUTexture *dof_far_blur;
+       GPUTexture *dof_concentric_samples_tex;
+
+       /* texture bound to the depth attachment of the gbuffer */
+       GPUTexture *depth_buffer;
+
+       /* texture used for jittering for various effects */
+       GPUTexture *jitter_buffer;
+
+       /* texture used for ssao */
+       int ssao_sample_count;
+       GPUTexture *ssao_concentric_samples_tex;
+
+       /* dimensions of the gbuffer */
+       int gbuffer_dim[2];
+
+       GPUFXSettings settings;
+
+       /* or-ed flags of enabled effects */
+       int effects;
+
+       /* number of passes, needed to detect if ping pong buffer allocation is needed */
+       int num_passes;
+
+       /* we have a stencil, restore the previous state */
+       bool restore_stencil;
+};
+
+/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
+ * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
+static GPUTexture * create_concentric_sample_texture(int side)
+{
+       GPUTexture *tex;
+       float midpoint = 0.5f * (side - 1);
+       float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
+       int i, j;
+
+       for (i = 0; i < side; i++) {
+               for (j = 0; j < side; j++) {
+                       int index = (i * side + j) * 2;
+                       float a = 1.0f - i / midpoint;
+                       float b = 1.0f - j / midpoint;
+                       float phi, r;
+                       if (a * a > b * b) {
+                               r = a;
+                               phi = (M_PI_4) * (b / a);
+                       }
+                       else {
+                               r = b;
+                               phi = M_PI_2 - (M_PI_4) * (a / b);
+                       }
+                       texels[index] = r * cos(phi);
+                       texels[index + 1] = r * sin(phi);
+               }
+       }
+
+       tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
+       MEM_freeN(texels);
+       return tex;
+}
+
+/* generate a new FX compositor */
+GPUFX *GPU_fx_compositor_create(void)
+{
+       GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
+
+       return fx;
+}
+
+static void cleanup_fx_dof_buffers(GPUFX *fx)
+{
+       if (fx->dof_near_coc_blurred_buffer) {
+               GPU_texture_free(fx->dof_near_coc_blurred_buffer);
+               fx->dof_near_coc_blurred_buffer = NULL;
+       }
+       if (fx->dof_near_coc_buffer) {
+               GPU_texture_free(fx->dof_near_coc_buffer);
+               fx->dof_near_coc_buffer = NULL;
+       }
+       if (fx->dof_near_coc_final_buffer) {
+               GPU_texture_free(fx->dof_near_coc_final_buffer);
+               fx->dof_near_coc_final_buffer = NULL;
+       }
+
+       if (fx->dof_half_downsampled) {
+               GPU_texture_free(fx->dof_half_downsampled);
+               fx->dof_half_downsampled = NULL;
+       }
+       if (fx->dof_nearfar_coc[0]) {
+               int i;
+               for (i = 0; i < 6; i++) {
+                       GPU_texture_free(fx->dof_nearfar_coc[i]);
+                       fx->dof_nearfar_coc[i] = NULL;
+               }
+       }
+       if (fx->dof_near_blur) {
+               GPU_texture_free(fx->dof_near_blur);
+               fx->dof_near_blur = NULL;
+       }
+       if (fx->dof_far_blur) {
+               GPU_texture_free(fx->dof_far_blur);
+               fx->dof_far_blur = NULL;
+       }
+       if (fx->dof_concentric_samples_tex) {
+               GPU_texture_free(fx->dof_concentric_samples_tex);
+               fx->dof_concentric_samples_tex = NULL;
+       }
+}
+
+static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
+{
+       if (fx->color_buffer) {
+               GPU_framebuffer_texture_detach(fx->color_buffer);
+               GPU_texture_free(fx->color_buffer);
+               fx->color_buffer = NULL;
+       }
+
+       if (fx->color_buffer_sec) {
+               GPU_framebuffer_texture_detach(fx->color_buffer_sec);
+               GPU_texture_free(fx->color_buffer_sec);
+               fx->color_buffer_sec = NULL;
+       }
+
+       if (fx->depth_buffer) {
+               GPU_framebuffer_texture_detach(fx->depth_buffer);
+               GPU_texture_free(fx->depth_buffer);
+               fx->depth_buffer = NULL;
+       }
+
+       cleanup_fx_dof_buffers(fx);
+
+       if (fx->ssao_concentric_samples_tex) {
+               GPU_texture_free(fx->ssao_concentric_samples_tex);
+               fx->ssao_concentric_samples_tex = NULL;
+       }
+
+       if (fx->jitter_buffer && do_fbo) {
+               GPU_texture_free(fx->jitter_buffer);
+               fx->jitter_buffer = NULL;
+       }
+
+       if (fx->gbuffer && do_fbo) {
+               GPU_framebuffer_free(fx->gbuffer);
+               fx->gbuffer = NULL;
+       }
+}
+
+/* destroy a text compositor */
+void GPU_fx_compositor_destroy(GPUFX *fx)
+{
+       cleanup_fx_gl_data(fx, true);
+       MEM_freeN(fx);
+}
+
+static GPUTexture * create_jitter_texture(void)
+{
+       float jitter [64 * 64][2];
+       int i;
+
+       for (i = 0; i < 64 * 64; i++) {
+               jitter[i][0] = 2.0f * BLI_frand() - 1.0;
+               jitter[i][1] = 2.0f * BLI_frand() - 1.0;
+               normalize_v2(jitter[i]);
+       }
+
+       return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], NULL);
+}
+
+
+bool GPU_fx_compositor_initialize_passes(
+        GPUFX *fx, const rcti *rect, const rcti *scissor_rect,
+        const GPUFXSettings *fx_settings)
+{
+       int w = BLI_rcti_size_x(rect) + 1, h = BLI_rcti_size_y(rect) + 1;
+       char err_out[256];
+       int num_passes = 0;
+       char fx_flag = fx_settings->fx_flag;
+
+       fx->effects = 0;
+
+       if (!fx_settings) {
+               cleanup_fx_gl_data(fx, true);
+               return false;
+       }
+
+       /* disable effects if no options passed for them */
+       if (!fx_settings->dof) {
+               fx_flag &= ~GPU_FX_FLAG_DOF;
+       }
+       if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
+               fx_flag &= ~GPU_FX_FLAG_SSAO;
+       }
+
+       if (!fx_flag) {
+               cleanup_fx_gl_data(fx, true);
+               return false;
+       }
+
+       fx->num_passes = 0;
+       /* dof really needs a ping-pong buffer to work */
+       if (fx_flag & GPU_FX_FLAG_DOF)
+               num_passes++;
+
+       if (fx_flag & GPU_FX_FLAG_SSAO)
+               num_passes++;
+
+       if (!fx->gbuffer)
+               fx->gbuffer = GPU_framebuffer_create();
+
+       /* try creating the jitter texture */
+       if (!fx->jitter_buffer)
+               fx->jitter_buffer = create_jitter_texture();
+
+       if (!fx->gbuffer)
+               return false;
+
+       /* check if color buffers need recreation */
+       if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
+               cleanup_fx_gl_data(fx, false);
+
+               if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+                       printf(".256%s\n", err_out);
+                       cleanup_fx_gl_data(fx, true);
+                       return false;
+               }
+
+               if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
+                       printf("%.256s\n", err_out);
+                       cleanup_fx_gl_data(fx, true);
+                       return false;
+               }
+       }
+
+       if (fx_flag & GPU_FX_FLAG_SSAO) {
+               if (fx_settings->ssao->samples != fx->ssao_sample_count || !fx->ssao_concentric_samples_tex) {
+                       if (fx_settings->ssao->samples < 1)
+                               fx_settings->ssao->samples = 1;
+
+                       fx->ssao_sample_count = fx_settings->ssao->samples;
+
+                       if (fx->ssao_concentric_samples_tex) {
+                               GPU_texture_free(fx->ssao_concentric_samples_tex);
+                       }
+
+                       fx->ssao_concentric_samples_tex = create_concentric_sample_texture(fx_settings->ssao->samples);
+               }
+       }
+       else {
+               if (fx->ssao_concentric_samples_tex) {
+                       GPU_texture_free(fx->ssao_concentric_samples_tex);
+                       fx->ssao_concentric_samples_tex = NULL;
+               }
+       }
+
+       /* create textures for dof effect */
+       if (fx_flag & GPU_FX_FLAG_DOF) {
+               if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
+                       fx->dof_downsampled_w = w / 4;
+                       fx->dof_downsampled_h = h / 4;
+
+                       if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
+                                 fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+                       {
+                               printf("%.256s\n", err_out);
+                               cleanup_fx_gl_data(fx, true);
+                               return false;
+                       }
+                       if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
+                                 fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+                       {
+                               printf("%.256s\n", err_out);
+                               cleanup_fx_gl_data(fx, true);
+                               return false;
+                       }
+                       if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
+                                 fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+                       {
+                               printf("%.256s\n", err_out);
+                               cleanup_fx_gl_data(fx, true);
+                               return false;
+                       }
+               }
+       }
+       else {
+               /* cleanup unnecessary buffers */
+               cleanup_fx_dof_buffers(fx);
+       }
+
+       /* we need to pass data between shader stages, allocate an extra color buffer */
+       if (num_passes > 1) {
+               if(!fx->color_buffer_sec) {
+                       if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+                               printf(".256%s\n", err_out);
+                               cleanup_fx_gl_data(fx, true);
+                               return false;
+                       }
+               }
+       }
+       else {
+               if (fx->color_buffer_sec) {
+                       GPU_framebuffer_texture_detach(fx->color_buffer_sec);
+                       GPU_texture_free(fx->color_buffer_sec);
+                       fx->color_buffer_sec = NULL;
+               }
+       }
+
+       /* bind the buffers */
+
+       /* first depth buffer, because system assumes read/write buffers */
+       if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
+               printf("%.256s\n", err_out);
+
+       if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
+               printf("%.256s\n", err_out);
+
+       if(!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
+               printf("%.256s\n", err_out);
+
+       GPU_texture_bind_as_framebuffer(fx->color_buffer);
+
+       /* enable scissor test. It's needed to ensure sculpting works correctly */
+       if (scissor_rect) {
+               int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
+               int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
+               glPushAttrib(GL_SCISSOR_BIT);
+               glEnable(GL_SCISSOR_TEST);
+               glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
+                                 w_sc, h_sc);
+               fx->restore_stencil = true;
+       }
+       else {
+               fx->restore_stencil = false;
+       }
+
+       fx->effects = fx_flag;
+
+       if (fx_settings)
+               fx->settings = *fx_settings;
+       fx->gbuffer_dim[0] = w;
+       fx->gbuffer_dim[1] = h;
+
+       fx->num_passes = num_passes;
+
+       return true;
+}
+
+static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
+{
+       if ((*passes_left)-- == 1) {
+               GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
+               if (ofs) {
+                       GPU_offscreen_bind(ofs, false);
+               }
+               else
+                       GPU_framebuffer_restore();
+       }
+       else {
+               /* bind the ping buffer to the color buffer */
+               GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
+       }
+}
+
+bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs)
+{
+       GPUTexture *src, *target;
+       int numslots = 0;
+       float invproj[4][4];
+       int i;
+       /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
+       int passes_left = fx->num_passes;
+       /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
+       float viewvecs[3][4] = {
+           {-1.0f, -1.0f, -1.0f, 1.0f},
+           {1.0f, -1.0f, -1.0f, 1.0f},
+           {-1.0f, 1.0f, -1.0f, 1.0f}
+       };
+
+       if (fx->effects == 0)
+               return false;
+
+       /* first, unbind the render-to-texture framebuffer */
+       GPU_framebuffer_texture_detach(fx->color_buffer);
+       GPU_framebuffer_texture_detach(fx->depth_buffer);
+
+       if (fx->restore_stencil)
+               glPopAttrib();
+
+       src = fx->color_buffer;
+       target = fx->color_buffer_sec;
+
+       /* set up quad buffer */
+       glVertexPointer(2, GL_FLOAT, 0, fullscreencos);
+       glTexCoordPointer(2, GL_FLOAT, 0, fullscreenuvs);
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+       /* full screen FX pass */
+
+       /* invert the view matrix */
+       invert_m4_m4(invproj, projmat);
+
+       /* convert the view vectors to view space */
+       for (i = 0; i < 3; i++) {
+               mul_m4_v4(invproj, viewvecs[i]);
+               /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+               mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+               if (is_persp)
+                       mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
+               viewvecs[i][3] = 1.0;
+       }
+
+       /* we need to store the differences */
+       viewvecs[1][0] -= viewvecs[0][0];
+       viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
+
+       /* calculate a depth offset as well */
+       if (!is_persp) {
+               float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+               mul_m4_v4(invproj, vec_far);
+               mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+               viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
+       }
+
+       /* set invalid color in case shader fails */
+       glColor3f(1.0, 0.0, 1.0);
+       glDisable(GL_DEPTH_TEST);
+
+       /* ssao pass */
+       if (fx->effects & GPU_FX_FLAG_SSAO) {
+               GPUShader *ssao_shader;
+               ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
+               if (ssao_shader) {
+                       const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
+                       int color_uniform, depth_uniform;
+                       int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
+                       int ssao_jitter_uniform, ssao_concentric_tex;
+                       float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
+                       float sample_params[4];
+
+                       sample_params[0] = fx->ssao_sample_count * fx->ssao_sample_count;
+                       /* multiplier so we tile the random texture on screen */
+                       sample_params[2] = fx->gbuffer_dim[0] / 64.0;
+                       sample_params[3] = fx->gbuffer_dim[1] / 64.0;
+
+                       ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
+                       ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
+                       color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
+                       depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
+                       viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
+                       ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
+                       ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
+                       ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");
+
+                       GPU_shader_bind(ssao_shader);
+
+                       GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
+                       GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
+                       GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
+                       GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 4, 1, sample_params);
+
+                       GPU_texture_bind(src, numslots++);
+                       GPU_shader_uniform_texture(ssao_shader, color_uniform, src);
+
+                       GPU_texture_bind(fx->depth_buffer, numslots++);
+                       GPU_depth_texture_mode(fx->depth_buffer, false, true);
+                       GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);
+
+                       GPU_texture_bind(fx->jitter_buffer, numslots++);
+                       GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);
+
+                       GPU_texture_bind(fx->ssao_concentric_samples_tex, numslots++);
+                       GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_concentric_samples_tex);
+
+                       /* draw */
+                       gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
+
+                       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+                       /* disable bindings */
+                       GPU_texture_unbind(src);
+                       GPU_depth_texture_mode(fx->depth_buffer, true, false);
+                       GPU_texture_unbind(fx->depth_buffer);
+                       GPU_texture_unbind(fx->jitter_buffer);
+                       GPU_texture_unbind(fx->ssao_concentric_samples_tex);
+
+                       /* may not be attached, in that case this just returns */
+                       if (target) {
+                               GPU_framebuffer_texture_detach(target);
+                               if (ofs) {
+                                       GPU_offscreen_bind(ofs, false);
+                               }
+                               else {
+                                       GPU_framebuffer_restore();
+                               }
+                       }
+
+                       /* swap here, after src/target have been unbound */
+                       SWAP(GPUTexture *, target, src);
+                       numslots = 0;
+               }
+       }
+
+       /* second pass, dof */
+       if (fx->effects & GPU_FX_FLAG_DOF) {
+               const GPUDOFSettings *fx_dof = fx->settings.dof;
+               GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
+               float dof_params[4];
+               float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
+               float scale_camera = 0.001f / scale;
+               float aperture = 2.0f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
+
+               dof_params[0] = aperture * fabs(scale_camera * fx_dof->focal_length / (fx_dof->focus_distance - scale_camera * fx_dof->focal_length));
+               dof_params[1] = fx_dof->focus_distance;
+               dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
+               dof_params[3] = 0.0f;
+
+               /* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original
+                        * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based
+                        * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
+               dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
+               dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
+               dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
+               dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
+               dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
+
+               /* error occured, restore framebuffers and return */
+               if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
+                       GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
+                       GPU_framebuffer_restore();
+                       return false;
+               }
+
+               /* pass first, first level of blur in low res buffer */
+               {
+                       int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
+                       int viewvecs_uniform;
+
+                       float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
+
+                       dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
+                       invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
+                       color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
+                       depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
+                       viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
+
+                       GPU_shader_bind(dof_shader_pass1);
+
+                       GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
+                       GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                       GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+                       GPU_texture_bind(src, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);
+
+                       GPU_texture_bind(fx->depth_buffer, numslots++);
+                       GPU_depth_texture_mode(fx->depth_buffer, false, true);
+                       GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
+
+                       /* target is the downsampled coc buffer */
+                       GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+                       /* binding takes care of setting the viewport to the downsampled size */
+                       GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
+
+                       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+                       /* disable bindings */
+                       GPU_texture_unbind(src);
+                       GPU_depth_texture_mode(fx->depth_buffer, true, false);
+                       GPU_texture_unbind(fx->depth_buffer);
+
+                       GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
+                       numslots = 0;
+               }
+
+               /* second pass, gaussian blur the downsampled image */
+               {
+                       int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
+                       int viewvecs_uniform;
+                       float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
+                                                      1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+                       float tmp = invrendertargetdim[0];
+                       invrendertargetdim[0] = 0.0f;
+
+                       dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
+
+                       dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
+                       invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
+                       color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
+                       depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
+                       viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");
+
+                       /* Blurring vertically */
+                       GPU_shader_bind(dof_shader_pass2);
+
+                       GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
+                       GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                       GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+                       GPU_texture_bind(fx->depth_buffer, numslots++);
+                       GPU_depth_texture_mode(fx->depth_buffer, false, true);
+                       GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);
+
+                       GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);
+
+                       /* use final buffer as a temp here */
+                       GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+
+                       /* Drawing quad */
+                       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+                       /* *unbind/detach */
+                       GPU_texture_unbind(fx->dof_near_coc_buffer);
+                       GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
+
+                       /* Blurring horizontally */
+                       invrendertargetdim[0] = tmp;
+                       invrendertargetdim[1] = 0.0f;
+                       GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+                       GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);
+
+                       GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
+                       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+                       /* *unbind/detach */
+                       GPU_depth_texture_mode(fx->depth_buffer, true, false);
+                       GPU_texture_unbind(fx->depth_buffer);
+
+                       GPU_texture_unbind(fx->dof_near_coc_final_buffer);
+                       GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
+
+                       dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
+
+                       numslots = 0;
+               }
+
+               /* third pass, calculate near coc */
+               {
+                       int near_coc_downsampled, near_coc_blurred;
+
+                       near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
+                       near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");
+
+                       GPU_shader_bind(dof_shader_pass3);
+
+                       GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);
+
+                       GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);
+
+                       GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+
+                       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+                       /* disable bindings */
+                       GPU_texture_unbind(fx->dof_near_coc_buffer);
+                       GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
+
+                       /* unbinding here restores the size to the original */
+                       GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
+
+                       numslots = 0;
+               }
+
+               /* fourth pass blur final coc once to eliminate discontinuities */
+               {
+                       int near_coc_downsampled;
+                       int invrendertargetdim_uniform;
+                       float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
+                                                      1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+
+                       near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
+                       invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
+
+                       GPU_shader_bind(dof_shader_pass4);
+
+                       GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
+                       GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+                       GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+
+                       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+                       /* disable bindings */
+                       GPU_texture_unbind(fx->dof_near_coc_final_buffer);
+
+                       /* unbinding here restores the size to the original */
+                       GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
+                       GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
+
+                       numslots = 0;
+               }
+
+               /* final pass, merge blurred layers according to final calculated coc */
+               {
+                       int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
+                       int invrendertargetdim_uniform, viewvecs_uniform;
+                       float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
+
+                       medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
+                       high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
+                       dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
+                       invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
+                       original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
+                       depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
+                       viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");
+
+                       GPU_shader_bind(dof_shader_pass5);
+
+                       GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
+                       GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                       GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+                       GPU_texture_bind(src, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);
+
+                       GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
+
+                       GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+                       GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);
+
+                       GPU_texture_bind(fx->depth_buffer, numslots++);
+                       GPU_depth_texture_mode(fx->depth_buffer, false, true);
+                       GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);
+
+                       /* if this is the last pass, prepare for rendering on the frambuffer */
+                       gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
+
+                       glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+                       /* disable bindings */
+                       GPU_texture_unbind(fx->dof_near_coc_buffer);
+                       GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
+                       GPU_texture_unbind(src);
+                       GPU_depth_texture_mode(fx->depth_buffer, true, false);
+                       GPU_texture_unbind(fx->depth_buffer);
+
+                       /* may not be attached, in that case this just returns */
+                       if (target) {
+                               GPU_framebuffer_texture_detach(target);
+                               if (ofs) {
+                                       GPU_offscreen_bind(ofs, false);
+                               }
+                               else {
+                                       GPU_framebuffer_restore();
+                               }
+                       }
+
+                       SWAP(GPUTexture *, target, src);
+                       numslots = 0;
+               }
+       }
+
+       glDisableClientState(GL_VERTEX_ARRAY);
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+       GPU_shader_unbind();
+
+       return true;
+}
+
+void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
+{
+       fx_dof->fstop = 128.0f;
+       fx_dof->focal_length = 1.0f;
+       fx_dof->focus_distance = 1.0f;
+       fx_dof->sensor = 1.0f;
+}
+
+void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
+{
+       fx_ssao->factor = 1.0f;
+       fx_ssao->distance_max = 0.2f;
+       fx_ssao->attenuation = 1.0f;
+       fx_ssao->samples = 4;
+}
index a6b711fd55622a81f933fef81e0ccab04311d8f0..4d1a9770c78ffbd4aaa5995776e7115413cfaa8e 100644 (file)
@@ -47,6 +47,7 @@
 
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
+#include "GPU_compositing.h"
 #include "GPU_simple_shader.h"
 
 #include "intern/gpu_extensions_private.h"
@@ -78,10 +79,17 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
 extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
 extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
 extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
+extern char datatoc_gpu_shader_fx_vert_glsl[];
+extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
+extern char datatoc_gpu_shader_fx_lib_glsl[];
 
 typedef struct GPUShaders {
        GPUShader *vsm_store;
        GPUShader *sep_gaussian_blur;
+       /* cache for shader fx. Those can exist in combinations so store them here */
+       GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
 } GPUShaders;
 
 static struct GPUGlobal {
@@ -364,7 +372,9 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i
        MEM_freeN(pixels);
 }
 
-static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256])
+static GPUTexture *GPU_texture_create_nD(
+        int w, int h, int n, float *fpixels, int depth, GPUHDRType hdr_type, int components,
+        char err_out[256])
 {
        GPUTexture *tex;
        GLenum type, format, internalformat;
@@ -411,12 +421,45 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
                internalformat = GL_DEPTH_COMPONENT;
        }
        else {
-               type = GL_UNSIGNED_BYTE;
-               format = GL_RGBA;
-               internalformat = GL_RGBA8;
+               type = GL_FLOAT;
+
+               if (components == 4) {
+                       format = GL_RGBA;
+                       switch (hdr_type) {
+                               case GPU_HDR_NONE:
+                                       internalformat = GL_RGBA8;
+                                       break;
+                               case GPU_HDR_HALF_FLOAT:
+                                       internalformat = GL_RGBA16F;
+                                       break;
+                               case GPU_HDR_FULL_FLOAT:
+                                       internalformat = GL_RGBA32F;
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+               else if (components == 2) {
+                       format = GL_RG;
+                       switch (hdr_type) {
+                               case GPU_HDR_NONE:
+                                       internalformat = GL_RG8;
+                                       break;
+                               case GPU_HDR_HALF_FLOAT:
+                                       internalformat = GL_RG16F;
+                                       break;
+                               case GPU_HDR_FULL_FLOAT:
+                                       internalformat = GL_RG32F;
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
 
-               if (fpixels)
+               if (fpixels && hdr_type == GPU_HDR_NONE) {
+                       type = GL_UNSIGNED_BYTE;
                        pixels = GPU_texture_convert_pixels(w*h, fpixels);
+               }
        }
 
        if (tex->target == GL_TEXTURE_1D) {
@@ -651,7 +694,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
 
 GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
 {
-       GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out);
+       GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, err_out);
 
        if (tex)
                GPU_texture_unbind(tex);
@@ -659,9 +702,9 @@ GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
        return tex;
 }
 
-GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, GPUHDRType hdr, char err_out[256])
 {
-       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, err_out);
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, err_out);
 
        if (tex)
                GPU_texture_unbind(tex);
@@ -671,7 +714,7 @@ GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256
 
 GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
 {
-       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, err_out);
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, err_out);
 
        if (tex)
                GPU_texture_unbind(tex);
@@ -684,13 +727,45 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
  */
 GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
 {
-       GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, err_out);
+       GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, err_out);
 
        if (tex) {
                /* Now we tweak some of the settings */
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-               glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, size, size, 0, GL_RG, GL_FLOAT, NULL);
+
+               GPU_texture_unbind(tex);
+       }
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, float *pixels, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+
+       if (tex) {
+               /* Now we tweak some of the settings */
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+               GPU_texture_unbind(tex);
+       }
+
+       return tex;
+}
+
+GPUTexture *GPU_texture_create_1D_procedural(int w, float *pixels, char err_out[256])
+{
+       GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+
+       if (tex) {
+               /* Now we tweak some of the settings */
+               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
                GPU_texture_unbind(tex);
        }
@@ -702,7 +777,7 @@ void GPU_invalid_tex_init(void)
 {
        float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
        GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
-       GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL);
+       GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
        GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
 }
 
@@ -792,6 +867,45 @@ void GPU_texture_unbind(GPUTexture *tex)
        GPU_print_error("Post Texture Unbind");
 }
 
+void GPU_depth_texture_mode(GPUTexture *tex, bool compare, bool use_filter)
+{
+       GLenum arbnumber;
+
+       if (tex->number >= GG.maxtextures) {
+               GPU_print_error("Not enough texture slots.");
+               return;
+       }
+
+       if (!tex->depth) {
+               GPU_print_error("Not a depth texture.");
+               return;
+       }
+
+       if (tex->number == -1)
+               return;
+
+       GPU_print_error("Pre Texture Unbind");
+
+       arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
+       if (tex->number != 0) glActiveTextureARB(arbnumber);
+       if (compare)
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+       else
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+
+       if (use_filter) {
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+       }
+       else {
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       }
+       if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
+
+       GPU_print_error("Post Texture Unbind");
+}
+
 void GPU_texture_free(GPUTexture *tex)
 {
        tex->refcount--;
@@ -982,13 +1096,23 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
        glPushMatrix();
 }
 
-void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot)
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
 {
+       int numslots = 0, i;
+       GLenum attachments[4];
+       
        if (!fb->colortex[slot]) {
                fprintf(stderr, "Error, framebuffer slot empty!");
                return;
        }
-
+       
+       for (i = 0 ; i < 4; i++) {
+               if (fb->colortex[i]) {
+                       attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+                       numslots++;
+               }
+       }
+       
        /* push attributes */
        glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
        glDisable(GL_SCISSOR_TEST);
@@ -997,7 +1121,7 @@ void GPU_framebuffer_slot_bind(GPUFrameBuffer *fb, int slot)
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
 
        /* last bound prevails here, better allow explicit control here too */
-       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+       glDrawBuffers(numslots, attachments);
        glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
 
        /* push matrices and set default viewport and matrix */
@@ -1023,6 +1147,18 @@ void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUS
        glPopAttrib();
 }
 
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+{
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+       /* last bound prevails here, better allow explicit control here too */
+       glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+       glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+       /* push matrices and set default viewport and matrix */
+       glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
+       GG.currentfb = fb->object;
+       GG.currentfb = fb->object;
+}
 
 bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
 {
@@ -1045,7 +1181,6 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
        return true;
 }
 
-
 void GPU_framebuffer_free(GPUFrameBuffer *fb)
 {
        int i;
@@ -1080,8 +1215,8 @@ void GPU_framebuffer_restore(void)
 
 void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
 {
-       float scaleh[2] = {1.0f/GPU_texture_opengl_width(blurtex), 0.0f};
-       float scalev[2] = {0.0f, 1.0f/GPU_texture_opengl_height(tex)};
+       const float scaleh[2] = {1.0f / GPU_texture_opengl_width(blurtex), 0.0f};
+       const float scalev[2] = {0.0f, 1.0f / GPU_texture_opengl_height(tex)};
 
        GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
        int scale_uniform, texture_source_uniform;
@@ -1103,7 +1238,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
        GG.currentfb = blurfb->object;
 
        GPU_shader_bind(blur_shader);
-       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scaleh);
+       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
        GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
        glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
 
@@ -1126,7 +1261,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
        glTexCoord2d(1, 1); glVertex2f(-1, -1);
        glTexCoord2d(0, 1); glVertex2f(1, -1);
        glEnd();
-               
+
        /* Blurring vertically */
 
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
@@ -1135,7 +1270,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
        GG.currentfb = fb->object;
        
        glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
-       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
+       GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
        GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
        GPU_texture_bind(blurtex, 0);
 
@@ -1180,7 +1315,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
                return NULL;
        }
 
-       ofs->color = GPU_texture_create_2D(width, height, NULL, err_out);
+       ofs->color = GPU_texture_create_2D(width, height, NULL, GPU_HDR_NONE, err_out);
        if (!ofs->color) {
                GPU_offscreen_free(ofs);
                return NULL;
@@ -1214,15 +1349,20 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
        MEM_freeN(ofs);
 }
 
-void GPU_offscreen_bind(GPUOffScreen *ofs)
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
 {
        glDisable(GL_SCISSOR_TEST);
-       GPU_texture_bind_as_framebuffer(ofs->color);
+       if (save)
+               GPU_framebuffer_slots_bind(ofs->fb, 0);
+       else {
+               GPU_framebuffer_bind_no_save(ofs->fb, 0);
+       }
 }
 
-void GPU_offscreen_unbind(GPUOffScreen *ofs)
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
 {
-       GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
+       if (restore)
+               GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
        GPU_framebuffer_restore();
        glEnable(GL_SCISSOR_TEST);
 }
@@ -1250,6 +1390,7 @@ struct GPUShader {
        GLhandleARB fragment;   /* handle for fragment shader */
        GLhandleARB lib;                /* handle for libment shader */
        int totattrib;                  /* total number of attributes */
+       int uniforms;                   /* required uniforms */
 };
 
 static void shader_print_errors(const char *task, char *log, const char **code, int totcode)
@@ -1494,7 +1635,7 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
        return glGetUniformLocationARB(shader->object, name);
 }
 
-void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, float *value)
+void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
 {
        if (location == -1)
                return;
@@ -1588,8 +1729,64 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
        return retval;
 }
 
+#define MAX_DEFINES 100
+
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
+{
+       int offset;
+       char defines[MAX_DEFINES] = "";
+       /* avoid shaders out of range */
+       if (effects >= MAX_FX_SHADERS)
+               return NULL;
+
+       offset = 2 * effects;
+
+       if (persp) {
+               offset += 1;
+               strcat(defines, "#define PERSP_MATRIX\n");
+       }
+
+       if (!GG.shaders.fx_shaders[offset]) {
+               switch(effects) {
+                       case GPU_SHADER_FX_SSAO:
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
+                               strcat(defines, "#define FIRST_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
+                               strcat(defines, "#define SECOND_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
+                               strcat(defines, "#define THIRD_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
+                               strcat(defines, "#define FOURTH_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
+                               break;
+
+                       case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
+                               strcat(defines, "#define FIFTH_PASS\n");
+                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
+                               break;
+               }
+       }
+
+       return GG.shaders.fx_shaders[offset];
+}
+
+
 void GPU_shader_free_builtin_shaders(void)
 {
+       int i;
+
        if (GG.shaders.vsm_store) {
                MEM_freeN(GG.shaders.vsm_store);
                GG.shaders.vsm_store = NULL;
@@ -1599,6 +1796,13 @@ void GPU_shader_free_builtin_shaders(void)
                MEM_freeN(GG.shaders.sep_gaussian_blur);
                GG.shaders.sep_gaussian_blur = NULL;
        }
+
+       for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
+               if (GG.shaders.fx_shaders[i]) {
+                       MEM_freeN(GG.shaders.fx_shaders[i]);
+                       GG.shaders.fx_shaders[i] = NULL;
+               }
+       }
 }
 
 #if 0
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
new file mode 100644 (file)
index 0000000..d52ab22
--- /dev/null
@@ -0,0 +1,206 @@
+/* amount of offset to move one pixel left-right.
+ * In second pass some dimensions are zero to control verical/horizontal convolution */
+uniform vec2 invrendertargetdim;
+// color buffer
+uniform sampler2D colorbuffer;
+//blurred color buffer for DOF effect
+uniform sampler2D blurredcolorbuffer;
+// slightly blurred buffer
+uniform sampler2D mblurredcolorbuffer;
+// depth buffer
+uniform sampler2D depthbuffer;
+
+// this includes focal distance in x and aperture size in y
+uniform vec4 dof_params;
+
+// viewvectors for reconstruction of world space
+uniform vec4 viewvecs[3];
+
+// coordinates on framebuffer in normalized (0.0-1.0) uv space
+varying vec4 uvcoordsvar;
+
+/* color texture coordinates, offset by a small amount */
+varying vec2 color_uv1;
+varying vec2 color_uv2;
+
+varying vec2 depth_uv1;
+varying vec2 depth_uv2;
+varying vec2 depth_uv3;
+varying vec2 depth_uv4;
+
+
+float calculate_far_coc(in float zdepth)
+{
+       float coc = dof_params.x * max(1.0 - dof_params.y / zdepth, 0.0);
+
+       /* multiply by 1.0 / sensor size to get the normalized size */
+       return coc * dof_params.z;
+}
+
+/* near coc only! when distance is nearer than focus plane first term is bigger than one */
+vec4 calculate_near_coc(in vec4 zdepth)
+{
+       vec4 coc = dof_params.x * max(vec4(dof_params.y) / zdepth - vec4(1.0), vec4(0.0));
+
+       /* multiply by 1.0 / sensor size to get the normalized size */
+       return coc * dof_params.z;
+}
+
+/* first pass blurs the color buffer heavily and gets the near coc only.
+ * There are many texture accesses here but they are done on a
+ * lower resolution image so overall bandwidth is not a concern */
+void first_pass()
+{
+       vec4 depth;
+       vec4 zdepth;
+       vec4 coc;
+       float final_coc;
+
+       /* amount to add to uvs so that they move one row further */
+       vec2 offset_row[3];
+       offset_row[0] = vec2(0.0, invrendertargetdim.y);
+       offset_row[1] = 2.0 * offset_row[0];
+       offset_row[2] = 3.0 * offset_row[0];
+
+       /* heavily blur the image */
+       vec4 color = texture2D(colorbuffer, color_uv1);
+       color += texture2D(colorbuffer, color_uv1 + offset_row[1]);
+       color += texture2D(colorbuffer, color_uv2);
+       color += texture2D(colorbuffer, color_uv2 + offset_row[1]);
+       color /= 4.0;
+
+       depth.r = texture2D(depthbuffer, depth_uv1).r;
+       depth.g = texture2D(depthbuffer, depth_uv2).r;
+       depth.b = texture2D(depthbuffer, depth_uv3).r;
+       depth.a = texture2D(depthbuffer, depth_uv4).r;
+
+       zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+       coc = calculate_near_coc(zdepth);
+
+       depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[0]).r;
+       depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[0]).r;
+       depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[0]).r;
+       depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[0]).r;
+
+       zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+       coc = max(calculate_near_coc(zdepth), coc);
+
+       depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[1]).r;
+       depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[1]).r;
+       depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[1]).r;
+       depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[1]).r;
+
+       zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+       coc = max(calculate_near_coc(zdepth), coc);
+
+       depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[2]).r;
+       depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[2]).r;
+       depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[2]).r;
+       depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[2]).r;
+
+       zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+       coc = max(calculate_near_coc(zdepth), coc);
+
+       final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w));
+       gl_FragColor = vec4(color.rgb, final_coc);
+}
+
+/* second pass, gaussian blur the downsampled image */
+void second_pass()
+{
+       vec4 depth = vec4(texture2D(depthbuffer, uvcoordsvar.xy).r);
+
+       /* clever sampling to sample 2 pixels at once. Of course it's not real gaussian sampling this way */
+       vec4 color =  texture2D(colorbuffer, uvcoordsvar.xy) * 0.3125;
+       color += texture2D(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
+       color += texture2D(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
+       color += texture2D(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
+       color += texture2D(colorbuffer, uvcoordsvar.xy -invrendertargetdim) * 0.234375;
+       color += texture2D(colorbuffer, uvcoordsvar.xy -2.5 * invrendertargetdim) * 0.09375;
+       color += texture2D(colorbuffer, uvcoordsvar.xy -4.5 * invrendertargetdim) * 0.015625;
+
+       gl_FragColor = color;
+}
+
+
+/* third pass, calculate the final coc from blurred and unblurred images */
+void third_pass()
+{
+       vec4 color =  texture2D(colorbuffer, uvcoordsvar.xy);
+       vec4 color_blurred =  texture2D(blurredcolorbuffer, uvcoordsvar.xy);
+       float coc = 2.0 * max(color_blurred.a, color.a); - color.a;
+       gl_FragColor = vec4(color.rgb, coc);
+}
+
+
+/* fourth pass, blur the final coc once to get rid of discontinuities */
+void fourth_pass()
+{
+       vec4 color = texture2D(colorbuffer, uvcoordsvar.xz);
+       color += texture2D(colorbuffer, uvcoordsvar.yz);
+       color += texture2D(colorbuffer, uvcoordsvar.xw);
+       color += texture2D(colorbuffer, uvcoordsvar.yw);
+
+       gl_FragColor = color / 4.0;
+}
+
+vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
+{
+       float weight = 1.0/ 17.0;
+       vec4 result = weight * color;
+       weight *= 4.0;
+
+       result += weight * texture2D(colorbuffer, uv + color_uv1.xy);
+       result += weight * texture2D(colorbuffer, uv - color_uv1.xy);
+       result += weight * texture2D(colorbuffer, uv + color_uv1.yx);
+       result += weight * texture2D(colorbuffer, uv - color_uv1.yx);
+
+       return result;
+}
+
+
+/* fourth pass, just visualize the third pass contents */
+void fifth_pass()
+{
+       vec4 factors;
+       vec4 color_orig = texture2D(colorbuffer, uvcoordsvar.xy);
+       vec4 highblurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
+       vec4 mediumblurred = texture2D(mblurredcolorbuffer, uvcoordsvar.xy);
+       vec4 smallblurred = small_sample_blur(colorbuffer, uvcoordsvar.xy, color_orig);
+       float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+
+       float zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)).r;
+       float coc_far = clamp(calculate_far_coc(zdepth), 0.0, 1.0);
+
+       /* calculate final coc here */
+       float coc = max(max(coc_far, mediumblurred.a), 0.0);
+
+       float width = 2.5;
+       float radius = 0.2;
+
+       factors.x = 1.0 - clamp(width * coc, 0.0, 1.0);
+       factors.y = 1.0 - clamp(abs(width * (coc - 2.0 * radius)), 0.0, 1.0);
+       factors.z = 1.0 - clamp(abs(width * (coc - 3.0 * radius)), 0.0, 1.0);
+       factors.w = 1.0 - clamp(abs(width * (coc - 4.0 * radius)), 0.0, 1.0);
+       /* blend! */
+       vec4 color = factors.x * color_orig + factors.y * smallblurred + factors.z * mediumblurred + factors.w * highblurred;
+
+       color /= dot(factors, vec4(1.0));
+       gl_FragColor = vec4(color.rgb, 1.0);
+}
+
+
+void main()
+{
+#ifdef FIRST_PASS
+       first_pass();
+#elif defined(SECOND_PASS)
+       second_pass();
+#elif defined(THIRD_PASS)
+       third_pass();
+#elif defined(FOURTH_PASS)
+       fourth_pass();
+#elif defined(FIFTH_PASS)
+       fifth_pass();
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
new file mode 100644 (file)
index 0000000..a2ef990
--- /dev/null
@@ -0,0 +1,68 @@
+uniform vec2 invrendertargetdim;
+
+//texture coordinates for framebuffer read
+varying vec4 uvcoordsvar;
+
+/* color texture coordinates, offset by a small amount */
+varying vec2 color_uv1;
+varying vec2 color_uv2;
+
+varying vec2 depth_uv1;
+varying vec2 depth_uv2;
+varying vec2 depth_uv3;
+varying vec2 depth_uv4;
+
+//very simple shader for gull screen FX, just pass values on
+
+void vert_generic()
+{
+       uvcoordsvar = gl_MultiTexCoord0;
+       gl_Position = gl_Vertex;
+}
+
+void vert_dof_first_pass()
+{
+       /* we offset the texture coordinates by 1.5 pixel,
+        * then we reuse that to sample the surrounding pixels */
+       color_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+       color_uv2 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
+
+       depth_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+       depth_uv2 = gl_MultiTexCoord0.xy + vec2(-0.5, -1.5) * invrendertargetdim;
+       depth_uv3 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
+       depth_uv4 = gl_MultiTexCoord0.xy + vec2(1.5, -1.5) * invrendertargetdim;
+
+       gl_Position = gl_Vertex;
+}
+
+void vert_dof_fourth_pass()
+{
+       vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
+       uvcoordsvar = gl_MultiTexCoord0.xxyy + halfpixel * vec4(invrendertargetdim.x,
+                     invrendertargetdim.x, invrendertargetdim.y, invrendertargetdim.y);
+
+       gl_Position = gl_Vertex;
+}
+
+void vert_dof_fifth_pass()
+{
+       vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
+       color_uv1 = vec2(0.5, 1.5) * invrendertargetdim;
+
+       uvcoordsvar = gl_MultiTexCoord0;
+       gl_Position = gl_Vertex;
+}
+
+void main()
+{
+#ifdef FIRST_PASS
+       vert_dof_first_pass();
+#elif defined(FOURTH_PASS)
+       vert_dof_fourth_pass();
+#elif defined(FIFTH_PASS)
+       vert_dof_fifth_pass();
+#else
+       vert_generic();
+#endif
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
new file mode 100644 (file)
index 0000000..6c4bf3b
--- /dev/null
@@ -0,0 +1,47 @@
+vec3 calculate_view_space_normal(in vec3 viewposition)
+{
+       vec3 normal = cross(normalize(dFdx(viewposition)),
+                           normalize(dFdy(viewposition)));
+       normalize(normal);
+       return normal;
+}
+
+/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
+ * we change the factors from the article to fit the OpennGL model.  */
+#ifdef PERSP_MATRIX
+
+/* perspective camera code */
+
+vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
+{
+       float d = 2.0 * depth - 1.0;
+
+       float zview = -gl_ProjectionMatrix[3][2] / (d + gl_ProjectionMatrix[2][2]);
+
+       return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff);
+}
+
+vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
+{
+       vec4 d = 2.0 * depth - vec4(1.0);
+
+       /* return positive value, so sign differs! */
+       return vec4(gl_ProjectionMatrix[3][2]) / (d + vec4(gl_ProjectionMatrix[2][2]));
+}
+
+#else
+/* orthographic camera code */
+
+vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
+{
+       vec3 offset = vec3(uvcoords, depth);
+
+       return vec3(viewvec_origin + offset * viewvec_diff);
+}
+
+vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
+{
+       return -(near + depth * range);
+}
+
+#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
new file mode 100644 (file)
index 0000000..b33fda9
--- /dev/null
@@ -0,0 +1,82 @@
+// 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];
+
+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;
+
+               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 color = mix(texture2D(colorbuffer, uvcoordsvar.xy), ssao_color, calculate_ssao_factor(depth));
+       gl_FragColor = vec4(color.rgb, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
new file mode 100644 (file)
index 0000000..5194e41
--- /dev/null
@@ -0,0 +1,9 @@
+varying vec4 uvcoordsvar;
+
+//very simple shader for full screen FX, just pass values on
+
+void main()
+{
+       uvcoordsvar = gl_MultiTexCoord0;
+       gl_Position = gl_Vertex;
+}
index da7d98d2b22ab0b26c01b5e05ef9ebf45c7644d1..c67a356a708b12241143724bf4a95f3a9a296032 100644 (file)
@@ -33,7 +33,7 @@
 #define __DNA_CAMERA_TYPES_H__
 
 #include "DNA_defs.h"
-
+#include "DNA_gpu_types.h"
 #include "DNA_ID.h"
 
 #ifdef __cplusplus
@@ -65,6 +65,7 @@ typedef struct Camera {
        struct Ipo *ipo  DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
        
        struct Object *dof_ob;
+       struct GPUDOFSettings gpu_dof;
 
        char sensor_fit;
        char pad[7];
diff --git a/source/blender/makesdna/DNA_gpu_types.h b/source/blender/makesdna/DNA_gpu_types.h
new file mode 100644 (file)
index 0000000..b6009b3
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file DNA_gpu_types.h
+ *  \ingroup DNA
+ */
+
+#ifndef __DNA_GPU_TYPES_H__
+#define __DNA_GPU_TYPES_H__
+
+/* properties for dof effect */
+typedef struct GPUDOFSettings {
+       float focus_distance; /* focal distance for depth of field */
+       float fstop;
+       float focal_length;
+       float sensor;
+} GPUDOFSettings;
+
+/* properties for SSAO effect */
+typedef struct GPUSSAOSettings {
+       float factor;
+       float color[3];
+       float distance_max;
+       float attenuation;
+       int samples; /* ray samples, we use presets here for easy control instead of */
+       int pad;
+} GPUSSAOSettings;
+
+typedef struct GPUFXSettings {
+       GPUDOFSettings *dof;
+       GPUSSAOSettings *ssao;
+       char fx_flag;  /* eGPUFXFlags */
+       char pad[7];
+} GPUFXSettings;
+
+/* shaderfx enables */
+typedef enum eGPUFXFlags {
+       GPU_FX_FLAG_DOF         = (1 << 0),
+       GPU_FX_FLAG_SSAO        = (1 << 1),
+} eGPUFXFlags;
+
+#endif  /* __DNA_GPU_TYPES_H__ */
index 2d2ee4ab30913524a57071b578b4b6bdd0c96e57..c20f5ff02f8f8012624b9adf72a5c5f5e05fe8c6 100644 (file)
@@ -46,6 +46,7 @@ extern "C" {
 #include "DNA_listBase.h"
 #include "DNA_ID.h"
 #include "DNA_freestyle_types.h"
+#include "DNA_gpu_types.h"
 
 struct CurveMapping;
 struct Object;
index 543a95cc1208c8125e866197c0e9a55661540597..210deddc8546f3d7dfa852ee42d8dc1e35d8a07c 100644 (file)
@@ -46,6 +46,7 @@ struct bGPdata;
 struct SmoothView3DStore;
 struct wmTimer;
 struct Material;
+struct GPUFX;
 
 /* This is needed to not let VC choke on near and far... old
  * proprietary MS extensions... */
@@ -60,6 +61,7 @@ struct Material;
 #include "DNA_listBase.h"
 #include "DNA_image_types.h"
 #include "DNA_movieclip_types.h"
+#include "DNA_gpu_types.h"
 
 /* ******************************** */
 
@@ -146,6 +148,7 @@ typedef struct RegionView3D {
        float rot_angle;
        float rot_axis[3];
 
+       struct GPUFX *compositor;
 } RegionView3D;
 
 /* 3D ViewPort Struct */
@@ -210,11 +213,17 @@ typedef struct View3D {
        struct ListBase afterdraw_transp;
        struct ListBase afterdraw_xray;
        struct ListBase afterdraw_xraytransp;
-       
+
        /* drawflags, denoting state */
        char zbuf, transp, xray;
+
+       /* built-in shader effects (eGPUFXFlags) */
        char pad3[5];
 
+       /* note, 'fx_settings.dof' is currently _not_ allocated,
+        * instead set (temporarily) from camera */
+       struct GPUFXSettings fx_settings;
+
        void *properties_storage;               /* Nkey panel stores stuff here (runtime only!) */
        struct Material *defmaterial;   /* used by matcap now */
 
index ca8f56289ca7b47fd04588b0e536ad1de5b088c5..7f3e9b7c19637d8fae26fa263dde0380574bfe0f 100644 (file)
@@ -73,6 +73,7 @@ static const char *includefiles[] = {
        "DNA_key_types.h",
        "DNA_text_types.h",
        "DNA_packedFile_types.h",
+       "DNA_gpu_types.h",
        "DNA_camera_types.h",
        "DNA_image_types.h",
        "DNA_texture_types.h",
index 5704004b4b6c3dfa80a6f46aea7284b6460cf649..31e991dd2b6d6948cc99597b4ef4cb1e1af62bcd 100644 (file)
@@ -284,8 +284,6 @@ void RNA_def_camera(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Lens Unit", "Unit to edit lens in for the user interface");
 
        /* pointers */
-       rna_def_animdata_common(srna);
-
        prop = RNA_def_property(srna, "dof_object", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "Object");
        RNA_def_property_pointer_sdna(prop, NULL, "dof_ob");
@@ -293,6 +291,13 @@ void RNA_def_camera(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "DOF Object", "Use this object to define the depth of field focal point");
        RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
 
+       prop = RNA_def_property(srna, "gpu_dof", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "GPUDOFSettings");
+       RNA_def_property_ui_text(prop, "GPU Depth Of Field", "");
+       RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+       rna_def_animdata_common(srna);
+
        /* Camera API */
        RNA_api_camera(srna);
 }
index 1c133db37b7d3a0f6a3c849471e9a63eaca25022..b3151d5a8448b294b7031a3fdcae939a0e4bd1dc 100644 (file)
@@ -1692,6 +1692,28 @@ static void rna_FreestyleSettings_module_remove(ID *id, FreestyleSettings *confi
        WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
 }
 
+char *rna_GPUDOF_path(PointerRNA *ptr)
+{
+       /* if there is ID-data, resolve the path using the index instead of by name,
+        * since the name used is the name of the texture assigned, but the texture
+        * may be used multiple times in the same stack
+        */
+       if (ptr->id.data) {
+               if (GS(((ID *)ptr->id.data)->name) == ID_CA) {
+                       return BLI_strdup("gpu_dof");
+               }
+       }
+
+       return BLI_strdup("");;
+}
+
+static void rna_GPUFXSettings_fx_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+       GPUFXSettings *fx_settings = ptr->data;
+
+       BKE_screen_gpu_fx_validate(fx_settings);
+}
+
 #else
 
 static void rna_def_transform_orientation(BlenderRNA *brna)
@@ -3822,6 +3844,114 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
        rna_def_scene_game_recast_data(brna);
 }
 
+static void rna_def_gpu_dof_fx(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna = RNA_def_struct(brna, "GPUDOFSettings", NULL);
+       RNA_def_struct_ui_text(srna, "GPU DOF", "Settings for GPU based depth of field");
+       RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+       RNA_def_struct_path_func(srna, "rna_GPUDOF_path");
+
+       prop = RNA_def_property(srna, "focus_distance", PROP_FLOAT, PROP_DISTANCE);
+       RNA_def_property_ui_text(prop, "Focus distance", "Viewport depth of field focus distance");
+       RNA_def_property_range(prop, 0.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_DISTANCE_CAMERA);
+       RNA_def_property_ui_text(prop, "Focal Length", "Foca Length for dof effect");
+       RNA_def_property_range(prop, 1.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "sensor", PROP_FLOAT, PROP_DISTANCE_CAMERA);
+       RNA_def_property_ui_text(prop, "Sensor", "Size of sensor");
+       RNA_def_property_range(prop, 1.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "F/Stop", "FStop for dof effect");
+       RNA_def_property_range(prop, 0.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
+static void rna_def_gpu_ssao_fx(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna = RNA_def_struct(brna, "GPUSSAOSettings", NULL);
+       RNA_def_struct_ui_text(srna, "GPU SSAO", "Settings for GPU based screen space ambient occlusion");
+       RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+
+       prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Strength", "Strength of 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, "distance_max", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the SSAO effect");
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "attenuation", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+       RNA_def_property_range(prop, 1.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Samples", "Number of samples. Final number is squared");
+       RNA_def_property_range(prop, 1, 30); /* 0 is needed for compression. */ 
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+       RNA_def_property_ui_text(prop, "SSAO Color", "Color for screen space ambient occlusion effect");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
+
+static void rna_def_gpu_fx(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       rna_def_gpu_ssao_fx(brna);
+       rna_def_gpu_dof_fx(brna);
+
+       srna = RNA_def_struct(brna, "GPUFXSettings", NULL);
+       RNA_def_struct_ui_text(srna, "GPU FX Settings", "Settings for GPU based compositing");
+       RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+
+       prop = RNA_def_property(srna, "dof", PROP_POINTER, PROP_NONE);
+       RNA_def_property_flag(prop, PROP_NEVER_NULL);
+       RNA_def_property_struct_type(prop, "GPUDOFSettings");
+       RNA_def_property_ui_text(prop, "Depth Of Field settings", "");
+
+       prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_DOF);
+       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, "rna_GPUFXSettings_fx_update");
+
+
+       prop = RNA_def_property(srna, "ssao", PROP_POINTER, PROP_NONE);
+       RNA_def_property_flag(prop, PROP_NEVER_NULL);
+       RNA_def_property_struct_type(prop, "GPUSSAOSettings");
+       RNA_def_property_ui_text(prop, "Screen Space Ambient Occlusion settings", "");
+
+       prop = RNA_def_property(srna, "use_ssao", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_SSAO);
+       RNA_def_property_ui_text(prop, "SSAO", "Use screen space ambient occlusion of field on viewport");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
+}
+
+
 static void rna_def_scene_render_layer(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -5862,7 +5992,9 @@ void RNA_def_scene(BlenderRNA *brna)
        /* *** Animated *** */
        rna_def_scene_render_data(brna);
        rna_def_scene_render_layer(brna);
-       
+
+       rna_def_gpu_fx(brna);
+
        /* Scene API */
        RNA_api_scene(srna);
 }
index 70b9f18df8c4bcdebdae7c751f3912f62fda84a6..24c80ccdb02762689f0b6a021710a20a2458eeea 100644 (file)
@@ -34,6 +34,7 @@
 #include "BKE_key.h"
 #include "BKE_movieclip.h"
 #include "BKE_node.h"
+#include "BKE_screen.h"
 
 #include "DNA_action_types.h"
 #include "DNA_key_types.h"
@@ -2128,7 +2129,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}
        };
        
-
        srna = RNA_def_struct(brna, "SpaceView3D", "Space");
        RNA_def_struct_sdna(srna, "View3D");
        RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data");
@@ -2470,6 +2470,10 @@ static void rna_def_space_view3d(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture, active objects only");
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_update");
 
+       prop = RNA_def_property(srna, "fx_settings", PROP_POINTER, PROP_NONE);
+       RNA_def_property_ui_text(prop, "FX Options", "Options used for real time compositing");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
        /* region */
 
        srna = RNA_def_struct(brna, "RegionView3D", NULL);