Merge branch 'master' into blender2.8

This commit is contained in:
Brecht Van Lommel 2018-01-13 02:05:49 +01:00
commit cdc31c3e6e
40 changed files with 530 additions and 239 deletions

View File

@ -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

View File

@ -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)

View File

@ -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!

View File

@ -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")
col = split.column()
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")
col = split.column()
col.prop(cscene, "offscreen_dicing_scale", text="Offscreen Scale")
col.prop(cscene, "max_subdivisions")
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"

View File

@ -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,

View File

@ -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());
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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",

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -42,6 +42,9 @@ public:
Shader *shader;
bool transparent;
bool transparent_glass;
float transparent_roughness_threshold;
bool need_update;
Background();

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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.separator()
col.label(text="Screen:")
col.prop(view, "show_layout_ui")
col.prop(view, "show_splash")
col.separator()
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")
class USERPREF_PT_edit(Panel):

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
/* eventually we can make the parts' channels to include
only the current view TODO */
if (strcmp(viewname, echan->m->view.c_str()) != 0)
continue;
for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) {
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()
);
/* eventually we can make the parts' channels to include
only the current view TODO */
if (strcmp(viewname, echan->m->view.c_str()) != 0)
continue;
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);

View File

@ -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(

View File

@ -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(

View File

@ -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 {

View File

@ -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);

View File

@ -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))
{

View File

@ -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);
}
}
}