Como posso redimensionar a pixel art no Pyglet sem torná-la embaçada?

7

Eu tenho um conjunto de imagens de 8x8 pixels e quero redimensioná-las no meu jogo para que sejam o dobro (16x16 pixels, por exemplo, transformando cada pixel em um bloco 2x2). O que estou tentando obter é um Minecraft- como efeito, em que você tem pequenas imagens de pixel dimensionadas para pixels bloqueadores maiores.

No Pyglet, a scalepropriedade do sprite desfoca os pixels. Existe alguma outra maneira?

Código de trabalho:

Aqui está a solução que funciona (graças à persistência do DMan e ao insight de Jimmy):

image = resource.image('tileset.png')                                                                                                                                                               
texture = image.get_texture()   
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)                                                                                                                               
texture.width = 16 # resize from 8x8 to 16x16                                                                                                                                                                  
texture.height = 16                                                                                                                                                                                                                                                                                                                       
texture.blit(100, 30) # draw                                                                                                                                                                        
theabraham
fonte
3
Eu não estou familiarizado com Pyglet suficiente para fazer deste uma resposta, mas eu vi que você pode usar OpenGL, por isso from pyglet.gl import *e, em seguida, fazer uma chamada para talisman.org/opengl-1.1/Reference/glTexParameter.html com GL_NEAREST.
dman
Obrigado, vou dar uma olhada nisso, mas nunca usei o OpenGL antes. Tipo de novidade na programação gráfica: \
theabraham 27/11
Eu não sei o quanto Pyglet faz nos bastidores, mas algo como isso poderia funcionar: glEnable(GL_TEXTURE_2D). Então, digamos que você tenha telefonado para a = image.load('blah.jpg'). Atribua tex = a.textureentão glBindTexture(GL_TEXTURE_2D, texture.id)e finalmente uma chamada para pyglet.gl.glTexParameteri(pyglet.gl.GL_TEXTURE_2D, pyglet.gl.GL_TEXTURE_MIN_FILTER, pyglet.gl.GL_NEAREST). Eu não estou muito familiarizado com o espaço para nome do OpenGL em python, então deixei a chamada completa qualificada. Desde que importamos o OpenGL, acredito que você pode remover pelo menos o pyglet na frente e talvez também o gl .
dman
Ei, eu tentei sem sucesso. Você poderia verificar meu código na atualização? Além disso, você tem bons recursos para me ajudar a entender esses comandos GL? Agradeço a ajuda.
Theabraham #
Uma coisa que notei imediatamente é que você define a largura e a altura da textura antes da sua chamada glTexParameteri. O OpenGL 1/2 / ~ 3 no qual presumo que o Pyglet se baseia tenha esses comandos de modo imediato . Ou seja, você executa um comando para alterar o estado, depois tudo muda. Eu começaria movendo as chamadas por baixo das chamadas gl.
dman

Respostas:

8

A pedido dos comentaristas ...

Aviso aos profissionais de Pyglet: Pode haver uma maneira agradável de fazer isso, e não é isso. É uma ótima maneira de OpenGL. Você foi avisado!

Você pode fazer isso no OpenGL ligando primeiro a textura e depois chamando glTexParameteriou variantes semelhantes. Você pode fazer isso no Pyglet importando o OpenGL:

from pyglet.gl import *

Você pode habilitar GL_TEXTURE_2Dpara definir o alvo. Isso nem sempre é necessário, mas estou mantendo isso completo para algumas outras ligações.

glEnable(GL_TEXTURE_2D)

No Pyglet, parece que você também não precisa vincular a textura. Às vezes, você precisa carregar sua imagem, obter o ID da textura e usar glBindTexture(GL_TEXTURE_2D, texture.id). Suponho que esses já sejam o estado definido para você no Pyglet.

O próximo passo é ligar glTexParameteri. Graças a Jimmy por me corrigir: a ligação correta é:

gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)

Uma rápida quebra: o primeiro é apenas definir o alvo para que o OpenGL saiba do que você está falando; o segundo parâmetro é o tipo de filtro que você deseja definir. MAG_FILTERestá correto porque controla as ampliações de texturas. O parâmetro final é GL_NEAREST, que controla como a textura é dimensionada. GL_NEARESTé basicamente uma escala rápida que fornece texturas com estilo de pixel. GL_LINEARé normal e, em vez disso, desfocará suavemente sua textura.

Esta versão do OpenGL da qual estou falando (sobre o <OpenGL 3.2 oficialmente) usa o modo imediato, que define o estado. Agora que o estado está definido, você pode dimensionar sua textura. Não vejo nada melhor do que mostrar o código que o próprio Renold postou como código de trabalho.

image = resource.image('tileset.png')                                                                                                                                                               
texture = image.get_texture()   
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)                                                                                                                               
texture.width = 16 # resize from 8x8 to 16x16                                                                                                                                                                  
texture.height = 16                                                                                                                                                                                                                                                                                                                       
texture.blit(100, 30) # draw
DMan
fonte
Renove, se você pudesse dar uma olhada nisso e sugerir melhorias, seria ótimo. Mas estou interessado em algo. Se você remover texture = image.get_texture(), isso funciona? Parece que você nunca ligou, a menos que vincule a textura internamente.
dman
Sim, acontece que você não precisa disso. Acabei colocando a imagem em um sprite e funcionou bem: image = resource.image('tileset.png') \n sprite = sprite.Sprite(image, x_pos, y_pos) \n sprite.scale = 2 \n
theabraham 30/11
4

Para quem gosta de mim, que está simplesmente criando um jogo de estilo retro, onde deseja que TUDO seja dimensionado para ser pixelizado, a resposta rápida e simples é iniciar seu código com:

from pyglet.gl import *
glEnable(GL_TEXTURE_2D)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)

Então todo o seu uso de sprites, etc., a partir de então, permanecerá agradável e pixelizado.

Nathan
fonte