Поиск текстуры в визуализированном FBO выключен на половину пикселя - PullRequest
5 голосов
/ 16 января 2012

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

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

Вот как я даю фрагментному шейдеру координаты для автоматической текстурирования геометрии с помощью моей полноэкранной текстуры:

// Vertex shader
uniform mat4 proj_modelview_mat;
out vec2 f_sceneCoord;
void main(void) {
    gl_Position = proj_modelview_mat * vec4(in_pos,0.0,1.0);
    f_sceneCoord = (gl_Position.xy + vec2(1,1)) * 0.5;
}

Я работаю в 2D, поэтому я не беспокоился о себес точки зрения разделения здесь.Я просто установил значение sceneCoord, используя позицию пространства клипа, уменьшенную с [-1,1] до [0,1].

uniform sampler2D scene;
in vec2 f_sceneCoord;
//in vec4 gl_FragCoord;
in float f_alpha;   
out vec4 out_fragColor;
void main (void) {
    //vec4 color = texelFetch(scene,ivec2(gl_FragCoord.xy - vec2(0.5,0.5)),0);
    vec4 color = texture(scene,f_sceneCoord);
    if (color.a == f_alpha) {
        out_fragColor = vec4(color.rgb,1);
    } else
        out_fragColor = vec4(1,0,0,1);
}

Обратите внимание, что я выплевываю красный фрагмент, если моя альфа не совпадает.Текстурный рендеринг устанавливает альфа для каждого визуализируемого объекта на определенный индекс, поэтому я знаю, что совпадает с чем.

Извините, у меня нет изображения для показа, но очень ясно, что мои пиксели отключены на (0.5,0.5): я получаю тонкую красную границу в один пиксель вокруг моих объектов, на их нижней и левой сторонах,это появляется и выходит.Это довольно "переходный" вид.Недостатком является то, что он появляется только на нижней и левой сторонах объектов.

Обратите внимание, у меня есть закомментированная строка, в которой используется texelFetch: этот метод работает, и у меня больше не отображаются красные фрагменты.Однако я бы хотел, чтобы это работало правильно с texture и нормализованными текстурными координатами, потому что я думаю, что большее количество оборудования будет поддерживать это.Возможно, реальный вопрос в том, возможно ли получить это право, не посылая в моем окне просмотра разрешение через униформу?Должен быть способ избежать этого!

Обновление: я пытался сместить доступ к текстуре на полпикселя, четверть пикселя, одну сотую пикселя, все это ухудшало и создавало сплошную границунеправильные значения по краям: похоже, мой трюк gl_Position.xy+vec2(1,1))*0.5 устанавливает правильные значения, но сэмплирование просто немного отключено.Это довольно странно ... Видите красные фрагменты?Когда объекты находятся в движении, они слегка переливаются внутрь и наружу.Это означает, что альфа-значения, которые я установил, не совпадают идеально на этих пикселях.

transient red fragments indicate a texture sampling mis-match

Для меня не критично получить точную пиксельную точность для этой альфа-проверки индекса для моего реального приложения, но это поведение совсем не то, что я ожидал.

Ответы [ 2 ]

4 голосов
/ 16 января 2012

Ну, во-первых, рассмотрите возможность отбрасывания этого f_sceneCoord, изменяющегося и просто используя gl_FragCoord / screenSize в качестве координаты текстуры (у вас это уже есть в вашем примере, но -0.5 - мусор), с screenSize - униформой (возможно, предварительно-divided).Это должно работать почти точно, потому что по умолчанию gl_FragCoord находится в центре пикселя (то есть i+0.5), и OpenGL возвращает точные значения текселя при выборке текстуры в центре текселя ((i+0.5)/textureSize).

Этоможет все еще вводить очень очень очень небольшие отклонения от точных значений текселей (если они есть) из-за конечной точности и тому подобное.Но с другой стороны, вы, вероятно, захотите использовать режим фильтрации GL_NEAREST для таких однозначных отображений текстуры на экран.На самом деле ваш существующий подход f_sceneCoord может уже работать хорошо, и только те небольшие проблемы округления, предотвращенные GL_NEAREST, создают ваши артефакты.Но опять же, вам все еще не нужна эта f_sceneCoord вещь.

РЕДАКТИРОВАТЬ: Относительно переносимости texelFetch.Эта функция была введена с GLSL 1.30 (аппаратное обеспечение SM4 / GL3 / DX10, GeForce 8), я думаю.Но эта версия уже требуется новым синтаксисом in/out, который вы используете (в отличие от старого синтаксиса varying/attribute).Поэтому, если вы не собираетесь их менять, предполагая, что texelFetch как указано, абсолютно не проблема и может также быть немного быстрее, чем texture (который также требует GLSL 1.30, в отличие от старого texture2D), обходя фильтрациюполностью.

1 голос
/ 09 июля 2012

Если вы работаете в идеальном X, Y [0,1] без ошибок округления, это здорово ... Но иногда - особенно если вы работаете с полярными координатами, вы можете подумать о выравнивании вычисленных координат с текстурой «сетка». ..

Я использую:

// align it to the nearest centered texel
curPt -= mod(curPt, (0.5 / vec2(imgW, imgH)));

работает как шарм, и я больше не получаю случайные ошибки округления по краям экрана ...

...