The Persistence of Vision Raytracer (POV-Ray).
This is the legacy Bug Tracking System for the POV-Ray project. Bugs listed here are being migrated to our github issue tracker. Please refer to that for new reports or updates to existing ones on this system.
Opened by Timwi - 2013-03-24
Last edited by William F Pokorny - 2017-01-23
FS#281 - Bug in rendering of Bézier patches
In version 3.7.0.RC7.msvc10.win64, there is a bug in rendering Bézier patches in which four points (along one edge) are all the same point.
The rendering can be seen here: [Edit: See attachment for the rendering]
http://i.imgur.com/eq2UIXR.png
As you can see, there is a visible unwanted artifact in the corner of each patch. The two patches shown are essentially the same, except with the 4×4 matrix of vertices transposed (just to demonstrate that simply transposing it didn’t fix it).
Expected rendering is a smooth surface without the artifact.
Below is the code used to render the above example.
#version 3.7;
global_settings { assumed_gamma 1.0 }
camera {
location <45, 31, -10> look_at <40, 21, 200> right x*image_width/image_height
}
light_source {
<660, 300, -525> color rgb 1
}
Example 1: First point in each row is the same point
bicubic_patch {
type 1 flatness 0.001
u_steps 4 v_steps 4
<32.2168, -23.78125, 0>, <34.4968, -23.78125, 0>, <35.2168, -23.78125, -0.72>, <35.2168, -23.78125, -3>,
<32.2168, -23.78125, 0>, <34.4968, -22.10256, 0>, <35.2168, -21.57244, -0.72>, <35.2168, -21.57244, -3>,
<32.2168, -23.78125, 0>, <33.9709, -21.55577, 0>, <34.52483, -20.85299, -0.72>, <34.52483, -20.85299, -3>,
<32.2168, -23.78125, 0>, <32.30556, -21.50298, 0>, <32.33359, -20.78352, -0.72>, <32.33359, -20.78352, -3>
rotate 180*x
scale 1.4
translate ←5, 0, 0>
pigment { color <1, 0, 0> }
}
Example 2: First row is all the same point
bicubic_patch {
type 1 flatness 0.001 u_steps 4 v_steps 4 <32.2168, -23.78125, 0>, <32.2168, -23.78125, 0>, <32.2168, -23.78125, 0>, <32.2168, -23.78125, 0>, <34.4968, -23.78125, 0>, <34.4968, -22.10256, 0>, <33.9709, -21.55577, 0>, <32.30556, -21.50298, 0>, <35.2168, -23.78125, -0.72>, <35.2168, -21.57244, -0.72>, <34.52483, -20.85299, -0.72>, <32.33359, -20.78352, -0.72>, <35.2168, -23.78125, -3>, <35.2168, -21.57244, -3>, <34.52483, -20.85299, -3>, <32.33359, -20.78352, -3> rotate 180*x
scale 1.4 pigment { color <1, 1, 0> }
}
Not a bug. Normally, bicubic patches are smooth, but by having all control points along a row or column equal, you create a "pinch" in the surface, where the derivative is not well defined (around that point, the surface is squeezed into a sharp wrinkle). Bicubic patches are internally tesselated (broken up into triangles) before rendering. If you increase u_steps and v_steps, this wrinkle will get smoothed out (I increased to 5x5 and the artifact got smaller). Don't go too far, increase by 1 in each dimension multiplies the number of triangles by 2.
What you did is just like at the top of a curtain - you wrinkled the entire edge into a point. You can't expect very smooth results if you force the surface into such bad corners.
Surely the derivative is only undefined at the vertex itself? It should be fine everywhere else. If you take any “normal” Bézier patch, then gradually move the four points closer until they are all the same point, I agree the limit of the derivative at the point itself depends on the path the four vertices take, but I’m pretty sure the limit of the surface exists and is the same surface for any such path, and is an unremarkable surface without any wrinkles or other artifacts. If I’m right and that surface exists and is unique, it should be POV-ray’s responsibility to render it correctly.
Is it really mathematically bad, or is it just “bad” in your implementation?
It's mathematically bad. Yes, the derivative is undefined only at the vertex, but because of that, you have rapid variation of the derivative around that point, so the second derivative (the curvature) gets extremely large. Povray does not actually render the patch directly from mathematical description, but splits it into triangles and just renders it in this approximation. For a very curved surface, you can imagine that you need smaller triangles to approximate the surface (you are trying to make a curved surface from flat triangles), and therefore need to increase u_steps and v_steps. These parameters are meant exactly for setting the precision: if you know that the curvatures are small, you can use a small number of large triangles, and it renders more quickly. If you have "bad" patches, the precision needs to be higher.
To make the process more automatic, you can use a larger u_steps,v_steps and specify "flatness" parameter, so that it only makes subdivisions on the curved parts, and uses larger triangles on the parts where this is not needed. However, this can create other artifacts if the curvature changes too quickly.
You should probably avoid patches like this. I know that it happens naturally sometimes (for instance, if you are rendering a 3D surface in polar coordinates, then at the origin two corners are the same), and in this case, you should either accept the artifact, increase the precision for that patch (needs special case treatment), or for all of them, but that increases time and memory cost.
What can I use instead? What POV-ray object would be equivalent to the surface I want but without artifacts?
I'm not sure what you want. To just remove the artifacts, increase u_steps and v_steps until it's good enough. That's why those parameters exist. Otherwise, if you want something more different, you can use meshes (your own triangulation) or parametric surfaces.
Currently, POV-Ray does not support triangular bicubic patches.
Note that this FlySpray issue has been changed from "possible bug" to "feature request", as a concession that it would be nice to have support for triangular bicubic patches without using excessively high quality settings.
Now tracked on github as issue #217.