Посмотрите на эти два изображения:
Красный и синий каналы равны нулю на обоих снимках, в то время как зеленый канал - это координата х этой точки. Координата x находится в диапазоне (-1, 1).
Первое изображение было рассчитано на CPU:
double screenHeight = 750;
double screenWidth = 750;
double viewportWidth = 2.0;
for (int i = 0; i < screenHeight; ++i) {
for (int j = 0; j < screenWidth; ++j) {
float greenChannel = (double)j / screenWidth * viewportWidth;
}
}
Второе было рассчитано на GPU: Первый, вершинный шейдер было приказано нарисовать три вершины (но ни одна из них не была дана, больше информации здесь ):
layout (location = 0) out vec2 outUV;
void main() {
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(vec2(outUV) * 2.0f + -1.0f, 0.0f, 1.0f);
}
Это, по сути, отправляло координаты baricentri c каждому из фрагментов. Они были интерполированы между тремя значениями. Затем фрагментный шейдер выполнил следующие вычисления:
layout (location = 0) in vec2 outUV;
layout(location = 0) out vec4 outColor;
void main() {
double viewportWidth = 2.0;
double c = (outUv.x - 0.5) * viewportWidth;
outColor = vec4(vec3(0.0, float(c), 0.0), 1.0);
}
Сначала он перемещает координату x так, чтобы она теперь находилась в диапазоне (-0,5, -0,5), а затем масштабирует ее, чтобы получить ее до (-1, 1). ) диапазон.
Если вы снова посмотрите на изображения, вы заметите, что они не совпадают. Процессор один гораздо более плавный вблизи центра, в то время как тот, что отображается на графическом процессоре, имеет более резкий переход. У вас есть идеи, что может вызвать это? Похоже, что это может быть связано с потерей точности где-то на GPU. Я думал, что интерполированные числа с плавающей точкой не были достаточно точными, поэтому я попробовал другой подход для c:
double screenWidth = 750;
double viewportWidth = 2.0;
double c = (gl_FragCoord.xy - 0.5 * screenWidth )/ screenWidth * viewportWidth;
При этом используется gl_FragCoord и разрешение экрана вместо того, чтобы полагаться на интерполированное значение. Это дало мне результаты, которые были неотличимы с первой попытки, так что я думаю, что это не интерполяция. Просто чтобы быть уверенным, я вычислил c в обе стороны и сравнил их. Они были точно такими же, вплоть до 7-го знака после запятой.
Кто-нибудь знает, почему два изображения не совпадают?