diff options
40 files changed, 529 insertions, 238 deletions
diff --git a/GNUmakefile b/GNUmakefile index 1143ac6e1f1..46f0fa18eec 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -48,6 +48,11 @@ DEPS_SOURCE_DIR:=$(BLENDER_DIR)/build_files/build_environment DEPS_BUILD_DIR:=$(BUILD_DIR)/deps DEPS_INSTALL_DIR:=$(shell dirname "$(BLENDER_DIR)")/lib/$(OS_NCASE) +ifneq ($(OS_NCASE),darwin) + # Add processor type to directory name + DEPS_INSTALL_DIR:=$(DEPS_INSTALL_DIR)_$(shell uname -p) +endif + # Allow to use alternative binary (pypy3, etc) ifndef PYTHON PYTHON:=python3 diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index d5e29164696..306a09a3a5b 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -23,6 +23,19 @@ # Libraries configuration for any *nix system including Linux and Unix. +# Detect precompiled library directory +set(LIBDIR_NAME ${CMAKE_SYSTEM_NAME}_${CMAKE_SYSTEM_PROCESSOR}) +string(TOLOWER ${LIBDIR_NAME} LIBDIR_NAME) +set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME}) + +if(EXISTS ${LIBDIR}) + file(GLOB LIB_SUBDIRS ${LIBDIR}/*) + set(CMAKE_PREFIX_PATH ${LIB_SUBDIRS}) + set(WITH_STATIC_LIBS ON) + set(WITH_OPENMP_STATIC ON) +endif() + +# Wrapper to prefer static libraries macro(find_package_wrapper) if(WITH_STATIC_LIBS) find_package_static(${ARGV}) @@ -141,8 +154,15 @@ if(WITH_CODEC_SNDFILE) endif() if(WITH_CODEC_FFMPEG) - set(FFMPEG /usr CACHE PATH "FFMPEG Directory") - set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") + if(EXISTS ${LIBDIR}) + # For precompiled lib directory, all ffmpeg dependencies are in the same folder + file(GLOB ffmpeg_libs ${LIBDIR}/ffmpeg/lib/*.a ${LIBDIR}/sndfile/lib/*.a) + set(FFMPEG ${LIBDIR}/ffmpeg CACHE PATH "FFMPEG Directory") + set(FFMPEG_LIBRARIES ${ffmpeg_libs} ${ffmpeg_libs} CACHE STRING "FFMPEG Libraries") + else() + set(FFMPEG /usr CACHE PATH "FFMPEG Directory") + set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") + endif() mark_as_advanced(FFMPEG) @@ -329,6 +349,14 @@ if(WITH_OPENCOLORIO) endif() if(WITH_LLVM) + # Symbol conflicts with same UTF library used by OpenCollada + if(EXISTS ${LIBDIR}) + set(LLVM_STATIC ON) + if(WITH_OPENCOLLADA) + list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY}) + endif() + endif() + find_package_wrapper(LLVM) if(NOT LLVM_FOUND) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 355fed124da..01dd612fccc 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -382,6 +382,23 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=12, ) + cls.dicing_camera = PointerProperty( + name="Dicing Camera", + description="Camera to use as reference point when subdividing geometry, useful to avoid crawling " + "artifacts in animations when the scene camera is moving", + type=bpy.types.Object, + poll=lambda self, obj: obj.type == 'CAMERA', + ) + cls.offscreen_dicing_scale = FloatProperty( + name="Offscreen Dicing Scale", + description="Multiplier for dicing rate of geometry outside of the camera view. The dicing rate " + "of objects is gradually increased the further they are outside the camera view. " + "Lower values provide higher quality reflections and shadows for off screen objects, " + "while higher values use less memory", + min=1.0, soft_max=25.0, + default=4.0, + ) + cls.film_exposure = FloatProperty( name="Exposure", description="Image brightness scale", @@ -390,9 +407,20 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ) cls.film_transparent = BoolProperty( name="Transparent", - description="World background is transparent with premultiplied alpha", + description="World background is transparent, for compositing the render over another background", + default=False, + ) + cls.film_transparent_glass = BoolProperty( + name="Transparent Glass", + description="Render transmissive surfaces as transparent, for compositing glass over another background", default=False, ) + cls.film_transparent_roughness = FloatProperty( + name="Transparent Roughness Threshold", + description="For transparent transmission, keep surfaces with roughness above the threshold opaque", + min=0.0, max=1.0, + default=0.1, + ) # Really annoyingly, we have to keep it around for a few releases, # otherwise forward compatibility breaks in really bad manner: CRASH! diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index b3b50fd6181..d069ec44f64 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -218,31 +218,32 @@ class CYCLES_RENDER_PT_geometry(CyclesButtonsPanel, Panel): cscene = scene.cycles ccscene = scene.cycles_curves + row = layout.row() + row.label("Volume Sampling:") + row = layout.row() + row.prop(cscene, "volume_step_size") + row.prop(cscene, "volume_max_steps") + + layout.separator() + if cscene.feature_set == 'EXPERIMENTAL': + layout.label("Subdivision Rate:") split = layout.split() col = split.column() - sub = col.column(align=True) - sub.label("Volume Sampling:") - sub.prop(cscene, "volume_step_size") - sub.prop(cscene, "volume_max_steps") + sub.prop(cscene, "dicing_rate", text="Render") + sub.prop(cscene, "preview_dicing_rate", text="Preview") col = split.column() + col.prop(cscene, "offscreen_dicing_scale", text="Offscreen Scale") + col.prop(cscene, "max_subdivisions") - sub = col.column(align=True) - sub.label("Subdivision Rate:") - sub.prop(cscene, "dicing_rate", text="Render") - sub.prop(cscene, "preview_dicing_rate", text="Preview") - sub.separator() - sub.prop(cscene, "max_subdivisions") - else: - row = layout.row() - row.label("Volume Sampling:") - row = layout.row() - row.prop(cscene, "volume_step_size") - row.prop(cscene, "volume_max_steps") + layout.prop(cscene, "dicing_camera") + + layout.separator() + layout.label("Hair:") layout.prop(ccscene, "use_curves", text="Use Hair") col = layout.column() col.active = ccscene.use_curves @@ -359,14 +360,21 @@ class CYCLES_RENDER_PT_film(CyclesButtonsPanel, Panel): col = split.column() col.prop(cscene, "film_exposure") - col.prop(cscene, "film_transparent") - - col = split.column() + col.separator() sub = col.column(align=True) sub.prop(cscene, "pixel_filter_type", text="") if cscene.pixel_filter_type != 'BOX': sub.prop(cscene, "filter_width", text="Width") + col = split.column() + col.prop(cscene, "film_transparent") + sub = col.row() + sub.prop(cscene, "film_transparent_glass", text="Transparent Glass") + sub.active = cscene.film_transparent + sub = col.row() + sub.prop(cscene, "film_transparent_roughness", text="Roughness Threshold") + sub.active = cscene.film_transparent and cscene.film_transparent_glass + class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel): bl_label = "Performance" diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index b29711d30d3..62e950e3bef 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -81,6 +81,8 @@ struct BlenderCamera { BoundBox2D viewport_camera_border; Transform matrix; + + float offscreen_dicing_scale; }; static void blender_camera_init(BlenderCamera *bcam, @@ -104,6 +106,7 @@ static void blender_camera_init(BlenderCamera *bcam, bcam->pano_viewplane.top = 1.0f; bcam->viewport_camera_border.right = 1.0f; bcam->viewport_camera_border.top = 1.0f; + bcam->offscreen_dicing_scale = 1.0f; /* render resolution */ bcam->full_width = render_resolution_x(b_render); @@ -353,7 +356,11 @@ static void blender_camera_viewplane(BlenderCamera *bcam, } } -static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height, const char *viewname) +static void blender_camera_sync(Camera *cam, + BlenderCamera *bcam, + int width, int height, + const char *viewname, + PointerRNA *cscene) { /* copy camera to compare later */ Camera prevcam = *cam; @@ -466,6 +473,9 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->border = bcam->border; cam->viewport_camera_border = bcam->viewport_camera_border; + bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale"); + cam->offscreen_dicing_scale = bcam->offscreen_dicing_scale; + /* set update flag */ if(cam->modified(prevcam)) cam->tag_update(); @@ -525,7 +535,21 @@ void BlenderSync::sync_camera(BL::RenderSettings& b_render, /* sync */ Camera *cam = scene->camera; - blender_camera_sync(cam, &bcam, width, height, viewname); + blender_camera_sync(cam, &bcam, width, height, viewname, &cscene); + + /* dicing camera */ + b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera")); + if(b_ob) { + BL::Array<float, 16> b_ob_matrix; + blender_camera_from_object(&bcam, b_engine, b_ob); + b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix); + bcam.matrix = get_transform(b_ob_matrix); + + blender_camera_sync(scene->dicing_camera, &bcam, width, height, viewname, &cscene); + } + else { + *scene->dicing_camera = *cam; + } } void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render, @@ -818,7 +842,22 @@ void BlenderSync::sync_view(BL::SpaceView3D& b_v3d, b_v3d, b_rv3d, width, height); - blender_camera_sync(scene->camera, &bcam, width, height, ""); + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + blender_camera_sync(scene->camera, &bcam, width, height, "", &cscene); + + /* dicing camera */ + BL::Object b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera")); + if(b_ob) { + BL::Array<float, 16> b_ob_matrix; + blender_camera_from_object(&bcam, b_engine, b_ob); + b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix); + bcam.matrix = get_transform(b_ob_matrix); + + blender_camera_sync(scene->dicing_camera, &bcam, width, height, "", &cscene); + } + else { + *scene->dicing_camera = *scene->camera; + } } BufferParams BlenderSync::get_buffer_params(BL::RenderSettings& b_render, diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 4622dce286f..2c0548adbed 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -920,8 +920,8 @@ static void create_subd_mesh(Scene *scene, sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); sdparams.max_level = max_subdivisions; - scene->camera->update(); - sdparams.camera = scene->camera; + scene->dicing_camera->update(scene); + sdparams.camera = scene->dicing_camera; sdparams.objecttoworld = get_transform(b_ob.matrix_world()); } diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp index 0333c027f70..1d747de647a 100644 --- a/intern/cycles/blender/blender_object_cull.cpp +++ b/intern/cycles/blender/blender_object_cull.cpp @@ -62,7 +62,7 @@ void BlenderObjectCulling::init_object(Scene *scene, BL::Object& b_ob) if(use_camera_cull_ || use_distance_cull_) { /* Need to have proper projection matrix. */ - scene->camera->update(); + scene->camera->update(scene); } } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 94c7aa3b248..29ed4b4a772 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -1344,6 +1344,15 @@ void BlenderSync::sync_world(bool update_all) else background->transparent = b_scene.render().alpha_mode() == BL::RenderSettings::alpha_mode_TRANSPARENT; + if(background->transparent) { + background->transparent_glass = get_boolean(cscene, "film_transparent_glass"); + background->transparent_roughness_threshold = get_float(cscene, "film_transparent_roughness"); + } + else { + background->transparent_glass = false; + background->transparent_roughness_threshold = 0.0f; + } + background->use_shader = view_layer.use_background_shader; background->use_ao = background->use_ao && view_layer.use_background_ao; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index f3312e2909f..870183aa1d6 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -225,9 +225,7 @@ void BlenderSync::sync_data(BL::RenderSettings& b_render, void BlenderSync::sync_integrator() { -#ifdef __CAMERA_MOTION__ BL::RenderSettings r = b_scene.render(); -#endif PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); experimental = (get_enum(cscene, "feature_set") != 0); @@ -272,7 +270,6 @@ void BlenderSync::sync_integrator() integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct"); integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect"); -#ifdef __CAMERA_MOTION__ if(!preview) { if(integrator->motion_blur != r.use_motion_blur()) { scene->object_manager->tag_update(scene); @@ -281,7 +278,6 @@ void BlenderSync::sync_integrator() integrator->motion_blur = r.use_motion_blur(); } -#endif integrator->method = (Integrator::Method)get_enum(cscene, "progressive", diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index e4573024e85..6f0bdb3fa38 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -38,7 +38,7 @@ CCL_NAMESPACE_BEGIN /* Returns the square of the roughness of the closure if it has roughness, * 0 for singular closures and 1 otherwise. */ -ccl_device_inline float bsdf_get_roughness_sqr(const ShaderClosure *sc) +ccl_device_inline float bsdf_get_roughness_squared(const ShaderClosure *sc) { if(CLOSURE_IS_BSDF_SINGULAR(sc->type)) { return 0.0f; @@ -173,6 +173,17 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg, break; } + /* Test if BSDF sample should be treated as transparent for background. */ + if(label & LABEL_TRANSMIT) { + float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold; + + if(threshold_squared >= 0.0f) { + if(bsdf_get_roughness_squared(sc) <= threshold_squared) { + label |= LABEL_TRANSMIT_TRANSPARENT; + } + } + } + return label; } diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index 90a9c2147cc..60a1e483b84 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -216,19 +216,19 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData * else { tfm = kernel_data.cam.worldtocamera; motion_center = normalize(transform_point(&tfm, center)); - motion_center = float2_to_float3(direction_to_panorama(kg, motion_center)); + motion_center = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_center)); motion_center.x *= kernel_data.cam.width; motion_center.y *= kernel_data.cam.height; tfm = kernel_data.cam.motion.pre; motion_pre = normalize(transform_point(&tfm, motion_pre)); - motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre)); + motion_pre = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_pre)); motion_pre.x *= kernel_data.cam.width; motion_pre.y *= kernel_data.cam.height; tfm = kernel_data.cam.motion.post; motion_post = normalize(transform_point(&tfm, motion_post)); - motion_post = float2_to_float3(direction_to_panorama(kg, motion_post)); + motion_post = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_post)); motion_post.x *= kernel_data.cam.width; motion_post.y *= kernel_data.cam.height; } diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 7c1b2a015e1..c0f281cae97 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -455,7 +455,7 @@ ccl_device_inline void path_radiance_accum_background( #ifdef __PASSES__ if(L->use_light_pass) { - if(state->bounce == 0) + if(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) L->background += throughput*value; else if(state->bounce == 1) L->direct_emission += throughput*value; diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 77e3446329a..96cdb04d955 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -18,9 +18,9 @@ CCL_NAMESPACE_BEGIN /* Perspective Camera */ -ccl_device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v) +ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, float u, float v) { - float blades = kernel_data.cam.blades; + float blades = cam->blades; float2 bokeh; if(blades == 0.0f) { @@ -29,12 +29,12 @@ ccl_device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v) } else { /* sample polygon */ - float rotation = kernel_data.cam.bladesrotation; + float rotation = cam->bladesrotation; bokeh = regular_polygon_sample(blades, rotation, u, v); } /* anamorphic lens bokeh */ - bokeh.x *= kernel_data.cam.inv_aperture_ratio; + bokeh.x *= cam->inv_aperture_ratio; return bokeh; } @@ -76,7 +76,7 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo if(aperturesize > 0.0f) { /* sample point on aperture */ - float2 lensuv = camera_sample_aperture(kg, lens_u, lens_v)*aperturesize; + float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v)*aperturesize; /* compute point on plane of focus */ float ft = kernel_data.cam.focaldistance/D.z; @@ -124,7 +124,7 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo } else { /* Spherical stereo */ - spherical_stereo_transform(kg, &P, &D); + spherical_stereo_transform(&kernel_data.cam, &P, &D); ray->P = P; ray->D = D; @@ -138,12 +138,12 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo float3 Pcenter = Pnostereo; float3 Dcenter = Pcamera; Dcenter = normalize(transform_direction(&cameratoworld, Dcenter)); - spherical_stereo_transform(kg, &Pcenter, &Dcenter); + spherical_stereo_transform(&kernel_data.cam, &Pcenter, &Dcenter); float3 Px = Pnostereo; float3 Dx = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f)); Dx = normalize(transform_direction(&cameratoworld, Dx)); - spherical_stereo_transform(kg, &Px, &Dx); + spherical_stereo_transform(&kernel_data.cam, &Px, &Dx); ray->dP.dx = Px - Pcenter; ray->dD.dx = Dx - Dcenter; @@ -151,7 +151,7 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo float3 Py = Pnostereo; float3 Dy = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f)); Dy = normalize(transform_direction(&cameratoworld, Dy)); - spherical_stereo_transform(kg, &Py, &Dy); + spherical_stereo_transform(&kernel_data.cam, &Py, &Dy); ray->dP.dy = Py - Pcenter; ray->dD.dy = Dy - Dcenter; @@ -186,7 +186,7 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl if(aperturesize > 0.0f) { /* sample point on aperture */ - float2 lensuv = camera_sample_aperture(kg, lens_u, lens_v)*aperturesize; + float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v)*aperturesize; /* compute point on plane of focus */ float3 Pfocus = D * kernel_data.cam.focaldistance; @@ -238,17 +238,17 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl /* Panorama Camera */ -ccl_device_inline void camera_sample_panorama(KernelGlobals *kg, +ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) { - Transform rastertocamera = kernel_data.cam.rastertocamera; + Transform rastertocamera = cam->rastertocamera; float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); /* create ray form raster position */ float3 P = make_float3(0.0f, 0.0f, 0.0f); - float3 D = panorama_to_direction(kg, Pcamera.x, Pcamera.y); + float3 D = panorama_to_direction(cam, Pcamera.x, Pcamera.y); /* indicates ray should not receive any light, outside of the lens */ if(is_zero(D)) { @@ -257,15 +257,15 @@ ccl_device_inline void camera_sample_panorama(KernelGlobals *kg, } /* modify ray for depth of field */ - float aperturesize = kernel_data.cam.aperturesize; + float aperturesize = cam->aperturesize; if(aperturesize > 0.0f) { /* sample point on aperture */ - float2 lensuv = camera_sample_aperture(kg, lens_u, lens_v)*aperturesize; + float2 lensuv = camera_sample_aperture(cam, lens_u, lens_v)*aperturesize; /* compute point on plane of focus */ float3 Dfocus = normalize(D); - float3 Pfocus = Dfocus * kernel_data.cam.focaldistance; + float3 Pfocus = Dfocus * cam->focaldistance; /* calculate orthonormal coordinates perpendicular to Dfocus */ float3 U, V; @@ -278,18 +278,18 @@ ccl_device_inline void camera_sample_panorama(KernelGlobals *kg, } /* transform ray from camera to world */ - Transform cameratoworld = kernel_data.cam.cameratoworld; + Transform cameratoworld = cam->cameratoworld; #ifdef __CAMERA_MOTION__ - if(kernel_data.cam.have_motion) { + if(cam->have_motion) { # ifdef __KERNEL_OPENCL__ - const MotionTransform tfm = kernel_data.cam.motion; + const MotionTransform tfm = cam->motion; transform_motion_interpolate(&cameratoworld, &tfm, ray->time); # else transform_motion_interpolate(&cameratoworld, - &kernel_data.cam.motion, + &cam->motion, ray->time); # endif } @@ -299,9 +299,9 @@ ccl_device_inline void camera_sample_panorama(KernelGlobals *kg, D = normalize(transform_direction(&cameratoworld, D)); /* Stereo transform */ - bool use_stereo = kernel_data.cam.interocular_offset != 0.0f; + bool use_stereo = cam->interocular_offset != 0.0f; if(use_stereo) { - spherical_stereo_transform(kg, &P, &D); + spherical_stereo_transform(cam, &P, &D); } ray->P = P; @@ -313,30 +313,30 @@ ccl_device_inline void camera_sample_panorama(KernelGlobals *kg, * ray origin and direction for the center and two neighbouring pixels * and simply take their differences. */ float3 Pcenter = Pcamera; - float3 Dcenter = panorama_to_direction(kg, Pcenter.x, Pcenter.y); + float3 Dcenter = panorama_to_direction(cam, Pcenter.x, Pcenter.y); Pcenter = transform_point(&cameratoworld, Pcenter); Dcenter = normalize(transform_direction(&cameratoworld, Dcenter)); if(use_stereo) { - spherical_stereo_transform(kg, &Pcenter, &Dcenter); + spherical_stereo_transform(cam, &Pcenter, &Dcenter); } float3 Px = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f)); - float3 Dx = panorama_to_direction(kg, Px.x, Px.y); + float3 Dx = panorama_to_direction(cam, Px.x, Px.y); Px = transform_point(&cameratoworld, Px); Dx = normalize(transform_direction(&cameratoworld, Dx)); if(use_stereo) { - spherical_stereo_transform(kg, &Px, &Dx); + spherical_stereo_transform(cam, &Px, &Dx); } ray->dP.dx = Px - Pcenter; ray->dD.dx = Dx - Dcenter; float3 Py = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f)); - float3 Dy = panorama_to_direction(kg, Py.x, Py.y); + float3 Dy = panorama_to_direction(cam, Py.x, Py.y); Py = transform_point(&cameratoworld, Py); Dy = normalize(transform_direction(&cameratoworld, Dy)); if(use_stereo) { - spherical_stereo_transform(kg, &Py, &Dy); + spherical_stereo_transform(cam, &Py, &Dy); } ray->dP.dy = Py - Pcenter; @@ -345,11 +345,11 @@ ccl_device_inline void camera_sample_panorama(KernelGlobals *kg, #ifdef __CAMERA_CLIPPING__ /* clipping */ - float nearclip = kernel_data.cam.nearclip; + float nearclip = cam->nearclip; ray->P += nearclip * ray->D; ray->dP.dx += nearclip * ray->dD.dx; ray->dP.dy += nearclip * ray->dD.dy; - ray->t = kernel_data.cam.cliplength; + ray->t = cam->cliplength; #else ray->t = FLT_MAX; #endif @@ -415,7 +415,7 @@ ccl_device_inline void camera_sample(KernelGlobals *kg, else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) camera_sample_orthographic(kg, raster_x, raster_y, lens_u, lens_v, ray); else - camera_sample_panorama(kg, raster_x, raster_y, lens_u, lens_v, ray); + camera_sample_panorama(&kernel_data.cam, raster_x, raster_y, lens_u, lens_v, ray); } /* Utilities */ @@ -472,7 +472,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd, else P = normalize(transform_direction(&tfm, P)); - float2 uv = direction_to_panorama(kg, P); + float2 uv = direction_to_panorama(&kernel_data.cam, P); return make_float3(uv.x, uv.y, 0.0f); } diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 29451b6b8b6..1933d695f92 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -140,7 +140,7 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg, /* All closures contribute to the normal feature, but only diffuse-like ones to the albedo. */ normal += sc->N * sc->sample_weight; sum_weight += sc->sample_weight; - if(bsdf_get_roughness_sqr(sc) > sqr(0.075f)) { + if(bsdf_get_roughness_squared(sc) > sqr(0.075f)) { albedo += sc->weight; sum_nonspecular_weight += sc->sample_weight; } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index c2421c1ec18..1e98bca66ad 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -136,7 +136,7 @@ ccl_device_forceinline void kernel_path_background( PathRadiance *L) { /* eval background shader if nothing hit */ - if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) { + if(kernel_data.background.transparent && (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { L->transparent += average(throughput); #ifdef __PASSES__ @@ -280,7 +280,7 @@ ccl_device_forceinline bool kernel_path_shader_apply( { #ifdef __SHADOW_TRICKS__ if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { - if(state->flag & PATH_RAY_CAMERA) { + if(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) { state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_STORE_SHADOW_INFO); @@ -302,7 +302,7 @@ ccl_device_forceinline bool kernel_path_shader_apply( #ifdef __HOLDOUT__ if(((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) && - (state->flag & PATH_RAY_CAMERA)) + (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { if(kernel_data.background.transparent) { float3 holdout_weight; diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index eccee54c0e3..505eed117e0 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -23,7 +23,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, int sample, ccl_addr_space Ray *ray) { - state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP; + state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP|PATH_RAY_TRANSPARENT_BACKGROUND; state->rng_hash = rng_hash; state->rng_offset = PRNG_BASE_NUM; @@ -86,12 +86,13 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta } state->bounce++; + state->flag &= ~(PATH_RAY_ALL_VISIBILITY|PATH_RAY_MIS_SKIP); #ifdef __VOLUME__ if(label & LABEL_VOLUME_SCATTER) { /* volume scatter */ state->flag |= PATH_RAY_VOLUME_SCATTER; - state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_TRANSMIT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT|PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP); + state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND; state->volume_bounce++; } @@ -101,7 +102,7 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta /* surface reflection/transmission */ if(label & LABEL_REFLECT) { state->flag |= PATH_RAY_REFLECT; - state->flag &= ~(PATH_RAY_TRANSMIT|PATH_RAY_VOLUME_SCATTER|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT); + state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND; if(label & LABEL_DIFFUSE) state->diffuse_bounce++; @@ -112,7 +113,10 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta kernel_assert(label & LABEL_TRANSMIT); state->flag |= PATH_RAY_TRANSMIT; - state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_VOLUME_SCATTER|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT); + + if(!(label & LABEL_TRANSMIT_TRANSPARENT)) { + state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND; + } state->transmission_bounce++; } @@ -120,17 +124,13 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta /* diffuse/glossy/singular */ if(label & LABEL_DIFFUSE) { state->flag |= PATH_RAY_DIFFUSE|PATH_RAY_DIFFUSE_ANCESTOR; - state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP); } else if(label & LABEL_GLOSSY) { state->flag |= PATH_RAY_GLOSSY; - state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP); } else { kernel_assert(label & LABEL_SINGULAR); - state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP; - state->flag &= ~PATH_RAY_DIFFUSE; } } diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h index cbb2442d1dc..4540d733af4 100644 --- a/intern/cycles/kernel/kernel_projection.h +++ b/intern/cycles/kernel/kernel_projection.h @@ -195,49 +195,49 @@ ccl_device float2 direction_to_mirrorball(float3 dir) return make_float2(u, v); } -ccl_device_inline float3 panorama_to_direction(KernelGlobals *kg, float u, float v) +ccl_device_inline float3 panorama_to_direction(ccl_constant KernelCamera *cam, float u, float v) { - switch(kernel_data.cam.panorama_type) { + switch(cam->panorama_type) { case PANORAMA_EQUIRECTANGULAR: - return equirectangular_range_to_direction(u, v, kernel_data.cam.equirectangular_range); + return equirectangular_range_to_direction(u, v, cam->equirectangular_range); case PANORAMA_MIRRORBALL: return mirrorball_to_direction(u, v); case PANORAMA_FISHEYE_EQUIDISTANT: - return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov); + return fisheye_to_direction(u, v, cam->fisheye_fov); case PANORAMA_FISHEYE_EQUISOLID: default: - return fisheye_equisolid_to_direction(u, v, kernel_data.cam.fisheye_lens, - kernel_data.cam.fisheye_fov, kernel_data.cam.sensorwidth, kernel_data.cam.sensorheight); + return fisheye_equisolid_to_direction(u, v, cam->fisheye_lens, + cam->fisheye_fov, cam->sensorwidth, cam->sensorheight); } } -ccl_device_inline float2 direction_to_panorama(KernelGlobals *kg, float3 dir) +ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, float3 dir) { - switch(kernel_data.cam.panorama_type) { + switch(cam->panorama_type) { case PANORAMA_EQUIRECTANGULAR: - return direction_to_equirectangular_range(dir, kernel_data.cam.equirectangular_range); + return direction_to_equirectangular_range(dir, cam->equirectangular_range); case PANORAMA_MIRRORBALL: return direction_to_mirrorball(dir); case PANORAMA_FISHEYE_EQUIDISTANT: - return direction_to_fisheye(dir, kernel_data.cam.fisheye_fov); + return direction_to_fisheye(dir, cam->fisheye_fov); case PANORAMA_FISHEYE_EQUISOLID: default: - return direction_to_fisheye_equisolid(dir, kernel_data.cam.fisheye_lens, - kernel_data.cam.sensorwidth, kernel_data.cam.sensorheight); + return direction_to_fisheye_equisolid(dir, cam->fisheye_lens, + cam->sensorwidth, cam->sensorheight); } } -ccl_device_inline void spherical_stereo_transform(KernelGlobals *kg, float3 *P, float3 *D) +ccl_device_inline void spherical_stereo_transform(ccl_constant KernelCamera *cam, float3 *P, float3 *D) { - float interocular_offset = kernel_data.cam.interocular_offset; + float interocular_offset = cam->interocular_offset; /* Interocular offset of zero means either non stereo, or stereo without * spherical stereo. */ kernel_assert(interocular_offset != 0.0f); - if(kernel_data.cam.pole_merge_angle_to > 0.0f) { - const float pole_merge_angle_from = kernel_data.cam.pole_merge_angle_from, - pole_merge_angle_to = kernel_data.cam.pole_merge_angle_to; + if(cam->pole_merge_angle_to > 0.0f) { + const float pole_merge_angle_from = cam->pole_merge_angle_from, + pole_merge_angle_to = cam->pole_merge_angle_to; float altitude = fabsf(safe_asinf((*D).z)); if(altitude > pole_merge_angle_to) { interocular_offset = 0.0f; @@ -257,7 +257,7 @@ ccl_device_inline void spherical_stereo_transform(KernelGlobals *kg, float3 *P, /* Convergence distance is FLT_MAX in the case of parallel convergence mode, * no need to modify direction in this case either. */ - const float convergence_distance = kernel_data.cam.convergence_distance; + const float convergence_distance = cam->convergence_distance; if(convergence_distance != FLT_MAX) { diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index 616ad71af3c..c79992ee99b 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -283,22 +283,23 @@ ccl_device_inline int subsurface_scatter_multi_intersect( object_normal_transform(kg, sd, &hit_Ng); } - /* probability densities for local frame axes */ + /* Probability densities for local frame axes. */ float pdf_N = pick_pdf_N * fabsf(dot(disk_N, hit_Ng)); float pdf_T = pick_pdf_T * fabsf(dot(disk_T, hit_Ng)); float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng)); - /* multiple importance sample between 3 axes, power heuristic - * found to be slightly better than balance heuristic */ - float mis_weight = power_heuristic_3(pdf_N, pdf_T, pdf_B); + /* Multiple importance sample between 3 axes, power heuristic + * found to be slightly better than balance heuristic. pdf_N + * in the MIS weight and denominator cancelled out. */ + float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B)); + if(ss_isect->num_hits > BSSRDF_MAX_HITS) { + w *= ss_isect->num_hits/(float)BSSRDF_MAX_HITS; + } - /* real distance to sampled point */ + /* Real distance to sampled point. */ float r = len(hit_P - sd->P); - /* evaluate */ - float w = mis_weight / pdf_N; - if(ss_isect->num_hits > BSSRDF_MAX_HITS) - w *= ss_isect->num_hits/(float)BSSRDF_MAX_HITS; + /* Evaluate profiles. */ float3 eval = subsurface_scatter_eval(sd, sc, disk_r, r, all) * w; ss_isect->weight[hit] = eval; @@ -417,20 +418,21 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_a /* setup new shading point */ shader_setup_from_subsurface(kg, sd, &ss_isect.hits[0], &ray); - /* probability densities for local frame axes */ + /* Probability densities for local frame axes. */ float pdf_N = pick_pdf_N * fabsf(dot(disk_N, sd->Ng)); float pdf_T = pick_pdf_T * fabsf(dot(disk_T, sd->Ng)); float pdf_B = pick_pdf_B * fabsf(dot(disk_B, sd->Ng)); - /* multiple importance sample between 3 axes, power heuristic - * found to be slightly better than balance heuristic */ - float mis_weight = power_heuristic_3(pdf_N, pdf_T, pdf_B); + /* Multiple importance sample between 3 axes, power heuristic + * found to be slightly better than balance heuristic. pdf_N + * in the MIS weight and denominator cancelled out. */ + float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B)); + w *= ss_isect.num_hits; - /* real distance to sampled point */ + /* Real distance to sampled point. */ float r = len(sd->P - origP); - /* evaluate */ - float w = (mis_weight * ss_isect.num_hits) / pdf_N; + /* Evaluate profiles. */ eval = subsurface_scatter_eval(sd, sc, disk_r, r, all) * w; } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index b052d668b7d..4f655784044 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -346,11 +346,12 @@ enum PathRayFlag { PATH_RAY_ALL_VISIBILITY = ((1 << 14)-1), - PATH_RAY_MIS_SKIP = (1 << 15), - PATH_RAY_DIFFUSE_ANCESTOR = (1 << 16), - PATH_RAY_SINGLE_PASS_DONE = (1 << 17), - PATH_RAY_SHADOW_CATCHER = (1 << 18), - PATH_RAY_STORE_SHADOW_INFO = (1 << 19), + PATH_RAY_MIS_SKIP = (1 << 15), + PATH_RAY_DIFFUSE_ANCESTOR = (1 << 16), + PATH_RAY_SINGLE_PASS_DONE = (1 << 17), + PATH_RAY_SHADOW_CATCHER = (1 << 18), + PATH_RAY_STORE_SHADOW_INFO = (1 << 19), + PATH_RAY_TRANSPARENT_BACKGROUND = (1 << 20), }; /* Closure Label */ @@ -364,6 +365,7 @@ typedef enum ClosureLabel { LABEL_SINGULAR = 16, LABEL_TRANSPARENT = 32, LABEL_VOLUME_SCATTER = 64, + LABEL_TRANSMIT_TRANSPARENT = 128, } ClosureLabel; /* Render Passes */ @@ -1259,7 +1261,7 @@ typedef struct KernelBackground { int surface_shader; int volume_shader; int transparent; - int pad; + float transparent_roughness_squared_threshold; /* ambient occlusion */ float ao_factor; diff --git a/intern/cycles/kernel/svm/svm_bevel.h b/intern/cycles/kernel/svm/svm_bevel.h index bbbc8dce2cf..dcfe4ad71b8 100644 --- a/intern/cycles/kernel/svm/svm_bevel.h +++ b/intern/cycles/kernel/svm/svm_bevel.h @@ -174,18 +174,17 @@ ccl_device_noinline float3 svm_bevel( float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng)); /* Multiple importance sample between 3 axes, power heuristic - * found to be slightly better than balance heuristic. */ - float mis_weight = power_heuristic_3(pdf_N, pdf_T, pdf_B); + * found to be slightly better than balance heuristic. pdf_N + * in the MIS weight and denominator cancelled out. */ + float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B)); + if(isect.num_hits > LOCAL_MAX_HITS) { + w *= isect.num_hits/(float)LOCAL_MAX_HITS; + } /* Real distance to sampled point. */ float r = len(hit_P - sd->P); /* Compute weight. */ - float w = mis_weight / pdf_N; - if(isect.num_hits > LOCAL_MAX_HITS) { - w *= isect.num_hits/(float)LOCAL_MAX_HITS; - } - float pdf = bssrdf_cubic_pdf(radius, 0.0f, r); float disk_pdf = bssrdf_cubic_pdf(radius, 0.0f, disk_r); diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp index 3ed96732b14..df3b65be110 100644 --- a/intern/cycles/render/background.cpp +++ b/intern/cycles/render/background.cpp @@ -38,7 +38,10 @@ NODE_DEFINE(Background) SOCKET_BOOLEAN(use_shader, "Use Shader", true); SOCKET_BOOLEAN(use_ao, "Use AO", false); SOCKET_UINT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY); + SOCKET_BOOLEAN(transparent, "Transparent", false); + SOCKET_BOOLEAN(transparent_glass, "Transparent Glass", false); + SOCKET_FLOAT(transparent_roughness_threshold, "Transparent Roughness Threshold", 0.0f); SOCKET_NODE(shader, "Shader", &Shader::node_type); @@ -81,6 +84,15 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene kbackground->transparent = transparent; kbackground->surface_shader = scene->shader_manager->get_shader_id(bg_shader); + if(transparent && transparent_glass) { + /* Square twice, once for principled BSDF convention, and once for + * faster comparison in kernel with anisotropic roughness. */ + kbackground->transparent_roughness_squared_threshold = sqr(sqr(transparent_roughness_threshold)); + } + else { + kbackground->transparent_roughness_squared_threshold = -1.0f; + } + if(bg_shader->has_volume) kbackground->volume_shader = kbackground->surface_shader; else diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h index db20b6ebf87..145c05f1c18 100644 --- a/intern/cycles/render/background.h +++ b/intern/cycles/render/background.h @@ -42,6 +42,9 @@ public: Shader *shader; bool transparent; + bool transparent_glass; + float transparent_roughness_threshold; + bool need_update; Background(); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 9b226140f08..a2fda12ec85 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -27,6 +27,15 @@ #include "util/util_math_cdf.h" #include "util/util_vector.h" +/* needed for calculating differentials */ +#include "kernel/kernel_compat_cpu.h" +#include "kernel/split/kernel_split_data.h" +#include "kernel/kernel_globals.h" +#include "kernel/kernel_projection.h" +#include "kernel/kernel_differential.h" +#include "kernel/kernel_montecarlo.h" +#include "kernel/kernel_camera.h" + CCL_NAMESPACE_BEGIN static float shutter_curve_eval(float x, @@ -128,6 +137,8 @@ NODE_DEFINE(Camera) SOCKET_FLOAT(border.bottom, "Border Bottom", 0); SOCKET_FLOAT(border.top, "Border Top", 0); + SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f); + return type; } @@ -166,6 +177,8 @@ Camera::Camera() need_device_update = true; need_flags_update = true; previous_need_motion = -1; + + memset(&kernel_camera, 0, sizeof(kernel_camera)); } Camera::~Camera() @@ -197,8 +210,17 @@ void Camera::compute_auto_viewplane() } } -void Camera::update() +void Camera::update(Scene *scene) { + Scene::MotionType need_motion = scene->need_motion(); + + if(previous_need_motion != need_motion) { + /* scene's motion model could have been changed since previous device + * camera update this could happen for example in case when one render + * layer has got motion pass and another not */ + need_device_update = true; + } + if(!need_update) return; @@ -273,6 +295,13 @@ void Camera::update() full_dx = transform_direction(&cameratoworld, full_dx); full_dy = transform_direction(&cameratoworld, full_dy); + if(type == CAMERA_PERSPECTIVE) { + float3 v = transform_perspective(&full_rastertocamera, make_float3(full_width, full_height, 1.0f)); + + frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x)); + frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y)); + } + /* TODO(sergey): Support other types of camera. */ if(type == CAMERA_PERSPECTIVE) { /* TODO(sergey): Move to an utility function and de-duplicate with @@ -290,28 +319,8 @@ void Camera::update() perspective_motion.post = screentocamera_post * rastertoscreen; } - need_update = false; - need_device_update = true; - need_flags_update = true; -} - -void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) -{ - Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); - - update(); - - if(previous_need_motion != need_motion) { - /* scene's motion model could have been changed since previous device - * camera update this could happen for example in case when one render - * layer has got motion pass and another not */ - need_device_update = true; - } - - if(!need_device_update) - return; - - KernelCamera *kcam = &dscene->data.cam; + /* Compute kernel camera data. */ + KernelCamera *kcam = &kernel_camera; /* store matrices */ kcam->screentoworld = screentoworld; @@ -350,7 +359,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } } } -#ifdef __CAMERA_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { if(use_motion) { transform_motion_decompose(&kcam->motion, &motion, &matrix); @@ -361,7 +369,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->have_perspective_motion = 1; } } -#endif /* depth of field */ kcam->aperturesize = aperturesize; @@ -370,26 +377,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->bladesrotation = bladesrotation; /* motion blur */ -#ifdef __CAMERA_MOTION__ kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: -1.0f; - scene->lookup_tables->remove_table(&shutter_table_offset); - if(need_motion == Scene::MOTION_BLUR) { - vector<float> shutter_table; - util_cdf_inverted(SHUTTER_TABLE_SIZE, - 0.0f, - 1.0f, - function_bind(shutter_curve_eval, _1, shutter_curve), - false, - shutter_table); - shutter_table_offset = scene->lookup_tables->add_table(dscene, - shutter_table); - kcam->shutter_table_offset = (int)shutter_table_offset; - } -#else - kcam->shuttertime = -1.0f; -#endif - /* type */ kcam->type = type; @@ -450,9 +439,39 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->rolling_shutter_type = rolling_shutter_type; kcam->rolling_shutter_duration = rolling_shutter_duration; + /* Set further update flags */ + need_update = false; + need_device_update = true; + need_flags_update = true; previous_need_motion = need_motion; } +void Camera::device_update(Device * /* device */, + DeviceScene *dscene, + Scene *scene) +{ + update(scene); + + if(!need_device_update) + return; + + scene->lookup_tables->remove_table(&shutter_table_offset); + if(kernel_camera.shuttertime != -1.0f) { + vector<float> shutter_table; + util_cdf_inverted(SHUTTER_TABLE_SIZE, + 0.0f, + 1.0f, + function_bind(shutter_curve_eval, _1, shutter_curve), + false, + shutter_table); + shutter_table_offset = scene->lookup_tables->add_table(dscene, + shutter_table); + kernel_camera.shutter_table_offset = (int)shutter_table_offset; + } + + dscene->data.cam = kernel_camera; +} + void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scene *scene) @@ -581,8 +600,27 @@ BoundBox Camera::viewplane_bounds_get() float Camera::world_to_raster_size(float3 P) { + float res = 1.0f; + if(type == CAMERA_ORTHOGRAPHIC) { - return min(len(full_dx), len(full_dy)); + res = min(len(full_dx), len(full_dy)); + + if(offscreen_dicing_scale > 1.0f) { + float3 p = transform_perspective(&worldtocamera, P); + float3 v = transform_perspective(&rastertocamera, make_float3(width, height, 0.0f)); + + /* Create point clamped to frustum */ + float3 c; + c.x = max(-v.x, min(v.x, p.x)); + c.y = max(-v.y, min(v.y, p.y)); + c.z = max(0.0f, p.z); + + float f_dist = len(p - c) / sqrtf((v.x*v.x+v.y*v.y)*0.5f); + + if(f_dist > 0.0f) { + res += res * f_dist * (offscreen_dicing_scale - 1.0f); + } + } } else if(type == CAMERA_PERSPECTIVE) { /* Calculate as if point is directly ahead of the camera. */ @@ -597,14 +635,98 @@ float Camera::world_to_raster_size(float3 P) /* dPdx */ float dist = len(transform_point(&worldtocamera, P)); float3 D = normalize(Ddiff); - return len(dist*dDdx - dot(dist*dDdx, D)*D); + res = len(dist*dDdx - dot(dist*dDdx, D)*D); + + /* Decent approx distance to frustum (doesn't handle corners correctly, but not that big of a deal) */ + float f_dist = 0.0f; + + if(offscreen_dicing_scale > 1.0f) { + float3 p = transform_point(&worldtocamera, P); + + /* Distance from the four planes */ + float r = dot(p, frustum_right_normal); + float t = dot(p, frustum_top_normal); + p = make_float3(-p.x, -p.y, p.z); + float l = dot(p, frustum_right_normal); + float b = dot(p, frustum_top_normal); + p = make_float3(-p.x, -p.y, p.z); + + if(r <= 0.0f && l <= 0.0f && t <= 0.0f && b <= 0.0f) { + /* Point is inside frustum */ + f_dist = 0.0f; + } + else if(r > 0.0f && l > 0.0f && t > 0.0f && b > 0.0f) { + /* Point is behind frustum */ + f_dist = len(p); + } + else { + /* Point may be behind or off to the side, need to check */ + float3 along_right = make_float3(-frustum_right_normal.z, 0.0f, frustum_right_normal.x); + float3 along_left = make_float3(frustum_right_normal.z, 0.0f, frustum_right_normal.x); + float3 along_top = make_float3(0.0f, -frustum_top_normal.z, frustum_top_normal.y); + float3 along_bottom = make_float3(0.0f, frustum_top_normal.z, frustum_top_normal.y); + + float dist[] = {r, l, t, b}; + float3 along[] = {along_right, along_left, along_top, along_bottom}; + + bool test_o = false; + + float *d = dist; + float3 *a = along; + for(int i = 0; i < 4; i++, d++, a++) { + /* Test if we should check this side at all */ + if(*d > 0.0f) { + if(dot(p, *a) >= 0.0f) { + /* We are in front of the back edge of this side of the frustum */ + f_dist = max(f_dist, *d); + } + else { + /* Possibly far enough behind the frustum to use distance to origin instead of edge */ + test_o = true; + } + } + } + + if(test_o) { + f_dist = (f_dist > 0) ? min(f_dist, len(p)) : len(p); + } + } + + if(f_dist > 0.0f) { + res += len(dDdx - dot(dDdx, D)*D) * f_dist * (offscreen_dicing_scale - 1.0f); + } + } } - else { - // TODO(mai): implement for CAMERA_PANORAMA - assert(!"pixel width calculation for panoramic projection not implemented yet"); + else if(type == CAMERA_PANORAMA) { + float3 D = transform_point(&worldtocamera, P); + float dist = len(D); + + Ray ray; + + /* Distortion can become so great that the results become meaningless, there + * may be a better way to do this, but calculating differentials from the + * point directly ahead seems to produce good enough results. */ +#if 0 + float2 dir = direction_to_panorama(&kernel_camera, normalize(D)); + float3 raster = transform_perspective(&cameratoraster, make_float3(dir.x, dir.y, 0.0f)); + + ray.t = 1.0f; + camera_sample_panorama(&kernel_camera, raster.x, raster.y, 0.0f, 0.0f, &ray); + if(ray.t == 0.0f) { + /* No differentials, just use from directly ahead. */ + camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); + } +#else + camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); +#endif + + differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist); + + return max(len(ray.dP.dx) * (float(width)/float(full_width)), + len(ray.dP.dy) * (float(height)/float(full_height))); } - return 1.0f; + return res; } CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index dd6b831b347..4ec0fe3bc6e 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -129,6 +129,8 @@ public: BoundBox2D viewplane; /* width and height change during preview, so we need these for calculating dice rates. */ int full_width, full_height; + /* controls how fast the dicing rate falls off for geometry out side of view */ + float offscreen_dicing_scale; /* border */ BoundBox2D border; @@ -163,19 +165,25 @@ public: float3 full_dx; float3 full_dy; + float3 frustum_right_normal; + float3 frustum_top_normal; + /* update */ bool need_update; bool need_device_update; bool need_flags_update; int previous_need_motion; + /* Kernel camera data, copied here for dicing. */ + KernelCamera kernel_camera; + /* functions */ Camera(); ~Camera(); void compute_auto_viewplane(); - void update(); + void update(Scene *scene); void device_update(Device *device, DeviceScene *dscene, Scene *scene); void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 4353fd4b819..5d5a416e293 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -2103,12 +2103,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen shader->need_update_attributes = false; } -#ifdef __OBJECT_MOTION__ - Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); + Scene::MotionType need_motion = scene->need_motion(); bool motion_blur = need_motion == Scene::MOTION_BLUR; -#else - bool motion_blur = false; -#endif /* Update objects. */ vector<Object *> volume_objects; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 380c12fa6b2..20f57cc8d97 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -398,7 +398,6 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+0], &mtfm.pre, sizeof(float4)*3); memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+3], &mtfm.post, sizeof(float4)*3); } -#ifdef __OBJECT_MOTION__ else if(state->need_motion == Scene::MOTION_BLUR) { if(ob->use_motion) { /* decompose transformations for interpolation. */ @@ -410,7 +409,6 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s state->have_motion = true; } } -#endif /* Dupli object coords and motion info. */ int totalsteps = mesh->motion_steps; @@ -482,7 +480,7 @@ void ObjectManager::device_update_transforms(Device *device, Progress& progress) { UpdateObejctTransformState state; - state.need_motion = scene->need_motion(device->info.advanced_shading); + state.need_motion = scene->need_motion(); state.have_motion = false; state.have_curves = false; state.scene = scene; @@ -694,14 +692,9 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u /* counter mesh users */ map<Mesh*, int> mesh_users; -#ifdef __OBJECT_MOTION__ Scene::MotionType need_motion = scene->need_motion(); bool motion_blur = need_motion == Scene::MOTION_BLUR; bool apply_to_motion = need_motion != Scene::MOTION_PASS; -#else - bool motion_blur = false; - bool apply_to_motion = false; -#endif int i = 0; bool have_instancing = false; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 260a325206c..09a69265de8 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -85,6 +85,7 @@ Scene::Scene(const SceneParams& params_, Device *device) memset(&dscene.data, 0, sizeof(dscene.data)); camera = new Camera(); + dicing_camera = new Camera(); lookup_tables = new LookupTables(); film = new Film(); background = new Background(); @@ -155,6 +156,7 @@ void Scene::free_memory(bool final) if(final) { delete lookup_tables; delete camera; + delete dicing_camera; delete film; delete background; delete integrator; @@ -289,10 +291,10 @@ void Scene::device_update(Device *device_, Progress& progress) } } -Scene::MotionType Scene::need_motion(bool advanced_shading) +Scene::MotionType Scene::need_motion() { if(integrator->motion_blur) - return (advanced_shading)? MOTION_BLUR: MOTION_NONE; + return MOTION_BLUR; else if(Pass::contains(film->passes, PASS_MOTION)) return MOTION_PASS; else @@ -359,6 +361,7 @@ void Scene::reset() /* ensure all objects are updated */ camera->tag_update(); + dicing_camera->tag_update(); film->tag_update(this); background->tag_update(this); integrator->tag_update(this); diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 204c38e5963..5f717e93b43 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -165,6 +165,7 @@ class Scene { public: /* data */ Camera *camera; + Camera *dicing_camera; LookupTables *lookup_tables; Film *film; Background *background; @@ -212,7 +213,7 @@ public: void need_global_attributes(AttributeRequestSet& attributes); enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR }; - MotionType need_motion(bool advanced_shading = true); + MotionType need_motion(); float motion_shutter_time(); bool need_update(); diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 1089b5c699d..849f678b5c3 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -315,13 +315,15 @@ class USERPREF_PT_interface(Panel): sub.prop(view, "pie_menu_threshold") sub.prop(view, "pie_menu_confirm") col.separator() - col.separator() + + col.prop(view, "show_splash") col.separator() - col.label(text="Screen:") + col.label(text="App Template:") + col.label(text="Options intended for use with app-templates only.") col.prop(view, "show_layout_ui") + col.prop(view, "show_view3d_cursor") - col.prop(view, "show_splash") class USERPREF_PT_edit(Panel): diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index d03be79baad..27d38fcfb37 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -285,8 +285,10 @@ void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *use DATA_SWAP(keyconfigstr); DATA_SWAP(manipulator_flag); + DATA_SWAP(app_flag); - FLAG_SWAP(uiflag, int, USER_LOCK_UI_LAYOUT); + /* We could add others. */ + FLAG_SWAP(uiflag, int, USER_QUIT_PROMPT); #undef SWAP_TYPELESS #undef DATA_SWAP diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 788c5fb3913..2eae452debb 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -2923,7 +2923,7 @@ void init_userdef_do_versions(void) USER_FLAG_DEPRECATED_6 | USER_FLAG_DEPRECATED_7 | USER_FLAG_DEPRECATED_9 | USER_FLAG_DEPRECATED_10); U.uiflag &= ~( - USER_LOCK_UI_LAYOUT); + USER_UIFLAG_DEPRECATED_7); U.transopts &= ~( USER_TR_DEPRECATED_2 | USER_TR_DEPRECATED_3 | USER_TR_DEPRECATED_4 | USER_TR_DEPRECATED_6 | USER_TR_DEPRECATED_7); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index e097cd34eac..274dbcc73cb 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -769,7 +769,7 @@ static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea return; } - if (U.uiflag & USER_LOCK_UI_LAYOUT) { + if (U.app_flag & USER_APP_LOCK_UI_LAYOUT) { return; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index f07f988d930..b1140113601 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1318,6 +1318,10 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) static bool is_cursor_visible(Scene *scene, ViewLayer *view_layer) { + if (U.app_flag & USER_APP_VIEW3D_HIDE_CURSOR) { + return false; + } + Object *ob = OBACT(view_layer); /* don't draw cursor in paint modes, but with a few exceptions */ diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index ca534e3e2a8..2fa830dc42a 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1059,11 +1059,11 @@ void IMB_exr_write_channels(void *handle) /* temporary function, used for FSA and Save Buffers */ /* called once per tile * view */ -void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname) +void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname, bool empty) { + /* Can write empty channels for incomplete renders. */ ExrHandle *data = (ExrHandle *)handle; FrameBuffer frameBuffer; - ExrChannel *echan; std::string view(viewname); const int view_id = imb_exr_get_multiView_id(*data->multiView, view); @@ -1071,28 +1071,32 @@ void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, c exr_printf("%s %-6s %-22s \"%s\"\n", "p", "view", "name", "internal_name"); exr_printf("---------------------------------------------------------------------\n"); - for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + if (!empty) { + ExrChannel *echan; + + for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { + + /* eventually we can make the parts' channels to include + only the current view TODO */ + if (strcmp(viewname, echan->m->view.c_str()) != 0) + continue; - /* eventually we can make the parts' channels to include - only the current view TODO */ - if (strcmp(viewname, echan->m->view.c_str()) != 0) - continue; - - exr_printf("%d %-6s %-22s \"%s\"\n", - echan->m->part_number, - echan->m->view.c_str(), - echan->m->name.c_str(), - echan->m->internal_name.c_str() - ); - - float *rect = echan->rect - echan->xstride * partx - echan->ystride * party; - frameBuffer.insert(echan->m->internal_name, - Slice(Imf::FLOAT, - (char *)rect, - echan->xstride * sizeof(float), - echan->ystride * sizeof(float) - ) - ); + exr_printf("%d %-6s %-22s \"%s\"\n", + echan->m->part_number, + echan->m->view.c_str(), + echan->m->name.c_str(), + echan->m->internal_name.c_str() + ); + + float *rect = echan->rect - echan->xstride * partx - echan->ystride * party; + frameBuffer.insert(echan->m->internal_name, + Slice(Imf::FLOAT, + (char *)rect, + echan->xstride * sizeof(float), + echan->ystride * sizeof(float) + ) + ); + } } TiledOutputPart out (*data->mpofile, view_id); diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index d9517d13cc4..d9338c888a7 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -67,7 +67,7 @@ float *IMB_exr_channel_rect(void *handle, const char *layname, const char *pass void IMB_exr_read_channels(void *handle); void IMB_exr_write_channels(void *handle); -void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname); +void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname, bool empty); void IMB_exr_clear_channels(void *handle); void IMB_exr_multilayer_convert( diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 05fddcb5fa5..301e827d739 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -47,7 +47,7 @@ float *IMB_exr_channel_rect (void * /*handle*/, const char * /*layname*/ void IMB_exr_read_channels (void * /*handle*/) { } void IMB_exr_write_channels (void * /*handle*/) { } -void IMB_exrtile_write_channels (void * /*handle*/, int /*partx*/, int /*party*/, int /*level*/, const char * /*viewname*/) { } +void IMB_exrtile_write_channels (void * /*handle*/, int /*partx*/, int /*party*/, int /*level*/, const char * /*viewname*/, bool /*empty*/) { } void IMB_exr_clear_channels (void * /*handle*/) { } void IMB_exr_multilayer_convert( diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 237091e1391..281c16ac892 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -471,7 +471,10 @@ typedef struct UserDef { short wheellinescroll; int uiflag; /* eUserpref_UI_Flag */ int uiflag2; /* eUserpref_UI_Flag2 */ - int language; + /* Experimental flag for app-templates to make changes to behavior + * which are outside the scope of typical preferences. */ + short app_flag; + short language; short userpref, viewzoom; int mixbufsize; @@ -681,7 +684,7 @@ typedef enum eUserpref_UI_Flag { USER_LOCK_CURSOR_ADJUST = (1 << 6), /* Avoid accidentally adjusting the layout * (exact behavior may change based on whats considered reasonable to lock down). */ - USER_LOCK_UI_LAYOUT = (1 << 7), + USER_UIFLAG_DEPRECATED_7 = (1 << 7), USER_ALLWINCODECS = (1 << 8), USER_MENUOPENAUTO = (1 << 9), USER_ZBUF_CURSOR = (1 << 10), @@ -714,7 +717,13 @@ typedef enum eUserpref_UI_Flag2 { USER_REGION_OVERLAP = (1 << 1), USER_TRACKPAD_NATURAL = (1 << 2), } eUserpref_UI_Flag2; - + +/* UserDef.app_flag */ +typedef enum eUserpref_APP_Flag { + USER_APP_LOCK_UI_LAYOUT = (1 << 0), + USER_APP_VIEW3D_HIDE_CURSOR = (1 << 1), +} eUserpref_APP_Flag; + /* Auto-Keying mode. * UserDef.autokey_mode */ typedef enum eAutokey_Mode { diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index e2a0769490d..4f396ea6161 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3399,17 +3399,24 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_SPLASH_DISABLE); RNA_def_property_ui_text(prop, "Show Splash", "Display splash screen on startup"); - prop = RNA_def_property(srna, "show_layout_ui", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_LOCK_UI_LAYOUT); - RNA_def_property_ui_text(prop, "Show Layout Widgets", "Show screen layout editing UI"); - RNA_def_property_update(prop, 0, "rna_userdef_update_ui"); prop = RNA_def_property(srna, "show_playback_fps", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_FPS); RNA_def_property_ui_text(prop, "Show Playback FPS", "Show the frames per second screen refresh rate, while animation is played back"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - + + /* app flags (use for app-templates) */ + prop = RNA_def_property(srna, "show_layout_ui", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "app_flag", USER_APP_LOCK_UI_LAYOUT); + RNA_def_property_ui_text(prop, "Show Layout Widgets", "Show screen layout editing UI"); + RNA_def_property_update(prop, 0, "rna_userdef_update_ui"); + + prop = RNA_def_property(srna, "show_view3d_cursor", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "app_flag", USER_APP_VIEW3D_HIDE_CURSOR); + RNA_def_property_ui_text(prop, "Show 3D View Cursor", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + /* menus */ prop = RNA_def_property(srna, "use_mouse_over_open", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_MENUOPENAUTO); diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index fc0cd9e475b..224c8295a9b 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -650,7 +650,7 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args) bool do_remove = true; if (!PyArg_ParseTuple( - args, "O|i:face_join", + args, "O|O&:face_join", &py_face_array, PyC_ParseBool, &do_remove)) { diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 92458e2e96b..c250a91f4cb 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1081,7 +1081,7 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons continue; } - IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname); + IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname, false); } BLI_unlock_thread(LOCK_IMAGE); @@ -1095,13 +1095,11 @@ void render_result_save_empty_result_tiles(Render *re) for (rr = re->result; rr; rr = rr->next) { for (rl = rr->layers.first; rl; rl = rl->next) { - IMB_exr_clear_channels(rl->exrhandle); - for (pa = re->parts.first; pa; pa = pa->next) { if (pa->status != PART_STATUS_MERGED) { int party = pa->disprect.ymin - re->disprect.ymin + pa->crop; int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop; - IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname); + IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname, true); } } } |