Files
test2/scripts/templates_osl/advanced_camera.osl
Damien Picard a2f94ab1ad Fix #147062: OSL Camera: Aperture size depends on focal length
In OSL custom cameras, the current aperture size depends on the focal
length of the Blender camera, even though it is not usable by the
shader. This gives incoherent values to the depth of field.

To ignore this factor, this commit makes the custom camera behave the
same as the orthographic camera, by not being multiplied by the focal
length.

To compensate for that, the multiplication must happen inside the
shader. This adjustment was done in the advanced camera shader
template.

Pull Request: https://projects.blender.org/blender/blender/pulls/147346
2025-10-13 00:23:25 +02:00

77 lines
2.4 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, 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);
}
}