Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Подсказки / Равномерное распределение глубины в z буфере.

Равномерное распределение глубины в z буфере.

Автор:

Как известно, при применении обычной перспективной матрицы проекций мы получаем следующие выражения для экранных координат...

(экранные координаты указаны с суффиксом s, координаты в view space указаны с суффиксом v)

Xs =  2*Xv*Znear/Zv/ScreenWidth              (1)
Ys =  2*Yv*Znear/Zv/ScreenHeight              (2)
Zs =  (Zv–Znear)*Zfar/Zv/(Zfar–Znear)        (3)

где ScreenWidth и ScreenHeight — размеры плоскости, на которую происходит проекция в мировых координатах. В формулах уже учтено деление всех компонент вектора на червертую (W)

Из формулы (3) видно, что преобразование z нелинейно. Это может приводить к неприятным последстиям (о них ниже). Для того, чтобы преобразование было линейным, было бы разумно применить следующую формулу для z:

Zs =  (Zv–Znear)/(Zfar–Znear)                      (4)

В этом случае мы получим равномерное распределение глубины. При этом соглашения о величинах z не нарушаются:

    -все так же ближней плоскости отсечения соответствует Zs=0 , а дальней — Zs=1,
    -все так же значение Zs для более близких к экрану точек меньше, чем для более далеких.

Вот так примерно это можно реализовать в шейдере (используя (1),(2),(4)):

matrix WorldView;
float Zfar;
float Znear;
float ScreenWidth;
float ScreemHeight;

float4 VertexShader (float4 inPos : POSITION)    :POSITION
{
  float4 vec;
  vec=mul(inPos,WorldView);
  vec=float4(vec.x/vec.z*Znear/ScreenWidth,vec.y/vec.z*Znear/ScreenHeight,(vec.z-Znear)/(Zfar-Znear),vec.w);  
  return vec;
}

Плюсы этой методики:

    +Потенциально код из предложенного шейдера может работать быстрее, чем еще одно перемножение матриц.
    +В шейдер нужно пересылать немного меньше данных (на 12 float меньше каждый DIP)
    +При применении этой методики можно спокойно обходиться буферами глубины меньшего размера для обеспечения той же точности.
    +Восстановление координаты z из буфера проще, быстрее и точнее, чем при использовании матрицы проекций. Это может быть полезно при использовании техник shadow map и Deferred Shading (Отложенное освещение).
    +Самое главное: решена проблема, в которой 90% сцены занимает 10% буфера глубины. Это помогает избежать необходимости слишком сильно отдалять ближнюю плоскость отсечения в случаях, когда надо выводить на экран огромные пространства, для получения приемлемой точности во избежание z-fighting.

Минусы этой методики:

    –Подобное преобразование невозможно выполнить при помощи умножения вектора на матрицу.
    –Как следствие из предыдущего: методику нельзя применять при использовании ffp (fixed function pipeline).

10 ноября 2009

#буферы, #z-fighting, #глубина


Обновление: 11 ноября 2009

Военная ипотека вариант от сбербанка www.molodostroy24.ru. , Auto автосигнализации www.abcproffi.ru.
2001—2017 © GameDev.ru — Разработка игр