2016-06-27 6 views
1

У меня возникли проблемы с отображением искусства на основе пикселя (думаю, ретро-плитки и искусство) на OpenGL Es 1.1 на iPhone.OpenGL ES Pixel Art - Масштабирование

Плитки представлены с использованием 8 байт (1 байт для каждой строки) с каждым битом, представляющим пиксель, который установлен или нет.

Например плитка с числом 8:

0 0 0 0 0 0 0 0  -> 
0 0 1 1 1 0 0 0  ->  xxx 
0 1 0 0 0 1 0 0  ->  x x 
0 1 0 0 0 1 0 0  ->  x x 
0 0 1 1 1 0 0 0  ->  xxx 
0 1 0 0 0 1 0 0  ->  x x 
0 1 0 0 0 1 0 0  ->  x x 
0 0 1 1 1 0 0 0  ->  xxx 

Преобразование это OpenGL на iPhone, используя

glDrawArrays(GL_POINTS, 0, 64); 

Simulator output at 100%

Логика является правильным, но проблема в том, что Безразлично 't дать ретро-эффект. Я искал больше блочного/ретро-стиля. Я читал, что могу отключить сглаживание пикселей, из-за чего пиксели будут отображаться как квадраты (я думаю, что это GL_Disable (POINT_SMOOTH), но не уверен, что это влияет на ES, поскольку ничего не изменилось.)

Возможные решения, которые я нашел связанные проблемы:

  1. использовать буфер кадра для рендеринга с меньшим разрешением, а затем масштабировать его в буфере визуализации. Я не знаю, как это делается, или если это сработает.
  2. Создайте изображение из пикселей, создайте текстуру с этого изображения и, наконец, визуализируйте эту текстуру.

Возможные решения я подумал выключен:

  1. Для каждого пикселя, нарисуйте два пикселя, а не как по горизонтали, так и по вертикали.
  2. Нарисуйте каждый пиксель как квадрат с помощью треугольников.
  3. Использование GLPointSize - дает правильный эффект при установке на 2, но координаты затем перепутаны. Выравнивание становится сложнее.

В конце концов я хотел бы плитки, которые будут представлены:

Retro pixels - Number 8

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

ответ

0

Я не уверен, что мой вопрос был не ясен, но чтобы нарисовать пиксели на экране, вам нужно создать текстуру и передать в нее пиксельные данные, а затем визуализировать эту текстуру на экране. Это будет эквивалент glDrawPixels.

Код будет:

#define W 255,255,255 

#define G 192,192,192 

//8 x 8 tile with 3 bytes for each pixel RGB format 
GLubyte pixels[8 * 8 * 3] = { 
W,W,W,W,W,W,W,W, 
W,W,G,G,G,W,W,W, 
W,G,W,W,W,G,W,W, 
W,G,W,W,W,G,W,W, 
W,W,G,G,G,W,W,W, 
W,G,W,W,W,G,W,W, 
W,G,W,W,W,G,W,W, 
W,W,G,G,G,W,W,W 
}; 

где-то в настройках:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
glGenTextures(1, &tex); 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, tex); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 
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_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 

Затем нарисовать текстуру как обычно:

glActiveTexture(GL_TEXTURE0); 
glUniform1i([program uniformLocation:@"s_texture"], 0); 
glBindTexture(GL_TEXTURE_2D, tex); 

glEnableVertexAttribArray(positionAttrib); 
glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 0, v); 
glEnableVertexAttribArray(texAttrib); 
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, t); 
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, i); 
+0

Право. Когда вы рисуете 'GL_POINTS', вы рисуете кучу отдельных частей геометрии, каждая из которых самая маленькая вещь, которая может быть освещена в буфере. Когда вы рисуете 'GL_TRIANGLES', вы рисуете непрерывную часть дисплея, гарантируя, что каждый пиксель, содержащийся в нем, получает какое-то значение. Предполагая, что то, что вам нужно, - это графика с низким разрешением, масштабируемая до более высокого разрешения с точечной выборкой, вы просто загружаете их по собственному разрешению и рисуете их в любой регион, в котором хотите представить результат, используя 'GL_NEAREST'. Все, что вы, кажется, уже выяснили! – Tommy

1

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

То, что вы ищете здесь, является FBO (объект буфера кадра). Найдите несколько примеров того, как создать FBO и прикрепить к нему текстуру. Это создаст буфер для вас с любыми измерениями, которые вы будете вводить. Некоторые распространенные проблемы здесь состоят в том, что вам, скорее всего, понадобится POT-текстура (мощность 2-х измерений: 2, 4, 8, 16 ... так, например, буфер 64x128), поэтому для управления другим размером вы должны использовать окно просмотра, которое затем используйте только часть необходимого вам буфера.

Таким образом, в конце это создаст текстуру с низким разрешением, которую можно использовать для рисования на холсте (вид). Как вы делаете для него то, с чем вам следует экспериментировать.Точки не могут быть лучшим решением, даже в вашем случае с буфером я бы использовал линии между точками, определенными вами в вашем примере. На этом этапе вы должны выбрать рисование с помощью антиалиасов или без них. Чтобы включить его, вы можете посмотреть мультисэмплинг на iOS.

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

Так полномочия здесь:

  • Различный буфер FBO размеры
  • Antialiasing на FBO
  • параметры текстуры
  • антиалиасинг при перерисовке на холст

Что касается FBO это одна из самых простых вещей:

  • Сформировать кадровый буфер (glGenFramebuffers)
  • Bind буфер кадра (glBindFramebuffer)
  • Создание текстуры (glGenTextures) и связать его (glBindTexture)
  • Набор текстурных данных glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  • Присоединить текстуру к frame buffer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.textureID, 0);
  • Теперь, когда вы рисуете текстуру, вам нужно связать буфер кадра FBO, и когда вы рисуете в основной буфер, просто привяжите этот буфер кадров.

Поскольку это довольно широкий ответ (как вопрос) ... Если вы будете реализовывать это и будете иметь дополнительные вопросы или проблемы, лучше всего создать отдельные вопросы и, возможно, связать их в Комментарии.

Удачи.

+0

FBOs не поддерживаются в ES 1.1, который является что OP хочет использовать. Не сказать, что использование ES 1.1 - хорошая идея, но на самом деле это не отвечает на заданный вопрос. –

+0

@RetoKoradi - Я перешел на es2 на основе вашего комментария. –

+0

Ive создал более конкретный вопрос относительно FBO - http: // stackoverflow.com/questions/38071480/opengl-es-fbo-scaling –

 Смежные вопросы

  • Нет связанных вопросов^_^