В рамках отложенного затенения я использую разные объекты кадрового буфера для выполнения различных проходов рендеринга. В первом проходе я записываю DEPTH_STENCIL_ATTACHMENT
для всей сцены в текстуру, назовем ее DepthStencilTexture
. Чтобы получить доступ к информации о глубине, хранящейся в DepthStencilTexture
, из разных проходов рендеринга, для которых я использую разные объекты кадрового буфера, я знаю два способа:
1) я привязываю DepthStencilTexture
к шейдеру и получаю доступ к нему во фрагментном шейдере, где я глубина вручную, вот так
uniform vec2 WinSize; //windows dimensions
vec2 uv=gl_FragCoord.st/WinSize;
float depth=texture(DepthStencilTexture ,uv).r;
if(gl_FragCoord.z>depth) discard;
Я также установил glDisable(GL_DEPTH_TEST)
и glDepthMask(GL_FALSE)
2) Я привязываю DepthStencilTexture
к объекту фреймбуфера как DEPTH_STENCIL_ATTACHMENT
и устанавливаю glEnable(GL_DEPTH_TEST)
и glDepthMask(GL_FALSE)
(редактировать: в этом случае я не буду привязывать DepthStencilTexture
к шейдеру, чтобы избежать циклической обратной связи, см. ответ Никола Боласа, и я, если я нужна глубина во фрагментном шейдере буду использовать gl_FragCorrd.z
)
В определенных ситуациях, таких как рисование легких объемов, для которых мне нужен тест трафарета и запись в буфер трафарета, я выбираю решение 2). В других ситуациях, когда я полностью игнорирую трафарет и просто нуждаюсь в глубине, сохраненной в DepthStencilTexture
, дает ли вариант 1) какие-либо преимущества по сравнению с более «естественным» вариантом 2)?
Например, у меня есть (глупые, я думаю) сомнения по этому поводу. Иногда в моих фрагментных шейдерах я вычисляю WorldPosition из глубины. В случае 1) было бы так
uniform mat4 invPV; //inverse PV matrix
vec2 uv=gl_FragCoord.st/WinSize;
vec4 WorldPosition=invPV*vec4(uv, texture(DepthStencilTexture ,uv).r ,1.0f );
WorldPosition=WorldPosition/WorldPosition.w;
В случае 2) это будет так (редактировать: это неправильно, gl_FragCoord.z - это текущая глубина фрагмента, а не фактическая глубина, хранящаяся в текстуре)
uniform mat4 invPV; //inverse PV matrix
vec2 uv=gl_FragCoord.st/WinSize;
vec4 WorldPosition=invPV*vec4(uv, gl_FragCoord.z, 1.0f );
WorldPosition=WorldPosition/WorldPosition.w;
Я предполагаю, что gl_FragCoord.z
в случае 2) будет таким же, как texture(DepthStencilTexture ,uv).r
в случае 1), или, другими словами, глубина, хранящаяся в DepthStencilTexture
. Это правда? Читается ли gl_FragCoord.z
из текущего связанного DEPTH_STENCIL_ATTACHMENT
также с glDisable(GL_DEPTH_TEST)
и glDepthMask(GL_FALSE)
?