§ Общие положения
Я очень долго и очень много размышлял над темой, каким сделать трехмерный растеризатор и наконец, пришел к определенному выводу, что можно будет сделать экран не 320 на 200, как я постоянно раньше думал, а 256 на 192. Это дает два преимущества — во-первых, экран в памяти будет занимать лишь 48Кб, если это 256-цветный, во-вторых, у него точное количество пикселей, что позволит разделить на несколько блочных RAM и записывать туда с разных вычислителей.Всего у DE0 внутрисхемной памяти весьма прилично, а именно 308 Кб. Если взять двойную буферизацию за основу, то вся цветовая видеопамять займет в памяти 48 + 48 = 96 Кб. Буфер глубины будет также иметь 2 байта на одну точку и тоже равен 96 Кб. Итого, 192Кб на двойной буфер и буфер глубины.
2 байта для одной точки глубины с Half Precision (16 bit) плавающей точкой, которое дает точность от 0.00006103515625 до 65504, что весьма прилично! Именно для буфера глубины и стоит использовать именно числа с плавающей точкой, поскольку именно они имеют логарифмическую шкалу для сравнения, ведь более дальние объекты будут именно в перспективе, так что это идеальный вариант.
Текстуры хранятся в виде 256 на 256 текстурной области, 64Кб памяти. На хранение остальной геометрии остается 52Кб, и этого вполне достаточно.
§ Структура геометрии
Есть 3 метода, которые могут быть использованы.1. Хранить вершины и грани в разных местах, причем вершины будут содержать еще и текстурные точки
2. Хранить вершины и грани отдельно, но грани содержат текстурные точки — наилучший вариант
3. Хранить только грани, которые будут включать и вершины, и текстуры
На одну точку приходится 3 координаты (xyz), по 2 байта на каждую, то есть, 6 байт. На одну грань также приходится по 3 точки и тоже по 2 байта, что дает 6 байт. Чтобы не дергать по одному байту из памяти, блочную память можно настроить на 16-бит.
Итак, чтобы нарисовать треугольник, потребуется сделать 3 запроса на вершины по 3 запроса на точки, итого, 9 запросов, или 9 тактов. Это без учета текстур. Если хранить текстуры на гранях, то придется выбрать на каждую вершину еще по 3 точки (uv), что даст 12 тактов.
Итого, одна грань выбирает 3 вершины:
[a][a.uv] [b][b.uv] [c][c.uv]
, то есть 6 запросов + 6 запросов на получение точек. В целом это займет 24 байта памяти. Если взять куб, то для куба потребуется 8 вершин (24 байта) и 12 граней (96 байт), что дает суммарно 120 байт потраченной памяти. В 16 Кб вершинно-граневой памяти можно вместить 136 кубов таким образом.Но если использовать этот видеоадаптер совместно с процессором, то процессор может генерировать геометрию.
Преимущество метода 3 заключается в том, что несмотря на то, что хоть и увеличивается объем памяти, в которой надо хранить данные, но эта память линейная и может располагаться в SDRAM, которая на порядок больше может содержать данных, чем в блочной (внутрисхемной) памяти плис.
Возьмем куб. У него 6 граней по 2 треугольника на грань, то есть 12 треугольников. Один треугольник описывается 3 точками, что занимает в памяти 8 байт (x,y,z,uv), итого 8*3=24 байта на треугольник, и на 12 треугольников по 24 байт получится 288 байт на куб. Это в 2.4 раза больше, чем метода 2, но все данные хранятся последовательно.