5
$\begingroup$

I am implementing a simple Phong shader in OpenGL GLSL, and the test object is the utah teapot. However on the bottom I get a solid red circle, and on the top there is are sharp sectors that are coloured incorrectly.

Is there any way to fix these issues? What would be the issue in the first place?

enter image description here enter image description here

$\endgroup$
  • $\begingroup$ Is it possible that the solid red is a hole? $\endgroup$ – ratchet freak Feb 8 '16 at 14:12
  • $\begingroup$ No I have checked that, and it is not $\endgroup$ – Jonathan. Feb 8 '16 at 15:14
  • 1
    $\begingroup$ Can you upload your code somewhere (gist, pastebin, etc.) and link it? We might be able to spot the error in the code. $\endgroup$ – RichieSams Feb 8 '16 at 15:37
  • 4
    $\begingroup$ Problem is most likely in your normal computation. The end is a singularity in the ubderlying parametric shape which can yeld bad results if you dont know what your doing. The visible artefact number 2 is pretty common in these cases. $\endgroup$ – joojaa Feb 8 '16 at 22:25
  • 1
    $\begingroup$ Your question would definitely be more answerable if you included relevant parts of the code. $\endgroup$ – Martin Ender Feb 11 '16 at 12:36
4
$\begingroup$

I'm fairly certain your problem lies in not handling so-called degenerate Bezier patches correctly, in particular (as Joojaa noted), the computation of the surface normal. I say "so-called degenerate" because, geometrically, the surfaces are often perfectly well behaved. It's just that some assumptions people frequently make regarding the parametric equations may not hold.

Books such as Gerald Farin's, snappily titled, "Curves and Surfaces for CAGD. A Practical Guide" will give more details, but I'll try to summarise two simple cases. Now assuming your Bezier is defined as $\bar{B}(u,v)$ the usual two causes of problems are:

Zero derivatives:

To compute the normal at $(a,b)$ one normally (pardon the pun) computes the two derivatives,

$\frac{\partial }{\partial v}\bar{B}(a,b)$ and $\frac{\partial }{\partial u}\bar{B}(a,b)$

or scaled versions thereof, to obtain two tangents and then take the cross product.

(Implementation note: Since we can use a scaled version of the tangent in the calculation, we really don't have to calculate the actual derivative. For example, especially at the corners, differences of control points can yield a scaled tangent. However for brevity in this discussion we will assume the actual derivatives).

A common occurrence, at least at the corners, is that the 1st partial derivatives at the location can be zero, which leads to an incorrect normal, i.e. a zero vector.

In the case of the tops and bottoms of the teapot, one whole edge of a number of the (bicubic) Bezier patches has been collapsed to a point, i.e. all 4 control points are the same, and thus, say

$\bar{B}(0,v)==\bar{B}(1,v)$ and $\frac{\partial }{\partial u}\bar{B}(0,0)=\bar{0}$.

The surface, however, is completely well behaved so you can simply choose another derivative that starts at that collapsed point. In this case, say, choosing

$\frac{\partial }{\partial v}\bar{B}(1,0)$

for the second tangent.

Having said this, you still have to check that your first derivatives are not zero for another reason (e.g 2 or 3 coincident control points), in which case, you can fall back (thanks to L'Hopital's rule) on the second (or if that's zero, even the third!) derivative(s) to obtain valid tangents.

Parallel tangents:

Another similar problem can arise if your two tangents, are parallel. - Farin has a good example in his book.

In this case, I think you may need to look at using something like $\frac{\partial^2 }{\partial u \partial v}\bar{B}$ or, possibly, just fall back to using a small UV offset to approximate a vector.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.