Files
test/scripts/templates_osl/advanced_camera.osl
2025-10-16 15:39:28 +02:00

79 lines
2.5 KiB
Plaintext

/* An advanced perspective camera, implementing several examples
* of things you can do with custom cameras. */
float invertDistortionModel(float x, float y, float k1, float k2, float k3)
{
// Solves u = d*(1 + k1*d^2 + k2*d^4 + k3*d^6) for d.
// Returns stretch factor.
float u = sqrt(x * x + y * y);
float d = u;
for (int i = 0; i < 50; i++) {
float d2 = d * d;
float f = u - d * (1 + d2 * (k1 + d2 * (k2 + d2 * k3)));
float fp = -(1 + d2 * (3 * k1 + d2 * (5 * k2 + d2 * 7 * k3)));
float diff = f / fp;
d -= diff;
if (fabs(diff) < 1e-7) {
// Iteration is converging, return result.
return d / u;
}
if (d > 100.0) {
// Iteration is diverging, give up.
return -1.0;
}
}
// Reached iteration limit, give up.
return -1.0;
}
shader camera(float focal_length = 50.0 [[ float min = 0.0,
string unit = "mm",
float sensitivity = 0.2 ]],
int do_distortion = 0 [[ string widget = "checkBox"]],
int do_swirl = 0 [[ string widget = "checkBox"]],
int do_dof = 0 [[ string widget = "checkBox"]],
float distortion_k1 = -0.2,
float distortion_k2 = 0.0,
float distortion_k3 = 0.0,
float swirl_scale = 100.0,
float swirl_amplitude = 0.01,
float swirl_w = 0.0 [[ float sensitivity = 1]],
output point position = 0.0,
output vector direction = 0.0,
output color throughput = 1.0)
{
point Pcam = camera_shader_raster_position() - vector(0.5);
if (do_distortion) {
float distort = invertDistortionModel(
Pcam.x, Pcam.y, distortion_k1, distortion_k2, distortion_k3);
if (distort < 0.0) {
// Distortion model failed, skip the path.
throughput = color(0.0);
return;
}
Pcam *= distort;
}
vector sensor_size;
getattribute("cam:sensor_size", sensor_size);
Pcam = Pcam * sensor_size / focal_length;
if (do_swirl) {
Pcam += swirl_amplitude * noise("perlin", Pcam * swirl_scale, swirl_w);
}
direction = normalize(vector(Pcam.x, Pcam.y, 1.0));
if (do_dof) {
float focal_distance;
getattribute("cam:focal_distance", focal_distance);
getattribute("cam:aperture_position", position);
position *= focal_length * 1e-3;
point Pfocus = direction * focal_distance / direction.z;
direction = normalize(Pfocus - position);
}
}