Рендеринг Z-буфера в текстуру в WebGL

Когда я создаю текстуру z-буфера следующим образом:

gl.bindTexture(GL_TEXTURE_2D, texBuff);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl.texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, frameBuff.width, frameBuff.height,    0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, null);

Я получаю правильный z-буфер, который затем могу использовать для теней (и мои тени хорошо отображаются). Однако, если я создаю цветную текстуру и раскрашиваю текстуру с помощью z-значения, в моих тенях появляется много артефактов (даже при большом смещении). Цветовой буфер создается следующим образом:

gl.bindTexture(GL_TEXTURE_2D, colorBuff);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frameBuff.width, frameBuff.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);

Это программа фрагментного шейдера, которая записывает в цветовой буфер:

precision highp float;
void main() {
    float z = gl_FragCoord.z;
    gl_FragColor = vec4(z, z, z, 1.0); 
}

Когда я визуализирую две текстуры на какую-либо поверхность, они выглядят одинаково.

Итак, мой вопрос: почему моя цветовая текстура не работает? Является ли gl_FragCoord.z ​​неверным значением z, записанным в z-буфер? Согласно http://www.opengl.org/sdk/docs/manglsl/xhtml/gl_FragCoord.xml да. Координация текстуры отличается, когда я привязываю цветовой буфер? Или значение z неверно?


person spearmunkie    schedule 15.10.2013    source источник


Ответы (1)


Этот вопрос занял у меня много времени, чтобы разобрать :) Надеюсь, я получил правильный ответ:

Это просто точность. Текстура компонента глубины имеет как минимум 16 бит для значения z. В цвете у вас есть только 8 бит на канал. Вместо того, чтобы записывать одно и то же z в rgb, вы можете написать что-то вроде (z,frac(z*256.0),frac(z*256.0*256.0)) для записи полных 24 бит. Это будет выглядеть странно, но вы можете расшифровать его с помощью dp3 (1,1/256,1/(256*256)), если прочитаете его обратно.

Кстати, основная причина, по которой ваш вопрос было трудно прочитать, заключалась в том, что я никогда не читал fragCoord, чтобы получить z. Я всегда просто использовал координату текстуры, чтобы получить текстуру z. Это дает вам немного больше контроля над тем, как вы генерируете и интерполируете z из вершинного шейдера.

person starmole    schedule 15.10.2013
comment
Вы правы, это была проблема точности. Я пытался использовать цветовую текстуру, чтобы получить полную 32-битную точность значения глубины. По какой-то причине ваше решение создает больше артефактов, и я не могу от них избавиться. Он также создает тени случайным образом. Я думаю, что openGL делает некоторые дополнительные оптимизации. - person spearmunkie; 15.10.2013