POV-Ray : Newsgroups : povray.bugreports : Reflection bug? : Re: Reflection bug? Server Time
28 Jun 2024 02:30:32 EDT (-0400)
  Re: Reflection bug?  
From: Nathan Kopp
Date: 29 Nov 1998 19:29:18
Message: <3661E5BE.1F6120DC@Kopp.com>
I was able to produce a fix for this bug.  I submit it here to the
POV-Ray team.  If you'd like a copy of my LIGHTING.C file, just let
me know and I'll send it.

-Nathan Kopp

=================

The cause of the bug is kind of tricky.  Imagine a bumpy surface:
        _______
       /       \
       |       |  <--- these don't have to be exactly vertical
______/         \________     (object X)

In POV, the faked bump really looks like this:

______/|/_____\|\________     (object Y)
       A       B

Reflecting rays don't have much of a problem unless they hit the
parts where the slope is almost perpendicular to un-perturbed normal
(for example, points A or B).  In this case, if you have a faked
normal, rays coming straight down towards the object just "fall
through the cracks."  In real life, they would really get reflected
two (or more) times:

__    ray in
##\  /
##| /
##|/     ray out (if the surface was shaped like this)
##|\    /
##| \  /
###\_\/_______
##############
##############

With a faked normal, you don't get the second intersection:

      ray in
     /
    /
__\|\________
    \
     \
      \ ray out


So here's how I fixed it.  The bug occurs when the direction of the
reflection ray is going the opposite direction of the non-perturbed (raw)
normal.  (Note that this version of the raw normal has been flipped to point
towards the camera.)

So when this situation arises, I reflect the ray's direction across
the non-perturbed surface of the object.

===============

Here are the changes (all are in LIGHTING.C):
These changes HAVE been tested. (Of course, only to a limited extent.)

First, I fixed some redundant and buggy code in compute_lighted_texture()
The code
------------------
  /* If the surface normal points away, flip its direction. */
  VDot(Normal_Direction, RawNormal, Ray->Direction);
  if (Normal_Direction > 0.0)
  {
    VScaleEq(RawNormal, -1.0);
  }
------------------
appears in some radiosity-related stuff at the beginning of the funciton,
and then again (in a slightly different form) when the normals are being
perturbed.  I simply consolidated this code and moved it to the beginning
of the function (outside of all if statements) so that it always gets
executed.

Now that I was sure that RawNormal had been properly flipped in all
situations, I added a vector parameter "Raw_Normal" to both Reflect()
and Refract(), passed the "RawNormal" variable to it.  When Refract()
calls Reflect(), it just passes on the same "Raw_Normal" that it recieved.

Then, right after the line
------------------
  VLinComb2(NRay.Direction, n, Normal, 1.0, Ray->Direction);
------------------
in Reflect(), I added:
------------------
  /* NK 1998 - Reflection bugfix
    if the new ray is going the same direction as raw normal, we
    reflect it across the un-perturbed surface. */
  VDot(NRay_Direction, NRay.Direction, Raw_Normal);
  if (NRay_Direction < 0.0)
  {
    /* subtract twice the projection of NRay.Direction onto Raw_Normal
       from Raw_Normal */
    DBL Proj;
    Proj = NRay_Direction * -2;
    VAddScaledEq(NRay.Direction, Proj, Raw_Normal);
  }
  /* NK ---- */
------------------

This should fix the problem, and should not cause any un-wanted side
effects.  Of course, it needs further testing.

-Nathan Kopp


Markus Becker wrote:
> 
> Hello,
> 
> here's another one that someone postet over there on c.g.r.r:
> 
> The following scene consists of an opaque, reflective plane with
> a normal applied to it. The underlying plane with a checker
> pigment seems to come through the upper plane.
> 
> camera { location <-1,20,-20> look_at <0,12,0> }
> 
> light_source {
>   <300,500,100>
>   color rgb <1,1,1>
> }
> 
> background { color rgb <0,1,0> }
> 
> plane {
>   y, 0
>   texture {
>     pigment { color rgb<.5,.5,.5> }
>     normal { wood 0.5 scale 10 }
>     finish { reflection 1}
>   }
> }
> 
> plane{
>   y,-1
>   texture {
>     pigment {
>       checker
>         color rgb<1,0,0>
>         color rgb<0,1,0>
>       }
>     scale 10
>   }
>   finish { ambient 1 }
> }
> 
> //----------------- cut here ----------------------
> 
> Markus


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.