Cycles: Display RenderPass in Viewport
authorJeroen Bakker <j.bakker@atmind.nl>
Thu, 5 Sep 2019 10:47:20 +0000 (12:47 +0200)
committerJeroen Bakker <j.bakker@atmind.nl>
Wed, 11 Sep 2019 10:19:44 +0000 (12:19 +0200)
This change allows the user to select a renderpass in the 3d viewport.

Added support for external renderers to extend the `View3DShading` struct.
This way Blender doesn't need to know the features an external render engine wants to support.
Note that the View3DShading is also available in the scene->display.shading; although this is
supported, it does not make sense for render engines to put something here as it is really
scene/workbench related.

Currently cycles assumes that it always needs to calculate the combined pass; it ignores the
`pass_flag` in KernelFilm. We could optimize this but that was not in scope of this change

Reviewed By: brecht

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

20 files changed:
intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_camera.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/blender/blender_sync.h
intern/cycles/blender/blender_viewport.cpp
intern/cycles/blender/blender_viewport.h
intern/cycles/kernel/kernel_film.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/buffers.h
intern/cycles/render/film.cpp
intern/cycles/render/film.h
intern/cycles/render/session.cpp
intern/cycles/render/session.h
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_space.c

index 3acdfc391a68589853da669d8674fe5020f96b93..93f8f76cd6a68a4f3a483dd6a56d31b05024a0d9 100644 (file)
@@ -151,6 +151,44 @@ enum_texture_limit = (
     ('8192', "8192", "Limit texture size to 8192 pixels", 7),
 )
 
+enum_view3d_shading_render_pass= (
+    ('', "General", ""),
+
+    ('COMBINED', "Combined", "Show the Combined Render pass", 1),
+    ('EMISSION', "Emission", "Show the Emission render pass", 33),
+    ('BACKGROUND', "Background", "Show the Background render pass", 34),
+    ('AO', "Ambient Occlusion", "Show the Ambient Occlusion render pass", 35),
+
+    ('', "Light", ""),
+
+    ('DIFFUSE_DIRECT', "Diffuse Direct", "Show the Diffuse Direct render pass", 38),
+    ('DIFFUSE_INDIRECT', "Diffuse Indirect", "Show the Diffuse Indirect render pass", 39),
+    ('DIFFUSE_COLOR', "Diffuse Color", "Show the Diffuse Color render pass", 40),
+
+    ('GLOSSY_DIRECT', "Glossy Direct", "Show the Glossy Direct render pass", 41),
+    ('GLOSSY_INDIRECT', "Glossy Indirect", "Show the Glossy Indirect render pass", 42),
+    ('GLOSSY_COLOR', "Glossy Color", "Show the Glossy Color render pass", 43),
+
+    ('', "", ""),
+
+    ('TRANSMISSION_DIRECT', "Transmission Direct", "Show the Transmission Direct render pass", 44),
+    ('TRANSMISSION_INDIRECT', "Transmission Indirect", "Show the Transmission Indirect render pass", 45),
+    ('TRANSMISSION_COLOR', "Transmission Color", "Show the Transmission Color render pass", 46),
+
+    ('SUBSURFACE_DIRECT', "Subsurface Direct", "Show the Subsurface Direct render pass", 47),
+    ('SUBSURFACE_INDIRECT', "Subsurface Indirect", "Show the Subsurface Indirect render pass", 48),
+    ('SUBSURFACE_COLOR', "Subsurface Color", "Show the Subsurface Color render pass", 49),
+
+    ('VOLUME_DIRECT', "Volume Direct", "Show the Volume Direct render pass", 50),
+    ('VOLUME_INDIRECT', "Volume Indirect", "Show the Volume Indirect render pass", 51),
+
+    ('', "Data", ""),
+
+    ('NORMAL', "Normal", "Show the Normal render pass", 3),
+    ('UV', "UV", "Show the UV render pass", 4),
+    ('MIST', "Mist", "Show the Mist render pass", 32),
+)
+
 
 class CyclesRenderSettings(bpy.types.PropertyGroup):
 
@@ -1475,6 +1513,15 @@ class CyclesPreferences(bpy.types.AddonPreferences):
         self.draw_impl(self.layout, context)
 
 
+class CyclesView3DShadingSettings(bpy.types.PropertyGroup):
+    render_pass: EnumProperty(
+        name="Render Pass",
+        description="Render pass to show in the 3D Viewport",
+        items=enum_view3d_shading_render_pass,
+        default='COMBINED',
+    )
+
+
 def register():
     bpy.utils.register_class(CyclesRenderSettings)
     bpy.utils.register_class(CyclesCameraSettings)
@@ -1488,6 +1535,12 @@ def register():
     bpy.utils.register_class(CyclesDeviceSettings)
     bpy.utils.register_class(CyclesPreferences)
     bpy.utils.register_class(CyclesRenderLayerSettings)
+    bpy.utils.register_class(CyclesView3DShadingSettings)
+
+    bpy.types.View3DShading.cycles = bpy.props.PointerProperty(
+        name="Cycles Settings",
+        type=CyclesView3DShadingSettings,
+    )
 
 
 def unregister():
@@ -1503,3 +1556,4 @@ def unregister():
     bpy.utils.unregister_class(CyclesDeviceSettings)
     bpy.utils.unregister_class(CyclesPreferences)
     bpy.utils.unregister_class(CyclesRenderLayerSettings)
+    bpy.utils.unregister_class(CyclesView3DShadingSettings)
index 0af59411c5caf3bbcdb6f88e60a642285e64efb1..9028100ad7aaf6f25881dbc46eca1c6a28e79798 100644 (file)
@@ -2050,6 +2050,25 @@ class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
         sub.prop(cscene, "distance_cull_margin", text="Distance")
 
 
+class CYCLES_VIEW3D_PT_shading_render_pass(Panel):
+    bl_space_type = 'VIEW_3D'
+    bl_region_type = 'HEADER'
+    bl_label = "Render Pass"
+    bl_parent_id = 'VIEW3D_PT_shading'
+    COMPAT_ENGINES = {'CYCLES'}
+
+    @classmethod
+    def poll(cls, context):
+        return (context.engine in cls.COMPAT_ENGINES
+            and context.space_data.shading.type == 'RENDERED')
+
+    def draw(self, context):
+        shading = context.space_data.shading
+
+        layout = self.layout
+        layout.prop(shading.cycles, "render_pass", text="")
+
+
 class CYCLES_VIEW3D_PT_shading_lighting(Panel):
     bl_space_type = 'VIEW_3D'
     bl_region_type = 'HEADER'
@@ -2172,6 +2191,7 @@ classes = (
     CYCLES_RENDER_PT_simplify_render,
     CYCLES_RENDER_PT_simplify_culling,
     CYCLES_VIEW3D_PT_shading_lighting,
+    CYCLES_VIEW3D_PT_shading_render_pass,
     CYCLES_RENDER_PT_motion_blur,
     CYCLES_RENDER_PT_motion_blur_curve,
     CYCLES_RENDER_PT_film,
index da43f94708cb8d25d80288afb687b59dc6980933..3b19e78894a8f2b675f535b88fd706b58209effd 100644 (file)
@@ -899,6 +899,8 @@ BufferParams BlenderSync::get_buffer_params(BL::RenderSettings &b_render,
     params.height = height;
   }
 
+  update_viewport_display_passes(b_v3d, params.passes, false);
+
   return params;
 }
 
index e50d96cf345132ea5f488150b2e20b03fd49ffd9..8b7c66363d965b92658de4b28f62424f1a91bfef 100644 (file)
@@ -206,7 +206,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
 
   sync_view_layer(b_v3d, b_view_layer);
   sync_integrator();
-  sync_film();
+  sync_film(b_v3d);
   sync_shaders(b_depsgraph, b_v3d);
   sync_images();
   sync_curve_settings();
@@ -336,13 +336,17 @@ void BlenderSync::sync_integrator()
 
 /* Film */
 
-void BlenderSync::sync_film()
+void BlenderSync::sync_film(BL::SpaceView3D &b_v3d)
 {
   PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
 
   Film *film = scene->film;
   Film prevfilm = *film;
 
+  if (b_v3d) {
+    film->display_pass = update_viewport_display_passes(b_v3d, film->passes, true);
+  }
+
   film->exposure = get_float(cscene, "film_exposure");
   film->filter_type = (FilterType)get_enum(
       cscene, "pixel_filter_type", FILTER_NUM_TYPES, FILTER_BLACKMAN_HARRIS);
@@ -368,8 +372,10 @@ void BlenderSync::sync_film()
     }
   }
 
-  if (film->modified(prevfilm))
+  if (film->modified(prevfilm)) {
     film->tag_update(scene);
+    film->tag_passes_update(scene, prevfilm.passes, false);
+  }
 }
 
 /* Render Layer */
index c6c7b7549cf24320bbcf466d112a57216ef77fb5..a80f484fb924d06af590bfda6b53bf703b82afe5 100644 (file)
@@ -116,7 +116,7 @@ class BlenderSync {
                    int width,
                    int height,
                    void **python_thread_state);
-  void sync_film();
+  void sync_film(BL::SpaceView3D &b_v3d);
   void sync_view();
   void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
   void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d);
index 93dd8faa450db57067774ab46d50a5fb72e3a97d..a74b20f150bd0d64e85494c97f07679a6643e52e 100644 (file)
@@ -15,6 +15,8 @@
  */
 #include "blender_viewport.h"
 
+#include "blender_util.h"
+
 CCL_NAMESPACE_BEGIN
 
 BlenderViewportParameters::BlenderViewportParameters()
@@ -59,4 +61,38 @@ const bool BlenderViewportParameters::custom_viewport_parameters() const
   return !(use_scene_world && use_scene_lights);
 }
 
+PassType BlenderViewportParameters::get_viewport_display_render_pass(BL::SpaceView3D &b_v3d)
+{
+  PassType display_pass = PASS_NONE;
+  if (b_v3d) {
+    BL::View3DShading b_view3dshading = b_v3d.shading();
+    PointerRNA cshading = RNA_pointer_get(&b_view3dshading.ptr, "cycles");
+    display_pass = (PassType)get_enum(cshading, "render_pass", -1, -1);
+  }
+  return display_pass;
+}
+
+PassType update_viewport_display_passes(BL::SpaceView3D &b_v3d,
+                                        vector<Pass> &passes,
+                                        bool reset_passes)
+{
+  if (b_v3d) {
+    PassType display_pass = BlenderViewportParameters::get_viewport_display_render_pass(b_v3d);
+
+    if (reset_passes) {
+      passes.clear();
+      /* We always need a combined pass for now. It would be a good optimization
+       * to support rendering without combined pass. */
+      Pass::add(PASS_COMBINED, passes);
+    }
+
+    if (display_pass != PASS_COMBINED) {
+      Pass::add(display_pass, passes);
+    }
+
+    return display_pass;
+  }
+  return PASS_NONE;
+}
+
 CCL_NAMESPACE_END
index 6b2f8ea42156cb555113368176f48f0b2bd98885..564c4f2b210ebe8c2f3c49c539ca584c6ad55b68 100644 (file)
@@ -22,6 +22,7 @@
 #include "RNA_access.h"
 #include "RNA_blender_cpp.h"
 
+#include "render/film.h"
 #include "util/util_param.h"
 
 CCL_NAMESPACE_BEGIN
@@ -41,8 +42,17 @@ class BlenderViewportParameters {
   const bool modified(const BlenderViewportParameters &other) const;
   const bool custom_viewport_parameters() const;
   friend class BlenderSync;
+
+ public:
+  /* Retrieve the render pass that needs to be displayed on the given `SpaceView3D`
+   * When the `b_v3d` parameter is not given `PASS_NONE` will be returned. */
+  static PassType get_viewport_display_render_pass(BL::SpaceView3D &b_v3d);
 };
 
+PassType update_viewport_display_passes(BL::SpaceView3D &b_v3d,
+                                        vector<Pass> &passes,
+                                        bool reset_passes);
+
 CCL_NAMESPACE_END
 
 #endif
index d20f1adf663f141c682bea995cbe2fe58c854a7b..7a974e9d852bd7c9ab665ced4f41d5e4cf2af369 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-ccl_device float4 film_map(KernelGlobals *kg, float4 irradiance, float scale)
+ccl_device float4 film_get_pass_result(KernelGlobals *kg,
+                                       ccl_global float *buffer,
+                                       float sample_scale,
+                                       int index,
+                                       bool use_display_sample_scale)
 {
-  float exposure = kernel_data.film.exposure;
-  float4 result = irradiance * scale;
+  float4 pass_result;
+
+  int display_pass_stride = kernel_data.film.display_pass_stride;
+  int display_pass_components = kernel_data.film.display_pass_components;
+
+  if (display_pass_components == 4) {
+    ccl_global float4 *in = (ccl_global float4 *)(buffer + display_pass_stride +
+                                                  index * kernel_data.film.pass_stride);
+    float alpha = use_display_sample_scale ?
+                      (kernel_data.film.use_display_pass_alpha ? in->w : 1.0f / sample_scale) :
+                      1.0f;
+
+    pass_result = make_float4(in->x, in->y, in->z, alpha);
+
+    int display_divide_pass_stride = kernel_data.film.display_divide_pass_stride;
+    if (display_divide_pass_stride != -1) {
+      ccl_global float4 *divide_in = (ccl_global float4 *)(buffer + display_divide_pass_stride +
+                                                           index * kernel_data.film.pass_stride);
+      if (divide_in->x != 0.0f) {
+        pass_result.x /= divide_in->x;
+      }
+      if (divide_in->y != 0.0f) {
+        pass_result.y /= divide_in->y;
+      }
+      if (divide_in->z != 0.0f) {
+        pass_result.z /= divide_in->z;
+      }
+    }
+
+    if (kernel_data.film.use_display_exposure) {
+      float exposure = kernel_data.film.exposure;
+      pass_result *= make_float4(exposure, exposure, exposure, alpha);
+    }
+  }
+  else if (display_pass_components == 1) {
+    ccl_global float *in = (ccl_global float *)(buffer + display_pass_stride +
+                                                index * kernel_data.film.pass_stride);
+    pass_result = make_float4(*in, *in, *in, 1.0f / sample_scale);
+  }
+
+  return pass_result;
+}
+
+ccl_device float4 film_map(KernelGlobals *kg, float4 rgba_in, float scale)
+{
+  float4 result;
 
   /* conversion to srgb */
-  result.x = color_linear_to_srgb(result.x * exposure);
-  result.y = color_linear_to_srgb(result.y * exposure);
-  result.z = color_linear_to_srgb(result.z * exposure);
+  result.x = color_linear_to_srgb(rgba_in.x);
+  result.y = color_linear_to_srgb(rgba_in.y);
+  result.z = color_linear_to_srgb(rgba_in.z);
 
   /* clamp since alpha might be > 1.0 due to russian roulette */
-  result.w = saturate(result.w);
+  result.w = saturate(rgba_in.w);
 
   return result;
 }
@@ -57,15 +105,22 @@ ccl_device void kernel_film_convert_to_byte(KernelGlobals *kg,
   /* buffer offset */
   int index = offset + x + y * stride;
 
+  bool use_display_sample_scale = (kernel_data.film.display_divide_pass_stride == -1);
+  float4 rgba_in = film_get_pass_result(kg, buffer, sample_scale, index, use_display_sample_scale);
+
   rgba += index;
-  buffer += index * kernel_data.film.pass_stride;
 
   /* map colors */
-  float4 irradiance = *((ccl_global float4 *)buffer);
-  float4 float_result = film_map(kg, irradiance, sample_scale);
-  uchar4 byte_result = film_float_to_byte(float_result);
-
-  *rgba = byte_result;
+  if (use_display_sample_scale) {
+    float4 float_result = film_map(kg, rgba_in, sample_scale);
+    uchar4 byte_result = film_float_to_byte(float_result);
+    *rgba = byte_result;
+  }
+  else {
+    float4 float_result = film_map(kg, rgba_in, 1.0);
+    uchar4 byte_result = film_float_to_byte(float_result);
+    *rgba = byte_result;
+  }
 }
 
 ccl_device void kernel_film_convert_to_half_float(KernelGlobals *kg,
@@ -79,21 +134,16 @@ ccl_device void kernel_film_convert_to_half_float(KernelGlobals *kg,
 {
   /* buffer offset */
   int index = offset + x + y * stride;
+  bool use_display_sample_scale = (kernel_data.film.display_divide_pass_stride == -1);
+  float4 rgba_in = film_get_pass_result(kg, buffer, sample_scale, index, use_display_sample_scale);
 
-  ccl_global float4 *in = (ccl_global float4 *)(buffer + index * kernel_data.film.pass_stride);
   ccl_global half *out = (ccl_global half *)rgba + index * 4;
-
-  float exposure = kernel_data.film.exposure;
-
-  float4 rgba_in = *in;
-
-  if (exposure != 1.0f) {
-    rgba_in.x *= exposure;
-    rgba_in.y *= exposure;
-    rgba_in.z *= exposure;
+  if (use_display_sample_scale) {
+    float4_store_half(out, rgba_in, sample_scale);
+  }
+  else {
+    float4_store_half(out, rgba_in, 1.0f);
   }
-
-  float4_store_half(out, rgba_in, sample_scale);
 }
 
 CCL_NAMESPACE_END
index b3cb6ca7c1946269fd16a48bf30e88039c18e1b1..f0054691b54e32f1566192acf1a0f483e0f871fd 100644 (file)
@@ -1168,6 +1168,7 @@ static_assert_align(KernelCamera, 16);
 typedef struct KernelFilm {
   float exposure;
   int pass_flag;
+
   int light_pass_flag;
   int pass_stride;
   int use_light_pass;
@@ -1233,6 +1234,13 @@ typedef struct KernelFilm {
   int pass_bvh_intersections;
   int pass_ray_bounces;
 #endif
+
+  /* viewport rendering options */
+  int display_pass_stride;
+  int display_pass_components;
+  int display_divide_pass_stride;
+  int use_display_exposure;
+  int use_display_pass_alpha;
 } KernelFilm;
 static_assert_align(KernelFilm, 16);
 
index 1c49038cd4b3b6fc0b9899360f81523bd5356ccd..74bb656c5a476300f05596a9654853b99737a642 100644 (file)
@@ -64,7 +64,6 @@ class BufferParams {
 
   void get_offset_stride(int &offset, int &stride);
   bool modified(const BufferParams &params);
-  void add_pass(PassType type);
   int get_passes_size();
   int get_denoising_offset();
   int get_denoising_prefiltered_offset();
index d6c44b66117f89aa0d741b748bdf79c38d106bfa..5bf7ba97515094e8ccf992204cf0aa83cd8d1dfd 100644 (file)
@@ -267,7 +267,7 @@ NODE_DEFINE(Film)
   NodeType *type = NodeType::add("film", create);
 
   SOCKET_FLOAT(exposure, "Exposure", 0.8f);
-  SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.5f);
+  SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.0f);
 
   static NodeEnum filter_enum;
   filter_enum.insert("box", FILTER_BOX);
@@ -318,6 +318,13 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
   /* update __data */
   kfilm->exposure = exposure;
   kfilm->pass_flag = 0;
+
+  kfilm->display_pass_stride = -1;
+  kfilm->display_pass_components = 0;
+  kfilm->display_divide_pass_stride = -1;
+  kfilm->use_display_exposure = false;
+  kfilm->use_display_pass_alpha = (display_pass == PASS_COMBINED);
+
   kfilm->light_pass_flag = 0;
   kfilm->pass_stride = 0;
   kfilm->use_light_pass = use_light_visibility || use_sample_clamp;
@@ -464,6 +471,16 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
         break;
     }
 
+    if (pass.type == display_pass) {
+      kfilm->display_pass_stride = kfilm->pass_stride;
+      kfilm->display_pass_components = pass.components;
+      kfilm->use_display_exposure = pass.exposure && (kfilm->exposure != 1.0f);
+    }
+    else if (pass.type == PASS_DIFFUSE_COLOR || pass.type == PASS_TRANSMISSION_COLOR ||
+             pass.type == PASS_GLOSSY_COLOR || pass.type == PASS_SUBSURFACE_COLOR) {
+      kfilm->display_divide_pass_stride = kfilm->pass_stride;
+    }
+
     kfilm->pass_stride += pass.components;
   }
 
@@ -485,7 +502,18 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
   }
 
   kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
-  kfilm->pass_alpha_threshold = pass_alpha_threshold;
+
+  /* When displaying the normal/uv pass in the viewport we need to disable
+   * transparency.
+   *
+   * We also don't need to perform light accumulations. Later we want to optimize this to suppress
+   * light calculations. */
+  if (display_pass == PASS_NORMAL || display_pass == PASS_UV) {
+    kfilm->use_light_pass = 0;
+  }
+  else {
+    kfilm->pass_alpha_threshold = pass_alpha_threshold;
+  }
 
   /* update filter table */
   vector<float> table = filter_table(filter_type, filter_width);
@@ -518,7 +546,7 @@ bool Film::modified(const Film &film)
   return !Node::equals(film) || !Pass::equals(passes, film.passes);
 }
 
-void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_)
+void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes)
 {
   if (Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
     scene->mesh_manager->tag_update(scene);
@@ -526,10 +554,16 @@ void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_)
     foreach (Shader *shader, scene->shaders)
       shader->need_update_mesh = true;
   }
-  else if (Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
+  else if (Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION)) {
     scene->mesh_manager->tag_update(scene);
+  }
+  else if (Pass::contains(passes, PASS_AO) != Pass::contains(passes_, PASS_AO)) {
+    scene->integrator->tag_update(scene);
+  }
 
-  passes = passes_;
+  if (update_passes) {
+    passes = passes_;
+  }
 }
 
 void Film::tag_update(Scene * /*scene*/)
index 1cfa7c3b77d95480fd0b963732c246c5a734838c..20f6261a8710aa890650eb1ac2fe6a5310c082bc 100644 (file)
@@ -64,6 +64,7 @@ class Film : public Node {
   int denoising_flags;
   float pass_alpha_threshold;
 
+  PassType display_pass;
   int pass_stride;
   int denoising_data_offset;
   int denoising_clean_offset;
@@ -90,7 +91,7 @@ class Film : public Node {
   void device_free(Device *device, DeviceScene *dscene, Scene *scene);
 
   bool modified(const Film &film);
-  void tag_passes_update(Scene *scene, const vector<Pass> &passes_);
+  void tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes=true);
   void tag_update(Scene *scene);
 };
 
index 332f1fb61670cc02a92f20bafa364828783ddbce..7a894c1e98a8e931f3d239fc1bf8118939adc5b1 100644 (file)
@@ -83,7 +83,7 @@ Session::Session(const SessionParams &params_)
 
   display_outdated = false;
   gpu_draw_ready = false;
-  gpu_need_tonemap = false;
+  gpu_need_display_buffer_update = false;
   pause = false;
   kernels_loaded = false;
 
@@ -97,8 +97,8 @@ Session::~Session()
     /* wait for session thread to end */
     progress.set_cancel("Exiting");
 
-    gpu_need_tonemap = false;
-    gpu_need_tonemap_cond.notify_all();
+    gpu_need_display_buffer_update = false;
+    gpu_need_display_buffer_update_cond.notify_all();
 
     {
       thread_scoped_lock pause_lock(pause_mutex);
@@ -110,12 +110,12 @@ Session::~Session()
   }
 
   if (params.write_render_cb) {
-    /* tonemap and write out image if requested */
+    /* Copy to display buffer and write out image if requested */
     delete display;
 
     display = new DisplayBuffer(device, false);
     display->reset(buffers->params);
-    tonemap(params.samples);
+    copy_to_display_buffer(params.samples);
 
     int w = display->draw_width;
     int h = display->draw_height;
@@ -168,8 +168,8 @@ void Session::reset_gpu(BufferParams &buffer_params, int samples)
 
   reset_(buffer_params, samples);
 
-  gpu_need_tonemap = false;
-  gpu_need_tonemap_cond.notify_all();
+  gpu_need_display_buffer_update = false;
+  gpu_need_display_buffer_update_cond.notify_all();
 
   pause_cond.notify_all();
 }
@@ -186,11 +186,11 @@ bool Session::draw_gpu(BufferParams &buffer_params, DeviceDrawParams &draw_param
     if (!buffer_params.modified(display->params)) {
       /* for CUDA we need to do tone-mapping still, since we can
        * only access GL buffers from the main thread. */
-      if (gpu_need_tonemap) {
+      if (gpu_need_display_buffer_update) {
         thread_scoped_lock buffers_lock(buffers_mutex);
-        tonemap(tile_manager.state.sample);
-        gpu_need_tonemap = false;
-        gpu_need_tonemap_cond.notify_all();
+        copy_to_display_buffer(tile_manager.state.sample);
+        gpu_need_display_buffer_update = false;
+        gpu_need_display_buffer_update_cond.notify_all();
       }
 
       display->draw(device, draw_params);
@@ -307,17 +307,17 @@ void Session::run_gpu()
       /* update status and timing */
       update_status_time();
 
-      gpu_need_tonemap = true;
+      gpu_need_display_buffer_update = true;
       gpu_draw_ready = true;
       progress.set_update();
 
-      /* wait for tonemap */
+      /* wait for until display buffer is updated */
       if (!params.background) {
-        while (gpu_need_tonemap) {
+        while (gpu_need_display_buffer_update) {
           if (progress.get_cancel())
             break;
 
-          gpu_need_tonemap_cond.wait(buffers_lock);
+          gpu_need_display_buffer_update_cond.wait(buffers_lock);
         }
       }
 
@@ -561,7 +561,7 @@ void Session::run_cpu()
   while (!progress.get_cancel()) {
     /* advance to next tile */
     bool no_tiles = !tile_manager.next();
-    bool need_tonemap = false;
+    bool need_copy_to_display_buffer = false;
 
     DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
     if (no_tiles) {
@@ -650,7 +650,7 @@ void Session::run_cpu()
       update_status_time();
 
       if (!params.background)
-        need_tonemap = true;
+        need_copy_to_display_buffer = true;
 
       if (!device->error_message().empty())
         progress.set_error(device->error_message());
@@ -668,10 +668,10 @@ void Session::run_cpu()
         delayed_reset.do_reset = false;
         reset_(delayed_reset.params, delayed_reset.samples);
       }
-      else if (need_tonemap) {
-        /* tonemap only if we do not reset, we don't we don't
+      else if (need_copy_to_display_buffer) {
+        /* Only copy to display_buffer if we do not reset, we don't
          * want to show the result of an incomplete sample */
-        tonemap(tile_manager.state.sample);
+        copy_to_display_buffer(tile_manager.state.sample);
       }
 
       if (!device->error_message().empty())
@@ -1044,9 +1044,9 @@ void Session::render()
   device->task_add(task);
 }
 
-void Session::tonemap(int sample)
+void Session::copy_to_display_buffer(int sample)
 {
-  /* add tonemap task */
+  /* add film conversion task */
   DeviceTask task(DeviceTask::FILM_CONVERT);
 
   task.x = tile_manager.state.buffer.full_x;
index 60d8f7a8b143e1833644acbc3e0fcf35384f51f8..9fffc13dd41d696ea5aa0fca937ccaea5829ddc1 100644 (file)
@@ -176,7 +176,7 @@ class Session {
 
   void update_status_time(bool show_pause = false, bool show_done = false);
 
-  void tonemap(int sample);
+  void copy_to_display_buffer(int sample);
   void render();
   void reset_(BufferParams &params, int samples);
 
@@ -202,8 +202,8 @@ class Session {
   volatile bool display_outdated;
 
   volatile bool gpu_draw_ready;
-  volatile bool gpu_need_tonemap;
-  thread_condition_variable gpu_need_tonemap_cond;
+  volatile bool gpu_need_display_buffer_update;
+  thread_condition_variable gpu_need_display_buffer_update_cond;
 
   bool pause;
   thread_condition_variable pause_cond;
index 3ea009b001495698b6eef71272ad786413b2bda3..5054a0d1a4fd7e5ba196f358879a3d05c4754e8a 100644 (file)
@@ -550,6 +550,11 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
     sce->eevee.light_cache = NULL;
   }
 
+  if (sce->display.shading.prop) {
+    IDP_FreeProperty(sce->display.shading.prop);
+    sce->display.shading.prop = NULL;
+  }
+
   /* These are freed on doversion. */
   BLI_assert(sce->layer_properties == NULL);
 }
index bd2580dba74f05cf6bb3f7d9cf55809fde179e6a..e9d4af447e0b2356824f25db1694bf1b0a30ae72 100644 (file)
@@ -6353,6 +6353,14 @@ static void direct_link_lightcache(FileData *fd, LightCache *cache)
   cache->grid_data = newdataadr(fd, cache->grid_data);
 }
 
+static void direct_link_view3dshading(FileData *fd, View3DShading *shading)
+{
+  if (shading->prop) {
+    shading->prop = newdataadr(fd, shading->prop);
+    IDP_DirectLinkGroup_OrFree(&shading->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+  }
+}
+
 /* check for cyclic set-scene,
  * libs can cause this case which is normally prevented, see (T#####) */
 #define USE_SETSCENE_CHECK
@@ -6987,6 +6995,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
     }
   }
 
+  direct_link_view3dshading(fd, &sce->display.shading);
+
   sce->layer_properties = newdataadr(fd, sce->layer_properties);
   IDP_DirectLinkGroup_OrFree(&sce->layer_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 }
@@ -7255,6 +7265,8 @@ static void direct_link_area(FileData *fd, ScrArea *area)
         v3d->fx_settings.ssao = newdataadr(fd, v3d->fx_settings.ssao);
       }
 
+      direct_link_view3dshading(fd, &v3d->shading);
+
       blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
     }
     else if (sl->spacetype == SPACE_GRAPH) {
index c9c3a96fb32b14ed88e92e95bc1372dc37ad2d4d..d698c94dbfbf5f6309eccf73481ddca3c89cf56a 100644 (file)
@@ -2413,6 +2413,13 @@ static void write_view_settings(WriteData *wd, ColorManagedViewSettings *view_se
   }
 }
 
+static void write_view3dshading(WriteData *wd, View3DShading *shading)
+{
+  if (shading->prop) {
+    IDP_WriteProperty(shading->prop, wd);
+  }
+}
+
 static void write_paint(WriteData *wd, Paint *p)
 {
   if (p->cavity_curve) {
@@ -2684,6 +2691,8 @@ static void write_scene(WriteData *wd, Scene *sce)
     write_lightcache(wd, sce->eevee.light_cache);
   }
 
+  write_view3dshading(wd, &sce->display.shading);
+
   /* Freed on doversion. */
   BLI_assert(sce->layer_properties == NULL);
 }
@@ -2850,6 +2859,7 @@ static void write_area_regions(WriteData *wd, ScrArea *area)
       if (v3d->fx_settings.dof) {
         writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
       }
+      write_view3dshading(wd, &v3d->shading);
     }
     else if (sl->spacetype == SPACE_GRAPH) {
       SpaceGraph *sipo = (SpaceGraph *)sl;
index 5974100b53455f7df8130115d1c7594411a80a54..a8f662991b63f9771bad1708f51aa64c3d961119 100644 (file)
@@ -39,6 +39,7 @@
 #include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_icons.h"
+#include "BKE_idprop.h"
 #include "BKE_lattice.h"
 #include "BKE_main.h"
 #include "BKE_mball.h"
@@ -363,6 +364,11 @@ static void view3d_free(SpaceLink *sl)
   if (vd->fx_settings.dof) {
     MEM_freeN(vd->fx_settings.dof);
   }
+
+  if (vd->shading.prop) {
+    IDP_FreeProperty(vd->shading.prop);
+    vd->shading.prop = NULL;
+  }
 }
 
 /* spacetype; init callback */
index 3a7675eb92ac80488871ca9b76da6b0628304a43..106bf1252b21d96bc68aa79b89235922893560a0 100644 (file)
@@ -179,6 +179,8 @@ typedef struct View3DShading {
 
   float curvature_ridge_factor;
   float curvature_valley_factor;
+
+  struct IDProperty *prop;
 } View3DShading;
 
 /** 3D Viewport Overlay settings. */
index 4da0dd1d4ce87627f4a1b8938fb8cf9438b53079..43f77a3cf884f4f0fe0de57a2c1797ab715f065e 100644 (file)
@@ -458,6 +458,7 @@ const EnumPropertyItem rna_enum_file_sort_items[] = {
 #  include "BKE_brush.h"
 #  include "BKE_colortools.h"
 #  include "BKE_context.h"
+#  include "BKE_idprop.h"
 #  include "BKE_layer.h"
 #  include "BKE_global.h"
 #  include "BKE_nla.h"
@@ -938,6 +939,18 @@ static bool rna_RegionView3D_is_orthographic_side_view_get(PointerRNA *ptr)
   return RV3D_VIEW_IS_AXIS(rv3d->view);
 }
 
+static IDProperty *rna_View3DShading_idprops(PointerRNA *ptr, bool create)
+{
+  View3DShading *shading = ptr->data;
+
+  if (create && !shading->prop) {
+    IDPropertyTemplate val = {0};
+    shading->prop = IDP_New(IDP_GROUP, &val, "View3DShading ID properties");
+  }
+
+  return shading->prop;
+}
+
 static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
   ID *id = ptr->owner_id;
@@ -3003,6 +3016,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
   RNA_def_struct_path_func(srna, "rna_View3DShading_path");
   RNA_def_struct_ui_text(
       srna, "3D View Shading Settings", "Settings for shading in the 3D viewport");
+  RNA_def_struct_idprops_func(srna, "rna_View3DShading_idprops");
 
   prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
   RNA_def_property_enum_items(prop, rna_enum_shading_type_items);