Как получить доступ к значениям буфера глубины вне контекста WebGL?

Учитывая сцену WebGL (созданную из THREE.js), как бы вы поступили для доступа к значениям с плавающей запятой (как массиву данных вне контекста WebGL) из DEPTH_ATTACHMENT, учитывая, что буфер кадра был привязан к текстуре с помощью framebufferTexture2D.

На данный момент я собрал одно решение, которое заключается в визуализации сцены в целевой текстуре с использованием пользовательского переопределения шейдера, который обращается к информации о глубине текстуры и затем кодирует ее в формат RGB. Используемый код очень похож на этот пример THREE.js, найденный здесь: Глубина-Текстура-Пример.

#include <packing>

varying vec2 vUv;
uniform sampler2D tDiffuse;
uniform sampler2D tDepth;
uniform float cameraNear;
uniform float cameraFar;

float readDepth (sampler2D depthSampler, vec2 coord) {
    float fragCoordZ = texture2D(depthSampler, coord).x;
    float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );
    return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
}

void main() {
    vec3 diffuse = texture2D(tDiffuse, vUv).rgb;
    float depth = readDepth(tDepth, vUv);
    gl_FragColor.rgb = vec3(depth);
    gl_FragColor.a = 1.0;
}

После рендеринга я могу использовать readPixels для считывания конкретных пикселей в массив. Однако этот параметр имеет невероятно низкую точность, ограниченную 256 дискретными значениями, заданными vec3(float) = vec3(float, float, float). Есть ли способ получить более высокую точность с помощью этого конкретного метода или альтернативы?

В конечном итоге мне нужен эффективный доступ к буферу глубины как к массиву значений с плавающей запятой вне контекста WebGL. У меня есть собственный растеризатор, который может создать довольно хороший буфер глубины, но я не хочу тратить время на повторение уже выполненных шагов.


person Andy    schedule 22.12.2017    source источник


Ответы (1)


Одна из возможностей заключается в кодировании 24 значащих битов 32-битного значения с плавающей запятой IEEE 754 в а vec3:

vec3 PackDepth(float depth)
{
    float depthVal = depth * (256.0*256.0*256.0 - 1.0) / (256.0*256.0*256.0);
    vec4 encode    = fract(depthVal * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0));
    return encode.xyz - encode.yzw / 256.0 + 1.0/512.0;
}

Цветовые каналы R, G и B можно декодировать с глубиной в диапазоне [0,0, 1,0] следующим образом:

depth = (R*256.0*256.0 + G*256.0 + B) / (256.0*256.0*256.0 - 1.0);
person Rabbid76    schedule 22.12.2017