diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-02-28 20:44:54 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-02-28 20:44:54 +0400 |
commit | 4a903395194aef1cfe97e4d50d73320a72280cf3 (patch) | |
tree | 056c15cc54f0d0446aef69c9b7f299023c01a69f /intern | |
parent | 0052cbed0dadafce44f818d3d2016254c3d914d0 (diff) |
Cycles: support for camera rendering an environment map with equirectangular
environment map, by enabling the Panorama option in the camera.
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Camera#Panorama
The focal length or sensor settings are not used, the UI can be tweaked still to
communicate this, also panorama should probably become a proper camera type like
perspective or ortho.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/app/cycles_xml.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/blender/blender_camera.cpp | 84 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_camera.h | 44 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_displace.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_light.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_montecarlo.h | 11 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 10 | ||||
-rw-r--r-- | intern/cycles/render/camera.cpp | 24 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 6 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 3 |
10 files changed, 142 insertions, 58 deletions
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 5e4b3da071d..283bdf52e03 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -288,9 +288,11 @@ static void xml_read_camera(const XMLReadState& state, pugi::xml_node node) xml_read_float(&cam->shutterclose, node, "shutterclose"); if(xml_equal_string(node, "type", "orthographic")) - cam->ortho = true; + cam->type = CAMERA_ORTHOGRAPHIC; else if(xml_equal_string(node, "type", "perspective")) - cam->ortho = false; + cam->type = CAMERA_PERSPECTIVE; + else if(xml_equal_string(node, "type", "environment")) + cam->type = CAMERA_ENVIRONMENT; cam->matrix = state.tfm; diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index cbc430d9240..7c9c162f8b1 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -31,7 +31,7 @@ struct BlenderCamera { float nearclip; float farclip; - bool ortho; + CameraType type; float ortho_scale; float lens; @@ -58,6 +58,7 @@ static void blender_camera_init(BlenderCamera *bcam) { memset(bcam, 0, sizeof(BlenderCamera)); + bcam->type = CAMERA_PERSPECTIVE; bcam->zoom = 1.0f; bcam->pixelaspect = make_float2(1.0f, 1.0f); bcam->sensor_width = 32.0f; @@ -91,7 +92,9 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob) bcam->nearclip = b_camera.clip_start(); bcam->farclip = b_camera.clip_end(); - bcam->ortho = (b_camera.type() == BL::Camera::type_ORTHO); + bcam->type = (b_camera.type() == BL::Camera::type_ORTHO)? CAMERA_ORTHOGRAPHIC: CAMERA_PERSPECTIVE; + if(bcam->type == CAMERA_PERSPECTIVE && b_camera.use_panorama()) + bcam->type = CAMERA_ENVIRONMENT; bcam->ortho_scale = b_camera.ortho_scale(); bcam->lens = b_camera.lens(); @@ -159,39 +162,48 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int } /* modify aspect for orthographic scale */ - if(bcam->ortho) { + if(bcam->type == CAMERA_ORTHOGRAPHIC) { xaspect = xaspect*bcam->ortho_scale/(aspectratio*2.0f); yaspect = yaspect*bcam->ortho_scale/(aspectratio*2.0f); aspectratio = bcam->ortho_scale/2.0f; } - /* set viewplane */ - cam->left = -xaspect; - cam->right = xaspect; - cam->bottom = -yaspect; - cam->top = yaspect; - - /* zoom for 3d camera view */ - cam->left *= bcam->zoom; - cam->right *= bcam->zoom; - cam->bottom *= bcam->zoom; - cam->top *= bcam->zoom; - - /* modify viewplane with camera shift and 3d camera view offset */ - float dx = 2.0f*(aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); - float dy = 2.0f*(aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); - - cam->left += dx; - cam->right += dx; - cam->bottom += dy; - cam->top += dy; + if(bcam->type == CAMERA_ENVIRONMENT) { + /* set viewplane */ + cam->left = 0.0f; + cam->right = 1.0f; + cam->bottom = 0.0f; + cam->top = 1.0f; + } + else { + /* set viewplane */ + cam->left = -xaspect; + cam->right = xaspect; + cam->bottom = -yaspect; + cam->top = yaspect; + + /* zoom for 3d camera view */ + cam->left *= bcam->zoom; + cam->right *= bcam->zoom; + cam->bottom *= bcam->zoom; + cam->top *= bcam->zoom; + + /* modify viewplane with camera shift and 3d camera view offset */ + float dx = 2.0f*(aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); + float dy = 2.0f*(aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); + + cam->left += dx; + cam->right += dx; + cam->bottom += dy; + cam->top += dy; + } /* clipping distances */ cam->nearclip = bcam->nearclip; cam->farclip = bcam->farclip; - /* orthographic */ - cam->ortho = bcam->ortho; + /* type */ + cam->type = bcam->type; /* perspective */ cam->fov = 2.0f*atan((0.5f*sensor_size)/bcam->lens/aspectratio); @@ -200,8 +212,24 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->blades = bcam->apertureblades; cam->bladesrotation = bcam->aperturerotation; - /* transform, note the blender camera points along the negative z-axis */ - cam->matrix = bcam->matrix * transform_scale(1.0f, 1.0f, -1.0f); + /* transform */ + cam->matrix = bcam->matrix; + + if(bcam->type == CAMERA_ENVIRONMENT) { + /* make it so environment camera needs to be pointed in the direction + of the positive x-axis to match an environment texture, this way + it is looking at the center of the texture */ + cam->matrix = cam->matrix * + make_transform( 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + } + else { + /* note the blender camera points along the negative z-axis */ + cam->matrix = cam->matrix * transform_scale(1.0f, 1.0f, -1.0f); + } + cam->matrix = transform_clear_scale(cam->matrix); /* set update flag */ @@ -269,7 +297,7 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int bcam.farclip *= 0.5; bcam.nearclip = -bcam.farclip; - bcam.ortho = true; + bcam.type = CAMERA_ORTHOGRAPHIC; bcam.ortho_scale = b_rv3d.view_distance(); } diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 2dbdd076891..251b2c280da 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -122,6 +122,44 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa #endif } +/* Environment Camera */ + +__device void camera_sample_environment(KernelGlobals *kg, float raster_x, float raster_y, Ray *ray) +{ + Transform rastertocamera = kernel_data.cam.rastertocamera; + float3 Pcamera = transform(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); + + /* create ray form raster position */ + ray->P = make_float3(0.0, 0.0f, 0.0f); + ray->D = equirectangular_to_direction(Pcamera.x, Pcamera.y); + + /* transform ray from camera to world */ + Transform cameratoworld = kernel_data.cam.cameratoworld; + + ray->P = transform(&cameratoworld, ray->P); + ray->D = transform_direction(&cameratoworld, ray->D); + ray->D = normalize(ray->D); + +#ifdef __RAY_DIFFERENTIALS__ + /* ray differential */ + ray->dP.dx = make_float3(0.0f, 0.0f, 0.0f); + ray->dP.dy = make_float3(0.0f, 0.0f, 0.0f); + + Pcamera = transform(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f)); + ray->dD.dx = equirectangular_to_direction(Pcamera.x, Pcamera.y) - ray->D; + + Pcamera = transform(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f)); + ray->dD.dy = equirectangular_to_direction(Pcamera.x, Pcamera.y) - ray->D; +#endif + +#ifdef __CAMERA_CLIPPING__ + /* clipping */ + ray->t = kernel_data.cam.cliplength; +#else + ray->t = FLT_MAX; +#endif +} + /* Common */ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, float filter_v, float lens_u, float lens_v, Ray *ray) @@ -134,10 +172,12 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo //ray->time = lerp(time_t, kernel_data.cam.shutter_open, kernel_data.cam.shutter_close); /* sample */ - if(kernel_data.cam.ortho) + if(kernel_data.cam.type == CAMERA_PERSPECTIVE) + camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray); + else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) camera_sample_orthographic(kg, raster_x, raster_y, ray); else - camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray); + camera_sample_environment(kg, raster_x, raster_y, ray); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index 73666892cf3..f4b33605f5b 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -41,9 +41,11 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou else { // SHADER_EVAL_BACKGROUND /* setup ray */ Ray ray; + float u = __int_as_float(in.x); + float v = __int_as_float(in.y); ray.P = make_float3(0.0f, 0.0f, 0.0f); - ray.D = make_float3(__int_as_float(in.x), __int_as_float(in.y), __int_as_float(in.z)); + ray.D = equirectangular_to_direction(u, v); ray.t = 0.0f; #ifdef __RAY_DIFFERENTIALS__ diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index aa125180a94..42260577069 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -120,13 +120,9 @@ __device float3 background_light_sample(KernelGlobals *kg, float randu, float ra float du = (randu - cdf_u.y) / (cdf_next_u.y - cdf_u.y); float u = (index_u + du) / res; - /* spherical coordinates */ - float theta = v * M_PI_F; - float phi = u * M_PI_F * 2.0f; - /* compute pdf */ float denom = cdf_last_u.x * cdf_last_v.x; - float sin_theta = sinf(theta); + float sin_theta = sinf(M_PI_F * v); if(sin_theta == 0.0f || denom == 0.0f) *pdf = 0.0f; @@ -136,7 +132,7 @@ __device float3 background_light_sample(KernelGlobals *kg, float randu, float ra *pdf *= kernel_data.integrator.pdf_lights; /* compute direction */ - return spherical_to_direction(theta, phi); + return -equirectangular_to_direction(u, v); } __device float background_light_pdf(KernelGlobals *kg, float3 direction) diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h index 9776baf65e4..66bd0ee9998 100644 --- a/intern/cycles/kernel/kernel_montecarlo.h +++ b/intern/cycles/kernel/kernel_montecarlo.h @@ -185,7 +185,7 @@ __device float2 regular_polygon_sample(float corners, float rotation, float u, f return make_float2(cr*p.x - sr*p.y, sr*p.x + cr*p.y); } -/* Spherical coordinates <-> Cartesion direction */ +/* Spherical coordinates <-> Cartesian direction */ __device float2 direction_to_spherical(float3 dir) { @@ -203,11 +203,11 @@ __device float3 spherical_to_direction(float theta, float phi) cosf(theta)); } -/* Equirectangular */ +/* Equirectangular coordinates <-> Cartesian direction */ __device float2 direction_to_equirectangular(float3 dir) { - float u = (atan2f(dir.y, dir.x) + M_PI_F)/(2.0f*M_PI_F); + float u = -atan2f(dir.y, dir.x)/(2.0f*M_PI_F) + 0.5f; float v = atan2f(dir.z, hypotf(dir.x, dir.y))/M_PI_F + 0.5f; return make_float2(u, v); @@ -215,9 +215,8 @@ __device float2 direction_to_equirectangular(float3 dir) __device float3 equirectangular_to_direction(float u, float v) { - /* XXX check correctness? */ - float theta = M_PI_F*v; - float phi = 2.0f*M_PI_F*u; + float phi = M_PI_F*(1.0f - 2.0f*u); + float theta = M_PI_F*(1.0f - v); return make_float3( sin(theta)*cos(phi), diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 9f4d5b00e2c..61335d5f9fa 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -240,6 +240,14 @@ typedef enum LightType { LIGHT_AREA } LightType; +/* Camera Type */ + +enum CameraType { + CAMERA_PERSPECTIVE, + CAMERA_ORTHOGRAPHIC, + CAMERA_ENVIRONMENT +}; + /* Differential */ typedef struct differential3 { @@ -387,7 +395,7 @@ typedef struct ShaderData { typedef struct KernelCamera { /* type */ - int ortho; + int type; int pad1, pad2, pad3; /* matrices */ diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index a83ae81844c..6edf9c66f1d 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -35,7 +35,7 @@ Camera::Camera() matrix = transform_identity(); - ortho = false; + type = CAMERA_PERSPECTIVE; fov = M_PI_F/4.0f; nearclip = 1e-5f; @@ -77,17 +77,21 @@ void Camera::update() Transform ndctoraster = transform_scale(width, height, 1.0f); /* raster to screen */ - Transform screentoraster = ndctoraster * + Transform screentoraster = ndctoraster; + + screentoraster = ndctoraster * transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) * transform_translate(-left, -bottom, 0.0f); Transform rastertoscreen = transform_inverse(screentoraster); /* screen to camera */ - if(ortho) + if(type == CAMERA_PERSPECTIVE) + screentocamera = transform_inverse(transform_perspective(fov, nearclip, farclip)); + else if(type == CAMERA_ORTHOGRAPHIC) screentocamera = transform_inverse(transform_orthographic(nearclip, farclip)); else - screentocamera = transform_inverse(transform_perspective(fov, nearclip, farclip)); + screentocamera = transform_identity(); rastertocamera = screentocamera * rastertoscreen; @@ -98,16 +102,20 @@ void Camera::update() worldtoraster = transform_inverse(rastertoworld); /* differentials */ - if(ortho) { + if(type == CAMERA_ORTHOGRAPHIC) { dx = transform_direction(&rastertocamera, make_float3(1, 0, 0)); dy = transform_direction(&rastertocamera, make_float3(0, 1, 0)); } - else { + else if(type == CAMERA_PERSPECTIVE) { dx = transform(&rastertocamera, make_float3(1, 0, 0)) - transform(&rastertocamera, make_float3(0, 0, 0)); dy = transform(&rastertocamera, make_float3(0, 1, 0)) - transform(&rastertocamera, make_float3(0, 0, 0)); } + else { + dx = make_float3(0, 0, 0); + dy = make_float3(0, 0, 0); + } dx = transform_direction(&cameratoworld, dx); dy = transform_direction(&cameratoworld, dy); @@ -147,7 +155,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene) kcam->shutterclose = shutterclose; /* type */ - kcam->ortho = ortho; + kcam->type = type; /* store differentials */ kcam->dx = float3_to_float4(dx); @@ -173,7 +181,7 @@ bool Camera::modified(const Camera& cam) (blades == cam.blades) && (bladesrotation == cam.bladesrotation) && (focaldistance == cam.focaldistance) && - (ortho == cam.ortho) && + (type == cam.type) && (fov == cam.fov) && (nearclip == cam.nearclip) && (farclip == cam.farclip) && diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 43537ce8c3c..cfcc5406ee3 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -19,6 +19,8 @@ #ifndef __CAMERA_H__ #define __CAMERA_H__ +#include "kernel_types.h" + #include "util_transform.h" #include "util_types.h" @@ -44,8 +46,8 @@ public: uint blades; float bladesrotation; - /* orthographic/perspective */ - bool ortho; + /* type */ + CameraType type; float fov; /* clipping */ diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 405aa800457..bd3acb00f6d 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -45,9 +45,8 @@ static void dump_background_pixels(Device *device, DeviceScene *dscene, int res, for(int x = 0; x < width; x++) { float u = x/(float)width; float v = y/(float)height; - float3 D = -equirectangular_to_direction(u, v); - uint4 in = make_uint4(__float_as_int(D.x), __float_as_int(D.y), __float_as_int(D.z), 0); + uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0); d_input_data[x + y*width] = in; } } |