Переделаем предыдущий проект для отображения двух треугольников. Для этого в InitGeometry добавим еще три вершины:

код на языке vb
 
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 добавим две строки:

код на языке vb
 
  d3dpp.EnableAutoDepthStencil = True
  d3dpp.AutoDepthStencilFormat = D3DFMT_D16
 

Первая указывает, что d3dDevice создается с ZBuffer, вторая устанавливает формат ZBuffer.
После создания d3dDevice добавляется еще одна строка:

код на языке vb
 
  d3dDevice.SetRenderState D3DRS_ZENABLE, D3DZB_TRUE
 

Здесь мы «включаем» ZBuffer.
Запускаем программу и смотрим результат. Видим искаженное изображение двух треугольников. При перемещении искажения усиливаются. В чем дело? А дело в том, что ZBuffer запоминает свое состояние с предыдущего кадра. После того, как была отрисована какая-то точка, более далекая точка на этой позиции уже не может быть отображена не только в текущем кадре, но и в следующих. Чтобы от этого избавиться, ZBuffer необходимо очищать перед каждым кадром так же, как мы очищаем BackBuffer.
Добавляем в процедуре Render флаг очистки ZBuffer:

код на языке vb
 
  d3dDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, &H346666, 1, 0
 

Теперь все отображается корректно. Убедитесь в этом, удаляя и приближая вершины треугольников (меняя значение PosZ).