[Bf-blender-cvs] [bb487bc2bc8] master: Fix T89984: Improve Icon previews reflective and transmissive materials.

Jeroen Bakker noreply at git.blender.org
Wed Aug 11 17:03:23 CEST 2021


Commit: bb487bc2bc82c02922722efb3ca1d2570d907ad9
Author: Jeroen Bakker
Date:   Wed Aug 11 16:59:09 2021 +0200
Branches: master
https://developer.blender.org/rBbb487bc2bc82c02922722efb3ca1d2570d907ad9

Fix T89984: Improve Icon previews reflective and transmissive materials.

Before this commit rendering material icons the floor will is hidden.
This reduces the readability of reflective/refractive materials.

check patch for additional screenshots and notes.

This patch will switch the floor material that uses ray visibility tricks to render a floor for reflective rays.

Eevee uses screen space reflections that makes this a different problem. There is nothing else drawn in
the scene in screen space so we need a different trick. Using math we convert a reflective ray to UV space
and generate a world that projects a checker pattern to infinity.

As now the floor is in the world it is being reflected via
a cubemap. As the film is transparent the background (including the floor isn't rendered)

In the future when Eevee supports vulkan raytracing we can re-evaluate and perhaps remove this
approximation.

We tried lightprobes but that wasn't able to do the trick.
Using the compositor would lead to more memory usage (render layers and intermediate buffers) and slower performance.
Solution has been validated with Simon

Reviewed By: sybren, Severin

Differential Revision: https://developer.blender.org/D11988

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

M	release/datafiles/preview.blend
M	source/blender/editors/render/render_preview.c

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

diff --git a/release/datafiles/preview.blend b/release/datafiles/preview.blend
index f92f68ad029..e342cb85158 100644
Binary files a/release/datafiles/preview.blend and b/release/datafiles/preview.blend differ
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index bd4c83c107e..95351de45f0 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -47,6 +47,7 @@
 #include "DNA_collection_types.h"
 #include "DNA_light_types.h"
 #include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
@@ -265,6 +266,11 @@ static const char *preview_collection_name(const ePreviewType pr_type)
   }
 }
 
+static bool render_engine_supports_ray_visibility(const Scene *sce)
+{
+  return !STREQ(sce->r.engine, RE_engine_id_BLENDER_EEVEE);
+}
+
 static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePreviewType pr_type)
 {
   /* Set appropriate layer as visible. */
@@ -281,29 +287,60 @@ static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePr
   }
 }
 
-static void switch_preview_floor_visibility(ViewLayer *view_layer,
+static const char *preview_floor_material_name(const Scene *scene,
+                                               const ePreviewRenderMethod pr_method)
+{
+  if (pr_method == PR_ICON_RENDER && render_engine_supports_ray_visibility(scene)) {
+    return "FloorHidden";
+  }
+  return "Floor";
+}
+
+static void switch_preview_floor_material(Main *pr_main,
+                                          Mesh *me,
+                                          const Scene *scene,
+                                          const ePreviewRenderMethod pr_method)
+{
+  if (me->totcol == 0) {
+    return;
+  }
+
+  const char *material_name = preview_floor_material_name(scene, pr_method);
+  Material *mat = BLI_findstring(&pr_main->materials, material_name, offsetof(ID, name) + 2);
+  if (mat) {
+    me->mat[0] = mat;
+  }
+}
+
+static void switch_preview_floor_visibility(Main *pr_main,
+                                            const Scene *scene,
+                                            ViewLayer *view_layer,
                                             const ePreviewRenderMethod pr_method)
 {
   /* Hide floor for icon renders. */
   LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
     if (STREQ(base->object->id.name + 2, "Floor")) {
+      base->object->visibility_flag &= ~OB_HIDE_RENDER;
       if (pr_method == PR_ICON_RENDER) {
-        base->object->visibility_flag |= OB_HIDE_RENDER;
+        if (!render_engine_supports_ray_visibility(scene)) {
+          base->object->visibility_flag |= OB_HIDE_RENDER;
+        }
       }
-      else {
-        base->object->visibility_flag &= ~OB_HIDE_RENDER;
+      if (base->object->type == OB_MESH) {
+        switch_preview_floor_material(pr_main, base->object->data, scene, pr_method);
       }
     }
   }
 }
 
-static void set_preview_visibility(Scene *scene,
+static void set_preview_visibility(Main *pr_main,
+                                   Scene *scene,
                                    ViewLayer *view_layer,
                                    const ePreviewType pr_type,
                                    const ePreviewRenderMethod pr_method)
 {
   switch_preview_collection_visibilty(view_layer, pr_type);
-  switch_preview_floor_visibility(view_layer, pr_method);
+  switch_preview_floor_visibility(pr_main, scene, view_layer, pr_method);
   BKE_layer_collection_sync(scene, view_layer);
 }
 
@@ -357,10 +394,31 @@ static ID *duplicate_ids(ID *id, const bool allow_failure)
   }
 }
 
-static World *preview_get_world(Main *pr_main)
+static const char *preview_world_name(const Scene *sce,
+                                      const ID_Type id_type,
+                                      const ePreviewRenderMethod pr_method)
+{
+  /* When rendering material icons the floor will not be shown in the output. Cycles will use a
+   * material trick to show the floor in the reflections, but hide the floor for camera rays. For
+   * Eevee we use a transparent world that has a projected grid.
+   *
+   * In the future when Eevee supports vulkan raytracing we can re-evaluate and perhaps remove this
+   * approximation.
+   */
+  if (id_type == ID_MA && pr_method == PR_ICON_RENDER &&
+      !render_engine_supports_ray_visibility(sce)) {
+    return "WorldFloor";
+  }
+  return "World";
+}
+
+static World *preview_get_world(Main *pr_main,
+                                const Scene *sce,
+                                const ID_Type id_type,
+                                const ePreviewRenderMethod pr_method)
 {
   World *result = NULL;
-  const char *world_name = "World";
+  const char *world_name = preview_world_name(sce, id_type, pr_method);
   result = BLI_findstring(&pr_main->worlds, world_name, offsetof(ID, name) + 2);
 
   /* No world found return first world. */
@@ -380,9 +438,13 @@ static void preview_sync_exposure(World *dst, const World *src)
   dst->range = src->range;
 }
 
-static World *preview_prepare_world(Main *pr_main, const World *world)
+static World *preview_prepare_world(Main *pr_main,
+                                    const Scene *sce,
+                                    const World *world,
+                                    const ID_Type id_type,
+                                    const ePreviewRenderMethod pr_method)
 {
-  World *result = preview_get_world(pr_main);
+  World *result = preview_get_world(pr_main, sce, id_type, pr_method);
   if (world) {
     preview_sync_exposure(result, world);
   }
@@ -436,7 +498,7 @@ static Scene *preview_prepare_scene(
     sce->r.cfra = scene->r.cfra;
 
     /* Setup the world. */
-    sce->world = preview_prepare_world(pr_main, scene->world);
+    sce->world = preview_prepare_world(pr_main, sce, scene->world, id_type, sp->pr_method);
 
     if (id_type == ID_TE) {
       /* Texture is not actually rendered with engine, just set dummy value. */
@@ -458,7 +520,7 @@ static Scene *preview_prepare_scene(
           /* Use current scene world to light sphere. */
           sce->world = preview_get_localized_world(sp, scene->world);
         }
-        else if (sce->world) {
+        else if (sce->world && sp->pr_method != PR_ICON_RENDER) {
           /* Use a default world color. Using the current
            * scene world can be slow if it has big textures. */
           sce->world->use_nodes = false;
@@ -472,7 +534,7 @@ static Scene *preview_prepare_scene(
                                            sp->pr_main == G_pr_main_grease_pencil) ?
                                               MA_SPHERE_A :
                                               mat->pr_type;
-        set_preview_visibility(sce, view_layer, preview_type, sp->pr_method);
+        set_preview_visibility(pr_main, sce, view_layer, preview_type, sp->pr_method);
 
         if (sp->pr_method != PR_ICON_RENDER) {
           if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
@@ -536,7 +598,7 @@ static Scene *preview_prepare_scene(
         BLI_addtail(&pr_main->lights, la);
       }
 
-      set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);
+      set_preview_visibility(pr_main, sce, view_layer, MA_LAMP, sp->pr_method);
 
       if (sce->world) {
         /* Only use lighting from the light. */
@@ -571,7 +633,7 @@ static Scene *preview_prepare_scene(
         BLI_addtail(&pr_main->worlds, wrld);
       }
 
-      set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
+      set_preview_visibility(pr_main, sce, view_layer, MA_SKY, sp->pr_method);
       sce->world = wrld;
 
       if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {



More information about the Bf-blender-cvs mailing list