opengl - mélange avec le contenu précédent de framebuffer
Je suis rendu à une texture à un objet framebuffer, et quand je dessine transparent primitives les primitives sont mélangés correctement avec les autres primitives attiré dans ce seul tirage étape, mais ils ne sont pas mélangés correctement avec le contenu de la mémoire de trame.
Est-il un moyen pour homogénéiser le contenu de la texture avec les nouvelles données arrivent?
EDIT: Plus d'informations requsted, je vais tenter de vous expliquer plus clairement;
La blendmode que j'utilise est GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA. (Je crois que c'est typiquement le standard de la propriété blendmode)
Je suis entrain de créer une application qui suit les mouvements de la souris. Il trace des lignes reliant la précédente position de la souris à la position actuelle de la souris, et comme je ne veux pas dessiner les lignes sur chaque image, j'ai pensé que je voudrais essayer de tirer la texture, jamais à la texture et puis il suffit de dessiner un rectangle avec cette texture sur lui pour l'afficher.
Tout cela fonctionne bien, sauf que quand j'ai dessiner des formes avec l'alpha moins de 1 sur la texture, il ne se mélange pas correctement avec la texture du contenu précédent. Disons que j'ai quelques lignes noires avec alpha = .6 établi sur la texture. Un couple tirage des cycles plus tard, ensuite, je dessine un cercle noir avec alpha = .4-dessus de ces lignes. Les lignes "en dessous" du cercle sont complètement écrasés. Bien que le cercle n'est pas plat noir (Il se marie bien avec le fond blanc) il n'y a pas de "lignes plus sombres" sous le cercle que vous attendez.
Si je dessine les lignes et le cercle dans le même cadre, cependant, ils s'intègrent correctement. Ma conjecture est que la texture ne se mélange pas avec son contenu précédent. C'est comme il ne se mélange avec le glclearcolor. (Qui, dans ce cas, est <1.0 f, 1.0 f, 1.0 f, 1.0 f>)
J'ai mis à jour avec plus d'informations. Je vous remercie pour votre réponse rapide.
OriginalL'auteur staticfloat | 2010-01-31
Vous devez vous connecter pour publier un commentaire.
Je pense qu'il y a deux problèmes ici.
Rappelez-vous que l'ensemble de la superposition de lignes sont mélangés deux fois ici. Une fois quand ils sont mélangés dans le FBO texture, et à nouveau lorsque la FBO texture est mixte au cours de la scène.
Donc la première possibilité est que vous n'avez pas de mélange activé lors de l'élaboration d'une ligne sur l'autre dans le FBO de superposition. Lorsque vous dessinez dans un RGBA la surface avec le mélange off, l'alpha actuelle est tout simplement écrit directement dans le FBO superposition de canal alpha. Ensuite, quand vous mélanger le tout FBO texture sur la scène, que alpha fait de vos lignes translucides. Donc, si vous avez de fusion contre "le monde", mais pas entre superposition d'éléments, il est possible qu'aucune fusion ne se passe.
Un autre problème: lors de la fusion d'une ligne sur l'autre dans la "norme" mode de fusion (src alpha, 1 - src alpha) dans le FBO, le canal alpha de la "mélangés" la partie va contenir un mélange de les alphas de la superposition de deux éléments. Ce n'est probablement pas ce que vous voulez.
Par exemple, si vous dessinez deux alpha de 50% des lignes les unes des autres, dans la superposition, d'obtenir l'équivalent de l'effet lorsque vous blit le FBO, vous avez besoin de la FBO alpha à...75%. (1 - (1-.5) * (1-0.5), qui est ce qui pourrait arriver si vous venez de piocher deux alpha de 50% des lignes au-dessus de votre scène. Mais lorsque vous dessinez les deux 50% des lignes, vous obtiendrez 50% de l'alpha dans le FBO (un mélange de 50%...50%.
Ceci nous amène à la dernière question: par pré-mélange les lignes les uns avec les autres avant de fondre sur le monde, vous sont en train de changer l'ordre. Alors que vous pourriez avoir eu:
mélange(blend(mélange(couleur de fond, modèle), en première ligne, deuxième ligne);
maintenant, vous aurez
mélange(blend(première ligne, la deuxième ligne), mélange(couleur de fond, modèle)).
En d'autres termes, pré-mixage de la superposition de lignes dans un FBO modifications de la commande de mélange et donc des modifications de l'aspect final dans une manière que vous ne pouvez pas voulez.
Tout d'abord, la manière la plus simple pour contourner ce problème: ne pas utiliser un FBO. Je réalise que c'est un "aller revoir la conception de votre application" genre de réponse, mais à l'aide d'un FBO n'est pas le moins cher de la chose, et moderne GL cartes sont très bon en dessin des lignes. Donc, une option pourrait être: au lieu de fondre les lignes dans un FBO, écrire la géométrie de la ligne dans un vertex buffer object (VBO). Simplement étendre le VBO un peu à chaque fois. Si vous êtes dessin moins de, disons, de 40 000 lignes à la fois, ce sera presque certainement être aussi rapide que ce que vous faisiez avant.
(Un conseil si vous aller dans cette voie: utiliser glBufferSubData à écrire les lignes, pas glMapBuffer - mapping peut être coûteux et ne fonctionne pas sur les sous-intervalles sur de nombreux pilotes...mieux que de laisser le pilote de copier les quelques nouveaux sommets.)
Si ce n'est pas une option (par exemple, si vous dessinez un mélange de formes ou d'utiliser un mélange de GL état, telles que "se souvenir de" ce que vous avez fait est beaucoup plus complexe que la simple accumulation de sommets), alors vous pouvez changer la façon dont vous dessinez dans le VBO.
Fondamentalement, ce que vous devez faire est de permettre de séparer le mélange; initialiser la superposition noir + 0% alpha (0,0,0,0) et le mélange à l' "standard fusion" le RVB, mais additif mélange les canaux alpha. Ce n'est pas encore tout à fait correct pour le canal alpha, mais il est généralement beaucoup plus proches - sans cela, plus de tiré zones sera trop transparent.
Ensuite, lors de l'élaboration de la FBO, l'utilisation de "pré-multiplié" alpha, qui est, (un, un-moins-src-alph).
Voici pourquoi cette dernière étape est nécessaire: quand vous dessinez dans le FBO, vous avez déjà multiplié chaque appel de par son canal alpha (si le mélange est sur). Puisque vous êtes dessin sur fond noir, un vert (0,1,0,0.5) la ligne est maintenant vert foncé (0,0.5,0,0.5). Si alpha est sur et vous mélangez à nouveau normalement, l'alpha est à nouveau appliquée et vous l avez 0,0.25,0,0.5.). En utilisant simplement la FBO couleur que est, vous évitez la deuxième alpha multiplication.
Cela est parfois appelé "pré-multiplié" alpha parce que l'alpha a déjà été multipliés dans la couleur RVB. Dans ce cas, vous voulez obtenir des résultats corrects, mais dans d'autres cas, les programmeurs de l'utiliser pour la vitesse. (En pré-multipliant, il enlève mult par pixel lorsque le mélange op est effectuée.)
Espère que ça aide! Se mélange à droite lorsque les couches ne sont pas mélangés dans l'ordre devient vraiment difficile, et séparer le mélange n'est pas disponible sur du vieux matériel, donc, il suffit de dessiner les contours à chaque fois peut être le chemin d'accès de moins de misère.
OriginalL'auteur Ben Supnik
Effacer le FBO transparent noir (0, 0, 0, 0), dessiner l'arrière vers l'avant avec
et en tirer les FBO avec
pour obtenir le résultat exact.
Ben Supnik a écrit, le FBO contient la couleur déjà multiplié avec le canal alpha, donc au lieu de le faire à nouveau avec GL_SRC_ALPHA, il est dessiné avec GL_ONE. La destination est la couleur atténuée normalement avec GL_ONE_MINUS_SRC_ALPHA.
La raison pour la fusion de la couche alpha dans le tampon de cette manière est différente:
La formule de combiner la transparence est
(J'utilise s et d en raison de la parallèle à OpenGL de source et de destination, mais comme vous pouvez le voir, l'ordre n'a pas d'importance.)
Écrit avec des opacités (valeurs alpha) cela devient
qui est le même que le mélange de la fonction (la source et la destination des facteurs) (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) avec la valeur par défaut mélange équation GL_FUNC_ADD.
En aparté:
Les réponses ci-dessus, le problème spécifique de la question, mais si vous pouvez facilement choisir le tirage au sort de l'ordre, il peut, en théorie, être mieux dessiner prémultiplié de la couleur dans la mémoire tampon de l'avant à l'arrière avec
et utiliser la même méthode.
Mon raisonnement derrière cela est que la carte graphique est peut-être ignorer exécution des shaders pour les régions qui sont déjà solide. Je n'ai pas testé cette même, de sorte qu'il ne peut pas faire de différence dans la pratique.
Heh, je suis content que cela vous a rejoint. J'ai été à la recherche pour quelqu'un d'autre qui tente de rendre imbriqués les contrôles d'INTERFACE utilisateur (je suis mauvaises pratiques de programmation graphique.) et la réponse précédente à bout de moi de séparer les modes de fusion, mais j'ai pensé qu'il serait très étrange si une solution exacte est impossible. D'y penser à nouveau cette solution n'est optimale que si vous avez à tirer fil de la précédente précédente de la mémoire tampon. Je vais ajouter une note pour les cas où vous pouvez choisir l'ordre, comme lors du rendu des contrôles d'interface utilisateur graphique dans une mémoire tampon, puisqu'il n'est pas rare pour les gens qui font ça à la fin jusqu'ici.
Fonctionne comme un charme! Cela m'a aidé à rendre transparent le texte à partir d'un FBO à l'écran. Comme pour la compréhension du pourquoi/comment il fonctionne, je pense que je dois faire un peu plus de la lecture 🙂
OriginalL'auteur Tamschi
Ben Supnik dit, la meilleure façon de le faire est le rendu de l'ensemble de la scène avec distinct mélange de fonctions pour la couleur et alpha. Si vous utilisez le classique non prémultiplié mélange de la fonction essayer glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE) pour le rendu de votre scène de FBO. et glBlendFuncSeparateOES(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) pour rendre l'FBO à l'écran.
Il n'est pas précis à 100%, mais dans la plupart des cas, de ne pas créer de inattendus de transparence.
Gardez à l'esprit que l'ancien Matériel et certains appareils mobiles (principalement OpenGL ES 1.x appareils, comme l'original de l'iPhone et 3G) ne prend pas en charge séparés mélange de fonctions. 🙁
OriginalL'auteur Filipi Nascimento Silva