
Комментарии 48

Кому интересно, слепок кода: github.com/FunkyCat/3dHabraLessons/tree/b8239503f9d251d94aa3e7b8a66f15495674d0cb
Вся компьютерная графика — это наука о том, как обмануть глаз наиболее дёшево. В большинстве случаев коррекция текстуры дороже тупого подразбиения больших треугольников. Например, на нашей тествой модели вы этого эффекта не заметите, даже несмотря на то, что я не сделал ни малейшего усилия для его уменьшения.
Соответственно, вам решать, как именно дешевле всего разобраться с этой проблемой. Я не планировал включать его коррекцию в этот (напоминаю, краткий) курс.
Мы все дружно просим вас — включите же! Это очень и очень нужый и полезный элемент.
А вот оказывается, что на самом деле не такое уж там и перспективное отображение используется…
Конкретный артефакт не из-за невыразимости перспективного преобразования (вершины-то мы прекрасно нарисовали где и как надо), а из-за линейности самого дешёвого интерполирования.
Да, произнесу очевидную вещь: этот артефакт будет заметен в очень специфических условиях
Например, на таких специфических поверхностях (которые практически не встречаются в играх) как потолок, стены и пол.
если вы наложите вместо шахматной доски на эти же треугольники текстуру песка, то проблемы нет
Если не считать проблемой, что текстура сплющивается в несколько раз вдоль диагоналей прямоугольников.
В софте перспективно-корректное (кусочно-линейное) текстурирование лучше применять всегда, кроме случаев, когда треугольники меньше предела разбиения (16-32 пикселей). Без него получается ужасно страшная картинка (к тому же, в софте обычно используют минимум мелких треугольников, потому что их дорого считать).
коммит тут: github.com/ssloy/tinyrenderer/commit/af1861a2bcab76bb6294e1971df8917ccd6ab0eb
В нем автоматически решилась эта проблема. (но в коммит примешалось чуть больше чем фикс искажений перспективы)
Между делом вот коммит, подготовленный для поправок, он даёт такую картинку:

Этот коммит даёт такую:

dvisvgm --no-fonts --scale=1.5 myfile.tex
Здесь мы требуем:
- --no-fonts — не пытаться применять вставку текста надписью, а рисовать векторную картинку из текста
- --scale=1.5 — увеличить все в 1,5 раза. Это зависит от того, какой был использован стиль и размер шрифта. 1,5 хорошо смотрится для article
#!/bin/sh
for i in `ls -1 *tex`; do
rubber $i
dvisvgm --no-fonts --scale=1.5 `basename $i tex`dvi
rubber --clean $i
done
www.codecogs.com/latex/eqneditor.php
Он автоматический генерит ссылку на картинку с формулой и очень стабильный.
UPD: Нашел, вот так нужно писать:
latex.codecogs.com/svg.download?sin(x)
Второе возражение — в процессе написания статьи (особенно, если для ее изложения понадобились формулы. Не зря Хокингу издатель сказал, что каждая формула вдове сокращает количество читателей) не очень-то удобно постоянно отвлекаться куда-то за формулой. Но у меня «TeX головного мозга», я в этом смысле очень предвзят.

Дошёл до этого урока про матричные преобразования, думая, что тут-то я просто возьму соответствующий код из своей старой реализации движения, вращения и проецирования проволочного куба, но, кажется, я запутался в столбцах и строках. Помню где-то читал, что в DirectX используются векторы строки и умножение на матрицу преобразования, а в OpenGL всё наоборот - вектора столбцы и умножение матрицы на этот вектор. Это так? Может быть тема раскрыта в следующих статьях курса (я их ознакомительно пролистал, но не нашёл)?
Причём всё было ещё более менее понятно до тех пор, пока я не решил погуглить про эффективные реализации матричной математики на JS, потому что я наткнулся вот на это: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Matrix_math_for_the_web
Где матрица сдвига выглядит как и в моей реализации (через умножение вектора на матрицу)
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1Но потом матрица вращения вокруг Oz там транспонирована по сравнению с той, что у меня.
cos(a), -sin(a), 0, 0,
sin(a), cos(a), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1Здесь то в статье всё одинаково транспонировано относительно моих матриц и сдвиг и вращение и проецирование.
Можно было бы предположить, что это в той статье ошибка, но у них там ссылка https://jsfiddle.net/b8zjc3ys/, где всё работает.
Возможно ещё дело в "правой" или "левой" системе координат, в том, направлен Z в экран или из, а Y -- вверх или вниз. Или в том, вращение по часовой стрелке или против.
Да ещё на странице https://glmatrix.net/ в разделе "A note about Matrix formatting", говорят что в докуемнтации OpenGL одно представление, а в коде другое.
Итак, вопрос в row major или в column major. Давайте отбросим старые версии OpenGL, где были заковыки (в одном месте пайплайна было одно соглашение, а в другом другое), и возьмём современный OpenGL. В нём вообще нет системных матриц, вы сами всё руками имплементируете. Поэтому выбирайте стиль хранения по вкусу и, главное, следуйте ему везде. Лично мне привычнее векторы представлять столбцами, а ковекторы строками. Впрочем, ковекторы вам вряд ли скоро попадутся. Поэтому самое частое представление вектора - это столбец. Если у вас вектор v преобразуется матрицей M, то их преобразование записывается M*v, то есть, v - это вектор-столбец.
Дальше вопрос про то, где у синусов стоят минусы в матрицах вращения - это отдельная договорённость. Реперы есть левые и правые, обычно пользуются правым, и с договорённостью типа буравчика. То есть, возьмите правую руку, покажите большой палец, вытяните большой палец вдоль положительной оси вращения, и остальные пальцы покажут направление вращения вокруг этой оси, если угол вращения положителен.
Результат

Ради быстрого результата пока оставил умножение вектора строки на матрицу, и, если я правильно понял, вращение получилось правильное - это вокруг OZ на 0.2 Пи с помощью матрицы
[[cos, sin, 0, 0],
[-sin, cos, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]Да, всё чётко. Если вектор - это строка, которая умножается справа на матрицу, то Rz так и выглядит. Вращение вокруг осей OX и OZ выглядит так:
Rx = [[1, 0, 0, 0], [0, cos, sin, 0], [0, -sin, cos, 0], [0, 0, 0, 1]]
Ry = [[cos, 0, -sin, 0], [0, 1, 0, 0], [sin, 0, cos, 0], [0, 0, 0, 1]]
Обратите внимание на то, что у Ry паттерн знаков обратный.

Краткий курс компьютерной графики: пишем упрощённый OpenGL своими руками, статья 4a из 6