Comment puis-je implémenter un effet de ligne de balayage?

8

Je travaille sur un jeu de plateforme old-school dans libgdx et je veux qu'il ait un effet "scanline", comme ceci:

maldita castilla scanline effet

Ma première tentative a été de créer une petite texture et de la dessiner sur un quad en plein écran. J'ai utilisé deux modes de caméra orthogonale différents (un pour le tilemap principal du jeu et un second pour rendre la texture de la ligne de balayage). Parfois, la texture est collée sur le tilemap et parfois elle est trop grande et couvre tout l'écran en noir.

Mon approche utilisant deux caméras et une texture est-elle raisonnable? Quelle est la bonne solution pour obtenir cet effet?

Alexandre GUIDET
la source

Réponses:

4

Le problème avec le rendu naïf d'une petite texture de ligne de balayage sur un grand quadruple plein écran est que la texture augmentera, rendant ce qui était un ensemble de lignes de balayage à pixel unique dans la texture beaucoup plus épaisse, plus floue (selon votre méthode d'interpolation), et généralement plus laid.

Vous devriez plutôt carrelerla texture à travers le quad de manière à conserver un rapport pixel sur texel de 1: 1. Cela implique d'ajuster les coordonnées de texture du quadrilatère afin qu'elles soient supérieures à 1 au maximum, et également de définir le paramètre d'habillage des textures à répéter au lieu de pincer. Si votre texture est de 64x64 pixels et votre écran est de 1024x768 pixels, vous pouvez comprendre que dans l'axe X, vous devez carreler la texture 16 fois (1024/64). De même, sur l'axe Y, vous devez le carreler 12 fois (768/64). Vous pouvez ajuster ce calcul pour les limites réelles de votre texture et de votre écran. Utilisez ces nombres (16 et 12) comme l'étendue maximale des coordonnées de texture de votre quad et vous obtiendrez un bien meilleur résultat. Selon la façon dont votre projection orthographique est actuellement configurée pour les carreaux, vous n'aurez peut-être même pas besoin de la modifier pour le rendre.

Alternativement, vous pouvez adopter une approche de shader: restituer votre scène régulière à une texture, puis rendre cette texture en quadruple plein écran, mais en omettant chaque ligne impaire de pixels. Si vous connaissez les limites de l'écran dans le shader, vous pouvez le faire assez facilement (c'est un pseudo-code , vaguement HLSL-ish, mais devrait se traduire facilement):

float2    screenSize;
sampler2D textureSampler;
float2    textureCoordinate;

float4 main () { 
   // Interpolation of texture coordinates means that we don't get nice
   // integer boundaries we could take the modulus of.
   float half_y = textureCoordinate.y * screenSize.y * 0.5;
   float delta = round(half_y) - half_y;
   float delta_squared = delta * delta;
   if (delta_squared < 0.1) {
      return texture2D(textureSampler, textureCoordinate);
   } 

   return float4(0,0,0,0);
}

la source
0

Le problème avec l'utilisation d'un appareil photo est qu'il redimensionnera l'image. Ce que vous voulez essentiellement, c'est de toujours dessiner la même image à la même taille (100%). Je suppose qu'il est assez grand pour couvrir toujours tout l'écran.

Si tel est le cas, une solution serait d'appliquer la transformation inverse de la caméra sur l'image afin qu'elle dessine à une taille "pixel parfait".

L'option la plus simple serait de la mettre à l'échelle vous-même. Par exemple. si votre appareil photo est zoomé à 75%, votre image sera mise à l'échelle à 133% ( 1/0.75).

cendres999
la source
vous dites que l'image doit être assez grande pour couvrir tout l'écran, n'est-il pas possible de remplir un peu rect avec une petite texture?
Alexandre GUIDET
@AlexandreGUIDET Je ne suis pas sûr. J'utilise une texture pour un fondu entrant et sortant, et c'est un pixel 1x1 qui est mis à l'échelle. Pour les lignes de balayage, vous voulez qu'il se répète. Vous devriez vérifier si libGDX a une option pour cela.
ashes999
@AlexandreGUIDET avez-vous essayé cela?
ashes999
Je choisis une approche différente en utilisant un autre appareil photo et en dessinant l'effet de ligne de balayage au-dessus de la scène. Je ne suis pas encore satisfait du résultat car la scène semble se glisser derrière les lignes de balayage. Que pensez-vous de l'utilisation d'un shader à la place?
Alexandre GUIDET