Программирование графических процессоров с использованием Direct3D и HLSL


Буфер глубины


Если теперь мы попытаемся выводить объекты сцены, то они будут рисоваться в том порядке, в котором воспроизводятся. При этом нарисованные позже примитивы будут "лежать" поверх ранее выведенных. Для адекватной визуализации трехмерных объектов в графических библиотеках предусмотрен так называемый буфер глубины или z-буфер, который представляет собой двумерный массив, хранящий для каждого растеризуемого пикселя значение координаты z. Рассмотрим принцип работы буфера глубины на примере левосторонней системы координат. В начале в z-буфер заносятся (очищается) максимально возможные значения z, а буфер регенерации заполняется значениями пикселей, соответствующими фону. Затем каждая грань объекта преобразуется в растровую форму, причем порядок растеризации грани не играет особой роли. При разложении многоугольника в растр для каждой его точки выполняются следующие шаги:

  1. Вычисление глубины (z-координаты) в точке (x,y);
  2. Если z(x,y) меньше чем значение в z-буфере в позиции (x,y) то в z-буфер заносится значение z-координаты растеризуемой точки, а в буфер регенерации помещается обрабатываемый пиксель.

Если выполняется условие шага 2, это означает, что точка многоугольника расположена ближе к наблюдателю, чем точка, значение яркости которой находится в данный момент в позиции (x,y) буфера регенерации.


Единственный недостаток рассмотренного алгоритма – необходимость дополнительной памяти для хранения z-буфера, однако простая и эффективная реализация позволяет использовать этот алгоритм во многих приложениях. Для инициализации буфера глубины в библиотеке Direct3D достаточно заполнить два поля структуры D3DPRESENT_PARAMETERS:

C++D3DPRESENT_PARAMETERS params; … ZeroMemory( &params, sizeof(params) ); … params.EnableAutoDepthStencil = true; params.AutoDepthStencilFormat = D3DFMT_D16; …
Pascal

var params: TD3DPresentParameters; … ZeroMemory( @params, SizeOf(params) ); … params.EnableAutoDepthStencil := true; params.AutoDepthStencilFormat := D3DFMT_D16; …

Программист может не беспокоиться о линейных размерах буфера глубины, т.к.
система автоматически определяет размеры. Для работы с буфером глубины необходимо также установить константу режима D3DRS_ZENABLE в значение "истина".

C++device->SetRenderState (D3DRS_ZENABLE, D3DZB_TRUE);
Pascaldevice.SetRenderState(D3DRS_ZENABLE, 1);
Чтобы отключить z-буфер, нужно установить данную константу D3DRS_ZENABLE в значение "ложь".

C++device->SetRenderState (D3DRS_ZENABLE, D3DZB_FALSE);
Pascaldevice.SetRenderState(D3DRS_ZENABLE, 0);
Теперь в процессе вывода примитивов на экран, при каждом обновлении буфера кадра, необходимо производить очистку, как буфера кадра, так и буфера глубины. Это производится с помощью вызова метода Clear интерфейса IDirect3DDevice9.

C++

device->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );
Pascal

device.Clear( 0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255,255,255), 1.0, 0 );
Предпоследний параметр метода Clear задает значение, которым будем заполнен буфер глубины при очистке. Значение единица соответствует бесконечно удаленной точке трехмерного пространства; значение ноль – определяет самую близкую точку.


Содержание раздела