В моей игре есть Minecraft-подобная местность из кубов. Я генерирую буфер вершин из данных вокселей и использую атлас текстуры для внешнего вида различных блоков:
Проблема в том, что текстура удаленных кубов интерполируется с соседними плитками в текстурном атласе. Это приводит к появлению линий неправильных цветов между кубами (вам может понадобиться просмотреть скриншот ниже в полном размере, чтобы увидеть графические недостатки):
Пока я использую эти настройки интерполяции, но я пробовал каждую комбинацию и даже GL_NEAREST
без mipmapping не дает лучших результатов.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Я также попытался добавить смещение в координатах текстуры, чтобы выбрать немного меньшую площадь плитки, но поскольку нежелательный эффект зависит от расстояния до камеры, это не может полностью решить проблему. На дальних расстояниях полосы все равно встречаются.
Как я могу решить эту текстуру кровотечение? Поскольку использование текстурного атласа является популярной техникой, может быть общий подход. К сожалению, по некоторым причинам, объясненным в комментариях, я не могу перейти на другие текстуры или массивы текстур.
GL_LINEAR
что даст аналогичный результат, либо выберет ближайший пиксель,GL_NEAREST
что в любом случае также приведет к полосам между блоками. Последняя упомянутая опция уменьшается, но не устраняет дефект пикселей.Ответы:
Хорошо, я думаю, что у вас есть две проблемы здесь.
Первая проблема связана с mipmapping. В общем, вы не хотите наивно смешивать atlasing с mipmapping, потому что, если все ваши подтексты не имеют размер 1x1 пикселя, вы будете испытывать наложение текстуры. Добавление отступов просто переместит проблему на более низкий уровень.
Как правило, для 2D, где вы обычно делаете атлас, вы не используете mipmap; в то время как для 3D, где вы делаете mipmap, вы не атласируете (на самом деле, вы снимаете кожу таким образом, что кровотечение не будет проблемой)
Тем не менее, я думаю, что сейчас с вашей программой происходит то, что вы, вероятно, не используете правильные координаты текстуры, и из-за этого ваши текстуры кровоточат.
Давайте предположим, что текстура 8x8. Вы, вероятно, получаете верхнюю левую четверть, используя ультрафиолетовые координаты от (0,0) до (0,5, 0,5):
И проблема в том, что при u-координате 0,5 сэмплер будет интерполировать целевой фрагмент, используя половину левого текселя и половину правого текселя. То же самое произойдет в точке с координатами 0 и то же самое с координатами v. Это потому, что вы обращаетесь к границам между текселями, а не к центрам.
Вместо этого вам следует обратиться к центру каждого текста. В этом примере это координаты, которые вы хотите использовать:
В этом случае вы всегда будете пробовать центр каждого текселя, и у вас не должно быть никакого кровотечения ... Если только вы не используете mipmapping, в этом случае у вас всегда будет кровотечение, начиная с уровня mip, где масштабированная субтекстура не является аккуратно вписаться в сетку пикселей .
В целом, если вы хотите получить доступ к определенному текселю, координаты рассчитываются следующим образом:
Это называется «полупиксельной коррекцией». Там есть более подробное объяснение в здесь , если вы заинтересованы.
источник
Один из вариантов, который будет намного проще, чем возиться с мипмапами и добавлять факторы размытия координат текстуры, - это использовать массив текстур. Текстурные массивы похожи на трехмерные текстуры, но в 3-м измерении без отображения, поэтому они идеально подходят для текстурных атласов, где «подтексты» имеют одинаковый размер.
http://www.opengl.org/wiki/Array_Texture
источник
После долгих попыток решить эту проблему, я наконец нашел решение.
Чтобы использовать оба, текстурный атлас и mipmapping, я должен сам выполнить понижающую дискретизацию, потому что в противном случае OpenGL интерполировал бы границы границ плиток в атласе. Более того, мне нужно было установить правильные параметры текстуры, потому что интерполяция между мипмапами также вызывала бы наложение текстуры.
С этими параметрами кровотечение не происходит.
Есть одна вещь, которую вы должны заметить при предоставлении пользовательских mipmaps. Поскольку нет смысла сокращать атлас, даже если каждая плитка уже есть
1x1
, максимальный уровень mipmap должен быть установлен в соответствии с тем, что вы предоставляете.Спасибо за все остальные ответы и очень полезные комментарии! Кстати, я до сих пор не знаю, как использовать линейное масштабирование, но я думаю, что нет никакого способа.
источник
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_NEAREST_MIPMAP_LINEAR);
GL_TEXTURE_MAX_FILTER
наGL_NEAREST_MIPMAP_LINEAR
причины кровотечения не по причине множественного отображения, но по причине интерполяции. Так что в этом случае это эквивалентно,GL_LINEAR
так как в любом случае используется самый низкий уровень mipmap.glTexImage2D()
. Графический процессор автоматически выбирает правильный уровень в зависимости от размера объектов на экране.Похоже, что проблема может быть вызвана MSAA. Смотрите этот ответ и связанную статью :
Решение заключается в использовании центроидной выборки. Если вы рассчитываете обтекание координат текстуры в вершинном шейдере, перемещение этой логики в фрагментный шейдер также может решить проблему.
источник
Это старая тема, и у меня была проблема, похожая на тему.
У меня были очень хорошие координаты текстуры, но я изменил положение камеры (которая изменила положение моего элемента) следующим образом:
Вся проблема заключалась в том, что Util.lerp () возвращает число с плавающей запятой или двойное число. Это было плохо, потому что камера переводила вне сетки и вызывала некоторые странные проблемы с фрагментами текстуры, где> 0 в X и> 0 в Y.
TLDR: не твинируй и не используй поплавки
источник