У нас есть некоторые проблемы с трассировкой лучей в DirectX, особенно с некоторыми серьезными проблемами с зеркальным отражением. При высокой зеркальной мощности (выше 8) начинается полосатость. Мне интересно, если это проблема HDR / LDR или это может быть связано с чем-то другим, например с нормальными или другими векторами?
ОБНОВИТЬ
Смотрите ниже для обновлений.
Вот соответствующий код шейдера для Blinn-Phong на сфере:
float3 hitPoint = thisRay.origin + thisRay.direction * bestHit.hitT;
float3 normal = normalize(hitPoint - spheres[bestHit.hitID].center);
float3 toLight = pointLights[0].position.xyz - hitPoint;
float d = length(toLight);
toLight = normalize(toLight);
float diffuse = max(dot(normal, toLight), 0.0f);
float3 v = normalize(thisRay.origin - hitPoint);
float3 h = normalize(v + toLight);
float spec = 0;
if (diffuse > 0)
spec = pow(max(dot(normal, h), 0.0f), specPower) * diffuse;
output[threadID.xy] = spheres[bestHit.hitID].colour * diffuse + spheres[bestHit.hitID].specColour * spec;
specPower равно 8 на этом изображении
specPower на этом изображении равен 9
Это так же просто, как проблема HDR / LDR, или это как-то связано с нормальной точностью? Я полагаю, что я сталкивался с этой проблемой раньше в отложенном рендере, где нормали были низкой точности и неправильно упакованы / распакованы, но в этом случае нормали генерируются на лету, и все это передается непосредственно в буфер.
Обновление 1
Я хотел бы добавить к вышесказанному, что треугольники страдают от одного и того же артефакта, и их нормаль в настоящее время генерируется следующим образом:
float3 normal = normalize(cross(triangles[bestHit.hitID].vertices[1] - triangles[bestHit.hitID].vertices[0],
triangles[bestHit.hitID].vertices[2] - triangles[bestHit.hitID].vertices[0]));
Я бы сказал, что это делает еще более маловероятным, что нормаль поверхности является проблемой. На следующем изображении показано, что происходит, когда specPower достигает 2048.
источник
float3 h = normalize( reflect(toLight,normal) );
, иspec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;
spec
непосредственно, а такжеmax(dot(normal, h), 0.0f)
. Ищите этот возврат к значению 1 в любом расчете.Ответы:
Похоже, проблема с реализацией функции pow на этом конкретном графическом процессоре.
При подозрении на ошибку в математической функции замените математическую функцию ее эквивалентом, например, замените:
Если ошибка отображается в specPower = 9.0, закодируйте ее
Или
Если проблема исчезнет, это означает, что в функции pow, возможно, имеется ошибка недостаточного значения, связанная с показателем степени на этом графическом процессоре или драйвере.
Что можно сделать в качестве обходного пути, если предположить, что вычисление фрагмента шейдера выполняется внутри с помощью 16-битных операций с плавающей точкой Если я рассчитываю это право, вы должны сделать
Это может быть 32768 или 8192: я могу быть отключен на один бит или GPU может использовать более или менее точную точность. для pow (x, 9.0) зажим будет pow (max (temp, 0.3401975), 9.0). Значения X ниже этого значения приведут к снижению диапазона экспонент (от +15 до -14) 16-битных IEEE с плавающей запятой (опять же, я при условии, что это то, что использует графический процессор.)
из кода розетки ( http://rosettacode.org/wiki/Nth_root#C.2B.2B )
Вам нужно будет рассчитать это на CPU и передать значение в униформе: у GPU, вероятно, будет та же проблема точности, если вы вычислите это прямо в шейдере.
Если вы можете это подтвердить, попробуйте связаться с командой драйверов графического процессора с примером исходного кода шейдера, который повторяет проблему, чтобы сообщить им точную версию драйвера, версию ОС и модель графического процессора. Исполняемый файл может помочь, но не отправляйте его по электронной почте. попасть в ловушку вируса / спама. Просто создайте его и сохраните копию на случай, если они попросят предварительно скомпилированный пример исполняемого файла. В качестве любезности дайте им возможность исправить это, прежде чем называть его публично. Это может быть просто ошибка оптимизации в их шейдерном компиляторе, которая может случиться только с вашим конкретным шейдером. Это может занять некоторое время (месяцы), чтобы связаться с ними, эти парни часто недоукомплектованы.
источник