Комментарий к Статье Выбор объектов средствами OpenGL
По поводу буфера цвета. Есть у него один большой недостаток - он работает только в труколоре(24/32 bpp). Для режимов которые работают с палитрой (например 16bpp) этот способ работать не будет. Так же нужно не забывать при отрисовке буфера цвета выключать дизеринг(автоматическое внесение в картинку небольшого цветового шума): glDisable(GL_DITHER)
robot
Можно еще и glScissor поюзать...
Robin
>Для режимов которые работают с палитрой (например 16bpp)
16bpp - это не палитровый режим.
>выключать дизеринг
Дизеринг работает только в палитровом режиме, в котором надо пить йад, а не объекты выбирать.
>автоматическое внесение в картинку небольшого цветового шума
Опять нет. Перенос шумов квантования цвета в высокочастотный диапазон.
Вот второй способ честно говоря не понял. Лишний рендер + использование glReadPixels никогда быстрыми не были.
Я вот сейчас использую способ, кажущийся мне наиболее оптимальным. Мне нужно выбрать объекты, попадающие в рамку. Сначала нахожу 3д точки вершин этой рамки через glReadPixels & gluUnProject, а затем проверяю попадание объектов в трапецию.
А так ищу способ более быстрый, так как вышеописанный способ снижает производительность на ~15%.
У меня есть несколько вопросов на которые я никак не могу найти ответа.
Какое максимальное количество объектов выбора при использовании буфера выбора и как оно определяется?
Влияет ли на производительность количество объектов в буфере выбора?
P.S. Опыт с OpenGL имею не большой, пока использую только 2D.
Имеется перспективное приложение на OpenGL, использую буфер выбора для выбора около 40 тыс. объектов при этом имеется не большая задержка (в моем случае она в принципе не мешает). Причина задержки возможно и не в выборе объектов. Проблема в том что после добавления еще 40 тыс. объектов начали появляться не систематические ошибки :(
в первую очередь спасибо автору. статья хорошая, понятная. написана полюдски, без академического мат. выпендрёжа, и плотной подачи необъяснённых терменов )
прикольная оптимизация у меня тут придумалась к методу цветного выделения)
цвет в буфере кадра 4 байта.
размер dword 4 байта.
можно сделать так чтобы объекты сцены были в массиве, индексом которого была бы переменная DWORD полученная "сливанием подкурсорных" RGBA
DWORD emptyId = 0; // айдишник используемый для определения невыделения( промаха при щелчке)...для снятия выделения например.... DWORD maxId = 65535; // айдишник больше которого быть неможет!! (пожалуй единственное ограничение) DWORD actualId = emptyID; // айдишник для определения очередного айдишника при регистрации нового объекта. DWORD selectedId = emptyId; // для доп обрисовки выделенного объекта. .... class CGeomObject { // объект сцены. например стенка! /* .... вершины всякие, индексы, текскурды ну и всё такое .... */ DWORD id; // цыфра которая будет разделена на 4 байта, и переведена в цвет этого объекта. соответствует его индексу в массиве void create(dword _id); // создаёт и переписывает _id в id, вызывается при регистрации объекта void loadFromFile( std::string fn); // загружет из файла void drawToColorBuffer( ); // рсиует себя включенным цветом равным id разложенным на 4 байта void drawToScreen( ); // рисует всё со всем по нормальному }; ... void registerObjectFromFile( std::string fn) { // загрузка нового объекта с HDD if ( actualId+1 >= maxId) erroMsgAndReturn( "OOPS!!! больше объектов нельзя!"); actualId ++; //получили новый айди CGeomObject temp; temp.Create( actualId); // создаём temp.loadFromFile( fn); // грузим ojbectArray[actualId] = temp; //переписали его в кучу с другми объектами сцены? } void select( int x, int y) { /* сохранить значения glScissor тут было бы неплохо установить glScissor в районе кооррдинаты точки подмышкой. ScissorTest делается для пиксела впервую очередь и если этот тест непроходит все последующие шаги отрисовки точки OGL невыполняются а также выключаем свет текстуры и всё что может сделать проекцию объекта неравномерно закрашенной его цветом. */ byte r,b,g,a; convertDWORDTo4b( emptyId, r,g,b,a ) ; // получаем цветовое проедставление айдишника emptyId glClearColor( r,g,b,a); // чистим буфер цветом emptyId glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; for ( DWORD i = emptyId; i <= actualId; i++) objectArray[i].drawToColorBuffer( ); //выводим разнозцетные объекты на экран в области ограниченной glScissor glReadPixels( ....); // получаем цвет из под мышки записываем в переменные r, b, g, a DWORD Id; convert4bToDWORD( r,g,b,a, Id) ; // собираем DWORD- цыфру из четырёх компонентов цвета. if ( Id == emptyId) deselectAll( ); //шелкнули "вбуфер" else selectedId == id; // возвращаем на место координаты glScissor, текстуры, свет материалы и т.д } void render( ) { // чистим экран for ( DWORD i = emptyId; i <= actualId; i++) objectArray[i].drawToScreen( ); //выводим нормальную картинку объекта. if ( selectedId != emptyId ) { glColor3f( 1,0,0); // подсвечиваем красным что он выделен objectArray[ selectedId ].drawToScreen( ); // рисуем его!!! } }
вот.... минимум математики, и прямая адресация к объектам! массив насколько я знаю самый быстрый... перевод чисел из дворд в байта - делается побитовыми операциями. что тоже оч быстро делается.
а чтобы выделять множество объектов "насквозь" через всю сцену можно так
void select(int x, int y) { /* сохранить значения glScissor тут было бы неплохо установить glScissor в районе кооррдинаты точки подмышкой. ScissorTest делается для пиксела впервую очередь и если этот тест непроходит все последующие шаги отрисовки точки OGL невыполняются а также выключаем свет текстуры и всё что может сделать проекцию объекта неравномерно закрашенной его цветом. */ byte r,b,g,a; convertDWORDTo4b( emptyId, r,g,b,a ) ; // получаем цветовое проедставление айдишника emptyId glClearColor( r,g,b,a); // чистим буфер цветом emptyId glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; // чтобы цвета ВСЕХ объектов могли быть прорисованы под точкой курсора. депф_тест может нам напортачить, и спрятать коечто. поэтому выключаем его. glDisable( GL_DEPTH_TEST) ; for ( DWORD i = emptyId; i <= actualId; i++) { objectArray[i].drawToColorBuffer( ); //выводим ОДИН ОЧЕРЕДНОЙ объекты на экран в области ограниченной glScissor glReadPixels( ....); // получаем цвет из под мышки записываем в переменные r, b, g, a DWORD Id; convert4bToDWORD( r,g,b,a, Id) ; // selectedStack - стэк хранящий значения DWORD - Айди "щёлкнутых" объектов // второе условие чтобы небыло одинаковых значений подряд. // т.к объекты могут быть в стороне или глубже, а под курсором один и тотже. if ( ( Id != emptyId) && ( Id != selectedStack.getPrevId( ) ) ) selectedStack.addId( selectedId ); // добавляем его в стек выделенных объектов } // возвращаем glScissor, текстуры, свет материалы и т.д } void render( ) { // чистим экран for ( DWORD i = emptyId; i <= actualId; i++) objectArray[i].drawToScreen( ); //выводим нормальную картинку объекта. glColor3f( 1,0,0); // подсвечиваем красным выделеные объекты while ( !selectedStack.isEmpty( ) ) //пока стек непуст objectArray[ selectedStack.get( ) ].drawToScreen( ); // рисуем очередного выделенного }
вот.... на куски прошу нервать. в коде косяков много, ибо тут всё абстрактно, непроверено, неоткомпилено. (влом чесноговоря) и писалось прям тут походу.
просто как иллюстрация к идее. что думаете? имеет такая оптимизация право на жизнь?
во блин!
Мою бредятину подняли :)
Мне тогда 17 лет было, а на дворе 2003 год.
Но я старался, честно :)
http://www.gamedev.ru/flame/forum/?id=13515
а тут я свой ник пытался продать. Точнее id, ибо фсотне :)
//comment
ммм... как-бы так и делается...
Larik
за мой сколько даш? )))
17 лет в 2003-м ) тебе как бонус могу ещё уин продать) там год рождения твой в конце)
ну или почти твой.
MarkoPolo
вот что не придумаеш уже ктонить да спёр...
Ну хоть придумалось живое и то радует.
Всем привет.
Очень заботит один вопрос.
При использовании буфера цвета для выбора обьекта обязательным условием должно быть чтобы объекты были разных цветов?
Или есть какая нить хитроумная фича как это можно обойти. Перебывал на многих сайтах но понял что ни у кого такого вопроса даже не возникало.
largo20007
> Или есть какая нить хитроумная фича как это можно обойти.
Есть какая-нибудь объективная причина, ради которой это стоит "обходить"?
Разумеется есть. Смысл делать например графический редактор если потом чтобы смоделировать в нем например машинку потребуется чтобы каждая деталька ее была разного цвета :-)
largo20007
> Или есть какая нить хитроумная фича как это можно обойти.
Просто не используй буфер выбора, пиши свой функционал...
Дак дело то как раз не в буфере выбора, а в буфере цвета. По любому есть какое нибудь улучшение данного алгоритма чтобы пользователь мог моделировать множество фигур одинакового колора и потом выбирать их. Я думал кто нить подкинет дельную мысль. Иначе как раз придется переключиться на второй вариант-буфер выбора
Тема в архиве.