hlsl неожиданный результат acos

Я нашел несколько странных ошибок HLSL — или Пикс говорит глупости:

У меня есть 2 ортогональных вектора: A = {0.0f, -1.0f, 0.0f} и B {0.0f, 0.0f, 1.0f}

Если я использую точечную функцию HLSL, вывод будет (-0.0f), что имеет смысл, НО теперь значение этого вывода равно -0.0000675917 (это то, что говорит Пикс — и что выводит шейдер), а это не то, что я ожидал;

Даже если я сам вычислю точечный продукт (A.x * B.x + A.y * B.y + и т. Д.), Результат все равно 0.0f, но акос моего результата не равен нулю.

Мне нужно, чтобы результат acos был как можно точнее, потому что я хочу раскрасить свои вершины в соответствии с углом между нормалью треугольника и данным вектором.

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;
}

Он отлично работает для углов выше 0,01 градуса, но дает неправильные результаты для меньших значений.

Другие найденные мной ошибки: -функция length в hlsl возвращает 1 для вектора (0, -0, -0, 0) в Pix, а функция HLSL «any» в этом векторе также возвращает true. Это будет означать, что -0.0f! = 0.0f.

Кто-нибудь еще сталкивался с этим и, возможно, есть обходной путь для моей проблемы?
Я протестировал его на Intel HD Graphics 4600 и карте Nvidia с теми же результатами.

0

Решение

Одна из основных причин, почему acos может возвращать плохие результаты, заключается в том, что всегда помните, что acos принимает значения от -1,0 до 1,0.

Следовательно, если значение даже немного превышает (1,00001 вместо 1,0), оно может вернуть неверный результат.

Я имею дело с этой проблемой путем принудительного ограничения, т.е. ставя чек на

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]