OpenGL: как реализовать инструмент «ластик»? - PullRequest
4 голосов
/ 15 ноября 2008

Я работаю над игрой для iPhone, в которой задействован механизм рисования / рисования, и у меня возникают проблемы при попытке создать инструмент, который бы стирал уже нарисованные объекты.

Основная проблема заключается в том, что фон, на котором рисуется, - это не сплошной цвет, а статичное изображение или анимация. Я пытался использовать различные параметры смешивания и логические операции при рисовании, но ничего не получалось. Я новичок в OpenGL, поэтому я должен что-то упустить.

Любые советы?

РЕДАКТИРОВАТЬ: Чтобы дать немного больше информации, я использую текстуры для своих кистей и использую glVertexPointer () и glDrawArrays () для их рендеринга. Например:

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

РЕДАКТИРОВАТЬ 2: К сожалению, буферы трафарета не доступны на iPhone. : (

РЕДАКТИРОВАТЬ 3: объекты Framebuffer доступны на iPhone, и я выбрал этот путь. Я еще не полностью реализовал это, но пока все выглядит так, будто все работает так, как я хотел. Спасибо всем!

Ответы [ 5 ]

5 голосов
/ 18 ноября 2008

Нарисуйте полноэкранный текстурированный квад поверх вашей сцены. Когда пользователь рисует мазок кисти, используйте glTexSubImage2D, чтобы обновить текстуру.

glReadPixels / glDrawPixels работает медленно.

Использование FrameBufferObjects еще лучше, но я сомневаюсь, что это расширение доступно на iPhone (опять же, я точно не знаю, так что, возможно, попробуйте) FBO позволяют рисовать непосредственно в текстуру, как если бы это был другой контекст рендеринга.

4 голосов
/ 17 мая 2011

Трафаретный буфер - лучший способ приблизиться к этому наверняка ... Вы сэкономите время, процессор и потенциальные проблемы .., Они доступны на Iphone, вам просто нужно создать поверхность OpenGlES 2.0 (не gles 1.0 или 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

Найти этот пример: http://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.c

Вот визуальный результат: http://www.opengl.org/resources/code/samples/glut_examples/examples/stenciltst.jpg

Я внедрил такой же инструмент ластика с этим на Android и iPhone, и он работает как шарм!

Удачи!

Ура!

2 голосов
/ 16 ноября 2008

Вы можете использовать буфер трафарета для этой операции. Трафаретный буфер - это специальный буфер, в котором хранится информация для каждого пикселя, аналогичная буферу глубины. В отличие от буфера глубины, вы решаете, как шаблонный буфер изменяется во время рисования и как он влияет на решение рисовать в цветной буфер или нет. Для этого вы можете установить конкретные состояния перед любой операцией рисования. Вот что вы делаете:

  • В то время, когда пользователи стирают, нарисуйте «стертую» область в буфер трафарета (используя StencilOp, см. ниже). Вы можете использовать любой рисунок GL функция для этого.

  • В каждом проходе рендеринга первый тираж фон (если вы хотите, вы можете используйте отрицательный тест трафарета здесь, чтобы Нарисуйте только «стертую» часть фон - может увеличиться производительность).

  • Затем включите проверку трафарета для всех другие операции рисования. OpenGL будет тогда рисовать только на «не стираемые» регионы.

Функция для установки того, как буфер трафарета должен влиять на рисование (или нет): glStencilFunc ()

Функция для определения влияния буфера на сам трафарет: glStencilOp ()

Дальнейшее объяснение, также с аргументами для них: http://www.opengl.org/resources/code/samples/sig99/advanced99/notes/node117.html

2 голосов
/ 15 ноября 2008

Вы не предоставляете много информации, но я предполагаю, что вы сохраняете все, что они "рисуют" в буфере, а затем рисуете это на экране следующим образом:

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

С рисованием-> ImageData является буфером. Что вы можете сделать, так это создать отдельный фоновый буфер и нарисовать его первым. Затем инструмент стирания просто уберет буфер рисования (повернув все значения, включая альфа, вверх).

Чтобы это решение работало, вам нужно включить смешивание и отключить проверку глубины .

 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);

Это то, что вы ищете?

0 голосов
/ 04 июля 2010

Можно использовать режим glBlendFunc (GL_ONE, GL_ZERO).

...