Cycles: Pole merging for spherical stereo
The idea of pole merge is to fade interocular distance after a certain altitude to zero when altitude goes closer to a pole. This should prevent annoyances looking up in the sky or down to the bottom. Works for both panorama and perspective cameras when Spherical Stereo is enabled. Reviewers: dfelinto, brecht Reviewed By: brecht Subscribers: sebastian_k Differential Revision: https://developer.blender.org/D1998
This commit is contained in:
parent
7b356a8565
commit
cbe7f9dd03
|
@ -65,6 +65,9 @@ struct BlenderCamera {
|
|||
bool use_spherical_stereo;
|
||||
float interocular_distance;
|
||||
float convergence_distance;
|
||||
bool use_pole_merge;
|
||||
float pole_merge_angle_from;
|
||||
float pole_merge_angle_to;
|
||||
|
||||
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
|
||||
float sensor_width;
|
||||
|
@ -183,6 +186,10 @@ static void blender_camera_from_object(BlenderCamera *bcam,
|
|||
}
|
||||
bcam->use_spherical_stereo = b_engine.use_spherical_stereo(b_ob);
|
||||
|
||||
bcam->use_pole_merge = b_camera.stereo().use_pole_merge();
|
||||
bcam->pole_merge_angle_from = b_camera.stereo().pole_merge_angle_from();
|
||||
bcam->pole_merge_angle_to = b_camera.stereo().pole_merge_angle_to();
|
||||
|
||||
bcam->ortho_scale = b_camera.ortho_scale();
|
||||
|
||||
bcam->lens = b_camera.lens();
|
||||
|
@ -427,6 +434,10 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
|
|||
cam->stereo_eye = Camera::STEREO_NONE;
|
||||
}
|
||||
|
||||
cam->use_pole_merge = bcam->use_pole_merge;
|
||||
cam->pole_merge_angle_from = bcam->pole_merge_angle_from;
|
||||
cam->pole_merge_angle_to = bcam->pole_merge_angle_to;
|
||||
|
||||
/* anamorphic lens bokeh */
|
||||
cam->aperture_ratio = bcam->aperture_ratio;
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ ccl_device float3 spherical_stereo_position(KernelGlobals *kg,
|
|||
float3 dir,
|
||||
float3 pos)
|
||||
{
|
||||
const float interocular_offset = kernel_data.cam.interocular_offset;
|
||||
float interocular_offset = kernel_data.cam.interocular_offset;
|
||||
|
||||
/* Interocular offset of zero means either non stereo, or stereo without
|
||||
* spherical stereo.
|
||||
|
@ -234,6 +234,21 @@ ccl_device float3 spherical_stereo_position(KernelGlobals *kg,
|
|||
return pos;
|
||||
}
|
||||
|
||||
if(kernel_data.cam.pole_merge_angle_to > 0.0f) {
|
||||
float3 normalized_direction = normalize(dir);
|
||||
const float pole_merge_angle_from = kernel_data.cam.pole_merge_angle_from,
|
||||
pole_merge_angle_to = kernel_data.cam.pole_merge_angle_to;
|
||||
float altitude = fabsf(safe_asinf(normalized_direction.z));
|
||||
if(altitude > pole_merge_angle_to) {
|
||||
interocular_offset = 0.0f;
|
||||
}
|
||||
else if(altitude > pole_merge_angle_from) {
|
||||
float fac = (altitude - pole_merge_angle_from) / (pole_merge_angle_to - pole_merge_angle_from);
|
||||
float fade = cosf(fac * M_PI_2_F);
|
||||
interocular_offset *= fade;
|
||||
}
|
||||
}
|
||||
|
||||
float3 up = make_float3(0.0f, 0.0f, 1.0f);
|
||||
float3 side = normalize(cross(dir, up));
|
||||
|
||||
|
|
|
@ -909,9 +909,10 @@ typedef struct KernelCamera {
|
|||
float4 equirectangular_range;
|
||||
|
||||
/* stereo */
|
||||
int pad1, pad2;
|
||||
float interocular_offset;
|
||||
float convergence_distance;
|
||||
float pole_merge_angle_from;
|
||||
float pole_merge_angle_to;
|
||||
|
||||
/* matrices */
|
||||
Transform cameratoworld;
|
||||
|
|
|
@ -76,6 +76,9 @@ Camera::Camera()
|
|||
stereo_eye = STEREO_NONE;
|
||||
interocular_distance = 0.065f;
|
||||
convergence_distance = 30.0f * 0.065f;
|
||||
use_pole_merge = false;
|
||||
pole_merge_angle_from = 60.0f * M_PI_F / 180.0f;
|
||||
pole_merge_angle_to = 75.0f * M_PI_F / 180.0f;
|
||||
|
||||
sensorwidth = 0.036f;
|
||||
sensorheight = 0.024f;
|
||||
|
@ -367,6 +370,14 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
|||
}
|
||||
|
||||
kcam->convergence_distance = convergence_distance;
|
||||
if(use_pole_merge) {
|
||||
kcam->pole_merge_angle_from = pole_merge_angle_from;
|
||||
kcam->pole_merge_angle_to = pole_merge_angle_to;
|
||||
}
|
||||
else {
|
||||
kcam->pole_merge_angle_from = -1.0f;
|
||||
kcam->pole_merge_angle_to = -1.0f;
|
||||
}
|
||||
|
||||
/* sensor size */
|
||||
kcam->sensorwidth = sensorwidth;
|
||||
|
|
|
@ -104,6 +104,9 @@ public:
|
|||
bool use_spherical_stereo;
|
||||
float interocular_distance;
|
||||
float convergence_distance;
|
||||
bool use_pole_merge;
|
||||
float pole_merge_angle_from;
|
||||
float pole_merge_angle_to;
|
||||
|
||||
/* anamorphic lens bokeh */
|
||||
float aperture_ratio;
|
||||
|
|
|
@ -165,7 +165,15 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
|
|||
|
||||
if is_spherical_stereo:
|
||||
col.separator()
|
||||
col.prop(st, "use_spherical_stereo")
|
||||
row = col.row()
|
||||
row.prop(st, "use_spherical_stereo")
|
||||
sub = row.row()
|
||||
sub.active = st.use_spherical_stereo
|
||||
sub.prop(st, "use_pole_merge")
|
||||
row = col.row(align=True)
|
||||
row.active = st.use_pole_merge
|
||||
row.prop(st, "pole_merge_angle_from")
|
||||
row.prop(st, "pole_merge_angle_to")
|
||||
|
||||
col.label(text="Pivot:")
|
||||
row = col.row()
|
||||
|
|
|
@ -76,6 +76,8 @@ void BKE_camera_init(Camera *cam)
|
|||
/* stereoscopy 3d */
|
||||
cam->stereo.interocular_distance = 0.065f;
|
||||
cam->stereo.convergence_distance = 30.f * 0.065f;
|
||||
cam->stereo.pole_merge_angle_from = DEG2RAD(60.0f);
|
||||
cam->stereo.pole_merge_angle_to = DEG2RAD(75.0f);
|
||||
}
|
||||
|
||||
void *BKE_camera_add(Main *bmain, const char *name)
|
||||
|
|
|
@ -1190,4 +1190,15 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
for (Camera *camera = main->camera.first; camera != NULL; camera = camera->id.next) {
|
||||
if (camera->stereo.pole_merge_angle_from == 0.0f &&
|
||||
camera->stereo.pole_merge_angle_to == 0.0f)
|
||||
{
|
||||
camera->stereo.pole_merge_angle_from = DEG2RAD(60.0f);
|
||||
camera->stereo.pole_merge_angle_to = DEG2RAD(75.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,10 @@ typedef struct CameraStereoSettings {
|
|||
short pivot;
|
||||
short flag;
|
||||
short pad;
|
||||
/* Cut-off angle at which interocular distance start to fade down. */
|
||||
float pole_merge_angle_from;
|
||||
/* Cut-off angle at which interocular distance stops to fade down. */
|
||||
float pole_merge_angle_to;
|
||||
} CameraStereoSettings;
|
||||
|
||||
typedef struct Camera {
|
||||
|
@ -152,6 +156,7 @@ enum {
|
|||
/* stereo->flag */
|
||||
enum {
|
||||
CAM_S3D_SPHERICAL = (1 << 0),
|
||||
CAM_S3D_POLE_MERGE = (1 << 1),
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -151,6 +151,24 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
|
|||
"Render every pixel rotating the camera around the "
|
||||
"middle of the interocular distance");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_pole_merge", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_S3D_POLE_MERGE);
|
||||
RNA_def_property_ui_text(prop, "Use Pole Merge",
|
||||
"Fade interocular distance to 0 after the given cutoff angle");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "pole_merge_angle_from", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_range(prop, 0.0f, M_PI / 2.0f);
|
||||
RNA_def_property_ui_text(prop, "Pole Merge Start Angle",
|
||||
"Angle at which interocular distance starts to fade to 0");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "pole_merge_angle_to", PROP_FLOAT, PROP_ANGLE);
|
||||
RNA_def_property_range(prop, 0.0f, M_PI / 2.0f);
|
||||
RNA_def_property_ui_text(prop, "Pole Merge End Angle",
|
||||
"Angle at which interocular distance is 0");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
||||
}
|
||||
|
||||
void RNA_def_camera(BlenderRNA *brna)
|
||||
|
|
Loading…
Reference in New Issue