OpenGL все еще пытается размыть даже с GL_NEAREST (GL_TEXTURE_2D) - PullRequest
8 голосов
/ 30 декабря 2011

Изображение говорит тысячу слов, а что насчет двух?У меня есть эта карта:

map image

Чтобы использовать это как карту, я масштабирую эту текстуру 6 раз.Это, однако, пошло не так, как ожидалось:

desired-actual

Весь код OpenGL находится в моей доморощенной библиотеке рендеринга 2D OpenGL, и, поскольку OpenGL является конечным автоматом, на самом деле трудно документироватьвесь процесс рендеринга.Но вот что я делаю +/- (код Python):

width, height = window.get_size()
glViewport(0, 0, width, height)

glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()

glOrtho(0.0, width, height, 0.0, 0.0, 1.0)

glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()

# displacement trick for exact pixelization
glTranslatef(0.375, 0.375, 0.0)

glDisable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

glEnable(self.texture.target) # GL_TEXTURE_2D
glBindTexture(self.texture.target, self.texture.id)

glTexParameteri(self.texture.target, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(self.texture.target, GL_TEXTURE_MAG_FILTER, GL_NEAREST)

glPushMatrix()

glTranslatef(self.x, self.y, 0.0) # self.x and self.y are negative int offsets
glScalef(self.scale_x, self.scale_y, 1.0) # scale_x and scale_y are both 6

glBegin(GL_QUADS)
glTexCoord2i(0, 0)
glVertex2i(0, 0)
glTexCoord2i(0, 1)
glVertex2i(0, self.texture.height)
glTexCoord2i(1, 1)
glVertex2i(self.texture.width, self.texture.height)
glTexCoord2i(self.texture.width, 0)
glVertex2i(self.texture.width, 0)
glEnd()

glPopMatrix()
glDisable(self.texture.target)

Однако эта ошибка «размытия» не возникает, когда я использую GL_TEXTURE_RECTANGLE_ARB.Я также хотел бы иметь возможность использовать GL_TEXTURE_2D, поэтому кто-нибудь может указать, как этого избежать?

Ответы [ 2 ]

7 голосов
/ 30 декабря 2011

Если сомневаешься - замени свою текстуру на черно-белую шахматную доску того же размера (черный / белый 1px). Это даст вам хорошее представление о том, что происходит - будет ли оно равномерно серым (смещение неправильное) или будет иметь волны (масштабирование неправильное).

Убедитесь, что у вас нет автоматически создаваемых и используемых mip-карт.

Как правило, вам не нужно никаких специальных смещений, тексели соответствуют пикселям с правильно настроенным glOrtho.

Еще одна важная проблема - использование текстур PowerOfTwo, поскольку старые графические процессоры могли использовать различные схемы для поддержки текстур NPOT (прозрачное масштабирование или заполнение для пользователя), что могло привести только к такому типу размытия.

Чтобы вручную работать с текстурами NPOT, вам нужно заполнить их четкими пикселями до следующего размера POT и масштабировать ваши значения UV glTextCoord2f(u,v) с коэффициентом npotSize / potSize. Обратите внимание, что это несовместимо с мозаикой, но, судя по вашему искусству, вам это не нужно.

4 голосов
/ 30 декабря 2011
# displacement trick for exact pixelization
glTranslatef(0.375, 0.375, 0.0)

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

(2i + 1)/(2N)

Вы можете получить масштабирование и перевод из этого - или определить координаты текстуры напрямую.

РЕДАКТИРОВАТЬ из-за комментария.

Хорошо, допустим, ваша текстура имеет ширину 300 пикселей, и вы хотите адресовать в точности пиксели от 20 до 250, тогда координаты текстуры, которые нужно выбрать для матрицы идентичных текстур, будут

(2*20 + 1)/(2*300) = 41/600 = 0.0650

и

(2*250 + 1)/(2*300) = 501/600 = 0.8350

Но вы также можете применить преобразование через матрицу текстур. Вы хотите отобразить пиксели 0… 299 (для ширины 300 пикселей индекс идет от 0 до 300-1 = 299) к 0… 1. Итак, давайте вставим эти цифры:

(2*0 + 1)/(2*300) =  1/600 =~= 0.0017 = a
(2*299 + 1)/(2*300) = 599/600 =~= 0.9984 = b

b-a =~= 0.9967

Таким образом, вы должны уменьшить диапазон 0… 1 на 0,9967 и сместить его на 0,0017 по ширине. То же самое касается и высоты ← → t координат. Помните, что порядок преобразований имеет значение. Вы должны сначала масштабировать, а затем перевести при выполнении преобразования, поэтому при умножении матриц перевод умножается первым:

// for a texture 300 pixels wide
glTranslatef(0.0017, …, …);
glScale(0.9967, …, …);

Если вы хотите использовать пиксели вместо диапазона 0… 1, дополнительно разделите масштаб на ширину текстуры.

БОЛЬШОЙ ОДНАКО:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...