![image](https://habrastorage.org/webt/ip/4n/ub/ip4nubgxpz4qwmkxpgy8jgslqse.jpeg)
Перспективная проекция
Текстуры
Наш растеризатор может отрисовывать кубы или сферы. Но нам неинтересны абстрактные фигуры вроде кубов и сфер. Нас интересуют разные реальные объекты, например ящики и планеты или игральные кубики и шарики для рулетки. В этой главе вы научитесь добавлять на поверхность объектов разные визуальные детали с помощью текстур.
Закрашивание ящика
Допустим, нам в сцене нужен деревянный ящик. Как можно превратить в него куб? Первый вариант — добавить много треугольников для воссоздания фактуры дерева, шляпок гвоздей и т. д. Это сработает, но скажется на быстродействии.
Есть еще вариант — сымитировать детали: вместо изменения геометрии объекта мы просто «нарисуем» поверх него что-то похожее на дерево. Если не разглядывать ящик вплотную, то и отличий заметить не удастся, а вычислительная стоимость окажется намного ниже.
Эти два варианта можно совмещать: выбирать правильный баланс между добавлением геометрических деталей и рисованием поверх них для достижения требуемого качества и скорости отрисовки. Мы уже знаем, как работать с геометрией, поэтому сразу перейдем к изучению второго варианта.
Для начала нам нужно изображение, которое мы будем рисовать на треугольниках. Его мы будем звать текстурой. На рис. 14.1 показана текстура деревянного ящика.
![image](https://habrastorage.org/webt/je/jn/qc/jejnqcf4mpqkwftgohbuvi0mnke.png)
Дальше нужно указать, как эта текстура должна применяться к модели. Это наложение можно определить по треугольникам, сопоставив точки текстуры с их вершинами (рис. 14.2).
Для определения этого сопоставления нам понадобится система координат, позволяющая обращаться к точкам на текстуре. Напомню, что текстура — это просто изображение в виде прямоугольного массива пикселей. Можно было взять координаты x и y и рассматривать пиксели текстуры относительно них, но мы уже используем эти обозначения для холста. Поэтому координатами текстуры у нас будут u и v, а ее пиксели назовем текселями (сокр. от англ. texture elements — элементы текстуры).
Начало этой системы координат (u, v) мы установим в верхнем левом углу текстуры. Еще объявим, что u и v — это вещественные числа в диапазоне [0, 1], независимо от фактических размеров текселей. Это будет очень удобно по нескольким причинам. Например, нам может понадобиться использовать текстуры с разрешением выше или ниже, в зависимости от объема доступной памяти ОЗУ. Мы не привязаны к реальным размерам пикселей, поэтому можно изменять разрешение, не корректируя саму модель. Мы можем умножить u и v на ширину и высоту текстуры для получения фактических индексов tx и ty.
![image](https://habrastorage.org/webt/fz/6i/2f/fz6i2fjaiujb1qbbi9hfbamyx6o.png)
Основная идея наложения текстур проста: вычислить координаты (u, v) для каждого пикселя треугольника, получить соответствующий тексель и закрасить пиксель его цветом. Но модель указывает координаты u и v только для трех вершин треугольника, а нам они нужны для каждого пикселя…
Вы уже должны понемногу вникать в происходящее. Да, здесь снова появляется наш старый добрый друг — линейная интерполяция. Можно использовать отображение атрибутов, чтобы интерполировать значения u и v по всей грани треугольника. Это даст нам (u, v) для каждого пикселя. С их помощью мы сможем вычислить (tx, ty), получить тексель, применить затенение и закрасить пиксель итоговым цветом. Результат всего этого можно посмотреть на рис. 14.3.
Результат получается посредственный. Внешне ящики выглядят неплохо. Но если присмотреться к диагональным доскам, мы увидим, что они деформировались. Что же пошло не так?
Как и в главе 12, мы снова сделали неявное ошибочное допущение: то, что u и v изменяются по экрану линейно. Это не так. Рассмотрим стену очень длинного коридора, закрашенную чередующимися черными и белыми полосами. Чем дальше будет стена, тем тоньше будут полосы. Если мы сделаем так, чтобы координата u изменялась линейно относительно x, то получим неверный результат, как показано на рис. 14.4.
![image](https://habrastorage.org/webt/g7/uq/bx/g7uqbxez2yaz9sl0eokdptffcx0.png)
Ситуация схожа с той, что была у нас в главе 12, и решение тоже будет очень похожим: несмотря на то что u и v — не линейные в координатах экрана, такими являются u/z и
v/z (подтверждение этому будет похоже на подтверждение 1/z: представьте, что u изменяется линейно в 3D-пространстве, и подставьте x и y с их выражениями для области экрана). У нас уже есть интерполированные значения 1/z в каждом пикселе, этого достаточно для интерполяции u/z и v/z и получения назад u и v:
![image](https://habrastorage.org/webt/go/2p/yk/go2pykqyvl6etfbykh-fwkwvlpa.png)
На рис. 14.6 сравниваются оба результата, чтобы можно было увидеть разницу.
![image](https://habrastorage.org/webt/oy/1p/2u/oy1p2u4a9gmacnkqcb2cwh3kvmg.png)
Живая реализация алгоритма находится по ссылке gabrielgambetta.com/cgfs/textures-demo.
Эти примеры смотрятся красиво, потому что размер текстуры и пиксельный размер треугольников под ней приблизительно одинаковые.
Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок
По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Для Хаброжителей скидка 30% по купону — Гамбетта
Комментарии (2)
forthuser
01.03.2022 20:35Часть электроной версии книги на сайте автора.
Computer Graphics from Scratch
Tab10id
Я просто оставлю это здесь: https://habr.com/ru/post/342510/ https://habr.com/ru/post/342708/