Введите значение глубины в opengl с помощью шейдеров
Я хочу нарисовать буфер глубины в шейдере фрагментов, я делаю это:
Vertex shader:
varying vec4 position_;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
position_ = gl_ModelViewProjectionMatrix * gl_Vertex;
Фрагментный шейдер:
float depth = ((position_.z / position_.w) + 1.0) * 0.5;
gl_FragColor = vec4(depth, depth, depth, 1.0);
Но все, что я печатаю, белый, что я делаю неправильно?
Ответы
Ответ 1
В каком пространстве вы хотите нарисовать глубину? Если вы хотите нарисовать глубину оконного пространства, вы можете сделать это:
gl_FragColor = vec4(gl_FragCoord.z);
Однако это не будет особенно полезно, так как большая часть чисел будет очень близка к 1.0. Будут видны только очень близкие объекты. Это характер распределения значений глубины для буфера глубины с использованием стандартной проекции перспективы.
Или, другими словами, почему вы становитесь белыми.
Если вам нужны эти значения в линейном пространстве, вам нужно будет сделать что-то вроде следующего:
float ndcDepth = ndcPos.z =
(2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
(gl_DepthRange.far - gl_DepthRange.near);
float clipDepth = ndcDepth / gl_FragCoord.w;
gl_FragColor = vec4((clipDepth * 0.5) + 0.5);
Ответ 2
В самом деле, значение "глубины" фрагмента можно считать из него значением z в пространстве клипов (т.е. после всех преобразований матрицы). Это верно.
Однако ваша проблема заключается в делении на w
.
Подраздел w
называется перспективным делением. Да, для правильной работы проекции необходимо правильно работать.
Однако. Подраздел w
в этом случае "объединяет" все ваши значения (как вы видели), чтобы быть очень близок к 1.0. Для этого есть веская причина: в перспективе , w= (some multiplier) *z
. То есть вы делите значение z (независимо от того, что оно было вычислено) с помощью (некоторого коэффициента) оригинала z. Неудивительно, что вы всегда получаете значения около 1.0. Вы почти делите z на себя.
Как очень простое решение для этого, попробуйте делить z
просто на farPlane и отправить его в шейдер фрагмента как глубину.
Vertex shader
varying float DEPTH ;
uniform float FARPLANE ; // send this in as a uniform to the shader
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
DEPTH = gl_Position.z / FARPLANE ; // do not divide by w
Фрагментный шейдер:
varying float DEPTH ;
// far things appear white, near things black
gl_Color.rgb=vec3(DEPTH,DEPTH,DEPTH) ;
Результат - неплохое, очень линейное искажение.
![enter image description here]()