2012-04-22 1 views
17

Итак, у меня есть самозванец (реальная геометрия - это куб, возможно, обрезанный, а геометрия импостера - губка Менгера), и мне нужно рассчитать его глубину.GLSL gl_FragCoord.z ​​Расчет и настройка gl_FragDepth

Я могу рассчитать сумму, которую нужно компенсировать в мировом пространстве довольно легко. К сожалению, я потратил несколько часов, чтобы не беспокоить его глубину.

Только правильные результаты я могу получить то, когда я иду:

gl_FragDepth = gl_FragCoord.z 

В принципе, мне нужно знать, как gl_FragCoord.z ​​рассчитывается так, что я могу:

  • Возьмите обратное преобразование от gl_FragCoord.z ​​до глазного пространства
  • Добавить возмущение глубины
  • Преобразуйте эту возмущенную глубину обратно в то же пространство, что и исходное gl_FragCoord.z.

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

+0

Вы также написали вершинный шейдер? или только фрагментарный шейдер? –

+2

Я не дам вам код по общему принципу, но я могу дать вам [эту ссылку на OpenGL Wiki] (http://www.opengl.org/wiki/Compute_eye_space_from_window_space). Как и эта ссылка на мой учебник по [самозванцам и глубине, который показывает, как это сделать)] (http://www.arcsynthesis.org/gltut/Illumination/Tut13%20Deceit%20in%20Depth.html). Преобразование глубины назад тривиально. –

+0

Майкл: Да, но это всего лишь проход через шейдер.Как это происходит, вычисления выполняются в мировом пространстве, поэтому я могу рассчитать пространство глаз в программе фрагментов. Николь, я уже видел эту страницу. Я реализую его как: vec4 clip_pos = gl_ProjectionMatrix * vec4 (eye_pos, 1.0); float ndc_depth = clip_pos.z/clip_pos.w; gl_FragDepth = (((clip_far-clip_near) * ndc_depth) + clip_near + clip_far)/2.0; К сожалению, глубина, по-видимому, выпадает за пределы глубины, хотя смещения нет. Спасибо, – imallett

ответ

28

Для дальнейшего использования, ключевой код:

float far=gl_DepthRange.far; float near=gl_DepthRange.near; 

vec4 eye_space_pos = gl_ModelViewMatrix * /*something*/ 
vec4 clip_space_pos = gl_ProjectionMatrix * eye_space_pos; 

float ndc_depth = clip_space_pos.z/clip_space_pos.w; 

float depth = (((far-near) * ndc_depth) + near + far)/2.0; 
gl_FragDepth = depth; 
+0

Не должно быть «gl_DepthRange.far» и «gl_DepthRange.near;» заменить на ближний и дальний диапазоны проекционной матрицы вместо значений плоскости клипа? – Tara

+0

Совсем нет. gl_DepthRange - это не то же самое, что значения ближней и дальней плоскости, используемые для вычисления проекционной матрицы. Я мог бы не понимать вашу точку зрения. – Tara

+0

@ Dudeson Планы клипов просто определяют через матрицу проекции, какие значения будут отображаться вне NDC (и, следовательно, будут обрезаны аппаратным обеспечением). Мы полностью справились с ними после того, как указана матрица проекции. Между тем, 'gl_DepthRange. (Ne | f) ar' - это диапазон буфера глубины и необходим для преобразования из NDC в буфер глубины. HTH – imallett

4

Для другого в будущем, это та же формула, что дает imallett, который работал для меня в приложении OpenGL 4.0:

vec4 v_clip_coord = modelview_projection * vec4(v_position, 1.0); 
float f_ndc_depth = v_clip_coord.z/v_clip_coord.w; 
gl_FragDepth = (1.0 - 0.0) * 0.5 * f_ndc_depth + (1.0 + 0.0) * 0.5; 

Здесь modelview_projection представляет собой матрицу с разрешением модели 4x4, а v_position - это положение пространства-объекта отображаемого пикселя (в моем случае вычисляется raymarcher).

Уравнение относится к разделу window coordinates раздела this manual. Обратите внимание, что в моем коде около 0.0 и далеко 1.0, которые являются значениями по умолчанию gl_DepthRange. Обратите внимание, что gl_DepthRange является не то же самое, что и ближнее/дальнее расстояние в формуле для perspective projection matrix! Единственный трюк - использовать 0.0 и 1.0 (или gl_DepthRange, если вам действительно нужно его изменить), я боролся в течение часа с другим диапазоном глубины - но это уже «испечено» в моей (перспективной) матрице проекций ,

Обратите внимание, что в этом случае уравнение действительно содержит только одно умножение на константу ((far - near)/2) и одно добавление другой константы ((far + near)/2). Сравните это, чтобы умножить, добавить и разделить (возможно, преобразовать в умножение с помощью оптимизирующего компилятора), который требуется в коде imallett.

Смежные вопросы