Модераторы: Rickert, Alexeis, BorisVorontsov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Рисование в заданной области, Как сделать рисование по маске? 
V
    Опции темы
explorer
  Дата 20.5.2009, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



Здравствуйте, уважаемые знатоки OpenGL!
Хотелось бы узнать, возможно ли в OGL сделать рисование по маске. Поясню подробнее вопрос. 
Допустим, имеется окно. Хотелось бы задать в этом окне произвольную форму, например, полукруг (требуется не прямоугольная форма, а "кругоподобная").  И уже после указания этой формы хотелось бы иметь возможность рисования только в ней. Например, я рисую залитый прямоугольник, в который вписана та форма, и на выходе получаю залитый полукруг. Т.е. изображение отсеклось по краям заданной области. 
Возможно ли такое впринципе и какие стандартные средства для этого можно использовать (без использования GLUT)?

--------------------
 
PM MAIL WWW ICQ   Вверх
Alexeis
Дата 20.5.2009, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 5
Всего: 459



Есть такая функция glStencilFunc она позволяет задавать какие пикселы выводить а какие нет.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
explorer
Дата 21.5.2009, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



Спасибо, Alexis! Нашел всю необходимую инфу и все получилось. 
Если кто тоже занимается акой проблемой, то вот вам моё решение:
Код

glNewList(surfaceList, OpenGL.GL_COMPILE);
      glClearStencil(0);
      glClear(GL_STENCIL_BUFFER_BIT);
      glEnable(GL_STENCIL_TEST);

      /* Настраиваем буфер так, чтобыон запомнил все, что мы нарисуем */
      glStencilFunc(OpenGL.GL_ALWAYS, 1, 1);
      glStencilOp(OpenGL.GL_KEEP, OpenGL.GL_KEEP, OpenGL.GL_REPLACE);

      /* Заполяем буфер объектом с заливкой, иначе наша маска будет в виде контура */
     glBegin(GL_TRIANGLES);
          for (int i = 0; i < triangles.Count; i += 3)
          {
               glVertex2f(triangles[i].Х,  triangles[i].Y)
               glVertex2f(triangles[i + 1].X,  triangles[i + 1].Y);
               glVertex2f(triangles[i + 2].X,  triangles[i + 2].Y);
          }
    glEnd();

    /* Теперь пиксель будет нарисован, если его stencil бит равен 1 */ 
    glStencilFunc(GL_EQUAL, 1, 1);
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glEndList();


И не забываем отключать Stencil test там, где он не нужен. Иначе у вас будут лишние тормоза.
--------------------
 
PM MAIL WWW ICQ   Вверх
explorer
Дата 21.5.2009, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



Ну вот, рано я обрадовался  smile Только обновил драйвер на самый свежий, как от буфера остались рожки да ножки... Игнор полный. Все рисуется так, как будто буфера этого в помина нет. Может быть я в коде чего не так написал для инициализации этого буфера? Посмотрите, плиз. Код в посте выше. 
--------------------
 
PM MAIL WWW ICQ   Вверх
Alexeis
Дата 21.5.2009, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 5
Всего: 459



Цитата(explorer @  21.5.2009,  14:22 Найти цитируемый пост)
Все рисуется так, как будто буфера этого в помина нет.

  Может OpenGl инициализируюется по другому?


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
explorer
Дата 21.5.2009, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



То есть? Вроде бы об инициализации самого OGL речи не велось.. 
Вообще у программки довольно странное поведение. Вот например
Код

            glEnable(GL_STENCIL_TEST);
            glLineWidth(vertical.GridVWidth);

вызвращает ошибку 1282 (GL_INVALID_OPERATION).
А если ширину линии ставим до включения теста, то все ок.. Вообще ничего не понимаю  smile

Добавлено через 5 минут и 7 секунд
А, нет, с линиями все хорошо. Просто переменная была неицилизирована.. Эх.. 
Однако, первое применение буфер арасположено перед этими глючным местом в коде, и он-таки не отрабатывает ничего как надо. Он просто не проходит... Вот поэтому у мен я и возникли сомнения, что Stencil test у меня настроен правильно.
--------------------
 
PM MAIL WWW ICQ   Вверх
explorer
  Дата 22.5.2009, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



Ага. Кое-что пряснилось. До этого стояли дрова из стандартного набора Висты, а теперь родные NVidia. 
Майкрософт использует "нулевой" stencil буффер (0 бит) в своих драйверах, в то время как NVidia и ATI 8-битные буферы.
Теперь задача в том, чтобы сменить битность буфера. Насколько я понимаю, это делается в инициализации OpenGl (ChoosePixelFormat и иже с ними smile). Теперь стало ясно, почему вдруг отключился stencil после смены дров. 
--------------------
 
PM MAIL WWW ICQ   Вверх
explorer
Дата 22.5.2009, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



Ура!!! Заработало!!!!  smile  smile  smile 
Люди, документация - это наше всё!!!!! Не ленитесь, читайте, и будет всем счастье!  smile 
Проблема была в битности буфера, как и намекал Alexeis.

Но теперь проблема в том, чтобы как-то опознать изготовителя видеокарты (а точнее производителя драйверов), чтобы корректно проинициализировать OGL? 
--------------------
 
PM MAIL WWW ICQ   Вверх
Alexeis
Дата 22.5.2009, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 5
Всего: 459



  Грубо говоря дравера OpenGL от Microsoft это вообще не драйвера, а тупая эмуляция без аппаратной поддержки, я не стал бы даже запускать программу на них... Это может быть далеко не первый сюрприз. Я бы посоветовал просто уведомлять юзера о необходимости установки драйверов от производителя. Гм.. а вот как узнать... Ведь имя библиотеки как было так и осталось... Можно пройтись в реестре по спискам установленных программ и поискать там имена инсталях. Можно занести в базу имена вспомогательных библиотек для OpenGl и при загрузке основной проверять загружены ли библиотеки от производителя (по именам). Можно по ChoosePixelFormat проверить доступны ли режимы которые не поддерживает стандартный майкрософтовский. Если нужного режима нет то требовать установку драйверов от производителя.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
explorer
Дата 24.5.2009, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



ChoosePixelFormat вообще не подойдет, т.к. проверка его идет еще до создания контекста smile А это значит, что, по-крайней мере StencilBufferBit всегда будет 0, хоть что делай :(

По поводу просмотра реестра я сразу вспомнил свой опыт с поиском установленного ПО. Там может быть множество вариаций, к тому же производители могут быть с юмором. 

Придумал вот что. У меня есть утилитка для конфигурирования софтинки моей. Естественно, спрашивать пользователя  том, чего у него там стоит и с какими драйверами - это дохлый номер. Никогда не рассчитываю, что пользователь достаточно грамотный в таких вопросах. Поэтому сделал просто. В ту же утилитку добавил небольшую "картинку", созданную при помощи OpenGL с использованием stencil. При сохранении настроек появится вопрос "картинку видим?"  smile Проще быть не может для пользователя smile Варианты ответа либо да, либо нет. Если нет, переконфигурирую специльно заточенный для этого класс с поддержкой OGL  smile  и заставляю взглянуть на форму еще раз. Если и на сей раз эффекта нет, то тут да, придётся отослать несчастного за дровами свежими  smile 


--------------------
 
PM MAIL WWW ICQ   Вверх
Максим80
Дата 19.6.2009, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 1.6.2009

Репутация: нет
Всего: нет



Цитата

glNewList(surfaceList, OpenGL.GL_COMPILE);
      glClearStencil(0);
      glClear(GL_STENCIL_BUFFER_BIT);
      glEnable(GL_STENCIL_TEST);
      /* Настраиваем буфер так, чтобыон запомнил все, что мы нарисуем */
      glStencilFunc(OpenGL.GL_ALWAYS, 1, 1);
      glStencilOp(OpenGL.GL_KEEP, OpenGL.GL_KEEP, OpenGL.GL_REPLACE);
      /* Заполяем буфер объектом с заливкой, иначе наша маска будет в виде контура */
     glBegin(GL_TRIANGLES);
          for (int i = 0; i < triangles.Count; i += 3)
          {
               glVertex2f(triangles[i].Х,  triangles[i].Y)
               glVertex2f(triangles[i + 1].X,  triangles[i + 1].Y);
               glVertex2f(triangles[i + 2].X,  triangles[i + 2].Y);
          }
    glEnd();
    /* Теперь пиксель будет нарисован, если его stencil бит равен 1 */ 
    glStencilFunc(GL_EQUAL, 1, 1);
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glEndList();

я вставил этот код в функцию Display и у меня он не компилируется! может я чето не так делаю? Помогите пожалуйста!

Это сообщение отредактировал(а) Максим80 - 19.6.2009, 12:43
PM MAIL   Вверх
explorer
Дата 25.6.2009, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 104
Регистрация: 26.2.2008

Репутация: нет
Всего: 2



Кхм... Хочу немного извиниться за введение в заблуждение smile 
Дело в том, что это код на C#, и он использует специальный контрол с поддержкой OpenGL. 

Вы же, Максим80, вероятно, работаете с С++. Что в вашем случае надо поправить? Да самую малость (убрать все лишнее, вот так):
Код

static uint surfaceList = 1;
glNewList(surfaceList, GL_COMPILE);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
/* Настраиваем буфер так, чтобыон запомнил все, что мы нарисуем */
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
/* Заполяем буфер объектом с заливкой, иначе наша маска будет в виде контура */
glBegin(GL_TRIANGLES);
/* Здесь я изменю для облегчения примера. Будет нарисован один треугольник. */
glVertex2d(0, 0);
glVertex2d(50, 100);
glVertex2d(100, 0);
glEnd();
/* Теперь пиксель будет нарисован, если его stencil бит равен 1 */ 
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDisable(GL_STENCIL_TEST);
glEndList();


Теперь этот пример точно скомпилится.

В функцию Display этот код вставлять не надо! Там же создается дисплейный список (для повышения производительности). Так как Display вызывается в цикле, то этот список будет пересоздан несколько тысяч раз. Зачем же так издеваться? smile

Этот код  должен быть помещен в Init() или что-то подобное, где происходит настройка OpenGL (в самый конец, после всх операций по инициализации OpenGL'я).

В функцию Dislpay() же нужно вставить вот что: 
Код

glCallList(surfaceList);


Но и теперь эффекта маски не будет, ведь StencilTest не включен.

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

Код

...
glCallList(surfaceList); // после этой строки добавляем свои.
glEnable(GL_STENCIL_TEST); // включаем тест маски
glSetColor3f(0, 1, 0); // устанавливаем цвет
glRectd(0, 0, 200, 200); // пробуем залить квадрат 200 x 200 зеленым цветом
glDisable(GL_STENCIL_TEST); // выключаем тест маски
...


После выполнения этого кода будет залита только та область квадрата, которая попала в нашу маску.
--------------------
 
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Вы можете найти полезным что...
Alexeis
Rickert
  • Английская документация по DirectX лежит где-то здесь.
  • Английская документация по OpenGL лежит где-то там.
  • Гейм-дев у нас обсуждают где-то тут

Ждём вас! С уважением, Alexeis, Rickert.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Мультимедия, OpenGL/DirectX | Следующая тема »


 




[ Время генерации скрипта: 0.1154 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.