[Bf-blender-cvs] [d20b672e01c] tmp-workbench-rewrite2: wbench next: render to image

Miguel Pozo noreply at git.blender.org
Wed Nov 30 18:08:04 CET 2022


Commit: d20b672e01c2f7b64db3a5b43d3dda1b432bd816
Author: Miguel Pozo
Date:   Tue Nov 29 20:18:25 2022 +0100
Branches: tmp-workbench-rewrite2
https://developer.blender.org/rBd20b672e01c2f7b64db3a5b43d3dda1b432bd816

wbench next: render to image

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

M	release/scripts/startup/bl_ui/properties_view_layer.py
M	source/blender/draw/engines/workbench/workbench_engine.cc
M	source/blender/draw/engines/workbench/workbench_private.hh
M	source/blender/draw/engines/workbench/workbench_state.cc

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

diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index b18734ea98a..c45cafa07fa 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -44,7 +44,7 @@ class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel):
 
 class VIEWLAYER_PT_layer_passes(ViewLayerButtonsPanel, Panel):
     bl_label = "Passes"
-    COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT'}
+    COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH_NEXT'}
 
     def draw(self, context):
         pass
@@ -94,6 +94,23 @@ class VIEWLAYER_PT_eevee_next_layer_passes_data(ViewLayerButtonsPanel, Panel):
         sub.active = not scene.eevee.use_motion_blur
         sub.prop(view_layer, "use_pass_vector")
 
+class VIEWLAYER_PT_eevee_next_layer_passes_data(ViewLayerButtonsPanel, Panel):
+    bl_label = "Data"
+    bl_parent_id = "VIEWLAYER_PT_layer_passes"
+
+    COMPAT_ENGINES = {'BLENDER_WORKBENCH_NEXT'}
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+        layout.use_property_decorate = False
+
+        view_layer = context.view_layer
+
+        col = layout.column()
+        col.prop(view_layer, "use_pass_combined")
+        col.prop(view_layer, "use_pass_z")
+
 
 class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel):
     bl_label = "Light"
diff --git a/source/blender/draw/engines/workbench/workbench_engine.cc b/source/blender/draw/engines/workbench/workbench_engine.cc
index 0a3d89f37f0..483664b3f66 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.cc
+++ b/source/blender/draw/engines/workbench/workbench_engine.cc
@@ -6,6 +6,7 @@
 #include "BKE_paint.h"
 #include "BKE_particle.h"
 #include "BKE_pbvh.h"
+#include "BKE_report.h"
 #include "DEG_depsgraph_query.h"
 #include "DNA_fluid_types.h"
 #include "ED_paint.h"
@@ -34,9 +35,9 @@ class Instance {
   DofPass dof_ps;
   AntiAliasingPass anti_aliasing_ps;
 
-  void init()
+  void init(Object *camera_ob = nullptr)
   {
-    scene_state.init();
+    scene_state.init(camera_ob);
     resources.init(scene_state);
 
     outline_ps.init(scene_state);
@@ -462,19 +463,201 @@ static void workbench_id_update(void *vedata, struct ID *id)
   UNUSED_VARS(vedata, id);
 }
 
+/* RENDER */
+
+static bool workbench_render_framebuffers_init(void)
+{
+  /* For image render, allocate own buffers because we don't have a viewport. */
+  const float2 viewport_size = DRW_viewport_size_get();
+  const int2 size = {int(viewport_size.x), int(viewport_size.y)};
+
+  DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+  /* When doing a multi view rendering the first view will allocate the buffers
+   * the other views will reuse these buffers */
+  if (dtxl->color == nullptr) {
+    BLI_assert(dtxl->depth == nullptr);
+    dtxl->color = GPU_texture_create_2d("txl.color", size.x, size.y, 1, GPU_RGBA16F, nullptr);
+    dtxl->depth = GPU_texture_create_2d(
+        "txl.depth", size.x, size.y, 1, GPU_DEPTH24_STENCIL8, nullptr);
+  }
+
+  if (!(dtxl->depth && dtxl->color)) {
+    return false;
+  }
+
+  DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+
+  GPU_framebuffer_ensure_config(
+      &dfbl->default_fb,
+      {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
+
+  GPU_framebuffer_ensure_config(&dfbl->depth_only_fb,
+                                {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_NONE});
+
+  GPU_framebuffer_ensure_config(&dfbl->color_only_fb,
+                                {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(dtxl->color)});
+
+  return GPU_framebuffer_check_valid(dfbl->default_fb, nullptr) &&
+         GPU_framebuffer_check_valid(dfbl->color_only_fb, nullptr) &&
+         GPU_framebuffer_check_valid(dfbl->depth_only_fb, nullptr);
+}
+
+#ifdef DEBUG
+/* This is just to ease GPU debugging when the frame delimiter is set to Finish */
+#  define GPU_FINISH_DELIMITER() GPU_finish()
+#else
+#  define GPU_FINISH_DELIMITER()
+#endif
+
 static void workbench_render_to_image(void *vedata,
                                       struct RenderEngine *engine,
                                       struct RenderLayer *layer,
-                                      const struct rcti *UNUSED(rect))
+                                      const struct rcti *rect)
 {
-  UNUSED_VARS(vedata, engine, layer);
+  /* TODO(fclem): Remove once it is minimum required. */
+  if (!GPU_shader_storage_buffer_objects_support()) {
+    return;
+  }
+
+  if (!workbench_render_framebuffers_init()) {
+    RE_engine_report(engine, RPT_ERROR, "Failed to allocate GPU buffers");
+    return;
+  }
+
+  GPU_FINISH_DELIMITER();
+
+  /* Setup */
+
+  DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+  const DRWContextState *draw_ctx = DRW_context_state_get();
+  Depsgraph *depsgraph = draw_ctx->depsgraph;
+
+  WORKBENCH_Data *ved = reinterpret_cast<WORKBENCH_Data *>(vedata);
+  if (ved->instance == nullptr) {
+    ved->instance = new workbench::Instance();
+  }
+
+  /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
+  Object *camera_ob = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
+
+  /* Set the perspective, view and window matrix. */
+  float4x4 winmat, viewmat, viewinv;
+  RE_GetCameraWindow(engine->re, camera_ob, winmat.ptr());
+  RE_GetCameraModelMatrix(engine->re, camera_ob, viewinv.ptr());
+  viewmat = viewinv.inverted();
+
+  DRWView *view = DRW_view_create(viewmat.ptr(), winmat.ptr(), nullptr, nullptr, nullptr);
+  DRW_view_default_set(view);
+  DRW_view_set_active(view);
+
+  /* Render */
+  do {
+    if (RE_engine_test_break(engine)) {
+      break;
+    }
+
+    ved->instance->init(camera_ob);
+
+    DRW_manager_get()->begin_sync();
+
+    workbench_cache_init(vedata);
+    auto workbench_render_cache = [](void *vedata,
+                                     struct Object *ob,
+                                     struct RenderEngine *UNUSED(engine),
+                                     struct Depsgraph *UNUSED(depsgraph)) {
+      workbench_cache_populate(vedata, ob);
+    };
+    DRW_render_object_iter(vedata, engine, depsgraph, workbench_render_cache);
+    workbench_cache_finish(vedata);
+
+    DRW_manager_get()->end_sync();
+
+    /* Also we weed to have a correct FBO bound for #DRW_curves_update */
+    // GPU_framebuffer_bind(dfbl->default_fb);
+    // DRW_curves_update(); /* TODO(Miguel Pozo): Check this once curves are implemented */
+
+    workbench_draw_scene(vedata);
+
+    /* Perform render step between samples to allow
+     * flushing of freed GPUBackend resources. */
+    GPU_render_step();
+    GPU_FINISH_DELIMITER();
+  } while (ved->instance->scene_state.sample + 1 < ved->instance->scene_state.samples_len);
+
+  const char *viewname = RE_GetActiveRenderView(engine->re);
+  /* Write render output. */
+  {
+    RenderPass *rp = RE_pass_find_by_name(layer, RE_PASSNAME_COMBINED, viewname);
+    if (rp) {
+      GPU_framebuffer_bind(dfbl->default_fb);
+      GPU_framebuffer_read_color(dfbl->default_fb,
+                                 rect->xmin,
+                                 rect->ymin,
+                                 BLI_rcti_size_x(rect),
+                                 BLI_rcti_size_y(rect),
+                                 4,
+                                 0,
+                                 GPU_DATA_FLOAT,
+                                 rp->rect);
+    }
+  }
+  /* Write render Z output */
+  {
+    RenderPass *rp = RE_pass_find_by_name(layer, RE_PASSNAME_Z, viewname);
+    if (rp) {
+      GPU_framebuffer_bind(dfbl->default_fb);
+      GPU_framebuffer_read_depth(dfbl->default_fb,
+                                 rect->xmin,
+                                 rect->ymin,
+                                 BLI_rcti_size_x(rect),
+                                 BLI_rcti_size_y(rect),
+                                 GPU_DATA_FLOAT,
+                                 rp->rect);
+
+      int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
+
+      /* Convert ogl depth [0..1] to view Z [near..far] */
+      if (DRW_view_is_persp_get(nullptr)) {
+        for (float &z : MutableSpan(rp->rect, pix_num)) {
+          if (z == 1.0f) {
+            z = 1e10f; /* Background */
+          }
+          else {
+            z = z * 2.0f - 1.0f;
+            z = winmat[3][2] / (z + winmat[2][2]);
+          }
+        }
+      }
+      else {
+        /* Keep in mind, near and far distance are negatives. */
+        float near = DRW_view_near_distance_get(nullptr);
+        float far = DRW_view_far_distance_get(nullptr);
+        float range = fabsf(far - near);
+
+        for (float &z : MutableSpan(rp->rect, pix_num)) {
+          if (z == 1.0f) {
+            z = 1e10f; /* Background */
+          }
+          else {
+            z = z * range - near;
+          }
+        }
+      }
+    }
+  }
 }
 
 static void workbench_render_update_passes(RenderEngine *engine,
                                            Scene *scene,
                                            ViewLayer *view_layer)
 {
-  RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
+  if (view_layer->passflag & SCE_PASS_COMBINED) {
+    RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
+  }
+  if (view_layer->passflag & SCE_PASS_Z) {
+    RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_Z, 1, "Z", SOCK_FLOAT);
+  }
 }
 
 extern "C" {
diff --git a/source/blender/draw/engines/workbench/workbench_private.hh b/source/blender/draw/engines/workbench/workbench_private.hh
index fca61f2ec59..58451e92ab9 100644
--- a/source/blender/draw/engines/workbench/workbench_private.hh
+++ b/source/blender/draw/engines/workbench/workbench_private.hh
@@ -94,7 +94,7 @@ struct SceneState {
   /* When r == -1.0 the shader uses the vertex color */
   Material material_attribute_color = Material(float3(-1.0f));
 
-  void init();
+  void init(Object *camera_ob = nullptr);
 };
 
 struct ObjectState {
diff 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list