Нарисуйте значение глубины в OpenGL с помощью шейдеров - PullRequest
16 голосов
/ 20 июня 2011

Я хочу нарисовать буфер глубины во фрагментном шейдере, я делаю это:

Вершинный шейдер:

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);

Но я печатаю только белое, что я делаю не так?

Ответы [ 2 ]

22 голосов
/ 20 июня 2011

В каком пространстве вы хотите нарисовать глубину?Если вы хотите нарисовать глубину пространства окна, вы можете сделать это:

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); 
12 голосов
/ 12 июля 2013

Действительно, значение «глубины» фрагмента можно прочитать из его значения z в пространстве клипа (то есть после всех преобразований матрицы). Это правильно.

Однако ваша проблема в делении на w. Деление на w называется перспективным делением . Да, необходимо, чтобы перспективная проекция работала правильно.

1012 * Однако *. Деление на w в этом случае «объединяет» все ваши значения (как вы видели), чтобы быть очень близким к 1,0. Для этого есть веская причина: в перспективной проекции , w= (some multiplier) *z. Таким образом, вы делите значение z (каким бы оно ни было вычисленным) на (некоторый фактор) исходного z. Не удивительно, что вы всегда получаете значения около 1,0. Вы почти делите z на себя.

В качестве очень простого исправления для этого попробуйте разделить z только на дальний план и отправить его фрагментному шейдеру как глубина .

Вершинный шейдер

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

...