OpenGL: Como implementar uma ferramenta "borracha"?
-
08-07-2019 - |
Pergunta
Estou trabalhando em um jogo para o iPhone que tem um mecânico de desenho/pintura envolvido e estou tendo problemas para tentar criar uma ferramenta que apagarem as coisas já pintadas.
O principal problema é que o fundo está pintado não é uma cor sólida, mas uma imagem ou animação estática. Tentei usar diferentes opções de mistura e operações lógicas no desenho, mas nada parecia funcionar. Eu sou novo no OpenGL, então devo estar perdendo alguma coisa.
Alguma dica?
EDIT: Para fornecer um pouco mais de informação, estou usando texturas para meus pincéis e usando o glvertexPointer () e Gldrawarrays () para renderizá -los. Por exemplo:
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: Infelizmente, os buffers de estêncil não estão disponíveis no iPhone. : (
EDIT 3: Os objetos de estrutura estão disponíveis no iPhone e essa é a estrada que eu segui. Ainda não o implementei totalmente, mas até agora parece que funciona da maneira que eu queria. Obrigado a todos!
Solução
Desenhe um quadro texturizado em tela cheia sobre sua cena. Quando o usuário desenhar uma pincelada, use glTexSubImage2D
Para atualizar a sua textura.
GlReadpixels/GlDrawPixels é lento.
O uso do quadroBufferObjects é ainda melhor, mas duvido que essa extensão esteja disponível no iPhone (então, novamente, não sei ao certo, então talvez tente). O FBO permite que você desenhe diretamente em uma textura como se fosse outro contexto de renderização.
Outras dicas
O buffer de estêncil é a melhor maneira de abordar isso com certeza ... você economizará tempo, CPU e problemas em potencial. .
//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
Procure este exemplo:http://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.c
Aqui está o resultado visual:http://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.jpg
Eu impliquei o mesmo tipo de ferramenta de borracha com isso, no Android e no iPhone e funciona como um charme!
Boa sorte !
Felicidades !
Você não dá muita informação, mas suponho que você o armazenasse o que quer que eles "pintem" em um buffer e depois desenhem na tela como esta:
glWindowPos2i(X, Y);
glDrawPixels(drawing->Width, drawing->Height, drawing->Format,
GL_UNSIGNED_BYTE, drawing->ImageData);
Com o desenho-> imagedata sendo o buffer. O que você poderia fazer é ter um buffer de fundo separado e desenhá -lo primeiro. Em seguida, a ferramenta de apagamento simplesmente será interrompida no buffer de desenho (girando todos os valores, incluindo alfa, todo o caminho).
Para que esta solução funcione, você teria que ativar a mistura e Desligue o teste de profundidade.
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);
É isso que você está procurando?
Você pode usar o buffer de estêncil para esta operação. O buffer de estêncil é um buffer especial que mantém informações para cada pixel, semelhante ao buffer de profundidade. Ao contrário do buffer de profundidade, você decide como o buffer de estêncil é alterado durante o desenho e como ele influencia a decisão de atrair ou não o buffer de cores. Para fazer isso, você pode definir os estados específicos antes de qualquer operação de desenho. Aqui está o que você faz:
Na época em que os usuários apagam, desenhe a região "apagada" para o buffer de estêncil (usando o Stencilop, veja abaixo). Você pode usar qualquer função de desenho GL para isso.
Em cada passe de renderização, primeiro desenhe o plano de fundo (se você quiser, você pode usar um teste de estêncil negativo aqui para desenhar apenas a parte "apagada" do plano de fundo - pode aumentar o desempenho).
Em seguida, ative o teste de estêncil para todas as outras operações de desenho. O OpenGL apenas atrairá apenas as regiões "não-emeradas".
A função para definir como o buffer de estêncil deve influenciar o desenho (ou não): glstarkfunc ()
A função para definir como o próprio buffer de estêncil é influenciado pelo desenho: GlStopyChyop ()
Explicações adicionais, também com os argumentos para estes:http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node117.html
Usando o modo GLBLENDFUNC (GL_ONE, GL_ZERO) pode earse.