Calculation of refraction vector seems to be incorrect...

Started by
12 comments, last by data2 18 years, 8 months ago
well add some intermediate debug output.

does mu really have the value 1?

does the term (mu * nDotV - (float)Math.Sqrt(cosThetaT)) really return 0 like youd expect it to?

does that even matter? your normal suppposedly only has an y-component, yet the outcome, which is a linear combination of the input and normal, shows an error only in the x-component.
Advertisement
Here we are: The debug output. What I see is that mu is indeed 1. Also, the nDotV behaves as expected. But the weight is not always 0, but -2 (though the result will be correct again -- suspicious) and -1.414 == -sqrt(2). I indented the incorrect outputs.

incident:     0 /  1 / 0expected:     0 / -1 / 0mu: 1; nDotV: 1; cosThetaT^2: 1; weight: 0refracted:    0 / -1 / 0 => Correct?: Trueincident:     0 / -1 / 0expected:     0 /  1 / 0mu: 1; nDotV: -1; cosThetaT^2: 1; weight: -2refracted:    0 / 1 / 0 => Correct?: Trueincident:      0.7071068 /  0.7071068 / 0expected:     -0.7071068 / -0.7071068 / 0mu: 1; nDotV: 0.7071068; cosThetaT^2: 0.5; weight: 0refracted:    -0.7071068 / -0.7071068 / 0 => Correct?: True                    incident:      0.7071068 / -0.7071068 / 0                    expected:     -0.7071068 /  0.7071068 / 0                    mu: 1; nDotV: -0.7071068; cosThetaT^2: 0.5; weight: -1.414214                    refracted:     0.7071068 / 0.7071068 / 0                     => Correct?: Falseincident:     -0.7071068 /  0.7071068 / 0expected:      0.7071068 / -0.7071068 / 0mu: 1; nDotV:  0.7071068; cosThetaT^2: 0.5; weight: 0refracted:     0.7071068 / -0.7071068 / 0 => Correct?: True                    incident:     -0.7071068 / -0.7071068 / 0                    expected:      0.7071068 /  0.7071068 / 0                    mu: 1; nDotV: -0.7071068; cosThetaT^2: 0.5; weight: -1.414214                    refracted:    -0.7071068 / 0.7071068 / 0                     => Correct?: False
i think ive got it. ndotv should never be allowed to become negative, this is what messes up the weight calculation. the result of the sqrt will reduce to ndotv for mu=1, so when substracted from ndotv itself, should return 0. its just one of the assumptions made in the derivation, but its not a problem.

the way youve done your signs, the normal should always be facing in the same direction as the incoming vector, so its dotproduct will be positive. it makes more sense to flip your signs though, usually normals are facing outwards, whereas the incoming vector is ofcource facing inwards.
Hell, yes!!!! You're right!

I simply tried to invert nDotV if it is negative as well as the normal and everything is wonderfully correct...

Thank you very very much for the effort. I think I wouldn't have seen it (though it is absolutely clear now). Well, here is the final code, just for the sake of completeness:

    public static Vector3 RefractVector(Vector3 vector, Vector3 mirrorNormal, float muSurfaceFront, float muSurfaceBack)    {        float nDotV = Vector3.Dot(mirrorNormal, vector);        float mu;        if(nDotV > 0.0f)        {            mu = muSurfaceFront / muSurfaceBack;    // from front to back        }        else        {            mu = muSurfaceBack / muSurfaceFront;    // from back to front            nDotV = -nDotV;            mirrorNormal = -mirrorNormal;        }        float cosThetaT = 1 - (mu*mu * (1 - nDotV*nDotV));        // total internal reflection        if(cosThetaT < 0.0f)        {            return Vector3.Empty;        }        return ((mu * nDotV - (float)Math.Sqrt(cosThetaT)) * mirrorNormal) - (mu * vector);    }

This topic is closed to new replies.

Advertisement