diff options
Diffstat (limited to 'intern/cycles/render/camera.cpp')
-rw-r--r-- | intern/cycles/render/camera.cpp | 122 |
1 files changed, 73 insertions, 49 deletions
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 0fa1d512547..92cf712d32a 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -18,6 +18,7 @@ #include "render/mesh.h" #include "render/object.h" #include "render/scene.h" +#include "render/stats.h" #include "render/tables.h" #include "device/device.h" @@ -27,6 +28,7 @@ #include "util/util_logging.h" #include "util/util_math_cdf.h" #include "util/util_task.h" +#include "util/util_time.h" #include "util/util_vector.h" /* needed for calculating differentials */ @@ -96,7 +98,7 @@ NODE_DEFINE(Camera) type_enum.insert("perspective", CAMERA_PERSPECTIVE); type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC); type_enum.insert("panorama", CAMERA_PANORAMA); - SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE); + SOCKET_ENUM(camera_type, "Type", type_enum, CAMERA_PERSPECTIVE); static NodeEnum panorama_type_enum; panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR); @@ -146,8 +148,18 @@ NODE_DEFINE(Camera) SOCKET_FLOAT(border.bottom, "Border Bottom", 0); SOCKET_FLOAT(border.top, "Border Top", 0); + SOCKET_FLOAT(viewport_camera_border.left, "Viewport Border Left", 0); + SOCKET_FLOAT(viewport_camera_border.right, "Viewport Border Right", 0); + SOCKET_FLOAT(viewport_camera_border.bottom, "Viewport Border Bottom", 0); + SOCKET_FLOAT(viewport_camera_border.top, "Viewport Border Top", 0); + SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f); + SOCKET_INT(full_width, "Full Width", 1024); + SOCKET_INT(full_height, "Full Height", 512); + + SOCKET_BOOLEAN(use_perspective_motion, "Use Perspective Motion", false); + return type; } @@ -180,7 +192,6 @@ Camera::Camera() : Node(node_type) dx = make_float3(0.0f, 0.0f, 0.0f); dy = make_float3(0.0f, 0.0f, 0.0f); - need_update = true; need_device_update = true; need_flags_update = true; previous_need_motion = -1; @@ -194,7 +205,7 @@ Camera::~Camera() void Camera::compute_auto_viewplane() { - if (type == CAMERA_PANORAMA) { + if (camera_type == CAMERA_PANORAMA) { viewplane.left = 0.0f; viewplane.right = 1.0f; viewplane.bottom = 0.0f; @@ -228,9 +239,15 @@ void Camera::update(Scene *scene) need_device_update = true; } - if (!need_update) + if (!is_modified()) return; + scoped_callback_timer timer([scene](double time) { + if (scene->update_stats) { + scene->update_stats->camera.times.add_entry({"update", time}); + } + }); + /* Full viewport to camera border in the viewport. */ Transform fulltoborder = transform_from_viewplane(viewport_camera_border); Transform bordertofull = transform_inverse(fulltoborder); @@ -249,9 +266,9 @@ void Camera::update(Scene *scene) /* screen to camera */ ProjectionTransform cameratoscreen; - if (type == CAMERA_PERSPECTIVE) + if (camera_type == CAMERA_PERSPECTIVE) cameratoscreen = projection_perspective(fov, nearclip, farclip); - else if (type == CAMERA_ORTHOGRAPHIC) + else if (camera_type == CAMERA_ORTHOGRAPHIC) cameratoscreen = projection_orthographic(nearclip, farclip); else cameratoscreen = projection_identity(); @@ -276,13 +293,13 @@ void Camera::update(Scene *scene) worldtoraster = ndctoraster * worldtondc; /* differentials */ - if (type == CAMERA_ORTHOGRAPHIC) { + if (camera_type == CAMERA_ORTHOGRAPHIC) { dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0)); dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0)); full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0)); full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0)); } - else if (type == CAMERA_PERSPECTIVE) { + else if (camera_type == CAMERA_PERSPECTIVE) { dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) - transform_perspective(&rastertocamera, make_float3(0, 0, 0)); dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) - @@ -302,12 +319,15 @@ void Camera::update(Scene *scene) full_dx = transform_direction(&cameratoworld, full_dx); full_dy = transform_direction(&cameratoworld, full_dy); - if (type == CAMERA_PERSPECTIVE) { + if (camera_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)); + + v = transform_perspective(&full_rastertocamera, make_float3(0.0f, 0.0f, 1.0f)); + frustum_left_normal = normalize(make_float3(-v.z, 0.0f, v.x)); + frustum_bottom_normal = normalize(make_float3(0.0f, -v.z, v.y)); } /* Compute kernel camera data. */ @@ -337,7 +357,7 @@ void Camera::update(Scene *scene) if (need_motion == Scene::MOTION_PASS) { /* TODO(sergey): Support perspective (zoom, fov) motion. */ - if (type == CAMERA_PANORAMA) { + if (camera_type == CAMERA_PANORAMA) { if (have_motion) { kcam->motion_pass_pre = transform_inverse(motion[0]); kcam->motion_pass_post = transform_inverse(motion[motion.size() - 1]); @@ -366,7 +386,7 @@ void Camera::update(Scene *scene) } /* TODO(sergey): Support other types of camera. */ - if (use_perspective_motion && type == CAMERA_PERSPECTIVE) { + if (use_perspective_motion && camera_type == CAMERA_PERSPECTIVE) { /* TODO(sergey): Move to an utility function and de-duplicate with * calculation above. */ @@ -391,7 +411,7 @@ void Camera::update(Scene *scene) kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime : -1.0f; /* type */ - kcam->type = type; + kcam->type = camera_type; /* anamorphic lens bokeh */ kcam->inv_aperture_ratio = 1.0f / aperture_ratio; @@ -453,7 +473,7 @@ void Camera::update(Scene *scene) kcam->rolling_shutter_duration = rolling_shutter_duration; /* Set further update flags */ - need_update = false; + clear_modified(); need_device_update = true; need_flags_update = true; previous_need_motion = need_motion; @@ -466,6 +486,12 @@ void Camera::device_update(Device * /* device */, DeviceScene *dscene, Scene *sc if (!need_device_update) return; + scoped_callback_timer timer([scene](double time) { + if (scene->update_stats) { + scene->update_stats->camera.times.add_entry({"device_update", time}); + } + }); + scene->lookup_tables->remove_table(&shutter_table_offset); if (kernel_camera.shuttertime != -1.0f) { vector<float> shutter_table; @@ -510,7 +536,7 @@ void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scen [&](const blocked_range<size_t> &r) { for (size_t i = r.begin(); i != r.end(); i++) { Object *object = scene->objects[i]; - if (object->geometry->has_volume && + if (object->get_geometry()->has_volume && viewplane_boundbox.intersects(object->bounds)) { /* TODO(sergey): Consider adding more grained check. */ VLOG(1) << "Detected camera inside volume."; @@ -536,25 +562,10 @@ void Camera::device_free(Device * /*device*/, DeviceScene *dscene, Scene *scene) dscene->camera_motion.free(); } -bool Camera::modified(const Camera &cam) -{ - return !Node::equals(cam); -} - -bool Camera::motion_modified(const Camera &cam) -{ - return !((motion == cam.motion) && (use_perspective_motion == cam.use_perspective_motion)); -} - -void Camera::tag_update() -{ - need_update = true; -} - float3 Camera::transform_raster_to_world(float raster_x, float raster_y) { float3 D, P; - if (type == CAMERA_PERSPECTIVE) { + if (camera_type == CAMERA_PERSPECTIVE) { D = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); float3 Pclip = normalize(D); P = make_float3(0.0f, 0.0f, 0.0f); @@ -567,7 +578,7 @@ float3 Camera::transform_raster_to_world(float raster_x, float raster_y) */ P += nearclip * D / Pclip.z; } - else if (type == CAMERA_ORTHOGRAPHIC) { + else if (camera_type == CAMERA_ORTHOGRAPHIC) { D = make_float3(0.0f, 0.0f, 1.0f); /* TODO(sergey): Aperture support? */ P = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); @@ -586,7 +597,7 @@ BoundBox Camera::viewplane_bounds_get() * checks we need in a more clear and smart fashion? */ BoundBox bounds = BoundBox::empty; - if (type == CAMERA_PANORAMA) { + if (camera_type == CAMERA_PANORAMA) { if (use_spherical_stereo == false) { bounds.grow(make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w)); } @@ -611,7 +622,7 @@ BoundBox Camera::viewplane_bounds_get() bounds.grow(transform_raster_to_world(0.0f, (float)height)); bounds.grow(transform_raster_to_world((float)width, (float)height)); bounds.grow(transform_raster_to_world((float)width, 0.0f)); - if (type == CAMERA_PERSPECTIVE) { + if (camera_type == CAMERA_PERSPECTIVE) { /* Center point has the most distance in local Z axis, * use it to construct bounding box/ */ @@ -625,28 +636,33 @@ float Camera::world_to_raster_size(float3 P) { float res = 1.0f; - if (type == CAMERA_ORTHOGRAPHIC) { + if (camera_type == CAMERA_ORTHOGRAPHIC) { res = min(len(full_dx), len(full_dy)); if (offscreen_dicing_scale > 1.0f) { float3 p = transform_point(&worldtocamera, P); - float3 v = transform_perspective(&full_rastertocamera, - make_float3(full_width, full_height, 0.0f)); + float3 v1 = transform_perspective(&full_rastertocamera, + make_float3(full_width, full_height, 0.0f)); + float3 v2 = transform_perspective(&full_rastertocamera, make_float3(0.0f, 0.0f, 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.x = max(v2.x, min(v1.x, p.x)); + c.y = max(v2.y, min(v1.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); - + /* Check right side */ + float f_dist = len(p - c) / sqrtf((v1.x * v1.x + v1.y * v1.y) * 0.5f); + if (f_dist < 0.0f) { + /* Check left side */ + f_dist = len(p - c) / sqrtf((v2.x * v2.x + v2.y * v2.y) * 0.5f); + } if (f_dist > 0.0f) { res += res * f_dist * (offscreen_dicing_scale - 1.0f); } } } - else if (type == CAMERA_PERSPECTIVE) { + else if (camera_type == CAMERA_PERSPECTIVE) { /* Calculate as if point is directly ahead of the camera. */ float3 raster = make_float3(0.5f * full_width, 0.5f * full_height, 0.0f); float3 Pcamera = transform_perspective(&full_rastertocamera, raster); @@ -671,10 +687,8 @@ float Camera::world_to_raster_size(float3 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); + float l = dot(p, frustum_left_normal); + float b = dot(p, frustum_bottom_normal); if (r <= 0.0f && l <= 0.0f && t <= 0.0f && b <= 0.0f) { /* Point is inside frustum */ @@ -687,9 +701,9 @@ float Camera::world_to_raster_size(float3 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_left = make_float3(frustum_left_normal.z, 0.0f, -frustum_left_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); + float3 along_bottom = make_float3(0.0f, frustum_bottom_normal.z, -frustum_bottom_normal.y); float dist[] = {r, l, t, b}; float3 along[] = {along_right, along_left, along_top, along_bottom}; @@ -723,7 +737,7 @@ float Camera::world_to_raster_size(float3 P) } } } - else if (type == CAMERA_PANORAMA) { + else if (camera_type == CAMERA_PANORAMA) { float3 D = transform_point(&worldtocamera, P); float dist = len(D); @@ -774,6 +788,16 @@ bool Camera::use_motion() const return motion.size() > 1; } +void Camera::set_screen_size_and_resolution(int width_, int height_, int resolution_) +{ + if (width_ != width || height_ != height || resolution_ != resolution) { + width = width_; + height = height_; + resolution = resolution_; + tag_modified(); + } +} + float Camera::motion_time(int step) const { return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f; |