12 января 2010 в 13:23
Уроки Direct3D - 1.4. ZBuffer
Переделаем предыдущий проект для отображения двух треугольников. Для этого в InitGeometry добавим еще три вершины:
Private Sub InitGeometry() vSize = Len(Vert(0)) Set vBuffer = d3dDevice.CreateVertexBuffer(6 * vSize, 0, vFlag, D3DPOOL_DEFAULT) Vert(0).PosX = 250 Vert(0).PosY = 250 Vert(0).PosZ = 0.5 Vert(0).RHW = 1 Vert(0).Color = &H808080 Vert(1).PosX = 210 Vert(1).PosY = 10 Vert(1).PosZ = 0.5 Vert(1).RHW = 1 Vert(1).Color = &H808080 Vert(2).PosX = 10 Vert(2).PosY = 210 Vert(2).PosZ = 0.5 Vert(2).RHW = 1 Vert(2).Color = &H808080 D3DVertexBuffer8SetData vBuffer, 0, vSize * 3, 0, Vert(0) Vert(0).PosX = 10 Vert(0).PosY = 10 Vert(0).PosZ = 0.1 Vert(0).RHW = 1 Vert(0).Color = &HFF Vert(1).PosX = 250 Vert(1).PosY = 40 Vert(1).PosZ = 0.5 Vert(1).RHW = 1 Vert(1).Color = &HFF00& Vert(2).PosX = 40 Vert(2).PosY = 250 Vert(2).PosZ = 0.9 Vert(2).RHW = 1 Vert(2).Color = &HFF0000 D3DVertexBuffer8SetData vBuffer, vSize * 3, vSize * 3, 0, Vert(0) End Sub
Первый треугольник получается серого цвета, а второй – разноцветный, как в предыдущем проекте. Изменим в обработке события MouseMove в функции D3DVertexBuffer8SetData значение Offset с 0 на vSize * 3 – адрес первой вершины второго треугольника, а в процедуре Render в методе DrawPrimitive увеличим счетчик треугольников до двух.
Теперь рисуется два треугольника, причем второй всегда закрывает собой первый. Это не меняется, как бы мы не меняли значение PosZ для вершин треугольников.
Почему так происходит? Неужели для корректной отрисовки всегда нужно упорядочивать треугольники? А если треугольники пересекаются – тут уже не поможет никакое упорядочивание.
Вспомним, что вывод графики сначала происходит в BackBuffer, а он двумерный, в нем нет места третьему измерению. Для того, чтобы обойти это ограничение, создан ZBuffer – такой же, как и BackBuffer двумерный участок памяти, в который при рисовании записывается не цвет точки, а расстояние до нее.
Определение
ZBuffer – двумерный участок памяти, по размерам равный BackBuffer, в который при рисовании записывается не цвет точки, а расстояние до нее.
Как это может помочь? При выводе следующей точки вычисляется расстояние до нее и сравнивается с расстоянием, записанным в ZBuffer, если оно больше – точка не рисуется.
Приступим к созданию ZBuffer. В процедуру D3DInit до создания d3dDevice добавим две строки:
d3dpp.EnableAutoDepthStencil = True d3dpp.AutoDepthStencilFormat = D3DFMT_D16
Первая указывает, что d3dDevice создается с ZBuffer, вторая устанавливает формат ZBuffer.
После создания d3dDevice добавляется еще одна строка:
d3dDevice.SetRenderState D3DRS_ZENABLE, D3DZB_TRUE
Здесь мы «включаем» ZBuffer.
Запускаем программу и смотрим результат. Видим искаженное изображение двух треугольников. При перемещении искажения усиливаются. В чем дело? А дело в том, что ZBuffer запоминает свое состояние с предыдущего кадра. После того, как была отрисована какая-то точка, более далекая точка на этой позиции уже не может быть отображена не только в текущем кадре, но и в следующих. Чтобы от этого избавиться, ZBuffer необходимо очищать перед каждым кадром так же, как мы очищаем BackBuffer.
Добавляем в процедуре Render флаг очистки ZBuffer:
d3dDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &H346666, 1, 0
Теперь все отображается корректно. Убедитесь в этом, удаляя и приближая вершины треугольников (меняя значение PosZ).
комментарии отсутствуют
авторизуйтесь