Как избежать кровотечения текстуры в атласе текстуры?

В моей игре есть ландшафт Minecraft, сделанный из кубов. Я генерирую буфер вершин из данных воксела и использую текстурный атлас для поиска разных блоков:

текстурный атлас для местности, основанной на вокселе

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

43 голоса | спросил danijar 7 Jpm1000000pmMon, 07 Jan 2013 20:30:47 +040013 2013, 20:30:47

5 ответов


5

После многого с этой проблемой я наконец придумал решение.

Чтобы использовать как атлас текстуры, так и mipmapping, мне нужно выполнить downsampling самостоятельно, потому что OpenGL иначе интерполирует границы границ в атласе. Кроме того, мне нужно было установить правильные параметры текстуры, поскольку интерполирование между mipmaps также приведет к кровотечению текстуры.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

С этими параметрами не происходит кровотечения.

Есть одна вещь, которую вы должны заметить при предоставлении пользовательских mipmaps. Так как не имеет смысла сжимать атлас, даже если каждый фрагмент уже 1x1, максимальный уровень mipmap должен быть установлен в соответствии с тем, что вы предоставляете.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7); // pick mipmap level 7 or lower

Спасибо за все остальные ответы и очень полезные комментарии! Кстати, я до сих пор не знаю, как использовать линейное масштабирование, но я думаю, что нет способа.

ответил danijar 10 MarpmSun, 10 Mar 2013 19:53:11 +04002013-03-10T19:53:11+04:0007 2013, 19:53:11
30

Хорошо, думаю, у вас здесь две проблемы.

Первая проблема заключается в mipmapping. В общем, вы не хотите наивно смешивать atlasing с mipmapping, потому что, если все ваши субтекстуры не будут точно размером 1x1 пиксель, вы испытаете кровотечение из текстуры. Добавление дополнения просто переместит проблему на более низкий уровень mip.

Как правило, для 2D, где вы обычно делаете атаку, вы не mipmap; в то время как для 3D, где вы mipmap, вы не атлас (на самом деле, вы так кожу, что кровотечение не будет проблемой)

Однако, я думаю, что сейчас происходит с вашей программой, так это то, что вы, вероятно, не используете правильные координаты текстуры, и из-за этого ваши текстуры кровоточат.

Предположим, что текстура 8x8. Вероятно, вы получаете верхнюю левую четверть, используя uv-координаты (0,0) - (0,5, 0,5):

Неверное сопоставление

И проблема в том, что в u-координате 0.5 сэмплер будет интерполировать фрагмент адресата, используя половину левого текселя и половину правого текселя. То же самое произойдет и при u-координате 0, и то же самое для v-координат. Это происходит потому, что вы обращаетесь к границам между текселями, а не центрами.

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

Корректное сопоставление

В этом случае вы всегда будете отбирать центр каждого текселя, и вы не должны получать кровотечение ... Если вы не используете mipmapping, в этом случае у вас всегда будет кровотечение, начиная с уровня mip, где масштабированный подтекст не аккуратно вписывается в сетку пикселей .

Чтобы обобщить, если вы хотите получить доступ к определенному текселю, координаты вычисляются как:

function get_texel_coords(x, y, tex_width, tex_height)
    u = (x + 0.5) / tex_width
    v = (y + 0.5) / tex_height
    return u, v
end

Это называется «коррекция половинного пикселя». Ниже приведено более подробное объяснение в здесь , если вы заинтересованы.

ответил Panda Pajama 18 FebruaryEurope/MoscowbMon, 18 Feb 2013 14:44:50 +0400000000pmMon, 18 Feb 2013 14:44:50 +040013 2013, 14:44:50
18

Один из вариантов, который будет намного проще, чем использование mipmaps и добавление текстурных координатных факторов fuzz, - использовать массив текстур. Массивы текстур похожи на 3D-текстуры, но без mipmapping в 3-м измерении, поэтому они идеально подходят для текстурных атласов, где «подтекстуры» имеют одинаковый размер.

http://www.opengl.org/wiki/Array_Texture

ответил ccxvii 7 Jpm1000000pmMon, 07 Jan 2013 20:48:54 +040013 2013, 20:48:54
4

Похоже, что проблема может быть вызвана MSAA. См. этот ответ и связанная статья :

  

", когда вы включаете MSAA, тогда становится возможным, чтобы шейдер получал   выполняется для выборок, которые находятся внутри области пикселя, но вне   область треугольника "

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

ответил msell 18 FebruaryEurope/MoscowbMon, 18 Feb 2013 14:42:11 +0400000000pmMon, 18 Feb 2013 14:42:11 +040013 2013, 14:42:11
1

Это старая тема, и у меня была аналогичная проблема с темой.

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

public static void tween(Camera cam, Direction dir, Vec2 buffer, Vec2 start, Vec2 end) {
    if(step > steps) {
        tweening = false;
        return;
    }

    final float alpha = step/steps;

    switch(dir) {
    case UP:
    case DOWN:
        buffer = new Vec2(start.getX(), Util.lerp(start.getY(), (float)end.getY(), alpha));
        cam.getPosition().set(buffer);
        break;
    case LEFT:
    case RIGHT:
        buffer = new Vec2(Util.lerp(start.getX(), end.getX(), alpha), start.getY());
        cam.getPosition().set(buffer);
        break;
    }

    step += 1;
}

Вся проблема: Util.lerp () возвращает float или double. Это было плохо, потому что камера переводила off-grid и вызывала некоторые странные проблемы с фрагментами текстуры, где> 0 в X и> 0 в Y.

TLDR: не tween или ничего с помощью float

ответил Cody The Coder 25 AM00000050000001531 2015, 05:04:15

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132