DirectX Графика в проектах Delphi

       

Соприкасающиеся поверхности



Обращаю ваше внимание еще на одну проблему, с которой вы можете столкнуться. Наверняка в ваших построениях рано или поздно потребуется использовать соприкасающиеся поверхности, и здесь вы можете обнаружить, что на таких поверхностях появляется паразитный узор.
Посмотрим на данный эффект, запустив проект из каталога Ех08, где рисуются две частично перекрывающиеся разноцветные площадки. В местах их соприкосновения возникает картинка, которую мы не рисовали (рис. 10.6).

Рис. 10.6. Соприкасающиеся поверхности порождают нежелательные узоры

Связано появление таких узоров с использованием буфера глубины. При его заполнении одинаковыми значениями из-за погрешностей некоторые участки примитивов выводятся перепутанными. Проявляется эффект только после смены матрицы трансформаций, как в этом примере:

procedure TfrmD3D.DrawScene;
var
matRotateY, matTranslate : TD3DMatrix;
begin
// Сдвиг и поворот первого квадрата
SetTranslateMatrix (matTranslate, -0.5, -0.5, 0);
SetRotateYMatrix(matRotateY, Angle);
with FD3DDevice do begin
SetTransform(D3DTS WORLD, MatrixMul(matRotateY, matTranslate);;
SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
SetMaterial(MaterialRed);
DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // Сдвиг второго квадрата
SetTranslateMatrix (matTransiate, -0.4, -0.4, 0);
SetTransform(D3DTS_WORLD, MatrixMul(matRotateY, matTransiate) SetMaterial(MaterialBlue);
DrawPrimitive (D3DPT_TRIA1-IGLESTRIP, 0, 2) ;
end;
end;

Если второй квадрат воспроизводить сразу же после первого, т. е. перед его воспроизведением не изменять матрицу трансформаций, ошибок возникать не будет. В таких случаях примитив, нарисованный последним, перекроет предыдущий без проступающих узоров.
Решение проблемы состоит в том, чтобы на время воспроизведения соприкасающихся поверхностей запретить работу с буфером глубины. Так и делается в проекте из каталога Ех09, где рисуется аналогичная сцена, но во время воспроизведения второго квадрата работа с Z-буфером приостанавливается:

SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
SetRenderState(D3DRS_ZENABLE, D3DZBJTRUE);

Конечно, в этом конкретном примере можно и не включать буфер глубины вообще, но если на сцене присутствует множество объектов, то без использования Z-буфера положения их будут передаваться неправильно. Поэтому обычно такое действие выполняют только на время воспроизведения одного из примитивов, имеющих большие участки одинаковой координаты.



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