Commit: 825430c589e80ee0bfd5ebdee1ce855e81ff76db
Author: Campbell Barton
Date:   Wed May 3 21:59:03 2017 +1000
Branches: blender2.8
https://developer.blender.org/rB825430c589e80ee0bfd5ebdee1ce855e81ff76db

Cleanup: move off-screen drawing to view3d_draw.c

Since offscreen drawing now uses draw engine, this doesn't need to be
considered legacy.

Note that there are some calls into view3d_draw_legacy.c from view3d_draw.c
this is generally not accepted, so its only dont where there are checks
for new/old engine.
Functions exposed to do this use a VP_deprecated prefix.

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

M       source/blender/editors/space_view3d/view3d_draw.c
M       source/blender/editors/space_view3d/view3d_draw_legacy.c
M       source/blender/editors/space_view3d/view3d_intern.h

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

diff --git a/source/blender/editors/space_view3d/view3d_draw.c 
b/source/blender/editors/space_view3d/view3d_draw.c
index 1f46a891e76..c00a3e2b0b7 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -35,6 +35,7 @@
 
 #include "BKE_camera.h"
 #include "BKE_context.h"
+#include "BKE_global.h"
 #include "BKE_key.h"
 #include "BKE_scene.h"
 #include "BKE_object.h"
@@ -48,6 +49,7 @@
 #include "BLI_rect.h"
 #include "BLI_string.h"
 #include "BLI_threads.h"
+#include "BLI_jitter.h"
 
 #include "BLT_translation.h"
 
@@ -72,11 +74,13 @@
 
 #include "DEG_depsgraph_query.h"
 
+#include "GPU_draw.h"
 #include "GPU_matrix.h"
 #include "GPU_immediate.h"
 #include "GPU_immediate_util.h"
 #include "GPU_material.h"
 #include "GPU_viewport.h"
+#include "GPU_compositing.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -88,6 +92,9 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
 #include "view3d_intern.h"  /* own include */
 
 /* prototypes */
@@ -2444,11 +2451,416 @@ void view3d_main_region_draw(const bContext *C, 
ARegion *ar)
        v3d->flag |= V3D_INVALID_BACKBUF;
 }
 
-/* ******************** legacy interface ***************** */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Offscreen Drawing
+ * \{ */
+
+static void view3d_stereo3d_setup_offscreen(
+        Scene *scene, View3D *v3d, ARegion *ar,
+        float winmat[4][4], const char *viewname)
+{
+       /* update the viewport matrices with the new camera */
+       if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+               float viewmat[4][4];
+               const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
+
+               BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, 
is_left, viewmat);
+               VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, 
viewmat, winmat);
+       }
+       else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+               float viewmat[4][4];
+               Object *camera = BKE_camera_multiview_render(scene, 
v3d->camera, viewname);
+
+               BKE_camera_multiview_view_matrix(&scene->r, camera, false, 
viewmat);
+               VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, 
viewmat, winmat);
+       }
+}
+
+void ED_view3d_draw_offscreen_init(Scene *scene, SceneLayer *sl, View3D *v3d)
+{
+       RenderEngineType *type = RE_engines_find(scene->r.engine);
+       if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_LEGACY_PIPELINE) 
!= 0)) {
+               /* shadow buffers, before we setup matrices */
+               if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype)) {
+                       VP_deprecated_gpu_update_lamps_shadows_world(scene, 
v3d);
+               }
+       }
+}
+
+/*
+ * Function to clear the view
+ */
+static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
+{
+       glClear(GL_DEPTH_BUFFER_BIT);
+
+       if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
+               VP_view3d_draw_background_world(scene, v3d, ar->regiondata);
+       }
+       else {
+               VP_view3d_draw_background_none();
+       }
+}
+
+/* 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, bool is_persp, const char *viewname,
+        GPUFX *fx, GPUFXSettings *fx_settings,
+        GPUOffScreen *ofs)
+{
+       bool do_compositing = false;
+       RegionView3D *rv3d = ar->regiondata;
+
+       /* set temporary new size */
+       int bwinx = ar->winx;
+       int bwiny = ar->winy;
+       rcti brect = ar->winrct;
+
+       ar->winx = winx;
+       ar->winy = winy;
+       ar->winrct.xmin = 0;
+       ar->winrct.ymin = 0;
+       ar->winrct.xmax = winx;
+       ar->winrct.ymax = winy;
+
+       struct bThemeState theme_state;
+       UI_Theme_Store(&theme_state);
+       UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
+       /* set flags */
+       G.f |= G_RENDER_OGL;
+
+       if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
+               /* free images which can have changed on frame-change
+                * warning! can be slow so only free animated images - campbell 
*/
+               GPU_free_images_anim();
+       }
+
+       gpuPushProjectionMatrix();
+       gpuLoadIdentity();
+       gpuPushMatrix();
+       gpuLoadIdentity();
+
+       /* clear opengl buffers */
+       if (do_sky) {
+               view3d_main_region_clear(scene, v3d, ar);
+       }
+       else {
+               glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       }
+
+       if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && 
rv3d->persp == RV3D_CAMOB && v3d->camera)
+               view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, 
viewname);
+       else
+               VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, 
viewmat, winmat);
+
+       /* framebuffer fx needed, we need to draw offscreen first */
+       if (v3d->fx_settings.fx_flag && fx) {
+               GPUSSAOSettings *ssao = NULL;
+
+               if (v3d->drawtype < OB_SOLID) {
+                       ssao = v3d->fx_settings.ssao;
+                       v3d->fx_settings.ssao = NULL;
+               }
+
+               do_compositing = GPU_fx_compositor_initialize_passes(fx, 
&ar->winrct, NULL, fx_settings);
+
+               if (ssao)
+                       v3d->fx_settings.ssao = ssao;
+       }
+
+       /* main drawing call */
+       RenderEngineType *type = RE_engines_find(scene->r.engine);
+       if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_LEGACY_PIPELINE) 
!= 0)) {
+               VP_deprecated_view3d_draw_objects(NULL, scene, v3d, ar, NULL, 
do_bgpic, true, do_compositing ? fx : NULL);
+       }
+       else {
+               /* XXX, should take depsgraph as arg */
+               DRW_draw_render_loop_offscreen(scene->depsgraph, ar, v3d, ofs);
+       }
+
+       /* 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);
+
+               if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+                       /* draw grease-pencil stuff - needed to get 
paint-buffer shown too (since it's 2D) */
+                       ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
+               }
+
+               /* freeing the images again here could be done after the 
operator runs, leaving for now */
+               GPU_free_images_anim();
+       }
+
+       /* restore size */
+       ar->winx = bwinx;
+       ar->winy = bwiny;
+       ar->winrct = brect;
+
+       gpuPopProjectionMatrix();
+       gpuPopMatrix();
+
+       UI_Theme_Restore(&theme_state);
+
+       G.f &= ~G_RENDER_OGL;
+}
+
 /**
+ * Utility func for ED_view3d_draw_offscreen
+ *
+ * \param ofs: Optional off-screen buffer, can be NULL.
+ * (avoids re-creating when doing multiple GL renders).
+ */
+ImBuf *ED_view3d_draw_offscreen_imbuf(
+        Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, int sizex, int 
sizey,
+        unsigned int flag, bool draw_background,
+        int alpha_mode, int samples, bool full_samples, const char *viewname,
+        /* output vars */
+        GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+{
+       RegionView3D *rv3d = ar->regiondata;
+       const bool draw_sky = (alpha_mode == R_ADDSKY);
+
+       /* view state */
+       GPUFXSettings fx_settings = v3d->fx_settings;
+       bool is_ortho = false;
+       float winmat[4][4];
+
+       if (ofs && ((GPU_offscreen_width(ofs) != sizex) || 
(GPU_offscreen_height(ofs) != sizey))) {
+               /* sizes differ, can't reuse */
+               ofs = NULL;
+       }
+
+       const bool own_ofs = (ofs == NULL);
+
+       if (own_ofs) {
+               /* bind */
+               ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : 
samples, err_out);
+               if (ofs == NULL) {
+                       return NULL;
+               }
+       }
+
+       ED_view3d_draw_offscreen_init(scene, sl, v3d);
+
+       GPU_offscreen_bind(ofs, true);
+
+       /* read in pixels & stamp */
+       ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
+
+       /* render 3d view */
+       if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+               CameraParams params;
+               Object *camera = BKE_camera_multiview_render(scene, 
v3d->camera, viewname);
+
+               BKE_camera_params_init(&params);
+               /* fallback for non camera objects */
+               params.clipsta = v3d->near;
+               params.clipend = v3d->far;
+               BKE_camera_params_from_object(&params, camera);
+               BKE_camera_multiview_params(&scene->r, &params, camera, 
viewname);
+               BKE_camera_params_compute_viewplane(&params, sizex, sizey, 
scene->r.xasp, scene->r.yasp);
+               BKE_camera_params_compute_matrix(&params);
+
+               BKE_camera_to_gpu_dof(camera, &fx_settings);
+
+               is_ortho = params.is_ortho;
+               copy_m4_m4(winmat, params.winmat);
+       }
+       else {
+               rctf viewplane;
+               float clipsta, clipend;
+
+               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);
+               }
+       }
+
+       if ((samples && full_samples) == 0) {
+               /* Single-pass render, common case */
+               ED_view3d_draw_offscreen(
+                       scene, v3d, ar, sizex, sizey, NULL, winmat,
+                       draw_background, draw_sky, !is_ortho, viewname,
+                       fx, &fx_settings, ofs);
+
+               if (ibuf->rect_float) {
+                       GPU_offscreen_read_pixels(ofs, GL_FLOAT, 
ibuf->rect_float);
+               }
+               else if (ibuf->rect) {
+                       GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, 
ibuf->rect);
+               }
+       }
+       else {
+               /* Multi-pass render, use accumulation buffer & jitter for 
'full' oversampling.
+                * Use because OpenGL may use a lower quality MSAA, and only 
over-sample edges. */
+               static float jit_ofs[32][2];
+               float winmat_jitter[4][4];
+               /* use imbuf as temp storage, before writing into it from 
accumulation buffer */
+               unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : 
(void *)ibuf->rect_float;
+               unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * 
sizeof(int[4]), "accum1");
+
+               BLI_jitter_init(jit_ofs, samples);
+
+               /* first sample buffer, also initializes 'rv3d->persmat' */
+               ED_view3d_draw_offscreen(
+                       scene, v3d, ar, sizex, sizey, NULL, winmat,
+                       draw_background, draw_sky, !is_ortho, viewname,
+                       fx, &fx_settings, ofs);
+               GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
+
+               unsigned i = sizex * sizey * 4;
+               while (i--) {
+                       accum_buffer[i] = rect_temp[i];
+               }
+
+               /* skip the first sample */
+               for (int j = 1; j < samples; j++) {
+                       copy_m4_m4(winmat_jitter, winmat);
+                       window_translate_m4(
+                               winmat_jitter, rv3d->persmat,
+                               (jit_ofs[j][0] * 2.0f) / sizex,
+                               (jit_ofs[j][1] * 2.0f) / sizey);

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to