0
votes

I found a few strange HLSL bugs - or Pix is telling nonsense:

I have 2 orthogonal Vectors: A = { 0.0f, -1.0f, 0.0f } and B { 0.0f, 0.0f, 1.0f }

If I use the HLSL dot function, the output is (-0.0f) which makes sense BUT now the acos of that output is -0.0000675917 (that's what Pix says - and what the shader outputs) which is not what I had expected;

Even if I compute the dotproduct myself (A.x*B.x + A.y * B.y + etc.) the result is still 0.0f but the acos of my result isn't zero.

I do need the result of acos to be as precisely as possible because i want to color my vertices according to the angle between the triangle normal and a given vector.

float4 PS_MyPS(VS_OUTPUT input) : COLOR
{
float Light = saturate(dot(input.Normal, g_LightDir)) + saturate(dot(-input.Normal, g_LightDir));   // compute the lighting

if (dot(input.Vector, CameraDirection) < 0)     // if the angle between the normal and the camera direction is greater than 90 degrees
{
    input.Vector = -input.Vector;               // use a mirrored normal
}

float angle = acos(0.0f) - acos(dot(input.Vector, Vector));

float4 Color;

if (angle > Angles.x)                           // Set the color according to the Angle
{
    Color = Color1;
}
else if (angle > Angles.y)
{
    Color = Color2;
}
else if (angle >= -abs(Angles.y))
{
    Color = Color3;
}
else if (angle >= Angles.z)
{
    Color = Color4;
}
else
{
    Color = Color5;
}

return Light * Color;
}

It works fine for angles above 0.01 degrees, but gives wrong results for smaller values.

The other bugs I found are: The "length"-function in hlsl returns 1 for the vector (0, -0, -0, 0) in Pix and the HLSL function "any" on that vector returns true as well. This would mean that -0.0f != 0.0f.

Has anyone else encountered these and maybe has a workaround for my problem? I tested it on an Intel HD Graphics 4600 and a Nvidia card with the same results.

1
If you use the HLSL dot function on A = { 0.0f, -1.0f, 0.0f } and B { 0.0f, 0.0f, 1.0f } and the output is -0.0f (which makes sense according to your question), why do you attribute the bug to HLSL instead of to the acos function?Oswald
What do you mean by seems to have the lenght 1? How did you test it?Oswald
To answer all your questions: 1. I will provide the example tomorrow, 2. the acos function is used within a hlsl shader and 3. I opened my project in Pix and debugged the shader. There the length function returned 1 for the (0,-0,-0,0) vector.Tomas Dittmann
ok I get get some funny results with length also (seems the bug is in the compiler actually). using fxc I got some really odd stuff. About acos, acos(0) is not 0, but PI/2 , acos(1) = 0. On another note, your angle calculation can just use the dot product, you don't need acos there. Last one for the road, can I see how you declare your variables in your shader (might be a cbuffer issue), and your VS_OUTPUT definition?mrvux

1 Answers

0
votes

One of the primary reasons why acos may return bad results is because always remember that acos takes values between -1.0 and 1.0.

Hence if the value exceeds even slightly(1.00001 instead of 1.0) , it may return incorrect result.

I deal with this problem by forced capping i.e putting in a check for

if(something>1.0)
   something = 1.0;
else if(something<-1.0)
   something = -1.0;