Год назад я опубликовал цикл статей, имевший целью популяризацию графического программирования. Много воды утекло с тех пор, появилась англоязычная версия цикла, прошедшая некоторую полировку по сравнению с оригинальным. За этот год мне написало несколько сотен человек, причём многие просили помочь отладить их код.
Я предлагаю вам поиграть в игру: я даю только картинку, на которой видна проблема, попробуйте понять, в каком месте кода нужно искать баг, что именно сломано. Я в эту игру играю ежедневно, досконально смотреть сотни версий рендера у меня нет никакой возможности, поэтому я, как заправский экстрасенс, лечу по фотографии. Зачастую успешно.
Абсолютно все картинки сгенерированы не мной, я лишь собрал самые типичные баги. Настоящая людская боль перед вашими глазами, ко мне, понятно, обращаются (особенно по почте) только после того, как не могут сами найти баг в разумное время.
Вот первый баг для затравки, слева битый рендер, справа то, что ожидалось:
Скрытый текст
Наипервейший хинт: очень круглая форма. Сразу намекает на то, что вместо массива вершин человек загрузил массив нормальных векторов, точнее, перепутал строки «v x y z» и «vn x y z» из .obj файла
Скрытый текст
Треугольники плохо стыкуются друг с другом. В wavefront .obj файлах индексы массивов начинаются с единицы, а не с нуля, человек забыл отнять единицу после прочтения файл модели.
Скрытый текст
Обратите внимание, что все треугольники на их геометрическом месте, а проблемные места текстуры образуют полные кольца вокруг одной вершины, что намекает на то, что периодически одна вершина битая. Так и есть, был плавающий баг в прочтении текстурных индексов.
Скрытый текст
На картинке тонировка Гуро, заполнение треугольника явно сделано при помощи сканирующей линии, когда вершины сортируются по их игрек-координате, а затем горизонтальными линиями заметается треугольник. Порядок вершин изменился, а вот цвет вершин поменять местами забыли. Очень частый баг.
Скрытый текст
На картинке битый z-буфер. Практически то же самое, что и предыдущий баг, только забыли поменять z-координату вершин при сортировке.
Скрытый текст
И опять тот же самый баг, но чуть-чуть в другом месте: при заметании треугольника он для удобства делится на две части, каждая горизонтальная линия рисуется слева направо. Меняя местами вершины линии, забыли про текстурные координаты.
Скрытый текст
Ошибки округления, игрек сканирующей линии явно вычисляется интерполяцией, вместо того, чтобы по нему непосредственно сделать заметающий цикл.
Скрытый текст
Опять ошибки округления, экранные вершины треугольника не были округлены перед растеризацией.
Тут полезно знать, что человек пытался сделать блестящую поверхность (specular map):
Скрытый текст
Неважно что в степени ноль даёт единицу...
Скрытый текст
Растеризация треугольника явно сделана через барицентрические координаты, и их неплохо бы сдвинуть по кругу при вычислении текстурных координат.
Скрытый текст
Текстуру явно нужно перевернуть по вертикали
Ха, эта картинка очень похожа на предыдущую, но баг совсем другой (почему?)
Скрытый текст
Вместо текстурных координат человек просто использовал xy текущего пикселя для поиска цвета в текстуре...
Здесь и далее картинки до и после отладки:
Скрытый текст
Направление света было использовано для отсечения задних граней. А надо было бы направление взгляда...
Попытка применить карту нормалей:
Скрытый текст
Ну что, цвет, живущий в RGB [0,255]^3 был сконвертирован в XYZ, живущий в [0,2]^3, а не в [-1,1]^3.
Скрытый текст
При плоской тонировке (flat shading) вектор света и/или вектор нормали не был нормализован, в итоге попытка отрисовать цвета со значением более 255, переполнение unsigned char
Скрытый текст
Явно опять переполнение, но на сей раз отрицательные значения. Человек забыл, что скалярное произведение бывает отрицательным. Картинка справа — это fabs(интенсивности), предыдущая картинка могла бы быть получена, если бы вместо fabs мы использовали обычный clamp
Have fun!
Автор: haqreu
Источник