Повторяющиеся текстуры сильно искажаются / встряхиваются при вращении камеры

Я изначально задал этот вопрос на gamedev, но ни один из ответов не помог решить проблему, и я до сих пор не знаю, что является реальной причиной. Я ничего не видел о повторной публикации вопросов по SE В часто задаваемых вопросах, поэтому я могу только надеяться, что это нормально. Более того, в ретроспективе вопрос, вероятно, больше связан с графическим программированием в целом, чем просто разработкой игр.

редактирование 1 начинается

поведение оригинала сообщение относится только к Windows XP и Windows 7, браузерам Firefox и Chrome. На Ubuntu нет такого искажения, но вместо этого текстуры "дрожат" во время вращения камеры. Когда вращение остановлено, встряхивание прекращается, но текстуры могут быть не в полностью правильном положении.

редактировать 1 заканчивается

редактирование 3 начинается

программа была протестирована на 4 разных компьютерах и не работала по назначению ни на одном из них.

редактировать 3 конца

у меня есть большой воксель в WebGL, который я хочу покрыть плиточной текстурой, каждая плитка имеет длину стороны 1 в пространстве вершин. В этом тестовом сценарии камера указывает на отрицательное направление z, а стороны вокселя находятся в плоскостях x-y, x-z, y-Z.

меньшие воксели (т. е. меньше повторов) работают довольно хорошо, но примерно в 2000 x и y повторяется на лицо (т. е. размер вокселя 2000*2000*2000) текстуры начинают выглядит очень уродливо. Когда камера направлена перпендикулярно к лицу, текстуры выглядят правильно независимо от размера/количества повторов, но для вокселов указанного выше размера любое вращение даже на пару градусов вызывает видимую проблему. Увеличение размера воксела увеличивает искажение. Обратное также верно: с небольшими вокселями текстуры выглядят правильно независимо от вращения камеры. Мне кажется, что для размера нет жесткого порогового значения, но эффект начинает увеличьте постепенно от нул когда воксел увеличен в размере от приблизительно 2000 в сторону.

см.http://imgur.com/a/spQIv для визуализации. Первое изображение должно выглядеть именно так, но когда камера поворачивается, линии начинают искажаться, как на втором изображении. Эффект ухудшается за счет увеличения размера вокселя и большего поворота камеры. http://imgur.com/a/wRndy содержит два дополнительных изображения с более серьезными эффект.

текстуры (один X на текстуру) первоначально 512*512 px. Скриншоты никоим образом не были масштабированы.

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

моя вторая догадка была какой-то странной ошибкой округления int/float, но поскольку все всегда обрабатывается в поплавках, я не вижу, как это может произойти.

третья возможность I можно подумать, что это просто невозможно и что текстуры не должны повторяться много раз. Однако это кажется маловероятным. Я предполагаю (и надеюсь), что есть какая-то довольно элементарная проблема.

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

Я использование:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.generateMipmap(gl.TEXTURE_2D);

и в шейдере:

#ifdef GL_ES
precision highp float;
#endif

Я также выполнил некоторые очень элементарные вычисления: для 32-битных поплавков максимальный significand составляет около 8,4 миллиона. Для длины воксельной стороны 2000 (которая, как я заметил, была уровнем, где эффект стал видимым), можно было наивно ожидать приблизительно 0.00025 ошибки округления поплавка в координатах. Предполагая, что каждый повтор занимает около 100 пикселей на экране, ошибка должна быть значительно меньше 1 пикселя, что это не так. Если мой расчет выше не был сделан неправильно, поэтому я бы назвал, что Float32 не виноват и что причина должна быть где-то еще.

текстура линии используется только для визуализации проблемы. Проблема сохраняется и с другими (более естественными) видами текстур.

редактирование 2 начинается

включение или отключение сглаживания не имеет видимой разницы

редактировать 2 конца

2 ответов


Я считаю, что то, что вы видите действительно может быть вызвано точность. Вы правильно рассчитали, что координаты с плавающей запятой должны быть достаточно красивыми, проблема в том, что оборудование не использование поплавков для поиска текстур. Блоки интерполятора текстуры имеют значительно более низкую точность (не знаю, как это сегодня, но раньше она была всего лишь 16 бит на старых картах GeForce).

Так ... как можно превысить точность интерполятора? С помощью большой координаты текстуры (много повторов) на большой геометрии, что именно то, что вы делаете. Лекарство? Разделите свою геометрию на меньшие координаты текстуры (вы можете сдвигать координаты текстуры целыми шагами, чтобы они были ближе к 0).

здесь скриншот о том, как экстремально это может выглядеть (я не смог воспроизвести ошибку на моем GeForce 260, но она хорошо видна на моем планшете Tegra 2, как показано на рисунке ниже).


я столкнулся с аналогичной проблемой под iOS. После повторения текстуры 127 раз, начали происходить нехорошие вещи.

решение, которое сработало, было таково:

Я GL_TRIANGLE_STRIP с некоторыми вырожденными треугольниками. Текстура выровнена по вертикали, поэтому на краю текстуры есть невидимый (вырожденный) треугольник, где текстура "отображается" зеркально, когда я устанавливаю координату текстуры в начало координат. Таким образом, следующий видимый треугольник показывает текстуру координата (0.0, 0.0) и он никогда не переходит координат (x, 127.0).

есть блоге объясняя это с примерами и картинками.