4 votes

OpenGL : Comment implémenter un outil "gomme" ?

Je travaille sur un jeu pour l'iPhone qui comporte un mécanisme de dessin/peinture et j'ai du mal à créer un outil qui efface les éléments déjà peints.

Le principal problème est que le fond sur lequel on peint n'est pas une couleur solide mais une image statique ou une animation. J'ai essayé d'utiliser différentes options de mélange et opérations logiques dans le dessin, mais rien ne semble fonctionner. Je suis novice en OpenGL, je dois donc manquer quelque chose.

Des conseils ?

EDIT : Pour donner un peu plus d'informations, j'utilise des textures pour mes brosses et j'utilise glVertexPointer() et glDrawArrays() pour les rendre. Par exemple :

glBindTexture(GL_TEXTURE_2D, circleBrush);
glVertexPointer(3, GL_FLOAT, 0, verts);
glTexCoordPointer(2, GL_FLOAT, 0, coords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

EDIT 2 : Malheureusement, les tampons de pochoirs ne sont pas disponibles sur l'iPhone :(

EDIT 3 : Les objets Framebuffer sont disponibles sur l'iPhone et c'est le chemin que j'ai pris. Je ne l'ai pas encore complètement implémenté, mais jusqu'à présent, il semble que cela fonctionne comme je le voulais. Merci à tous !

5voto

joeld Points 5569

Dessinez un quadrillage texturé en plein écran sur votre scène. Lorsque l'utilisateur dessine un trait de pinceau, utilisez glTexSubImage2D pour mettre à jour votre texture.

glReadPixels/glDrawPixels est lent.

Utiliser FrameBufferObjects est encore mieux, mais je doute que cette extension soit disponible sur l'iPhone (encore une fois, je n'en suis pas sûr, alors essayez peut-être). Les FBO vous permettent de dessiner directement dans une texture comme s'il s'agissait d'un autre contexte de rendu.

4voto

Hypocritus Points 41

Stencil Buffer est la meilleure façon d'aborder cette question... Vous économiserez du temps, du cpu, et des problèmes potentiels... Ils sont disponibles sur Iphone, vous devez juste créer une surface OpenGlES 2.0 (pas gles 1.0 ou 1.1).

        //Turn off writing to the Color Buffer and Depth Buffer
        //We want to draw to the Stencil Buffer only
        glColorMask(false, false, false, false);
        glDepthMask(false);

        //Enable the Stencil Buffer
        glEnable(GL_STENCIL_TEST);

        //Set 1 into the stencil buffer
        glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

        //CALL YOUR DRAWING METHOD HERE

        //Turn on Color Buffer and Depth Buffer
        glColorMask(true, true, true, true);
        glDepthMask(true);

        //Only write to the Stencil Buffer where 1 is set
        glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
        //Keep the content of the Stencil Buffer
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

        //CALL OUR DRAWING METHOD AGAIN

Regardez cet exemple : http://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.c

Voici le résultat visuel : http://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.jpg

J'ai implanté le même type d'outil de gommage avec ceci, à la fois sur Android et sur iPhone et cela fonctionne comme un charme !

Bonne chance !

A la vôtre !

2voto

Whaledawg Points 2018

Vous ne donnez pas beaucoup d'informations, mais je suppose que vous stockez ce qu'ils "peignent" dans un tampon et que vous le dessinez ensuite à l'écran comme ceci :

 glWindowPos2i(X, Y);
 glDrawPixels(drawing->Width, drawing->Height, drawing->Format, 
              GL_UNSIGNED_BYTE, drawing->ImageData);

Avec drawing->ImageData étant le tampon. Ce que vous pouvez faire, c'est avoir un tampon d'arrière-plan séparé et le dessiner en premier. Ensuite, l'outil d'effacement blanchira simplement le tampon de dessin (en augmentant toutes les valeurs, y compris l'alpha, au maximum).

Pour que cette solution fonctionne, il faudrait activer le mélange et désactiver les tests de profondeur .

 glEnable(GL_BLEND);
 glDisable(GL_DEPTH_TEST);
 glWindowPos2i(X, Y);
 //background never changes
 glDrawPixels(background->Width, background->Height, background->Format, 
              GL_UNSIGNED_BYTE, background->ImageData);
 glWindowPos2i(X, Y);
 glDrawPixels(drawing->Width, drawing->Height, drawing->Format, 
              GL_UNSIGNED_BYTE, drawing->ImageData);
 glEnable(GL_DEPTH_TEST);
 glDisable(GL_BLEND);

C'est ce que vous cherchez ?

2voto

ypnos Points 21940

Vous pouvez utiliser le tampon du stencil pour cette opération. Le tampon stencil est un tampon spécial qui contient des informations pour chaque pixel, comme le tampon de profondeur. Contrairement au tampon de profondeur, c'est vous qui décidez comment le tampon de stencil est modifié pendant le dessin et comment il influence la décision de dessiner dans le tampon de couleur ou non. Pour ce faire, vous pouvez définir les états spécifiques avant toute opération de dessin. Voici ce que vous devez faire :

  • Au moment où les utilisateurs effacent, dessinez la région "effacée" dans le tampon du pochoir (en utilisant StencilOp, voir ci-dessous). Vous pouvez utiliser n'importe quelle fonction de dessin GL pour cela.

  • Dans chaque passe de rendu, dessinez d'abord l'arrière-plan (si vous voulez, vous pouvez utiliser un test de pochoir négatif ici pour pour ne dessiner que la partie "effacée" de l'arrière-plan. arrière-plan - cela peut augmenter performances).

  • Ensuite, activez le test du stencil pour tous les autres opérations de dessin. OpenGL ne dessinera alors que dans les régions "non effacées".

La fonction pour définir comment le tampon du stencil doit influencer le dessin (ou non) : glStencilFunc()

La fonction pour définir comment le tampon du stencil lui-même est influencé par le dessin : glStencilOp()

Plus d'explications, également avec les arguments pour ceux-ci : http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node117.html

1voto

new soul Points 211

L'utilisation du mode glBlendFunc(GL_ONE, GL_ZERO) peut s'avérer inutile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X