Cycles: Display RenderPass in Viewport
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
This commit is contained in:
parent
d4f8bc80a4
commit
7e61e59725
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -16,18 +16,66 @@
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -64,7 +64,6 @@ class BufferParams {
|
||||
|
||||
void get_offset_stride(int &offset, int &stride);
|
||||
bool modified(const BufferParams ¶ms);
|
||||
void add_pass(PassType type);
|
||||
int get_passes_size();
|
||||
int get_denoising_offset();
|
||||
int get_denoising_prefiltered_offset();
|
||||
|
@ -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*/)
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -83,7 +83,7 @@ Session::Session(const SessionParams ¶ms_)
|
||||
|
||||
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;
|
||||
|
@ -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 ¶ms, 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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -179,6 +179,8 @@ typedef struct View3DShading {
|
||||
|
||||
float curvature_ridge_factor;
|
||||
float curvature_valley_factor;
|
||||
|
||||
struct IDProperty *prop;
|
||||
} View3DShading;
|
||||
|
||||
/** 3D Viewport Overlay settings. */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user