2014-07-04 2 views
2

Dans libGdx, je suis en train de créer une texture en forme: Prenez une texture rectangulaire entièrement visible et un masque pour obtenir une texture en forme, comme indiqué ici:LibGDX mélange de textures avec fonction mélange OpenGL

Shaped texture creation

Ici, je le teste sur un rectangle, mais je veux l'utiliser sur n'importe quelle forme. Je l'ai regardé dans this tutorial et est venu avec une idée d'abord dessiner la texture, puis le masque avec la fonction mouchetée:

batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA); 
  • GL20.GL_ZERO - parce que je ne veux vraiment pas peindre des pixels de la masque
  • GL20.GL_SRC_ALPHA - à partir de la texture d'origine je veux peindre uniquement ces pixels, où le masque était visible (= blanc).

partie cruciale du code de test:

batch0.enableBlending(); 
batch0.begin(); 

batch0.draw(original, 0, 0); //to see the original 
batch0.draw(mask, width1, 0); //and the mask 

batch0.draw(original, 0, height1); //base for the result 

batch0.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA); 
batch0.draw(mask, 0, height1); //draw mask on result 
batch0.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 

batch0.end(); 

Le centre de The de get texture bien choisi, mais au lieu de la couleur transparente autour, je vois noir:

Screenshot

Pourquoi le résultat est-il vide et non transparent?

(Full code - Attention: très salissant)

+0

Pouvez-vous parler plus en détail quelles sont vos attentes? Comment déterminez-vous que le résultat n'est pas transparent? Je pense que votre alpha de destination sera zéro, donc en ce sens, il serait transparent. Aviez-vous quelque chose d'autre dans la région qui est maintenant noir, et vous vous attendiez à ce que le contenu précédent soit toujours là? –

+0

Oui, l'arrière-plan de l'application est constitué de carrés rouge et vert foncé, et il n'y a rien de noir à tracer, donc si la texture était transparente, je verrais les carrés, n'est-ce pas? – kajacx

Répondre

3

Qu'est-ce que vous essayez de faire ressemble à une utilisation assez intelligent de mélange. Mais je crois que la façon exacte dont vous l'appliquez est "brisée par la conception". Parcourons les étapes:

  1. Vous rendez votre arrière-plan avec des carrés rouges et verts.
  2. Vous obtenez une texture opaque au-dessus de votre arrière-plan.
  3. Vous effacez des parties de la texture que vous avez rendue à l'étape 2 en appliquant un masque.

Le problème est que pour les pièces que vous effacez à l'étape 3, l'arrière-plan précédent ne revient pas. Il ne peut vraiment pas, parce que vous l'avez effacé à l'étape 2. Le fond de la zone de texture entière a été remplacé à l'étape 2, et une fois qu'il est parti il ​​n'y a aucun moyen de le ramener. Maintenant, la question est de savoir comment vous pouvez résoudre ce problème. Il y a deux approches conventionnelles auxquelles je peux penser:

  • Vous pouvez combiner la texture et le masque en les transformant en un objet framebuffer off-sreen (FBO). Vous effectuez les étapes 1 et 2 comme vous le faites maintenant, mais rendez dans un FBO avec une pièce jointe de texture. La texture que vous avez rendue est alors une texture avec des valeurs alpha qui reflètent votre masque, et vous pouvez utiliser cette texture pour le rendre dans votre framebuffer par défaut avec un mélange standard.
  • Vous pouvez utiliser un tampon stencil. Le masquage des parties du rendu est une application principale des tampons stencil, et l'utilisation du stencil serait certainement une très bonne solution pour votre cas d'utilisation. Je ne vais pas élaborer sur les détails de la façon exacte d'appliquer des tampons stencil à votre cas dans cette réponse. Vous devriez être en mesure de trouver beaucoup d'exemples à la fois en ligne et dans les livres, y compris dans d'autres réponses sur ce site, si vous recherchez "gabarit OpenGL".Par exemple, cette question récente traite de faire quelque chose de similaire en utilisant un tampon stencil: OpenGL stencil (Clip Entity).

Donc, ceux-ci seraient les solutions standard. Mais inspiré par l'idée dans votre tentative, je pense qu'il est effectivement possible de faire fonctionner cela avec juste un mélange. L'approche que j'ai trouvée utilise une séquence légèrement différente et des fonctions de mélange différentes. Je n'ai pas essayé cela, mais je pense que cela devrait fonctionner:

  1. Vous rendez l'arrière-plan comme avant.
  2. Rend le masque. Pour l'empêcher d'effacer l'arrière-plan, désactivez l'écriture sur les composants de couleur du framebuffer et écrivez uniquement dans le composant alpha. Cela laisse le masque dans le composant alpha du framebuffer.
  3. Rend la texture en utilisant le composant alpha du framebuffer (DST_ALPHA) pour le fondu.

Vous aurez besoin d'un framebuffer avec un composant alpha pour que cela fonctionne. Assurez-vous de demander des bits alpha pour votre framebuffer lors de la configuration de votre contexte/surface.

La séquence de code ressemblerait à ceci:

// Draw background. 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); 
glDisable(GL_BLEND); 
// Draw mask. 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
glEnable(GL_BLEND); 
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); 
// Draw texture. 
+0

Merci, je me suis rendu compte de cela plus tard (que mon arrière-plan d'origine est complètement détruit par la texture opaque) et j'ai utilisé 'FrameBuffer' et tout va bien. – kajacx

Questions connexes