Opengl полезные и бесполезные мелочи


Содержание

11.2 Библиотека GLUT — создание примитивов, трансформация, перенос и масштабирование объектов в OpenGL.

Необходимые знания:

Мы создали оболочку программы, разместив все необходимые элементы управления. Принцип работы программы максимально прост. В зависимости от значений элементов формы, мы будем выбирать то, какие примитивы с какими параметрами и в каких режимах мы будем рисовать.

Перед визуализацией примитива будут выполняться функции переноса, поворота и масштабирования – данные функции будут ориентироваться на состояние ранее объявленных переменных. Данные переменные, в свою очередь, обновляются при перетаскивании ползунков, нажатии на checkBox или изменении элементов comboBox.

Объявление начальных переменных и инициализация OpenGL выглядит следующим образом:

Вы должны добавить обработку событий изменения элементов trackBar, событие отклика таймера и обработку изменения значений элементов checkbox и comboBox.

Ну и собственно функция отрисовки сцены. Обратите внимание на то, что перед использованием трансформации обязательно необходимо поместить состояние текущей матрицы в стек матриц, чтобы дальнейшие преобразования затронули только визуализируемые объекты.

Примеры работы программы:
Рисунок 1. Пример создания и управления трехмерными объектами с помощью OpenGl и библиотеки GLUT.
Рисунок 2. Пример создания и управления трехмерными объектами с помощью OpenGl и библиотеки GLUT.

Узкие места производительности OpenGL [закрыт]

На днях провёл небольшой анализ производительности OpenGL. Выяснилось, что самый проблемный момент заключается в выводе изображения на экран, когда полигоны рисуются поверх других полигонов. Всего лишь пару тысяч плоскостей способны привести к значительным тормозам, хотя это просто мелочь для видеокарты. Судя по всему, проблемы начинаются уже на уровне вершинного шейдера. Изменение дальности обзора помогает исправить эту ситуацию, так как матричные преобразования происходят в вершинном шейднере, но всё же это не решение проблемы.

Закрыт по причине того, что непонятна суть вопроса участниками dlarchikov, DeKaNszn, fori1ton, Mirdin, PashaPash 27 апр ’15 в 9:52 .

Постарайтесь писать более развёрнутые вопросы. Для получения ответа поясните, в чём именно вы видите проблему, как её воспроизвести, что вы хотите получить в результате и т. д. Приведите пример, наглядно демонстрирующий проблему. Если вопрос можно переформулировать согласно правилам, изложенным в справке, отредактируйте его.

5 ответов 5

Пара тысяч плоскостей это мелочь для вершинного шейдера. Для фрагментного шейдера это очень много, когда они рисуются поверх друг друга. Если плоскость занимает весь экран, то фрагментный шейдер сработает для каждого пикселя (для экрана 1280×1024 — 1,3 миллиона раз!). Если это всё умножить на «пару тысяч», то получится 2,6 миллиарда (в худшем случае, когда все плоскости полностью загораживают экран). Видеокарта такое плохо потянет. Даже если фрагментный шейдер очень простой, то происходит постоянная перезапись памяти. Один и тот же пиксель будет перезаписываться 2000 раз. Тест глубины поможет сократить это количество вызовов шейдера и перезаписей пикселя, если отсортировать все плоскости по удалению от камеры.

Алгоритм очень сложен. Если бы он был прост, его уже бы давно применяли везде и вся. Сортировать нужно, хотя бы приблизительно.
Ещё есть способ, называемый «Запрос о преградах». В книге «OpenGL Суперкнига» (OpenGL Superbible) авторов Райта, Липчака и Хаемеля (Wright, Lipchak, Haemel) есть целая глава, посвящённая этому методу. Всё делается специальными функциями OpenGL, так что изобретать велик не придётся. Смысл в том, чтобы сначала отобразить объекты простыми фигурами (людей с помощью параллелепипедов, сферы с помощью кубов или октаэдеров и т.д.), а потом проверить, какие из этих простых фигур не видно. Если простая фигура не видна, то не рисовать сложный объект, сопоставимый ей. Если не изменяет память, то фигуры можно загружать свои, настраивая под нужды. В любом случае почитайте.

Если что, то вот ссылка на эту главу в издательстве Вильямс: Запросы о преградах (pdf)

OpenGL использует z-буфер, чтобы заслонённые пикселы не появлялись на экране. Но вся проблема в том, что даже если он их не рисует и не вызывает фрагментный шейдер, то он всё равно их !обрабатывает!, хотя бы потому, что он сравнивает значения их глубины со значением в z-буфере. А теперь давайте представим, что будет,если единственный ближайший полигон заслонил все остальные? Конечно же, каждый заслонённый примитив будет обрабатываться, к каждому из них применятся алгоритм растеризации (для того чтобы узнать положение пиксела на экране), и, конечно же, значение каждого обрабатывающегося пиксела будет сравниваться со значением в z-буфере, с последующим отбасыванием самого пикслела. Ненужная работа! Отсюда и тормоза! А нам такой порнографии не надо. Премудрости с z-буфером в принципе не помогут. Надо вообще отсекать невидимые примитивы, чтобы не выполнялась их растеризация. Вопрос: как?

В любом случае, ему нужно делать так, чтобы треугольники, фрагменты которых будут полностью отсеяны в конечном изображении, не попадали на конвеер. Я понимаю, что говорю очевидные вещи, но решение проблемы кроется в понимании её мелких деталей. Мне кажется, что алгоритмы Z-Буферизации тут никоем образом не помогут. Нужно работать с нечто большим, а именно, с треугольниками. И по тому я думаю, что запросы о преградах будут хорошим решением (не факт, что лучшим, но всё же хорошим).

Топ дорогих и бесполезных вещей для миллионеров-шопоголиков

Любой человек, который хоть на малую толику подвержен такому явлению, как шопоголизм (так называемая магазиномания или непреодолимое влечение к покупкам), не раз приобретал в своей жизни что-то абсолютно бесполезное. Если не копаться в глубинах психики, то объяснение подобным покупкам достаточно простое – они были сделаны под влиянием мимолетного желания купить эту самую бесполезную фиговину.

Однако даже если вы не шопоголик, признайтесь – ведь было? Было же такое, что вы возвращались с похода по магазинам, и в пакете с необходимыми вещами лежала какая-то абсолютно ненужная вам ерундовина, иногда дешевая, а иногда не очень. И вот вы глядите на эту вещь и задаете себе сакраментальный вопрос: ЗАЧЕМ?! Зачем я купил эту фигню?! Вопрос остается без ответа, а эта самая фигня – без применения.

Однако представьте себе на минуту, что вы – миллионер! На что вы стали бы тратить свои миллионы? На яхты, машины, дома, украшения? Да, вы смогли бы тогда купить себе практически все, что пожелаете. Но вы уверены, что среди ваших покупок не нашлось бы места тем самым пресловутым «ерундовинам», «штуковинам» и «фиговинам»? Гарантировать этого нельзя, тем более, что рынок уже приготовил для «бедных» миллионеров целый вагон и маленькую тележку таких вот бесполезных вещей.

Предлагаем вашему вниманию список из наиболее бестолковых и бесполезных товаров, которые себе может позволить приобрести лишь весьма небедный человек. Таковых набралось аж 30 вещей, однако это вовсе не означает, что список исчерпан.


Кроме того, почему бы простому миллионеру не позволить себе золотые выключатели или эксклюзивную туалетную бумагу? Вопрос «ЗАЧЕМ?!» придет потом… Или не придет вовсе! Итак, вы – миллионер-шопоголик, который вернулся домой с шопинга и обнаружил в багажнике своего шикарного автомобиля следующие вещи.

Сложно представить ситуацию, при которой может понадобиться такая вот штуковина. Впрочем… Возможно, вы принимаете гостей в вашем загородном особняке, и хотите, чтобы входные двери в этот день были открыты. Негоже миллионеру подпирать эту дверь кирпичом или камнем! И тут ему на помощь пришли услужливые производители, которые изготовили вот такую вот увесистую фиговину за три с половиной штуки долларов. И пусть на первый взгляд этот дверной упор выглядит абсолютно бесполезной тратой денег. А вы попробуйте его приподнять! Тяжело? В таком случае, будем считать, что деньги были вложены в недвижимость!

Сложно переоценить пользу в хозяйстве обычного канцелярского ножа. Скажем, вы решили заменить самостоятельно всю проводку в доме – канцелярский нож отлично поможет вам справиться с изоляцией. А если вы – миллионер-шопоголик, который решил самостоятельно поменять всю проводку в своем доме? Звучит как фантастика. А канцелярский нож за 95 баксов – это не фантастика? Ведь только миллионеру, делающему ремонт собственными руками, придет в голову купить этот режущий чудо-инструмент с отламывающимися по мере износа лезвиями.

Следующий товар прямо таки создан для миллионеров, прокладывающих проводку в доме своими руками с помощью канцелярского ножа за 95 долларов. Вы только представьте себе: работа кипит, но наступает время обеда, миллионер пододвигает к себе дверной упор за 3500 долларов, садится на него, и достает лапшу… нет, не доширак – это же миллионер! Лапшу за 43 бакса в стаканчике, украшенном изготовленной вручную фольгой с золотым тиснением. В набор входит вилка и небольшая скатерть-салфетка. Приятного аппетита, уважаемые миллионеры-гастарбайтеры!

Не надоело «потчевать» свою пятую точку копеечной туалетной бумагой? Да, вы не миллионер, но ведь можно же один раз в жизни позволить себе купить шикарную цветную туалетную бумагу за 20 баксов, закрыться с ней в туалете и наслаждаться жизнью! Пусть хоть ваше седалище вкусит, так сказать, шикарной жизни. Скажете, бесполезная вещь? Тогда вспомните, сколько времени вы потеряли, подбирая ершик для унитаза под цвет плитки! Почему бы не подобрать бумагу аналогичной цветовой гаммы, тем паче, что сейчас это не проблема.

Кубики льда из холодильника – это для тех, кто ничего не понимает в колбасных обрезках. Настоящий эстет-миллионер-шопоголик не будет наполнять формочки питьевой водой и ждать, пока они замерзнут. Он закажет за 40 баксов штука вырезанные вручную ледяные шарики из самого настоящего ледника с канадских гор. И не важно, что из-за таких вот заскоков в канадских горах скоро не останется льда – есть же еще Эльбрус. Эверест, в конце концов! Будет стоить, конечно, подороже, но ведь и коньяк такие люди пьют не за 400 рублей.

Миллионеры – это ведь тоже люди. И у этих людей рождаются дети, которые потом ходят в школы. Школы эти, правда, не совсем обычные, но ведь и дети не простые – дети миллионеров. А непростым детям миллионеров просто по статусу положены золотые рюкзаки. Только вот ведь беда – в город ребенка самого с таким рюкзаком не выпустить! Не придумывать же для сумки, хоть и золотой, какую-то сложную систему сигнализации, в конце концов. А, ладно, пусть поваляется рюкзачок где-нибудь в кладовке, рядом с кучей таких же бесполезных, но жутко дорогих ерундовин.

Итак, вы – миллионер. Какой телефон вы себе приобретете? Vertu Diamond? Или Vertu Cobra? Или, быть может, Diamond Crypto Smartphone? Господи, как же тяжело выбрать среди этого изобилия инкрустированных бриллиантами и золотыми вензелями наиболее подходящий телефон! А ведь по нему надо будет еще и звонить… Хорошо хоть с Bluetooth гарнитурой ломать голову не придется. Вот она, простая гарнитура, обычные бриллианты. И самое главное, совсем же недорого – всего 50 штук баксов! И как же вы раньше без нее обходились?

Если вы богаты… Если только вы по-настоящему богаты, то… почему бы и нет? Золотые скобы для степлера за 175 баксов – это та самая вещь, которой вам и не хватало. Причем, производитель вовсе не настаивает, что эти скобы должны использоваться направо и налево. Но когда вам надо показать, что у вас этих денег на самом деле куры не клюют, то золотые скобы для степлера – самое то. Скрепленные такими скобами, к примеру, приглашения на свадьбу не стыдно вручить самым дорогим (в прямом смысле слова) гостям. Но каким же безупречным должен быть степлер, чтобы скобы не портил?!

Вот оно! Ну, наконец-то у миллионера-чудака, который самостоятельно прокладывает в доме проводку с помощью супер дорогого канцелярского ножа и ест лапшу быстрого приготовления из стаканчика ручной работы, появилась возможность установить достойные выключатели. Нет никаких сомнений, что в доме, в котором на стенах установлены подобные выключатели, имеется туалетная комната, в которой стоит обязательный золотой унитаз. Мы его даже в этот список включать не стали – кто посмеет замахнуться на святое, назвав золотой унитаз в доме миллионера бесполезной вещью?!

Как, вы не знаете, что такое фрисби? Быть может, вы и такую игру, как алтимат, не знаете? Впрочем, неудивительно – эта командная игра, в которой игроки пасуют друг другу летающий диск (собственно, фрисби), появилась в России относительно недавно. На самом деле, игра достаточно увлекательная. Но вот ведь вопрос – захотите ли вы, даже будучи весьма состоятельным человеком, чтобы ваш фрисби, который вы приобрели за 305 долларов, залетел навсегда куда-нибудь в кусты к соседям? Если вас не пугает такая перспектива, тогда срочно отделывайтесь от дешевых пластиковых фрисби и покупайте фрисби для богатых. Говорят, они даже лучше летают…

Ну, наконец-то. Хоть одна мало-мальски полезная вещь! Как, вы не знаете, для чего необходима баночка для теннисных мячиков? Для хранения теннисных мячиков! Теннис – это вам не фрисби какое-нибудь! Теннис – это игра миллионеров и политиков. Это игра элиты. Ну, а коль скоро вы причисляете себя к элите, тогда почему ваши элитные теннисные мячи должны храниться в каком-нибудь пластиковом тубе? Тем более что производитель заранее позаботился о такой мелочи, изготовив специальный туб из чистого серебра за полторы штуки баксов для теннисных мячей.

Как известно, бренды стоят недешево. И коль скоро вы, будучи миллионером, знаете эту простую истину, в вашем доме наверняка немало брендовых вещиц, за которые вы не стеснялись выкладывать кругленькие суммы. В таком случае, специально для вас есть еще одна идеальная бесполезная вещь. Она практически так же бесполезна, как и гантели, которые мы покупаем в воскресенье для того, чтобы в понедельник задвинуть их навсегда под диван. Речь идет о скейтборде за 8 штук баксов. Почему бесполезная, спросите вы? А вы видели хоть одного миллионера на скейтборде, спросим мы.

Маразм крепчает. А с ним увеличиваются и цены на самые бесполезные и дорогие вещи. Нет, конечно – если вы считаете полезным кухонный нож за 39600 долларов, тогда вопросов нет! Но вряд ли на кухне какого-нибудь миллионера вы увидите в пользовании такой вот нож с серебряной ручкой инкрустированной восемью бриллиантами. Место его все на той же полке бесполезных вещей, так как таким ножом разделывать рыбу или разрезать мясо просто грешно! Отмывать-то его придется обычным средством для мытья посуды… Или нефтью?

А вот и он! Нет, это не унитаз из черного золота (хотя такое золото действительно существует!). Это всего лишь стульчак. Нет, это не обычный пластиковый стульчак китайского производства за 5 баксов. Это уникальный стульчак из углеродного волокна, который отличается удивительной практичностью. Причем, практичность эта заключается не в отсутствии необходимости мыть такой вот девайс. Практичность заключается в удивительной прочности подобной крышки и стульчака. Поверьте – на нем еще ваши внуки сидеть будут! Если, конечно, вы не купите им золотые унитазы…

В мире бесполезных вещей есть такие вещи, которые даже на фоне других самых бесполезных вещей выглядят еще более бесполезными. Вот и данный девайс, который предназначен… понятно, для чего он предназначен, выглядит весьма бесполезным с практической точки зрения. Впрочем… Данный вибратор сделан из 24-ех каратного золота, и он отлично будет смотреться, скажем, на каминной полке, на черном бархате. Главное – не говорить своим гостям, для чего именно предназначен этот малыш. Хотя, кто его знает, какие там нравы!

Ну, хорошо, хорошо! Допустим, что вы – миллионер. Допустим, что вы можете себе позволить приобрести подобную игру. Но где же вы найдете столько бездельников, чтобы регулярно собираться за этой роскошной (в буквальном смысле слова) игрой, чтобы продать или купить парочку ненастоящих домов и заводов? Скорее, они в этот момент оперируют настоящими заводами и домами. Неужели в кладовку? За такие деньги?! Отнюдь! Если у вас есть дети, которые уже могут играть в «Монополию», отдайте игру им – пусть развлекаются. Да вот только растеряют они все фишки из золота в семь карат…

Илон Маск рекомендует:  transition в CSS

Чем займется меняющий проводку в доме своими руками миллионер-чудак, о котором мы говорили выше, после того, как закончит зачищать изоляцию? Правильно – захочет пропылесосить, убрав ошметки изоляции с пола. И в этом ему поможет пылесос за 18993 доллара. Не то чтобы данный пылесос чем-то отличался от любого другого добротного современного пылесоса по техническим параметрам… Возможно, он даже несколько уступает самым модерновым «пылеглотам». Однако он инкрустирован 3730-тью кристаллами Swarovski. Тяжеловат, не кажется?

Вы просто не представляете себе, насколько приятно скользить холеными пальцами по нежнейшей и прочнейшей одновременно поверхности этой замечательной уникальной клавиатуры! Нет, все-таки, эта вещь не такая уж и бесполезная. Однако к ней придется прикупить офис, отделанный крокодиловой кожей и мореным дубом, выстроить камин, облицованный гранитом, установить двухметровую плазму… Стоп! Если у вас такой офис, тогда зачем вам вообще там клавиатура и компьютер? Такая обстановка есть лишь у тех людей, которым нет необходимости стучать по клавишам самостоятельно. Вердикт – абсолютно бесполезная вещь!

Очевидно, эту толстовку придумал какой-то «четкий и реальный пацан», каким-то чудесным образом выбившийся в дизайнеры. Причем, исключительно в дизайнеры толстовок! Удивительно бесполезная вещь за десять тысяч баксов! Ну, на самом деле – для чего она нужна? На светском рауте в ней не появишься – там все ходят в смокингах; семечки в ней на улицах Челябинска не полузгаешь – там толстовку разберут по ниткам в мгновение ока! Остается только щелкать семечки в одиночестве, сидя на корточках где-нибудь на берегу испанской Ривьеры, к которой спускается тропинка прямо из вашего особняка.

Если вы считаете, что надо быть настоящим меломаном, чтобы позволить себе наушники за пять штук долларов, то вы глубоко заблуждаетесь, потому что звук в таких наушниках мало чем отличается от звука в любых других качественных наушниках-пуговках. Чтобы позволить себе наушники за пять тысяч баксов, надо просто… быть в состоянии позволить себе такие наушники. В соответствующем финансовом состоянии. Нет никаких сомнений, что человек, который сделает подобное приобретение, вряд ли будет слушать музыку с мобильного телефона. А вот как подарок даме эти наушники очень даже ничего…

Подобное увеличительное стекло просто обязано быть в коллекции какого-нибудь наркобарона, подторговывающего, помимо всего прочего, алмазами и прочими драгоценными каменьями. Картина вырисовывается просто эпическая: сидит такой наркобарон в своем массивном кресле из крокодиловой кожи в окружении вооруженной до зубов охраны, и изучает качество очередной контрабандной партии алмазов. Ни для чего другого это увеличительное стекло не сгодится! А стоит оно… Да не все ли равно, сколько оно стоит? В любом случае, место этой безделушке рядом с кухонным ножом за 39600 долларов.

«Металлические» джинсы за 600 баксов – сложно найти более надежную защиту для своих ног и прочих частей тела, которые обычно скрываются за брюками! Они, конечно, «простоваты» по цене по сравнению с покрытой бриллиантами толстовкой за десять тысяч баксов, зато сидят очень даже хорошо. Уникальный материал с «вживленными» в него металлическими нитями настолько прочен, что коленки уж точно не протрутся никогда. Впрочем, вряд ли человек, купивший такие джинсы, будет ползать на коленках… Ну что же, не такая уж и бесполезная вещь! Главное – не одевайте их на холод без трусов.


Этот шикарный зонт просто создан для тех, кто с детства мечтал побывать в Африке, но его останавливало предостережение Корнея Чуковского: мол, не ходите дети в Африку гулять, так как там большие и злые крокодилы! Ну и где теперь эти ваши «большие злые крокодилы»? А вот они, изошлись все на зонты! Впрочем, вряд ли все. Вообще, за крокодилов можно быть пока спокойными – с такой стоимостью найдется не так много желающих приобрести зонт из крокодиловой кожи. Интересно, а за эти деньги к зонту прилагается какой-нибудь человек, который будет регулярно раскрывать его над нуворишем, как только закаплет дождик?

Кто на рыбалку? Не забудьте прихватить с собой блесну за один миллион долларов. Конечно, это не та вещь, которая случайно окажется в багажнике миллионера-шопоголика после возвращения с шопинга, но бесполезности этой блесне не занимать! Да и сами производители этой уникальной блесны не обманываются насчет ее практического применения – вряд ли кто-то пожелает закинуть в мутные воды миллион баксов, чтобы выудить оттуда карасика. Интересно, поднимется ли рука у жены владельца такой блесны спрятать ее подальше от мужа, «чтобы эта скотина снова не нажралась на этой дурацкой рыбалке со своими собутыльниками»?!

Пришло время перекусить. И в самом деле, не одной же лапшой быстрого приготовления питаться! Даже и за 43 доллара стаканчик. Но не переживайте раньше времени, никто не собирается вас морить голодом. Напротив: если вы миллионер – вам предложат вкусную и сытную пиццу со специальным томатным соусом, копченым лососем, мясными медальонами из оленины, замаринованным в коньяке лобстером и отмоченной в шампанском икре. В качестве легкого штриха на пиццу небрежно накиданы тонкие золотые листья (неужели вместо салфеток?), что, собственно, и делает этот продукт столь баснословно дорогим – 2800 долларов США.

Перекусили? Самое время сходить… музыку послушать. Тем более что за это с вас, по миллионеровским понятиям, запросят не такие уж и большие деньги – всего 90 баксов. А в самом-то деле, как бездарно мы проводили время в туалете, пока не появилась эта чудесная конструкция с разъемами для iPod. Высококачественный звук производители гарантируют благодаря четырем встроенным динамикам. И если раньше в туалете вы зачитывались информацией, изложенной на стенке баллончика с освежителем воздуха, то теперь вы сможете заслушиваться, к примеру, произведениями Шопена. Впрочем, в туалете, для облегчения физиологических процессов, лучше слушать Джастина Бибера!

Как приятно и трогательно выглядит забота некоторых производителей о маленьких детях! И вот этот милый плюшевый мишка… как – он не плюшевый? Ах, его мех сделан из чистого золота… Ок, но его умилительные глаза-пуговки… ах, эти «пуговки» инкрустированы бриллиантами и сапфирами? Позвольте, а зачем нужен этот мишка? Какой взрослый дядя или тетя будет играть с ним? Потому что очень сложно представить себе, что этот мишка из золотого меха с бриллиантовыми глазами сделан для детей. А представить себе играющего с мишкой Прохорова или Абрамовича еще сложнее… Тупик, однако!

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

Если вашему ребенку еще далеко до окончания школы, купите ему игровую приставку Nintendo! Вспомните себя в его годы, когда вы еще не были миллионером и могли только мечтать об этом игровом чудо-девайсе. Они казались такими недоступными в руках единичных счастливчиков, которым родители привезли их из-за границы. Такой же недоступной выглядит и эта игровая приставка для вашего ребенка, так как, при всем его желании, никаких карманных денег не напасешься на покупку этой инкрустированной бриллиантами золотой приставки за 25 тысяч долларов. ТАКАЯ забота о детях не может не трогать…

Несомненный рекордсмен сегодняшнего топа бесполезных дорогих вещей – брендовое бикини, изготовленное из бриллиантов общим весом в 150 карат. Самый ценный из них – это бриллиант в 51 карат, имеющий форму жемчужины. Нет, ну хорошо же сидит на ней, правда? Кстати, отличный подарок вашей супруге, коль скоро она скандалит из-за вашей страсти к рыбалке. Если, конечно, вы миллионер. Нет, тут надо быть мультимиллионером, а надежнее всего — миллиардером! А знаете что? Возьмите вашу жену с собой на рыбалку. И правда, пусть позагорает в этом бикини, пока вы забрасываете блесну за миллион баксов в надежде поймать карпика на ужин…

Выбор объектов сцены мышью

18.12.2015, 22:33

Вращение сцены мышью
Здавствуйте! В общем не получается вращать сцену как хотелось бы. Помогите определить проблему. А.

Вращение сцены мышью
Всем доброго времени суток. Сижу, тренирусь в OpenGL. Сделал 3D фигуру, написал перемещение по.

Выделение объектов сцены центром экрана посредством камеры
Ку-ку, кодеры! Использую OpenGL 3.3+ c GLFW + GLSL. Пишу это все на C++ в QT Creator. Пишу свою.

Выбор объектов возвращает слишком много объектов
Делаю выбор объекта. Рисую объекты: . GL.InitNames() . Dim temp As Integer temp = 1.

Выбор объектов через шейдер
Привет всем! Кто давно дружит с OpenGL — помогите пожалуйста советом. Можно ли средствами OpenGL.

19.12.2015, 02:10 2 21.12.2015, 11:34 [ТС] 3 21.12.2015, 12:00 4
21.12.2015, 12:00
21.12.2015, 13:59 [ТС] 5
21.12.2015, 14:09 6
23.12.2015, 10:31 7
27.04.2020, 14:05 [ТС] 8

29.04.2020, 23:52 [ТС] 9

Возникла небольшая проблемка. Выбор объектов работает правильно только когда ширина окна меньше высоты. Когда наоборот, то по нажатию на место ниже объекта, происходит его выбор. И чем больше ширина, по отношению к высоте, тем на большее расстояние вниз от объекта нужно нажимать
Делал по уроку (http://masandilov.ru/opengl/object-selection), но немного изменил код под свои нужды.

03.05.2020, 12:15 [ТС] 10
03.05.2020, 22:12 11

SkyEX, а знаешь как сделать ,чтобы за пределы стены не выходил?
или за пределы поля? самый простой принцип одной строкой
3д квартиру не делал? с обоями,диванами

Добавлено через 6 минут

луч мыши это глупость,нету луча,есть координаты мыши X,Y

например ты прописал клик по обьекту при неподвижной сцене ,по осям X,Y

но если сцену повернуть то надо клик высчитывать по осям Y,Z

И вообще,это как если писать гонки,машину надо разворачивать по 3м осям,и двигать её в сцене тоже по трем осям,исходя из текущего glRotate() ,там уже идет сложная математика,вычесть поворот камеры,повернуть машину,и потом двигать машину исходя из градуса угла

Добавлено через 7 минут
луч мыши может быть по 3м осям,в трехмерной виндовс,а у нас 2х мерная виндовс

Я писал в правительство на счет создания 3х мерной российской ОС ,в 2006 году

Там например будет 3д комната в виндовс,и окна будут открываться не только по оси X,Y ,но и по оси Z вглубь экрана.

и можно будет лететь в глубь экрана,пришел тогда в 2006 году ответ из правительства,что моя идея принята к вниманию,будет изучаться

В чем недостатки технологии OpenGL?

OpenGL — процедурноориентированный, DirectX — объектноориентированный.

— трудно писать процедурноориентированный код из объектноориентированных блоков, поэтому ниже универсальность (наоборот — легко) .
— Microsoft.
— поддержка нововведений в железе появится только тогда, когда Микрософт захочет (если вообще появится) .

— плохая поддержка со стороны ATi.
— несколько более сложная работа с новыми (не вошедшими в стандарт) возможностями железа.
— это лишь 3D API, для работы с мышью, клавиатурой, джойстиком звуком и т. д. приходится применять какой-либо другой API, хотя бы тот же DirectX. (хотя есть OpenAL)

Они предоставляют практически идентичные возможности, поэтому любую задачу (кроме кроссплатформенных) можно решить с применением любого из них.

OGL ничем не хуже, развываются строго параллельно — просто потому, что разработчики новых карт поддерживают интерфесы к обоим стандартам.

Капитальый плюс OGL в том, что она свободная библиотека, не привязанная к конкретной фирме Майкрософт и конкретной платформе Windows.

Полезные, бесполезные и вредные ископаемые

Полезные, бесполезные и вредные ископаемые


Давно прошли те времена, когда полезными ископаемыми были корешки, которые можно было немедленно съесть. Начиная с эпохи бронзы, полезными стали руды меди, олова, свинца. Затем этот список пополнился: начали добывать железную руду, серебро, золото. Бесполезные ископаемые в виде переработанной породы, а также отходы, возникающие при изготовлении металла, особых беспокойств не вызывали, пока производство оставалось кустарным.

В настоящее время «полезным» стало практически все, что входит в таблицу Менделеева, а также разнообразнейшие соединения химических элементов, применяемые сами по себе и для создания новых материалов и веществ. На каждого американца ежегодно приходится более 20 т. новых материалов. Производство одной тонны материала связано с перемещением или использованием до 15 т. воды, земли или воздуха. Для золота это соотношение равно 1:350 000. Все это изымается у природы и практически немедленно превращается в бесполезные отходы, которые, в свою очередь, становятся вредными: они не только отнимают место у сельскохозяйственных угодий, но и отравляют почву, грунтовые и поверхностные воды, а также воздух.

«Полезные» ископаемые в виде органического топлива настолько ухудшили экологическую ситуацию, что, в соответствии с выводами Межправительственной комиссии по изменению климата, для прекращения увеличения содержимого углерода в атмосфере необходимо уменьшить применение горючего на 60—80 %.

Только в США каждый год закапывают 3.5 млн. т. промышленных отходов в дополнение к 160 млн. бытовых и прочих отходов. В Украине общий объем отходов, накопленный со времен начала индустриализации, оценивается в 20 млрд. т. (по 400 т. на человека!). Если судить по результатам, то промышленность создана для производства отходов, а товары являются побочным продуктом.

Известно, что тяжелые металлы (простейшие яды) никогда не распадутся, и любой контейнер или цистерна когда-нибудь разрушится, однако нет никаких признаков того, что безумие производства уменьшается. Элементарные яды, урановые руды и другие источники смерти для всего живого, которые были в естественном состоянии рассеяны и не представляли опасности, усилиями «человека мыслящего» сосредоточены в малых объемах и превратились в реальную угрозу жизни.

Ежегодно американская промышленность выбрасывает в воздух 160 т. ртути — элементарного яда. Все соединения ртути ядовиты и повреждают органические ткани, сворачивая протеины и дезактивируя энзимы; последствия: врожденные дефекты, заболевания мозга, слепота. В воде ртуть активно превращается в растворимые соединения метила, которые усваиваются водорослями и планктоном, а те в свою очередь, поедаются мелкой рыбой, которую съедает крупная рыба, попадающая на стол человеку, снабжая его биологически концентрированным ртутным ядом. Если рыба умирает в воде, продукты ее распада снова и снова поступают в обычный биологический цикл.

Недавние исследования биологов показали, что ртуть обнаруживается в водоемах, удаленных от мест сброса на тысячи километров. Ртутное отравление стало всеобщей проблемой: ртутное предупреждение получили рыбаки 40 штатов Америки, тысяч озер в Канаде, вся Скандинавия и многие страны Европы и Азии. От элементарного яда невозможно избавиться простым разрывом пищевой цепочки.

Еще одна форма организованного безумия проявляется в том, что федеральные инструкции позволяют заводам избегать больших расходов на захоронение промышленных отходов простым переименованием в «добавки к почве». Удобрения, содержащие промышленные попутные продукты такие как свинец, кадмий, мышьяк и ртуть, а также соединения диоксида и даже радиоактивные компоненты, широко распространяются в сельскохозяйственных районах на протяжении последних 20 лет. Например, завод по переработке урана в Оклахоме ежегодно «дополняет» 9000 акров пастбищ десятью миллионами галлонов слабо радиоактивных отходов, лицензированных как жидкое удобрение. Такое же «удобрение» выливается на 75 акров пастбища на Бермудах, где пасутся 400 голов крупного рогатого скота. В семьях, живущих вблизи пастбища, отмечено 124 случая раковых заболеваний и врожденных пороков.

Еще пример: министерство энергетики США пришло к заключению, что количество плутония и других радиоактивных элементов, попавших в почву в процессе производства ядерного оружия, в 10 раз превышает то, о котором шла речь до самого последнего времени. Соответственно оказалось значительно большим и количество радиоактивных элементов, попавших в воду и продукты питания. Необходимость проверить имеющиеся данные была вызвана настойчивостью частной инициативной группы под названием «Институт энергетических и природоохранных исследований», участники которой еще в 1997 году заявили, что правительственные сообщения об объемах захоронений плутония и остальных радиоактивных элементов «неубедительны и противоречивы». В то время как по официальным сообщениям утечка радиоактивных материалов не превышала трех процентов от их общего количества, в действительности этот показатель превысил 30-процентную отметку.

Предварительные расчеты показывают, что период востановления питьевой воды составляет 200 лет, земной экосистемы — 500 лет, атмосферы — 1 миллион лет, океана — 20 миллионов лет…

Выбор объектов средствами OpenGL.

Само понятие выбора объектов больше подходит графическим редакторам. Обычно в играх нет смысла делать такую возможность. Исключением, конечно же, являются стратегии, там данная технология жизненно необходима. В стрелялках тоже иногда используется выбор объектов, но чаще до них нужно просто дотронуться. Поэтому чаще всего эта технология используется в редакторах. Необходимость выбрать примитив и делать над ним дальнейшие операции одно из первых условий нормальной работы графического редактора. Вы скорее всего не найдете программ, где идет работа с графикой и при этом нет возможности выбирать объекты. Также выбор можно делать и в трехмерных графических интерфейсах. Если вы используете в качестве графической библиотеки OpenGL, то с её помощью можно сделать выбор объектов довольно качественно и быстро.

Далее я попытаюсь рассмотреть два способа выбора объектов исключительно средствами OpenGL.

Первый способ это, конечно же, буфер выбора в OpenGL.
Его достоинства в том, что это, пожалуй, единственный способ выбора объектов, где есть хоть какая-то надежда, что он более менее аппаратный. Поэтому и работает, возможно, быстрее других. Для OpenGL это также является неким стандартом выбора объектов. При этом минусов у этого способа достаточно. Чего только стоит отсутствие теста на пересечение с другими, не выделяющимися объектами. То есть для OpenGL нужно создать такие условия, при которых на сцене все объекты должны выделяться, тогда все будет работать корректно.

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

Об этом и многом другом читайте дальше.

Буфер выбора

Не совсем понятна логика инженеров-разработчиков OpenGL, зачем чисто в графической библиотеке понадобилось делать функции косвенно относящиеся к графике. Честно говоря, лучше бы сделали функции расчета lightmap’ов чем выбор объектов.

Ну, коли сделали, так сделали, никуда не денешься от этого. Фишка эта есть, а если она есть значит, нужно ее использовать по полной программе.

Смысл выбора объектов заключается в том, что имея двумерные координаты мышки, мы должны выбрать объект в трехмерном мире. Как не сложно догадаться, нужно делать какие-то переводы из 2D в 3D или обратно. Координата мышки представляет собой два числа, то есть точку. Координатная система окна в нашем случае почти ничем не отличается от координатной системы Windows, но за одним исключением — координата Y должна быть перевернута, то есть значение 600 соответствует значению 0, значение 583 соответствует значению 17. Разумеется, это только в том случае, если высота рабочей области будет 600. Другими словами из высоты (height) рабочего окна нужно вычесть значение Y координаты курсора мышки.

Для того чтобы буфер выбора имел силу, нужно чтобы все объекты имели свои идентификаторы. Без них OpenGL не будет знать, что чему должно соответствовать в вашей программе, а конкретнее — в вашем трехмерном мире. Идентификация (далее имя) объекта — это процесс, при котором OpenGL получает уникальное имя объекта. Данное действие похоже на то, что мы называем дисплейными списками (Display Lists) или текстурные объекты (Texture Objects). Но во всех этих случаях библиотека с помощью специальных для этого функций может сама генерировать имя, а в нашем случае его придется или задавать в ручную или писать функцию по их генерации.

Все поименованные объекты находятся в стеке имен. Для того чтобы начать работу с буфером выбора нужно очистить стек имен. Делает это функция glInitNames(). Эта и многие следующие операции обычно выполняются на этапе нажатия кнопки мышки, то есть потеря в производительности не должна быть столь существенна. Если же есть необходимость в динамической проверке выбора, то стоит поискать другие методы выбора объектов и взять их них самый быстрый. Пускай он будет большим, сложным в реализации, но самое главное он должен быть самым быстрым.

Есть несколько способов задачи имен для объектов.


Первый способ задачи имен заключается в том, что мы устанавливаем нулевой объект, а затем загружаем все имена через glLoadName(). То есть это выглядит так:

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

Второй способ заключается в использовании функций glPushName()/glPopName(). Но у него есть один малюсенький недостаток. Если вы используете эти команды на старых видео картах типа VooDoo, при этом используя старые драйвера (про новые я ничего сказать не могу), то FPS падает до абсолютно ничтожных отметок. Сейчас у меня нет возможности проверить это еще раз, но насколько я помню FPS падал до единицы.
И тем не менее:

То есть, вталкиваем один объект (glPushName) и передаем его вершины. Запомните — текстурные координаты, нормали, освещение, все это не интересует OpenGL на данном этапе, поэтому не следует ничего этого передавать, хотя бы в целях увеличения производительности.
А затем выталкиваем (glPopName). Все, объект записан. И так пробегаемся по всем объектам, которые можно выбирать. Но все-таки лучше пользуйтесь первым методом.

Также хотелось бы отметить, что запись объектов следует осуществлять только во время нажатия кнопки мышки. Если требуется в реальном времени делать выбор объектов, то, как я уже говорил — лучше найти другой способ выбора объектов, сравнить его с буфером выбора и выбрать самый быстрый по скорости.

Мы подошли к самому главному — выбор объектов. Итак, что нам нужно для выбора объекта:
1. Оконные координаты мышки.
2. Матрица рабочей области (Viewport Matrix).
3. Буфер записей нажатий ( Hit Records ) или другими словами — буфер выбора.
4. Ну а самое главное — корректно выполненные предыдущие действия.

Теперь разберем функцию выбора, а именно первую часть этой функции.

Функция glSelectBuffer() должна дать OpenGL сведения о буфере выбора. Не то чтобы сведения, сколько куда их записывать. Вообще каждый объект в буфере выбора имеет свои четыре поля. Для того чтобы буфер выбора работал и делал положенный ему результат нам понадобиться только второе поле и последнее, то бишь четвертое. Второе поле хранит в себе минимальное значение глубины объекта. В OpenGL глубина определяется clamp числом, то есть числом лежащим в интервале от 0 до 1. А также идентификатор объекта (четвертое поле). Также имеется первое и третье поле. В первом поле хранится число объектов на момент нажатия, то есть общее число объектов под курсором мышки, даже если они перекрывают друг друга. И третье поле это максимальная глубина (оконная координата Z) объекта.

А теперь все сразу:
Первое поле — количество объектов под курсором на момент нажатия.
Второе поле — минимальная Z глубина объекта (экранная Z координата).
Третье поле — максимальная Z глубина объекта (экранная Z координата).
Четвертое поле — идентификатор объекта.

Поэтому размер буфера задается так: (4 * КоличествоОбъектов).

Дальше принцип работы такой. Мы должны перейти в 2D режим, запомнив текущую матрицу и установить режим glRenderMode() в GL_SELECT. Этот режим позволяет рисовать нам плоские объекты при этом не портить FrameBuffer, при этом вся система буфера выбора начинает работать в «активном режиме», то есть вести запись в буфер выбора. Затем идет функция gluPickMatrix(), здесь нужно остановиться подробнее. Принцип работы этой функции заключается в том, что она создает матрицу проекции вокруг курсора. Это позволяет рисовать объекты в этом регионе (регион будет задан параметрами функции gluPickMatrix()). Следовательно, если объект в этом регионе рисуется, то буфер выбора запоминает его и записывает в массив, который мы передали в glSelectBuffer(). Первые два параметра функции gluPickMatrix() — это координаты мышки, только обратите внимание, что координата Y должна быть перевернута, то есть начало координат для Y идет не сверху окна, а снизу. Вторые два параметра ширина и высота области, начиная от начальной точки (первых двух параметров). Обычно их задают двойкой. Последний параметр это матрица рабочего окна (Viewport Matrix).

Далее мы вызываем стандартную для приложения перспективу. Это нужно для того чтобы создать проекционную матрицу для региона, который мы указали в функции gluPickMatrix(). Затем переходим в матрицу модели glMatrixMode(GL_MODELVIEW) и рисуем наши объекты в режиме выбора. Это двусмысленная фраза, с одной стороны мы действительно рисуем объекты в режиме выбора GL_SELECT, с другой стороны мы их рисуем через glInitNames()/LoadName() и так далее. Рисуем, как я уже говорил, без всяких текстур и прочего лишнего, только вершины. Как уже было замечено ранее, мы находимся в режиме GL_SELECT, поэтому все что мы нарисуем, не отразится на буфере кадра (FrameBuffer). Затем осталось вызвать функцию glRenderMode() с параметром GL_RENDER. Функция вернет количество объектов находящихся под тем регионом, который мы указали в функции gluPickMatrix().

Это была первая часть функции получения выбранного объекта.

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

Как мы уже заметили, OpenGL возвращает количество объектов под курсором, то есть он не может возвратить тот на который мы нажали. Но это и не нужно, дело в том, что если понадобиться делать выбор всех объектов под курсором, то это будет невозможно. Потому OpenGL предлагает нам универсальность, а за нее нужно платить. Поэтому сортировку мы будем производить сами. Сортировка в данном случае будет идти по Z координате каждого объекта попавшего в выбор. Значение Z записывается в массив, который мы указали функцией glSelectBuffer(). И как уже было сказано, каждый объект имеет в своем распоряжении четыре поля. Во втором поле находится минимальная Z глубина объекта.

Так выглядит вторая часть функции. В начале мы записываем минимальный Z первого объекта (стандартный поиск минимального элемента массива, чтобы было с чем сравнивать). А затем идентификатор. Хочу напомнить, что нумерация массивов начинается с нуля, поэтому и данные идут 0-3, 4-7, 8-11 и так далее. Далее мы проходимся по всем объектам найденным функцией glRenderMode(GL_RENDER). Дальнейшая запись не очень трудна в понимании — обычный поиск минимального элемента в массиве. Так как объект был найден (Found больше нуля), то в selObject запишется ближайший выбранный объект.

Вот и все. Еще раз хочу отметить одну вещь (кто внимательно читал, то я это уже говорю третий раз) — идеальное стечение обстоятельств для буфера выбора это когда на сцене все объекты представляют возможность быть выбранными. То есть полностью замкнутое пространство из объектов доступных к выбору. Иначе проверка на Z тест будет глупить. Откройте пример к этой статье, и сквозь стол попробуйте выбрать объект. В идеале для разработчика этого быть не должно. В идеале для буфера выбора стол тоже должен быть объектом выбора. И как я уже говорил, только графические редакторы располагают такой возможностью.

Читайте дальше. Выбор объектов через буфер цвета.

Opengl полезные и бесполезные мелочи

Этот урок покажет вам, как создавать прозрачные полигоны.
Этот эффект может быть очень красив, особенно если подключить текстуры.
Он позволяет вам сделать эффект воды, окон, частиц и многого другого.
В будущих уроках мы будем использовать прозрачность для создания эффекта частиц
и маски частиц. Прозрачность будет работать по маске; если на текстуре фон черный —
этот участок будет прозрачным.

В этом уроке мы создадим два вращающихся куба, один внутри другого. Внешний, бОльший
куб будет прозрачным, а внутренний — нет.

Исходный код урока взят из первого — «Инициализация». Файлы main.h и init.cpp остаются без
изменений.

// Для начала напишем новую функцию:


///////////////////////////////// CREATE CUBE \\\\*
/////
///// Создаёт куб с нижним левым углом в координате X,Y,Z.
///// Ширина и высота зависит от передаваемого в ф-ю радиуса.
/////
///////////////////////////////// CREATE CUBE \\\\*

void CreateCube ( float x , float y , float z , int radius , int color )
<
glBegin ( GL_QUADS ) ;
// Эти вершины создают заднюю сторону:
glColor3ub ( color , color , 255 — color ) ; glVertex3f ( x , y , z ) ;
glColor3ub ( 255 — color , color , 255 — color ) ; glVertex3f ( x , y + radius , z ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y + radius , z ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y , z ) ;

// Эти — переднюю
glColor3ub ( color , color , 255 — color ) ; glVertex3f ( x , y , z + radius ) ;
glColor3ub ( 255 — color , color , 255 — color ) ; glVertex3f ( x , y + radius , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y + radius , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y , z + radius ) ;

// Эти — нижнюю
glColor3ub ( color , color , 255 — color ) ; glVertex3f ( x , y , z ) ;
glColor3ub ( 255 — color , color , 255 — color ) ; glVertex3f ( x , y , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y , z ) ;

// Эти — верхнюю
glColor3ub ( color , color , 255 — color ) ; glVertex3f ( x , y + radius , z ) ;
glColor3ub ( 255 — color , color , 255 — color ) ; glVertex3f ( x , y + radius , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y + radius , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y + radius , z ) ;

// Эти — левую
glColor3ub ( color , color , 255 — color ) ; glVertex3f ( x , y , z ) ;
glColor3ub ( 255 — color , color , 255 — color ) ; glVertex3f ( x , y , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x , y + radius , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x , y + radius , z ) ;

// А эти — правую.
glColor3ub ( color , color , 255 — color ) ; glVertex3f ( x + radius , y , z ) ;
glColor3ub ( 255 — color , color , 255 — color ) ; glVertex3f ( x + radius , y , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y + radius , z + radius ) ;
glColor3ub ( color , 255 — color , 255 — color ) ; glVertex3f ( x + radius , y + radius , z ) ;

// Всё остальное будет происходить в функции RenderScene():

void RenderScene ( )
<
// Обьявим статические переменные вращения
static float rotX = 0.0f , rotZ = 0.0 , rotY = 0.0f ;

glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
glLoad >( ) ;

gluLookAt ( 0 , 0 , 6 , 0 , 0 , 0 , 0 , 1 , 0 ) ;

// Теперь нарисуем 2 куба внутри друг друга, и первому включим прозрачность.

glRotatef ( rotX , 1.0f , 0.0f , 0.0f ) ; // Вращение по оси X
glRotatef ( rotY , 0.0f , 1.0f , 0.0f ) ; // Вращение по оси Y
glRotatef ( rotZ , 0.0f , 0.0f , 1.0f ) ; // Вращение по оси Z

// Это будет меньший куб внутри большего. Заметьте, мы передаём 255 как значение цвета
// в конце. Это просто создаст цвета, противоположные цветам большего куба,
// для лучшего восприятия.

CreateCube ( — 0.5f , — 0.5f , — 0.5f , 1 , 255 ) ;

// Включим прозрачность. Всё, отрисованное после этого, будет прозрачным.

glEnable ( GL_BLEND ) ; // Вкл. Blending

// Код ниже просто определяет, какой режим прозрачности нам нужен. Без этого
// ничего не заработает. Первый параметр указывает, как будут рассчитаны красный,
// зеленый, синий и альфа source-blending факторы. Следующий параметр указывает, как
// будут рассчитаны R,G,B и A destination-blending факторы. Мы просто выбираем
// значение один к одному.
// В будущих уроках мы рассмотрим некоторые другие флани, например, GL_SRC_COLOR.

glBlendFunc ( GL_ONE , GL_ONE ) ; // Сделаем значение прозрачности 1:1

CreateCube ( — 1 , — 1 , — 1 , 2 , 0 ) ; // Это наш больший прозрачный куб.

// И последний шаг — выключить прозрачность. Это значит, что ничего, отрисованное
// позже, не будет прозрачным.

glDisable ( GL_BLEND ) ; // Выключаем прозрачность

rotX += 0.3f ; // Увеличим вращение X
rotY += 0.3f ; // Увеличим вращение Y
rotZ += 0.8f ; // Увеличим вращение Z


Вот и всё. Тоже ничего сложного. Давайте ещё раз повторим шаги:

1) Для включения прозрачности сначала вызываем:

2) Простое включение прозрачности — ещё не всё. Дальше нам нужно указать технологию
рассчета прозрачности. В этом уроке мы просто указали значение 1 к 1.

3) Далее мы рендерим что-нибуть на экран, и этот обьект будет прозрачным.

4) Чтобы выключить прозрачность, вызываем:

Вот и всё! Просто, да? Если мы выключили прозрачность, просто нужно включить её снова.
Нам не нужно вызывать glBlendFunc() снова, пока мы не хотим изменить факторы прозрачности.

Если вы не проходили урок текстурных матриц, советую вам обратить на него внимание.
Тогда вы сможете, совместив эти 2 урока, создать большой квадрат с текстурой воды и
включить прозрачность. Это выглядит неплохо. А ещё можно увеличить количество полигонов в
квадрате и заставить их двигаться. Может быть, я напишу об этом урок.

Надеюсь, этот урок помог вам освоить прозрачность.

Узкие места производительности OpenGL [закрыт]

На днях провёл небольшой анализ производительности OpenGL. Выяснилось, что самый проблемный момент заключается в выводе изображения на экран, когда полигоны рисуются поверх других полигонов. Всего лишь пару тысяч плоскостей способны привести к значительным тормозам, хотя это просто мелочь для видеокарты. Судя по всему, проблемы начинаются уже на уровне вершинного шейдера. Изменение дальности обзора помогает исправить эту ситуацию, так как матричные преобразования происходят в вершинном шейднере, но всё же это не решение проблемы.

Закрыт по причине того, что непонятна суть вопроса участниками dlarchikov, DeKaNszn, fori1ton, Mirdin, PashaPash 27 апр ’15 в 9:52 .

Постарайтесь писать более развёрнутые вопросы. Для получения ответа поясните, в чём именно вы видите проблему, как её воспроизвести, что вы хотите получить в результате и т. д. Приведите пример, наглядно демонстрирующий проблему. Если вопрос можно переформулировать согласно правилам, изложенным в справке, отредактируйте его.

5 ответов 5

Пара тысяч плоскостей это мелочь для вершинного шейдера. Для фрагментного шейдера это очень много, когда они рисуются поверх друг друга. Если плоскость занимает весь экран, то фрагментный шейдер сработает для каждого пикселя (для экрана 1280×1024 — 1,3 миллиона раз!). Если это всё умножить на «пару тысяч», то получится 2,6 миллиарда (в худшем случае, когда все плоскости полностью загораживают экран). Видеокарта такое плохо потянет. Даже если фрагментный шейдер очень простой, то происходит постоянная перезапись памяти. Один и тот же пиксель будет перезаписываться 2000 раз. Тест глубины поможет сократить это количество вызовов шейдера и перезаписей пикселя, если отсортировать все плоскости по удалению от камеры.

Алгоритм очень сложен. Если бы он был прост, его уже бы давно применяли везде и вся. Сортировать нужно, хотя бы приблизительно.
Ещё есть способ, называемый «Запрос о преградах». В книге «OpenGL Суперкнига» (OpenGL Superbible) авторов Райта, Липчака и Хаемеля (Wright, Lipchak, Haemel) есть целая глава, посвящённая этому методу. Всё делается специальными функциями OpenGL, так что изобретать велик не придётся. Смысл в том, чтобы сначала отобразить объекты простыми фигурами (людей с помощью параллелепипедов, сферы с помощью кубов или октаэдеров и т.д.), а потом проверить, какие из этих простых фигур не видно. Если простая фигура не видна, то не рисовать сложный объект, сопоставимый ей. Если не изменяет память, то фигуры можно загружать свои, настраивая под нужды. В любом случае почитайте.

Если что, то вот ссылка на эту главу в издательстве Вильямс: Запросы о преградах (pdf)

OpenGL использует z-буфер, чтобы заслонённые пикселы не появлялись на экране. Но вся проблема в том, что даже если он их не рисует и не вызывает фрагментный шейдер, то он всё равно их !обрабатывает!, хотя бы потому, что он сравнивает значения их глубины со значением в z-буфере. А теперь давайте представим, что будет,если единственный ближайший полигон заслонил все остальные? Конечно же, каждый заслонённый примитив будет обрабатываться, к каждому из них применятся алгоритм растеризации (для того чтобы узнать положение пиксела на экране), и, конечно же, значение каждого обрабатывающегося пиксела будет сравниваться со значением в z-буфере, с последующим отбасыванием самого пикслела. Ненужная работа! Отсюда и тормоза! А нам такой порнографии не надо. Премудрости с z-буфером в принципе не помогут. Надо вообще отсекать невидимые примитивы, чтобы не выполнялась их растеризация. Вопрос: как?

В любом случае, ему нужно делать так, чтобы треугольники, фрагменты которых будут полностью отсеяны в конечном изображении, не попадали на конвеер. Я понимаю, что говорю очевидные вещи, но решение проблемы кроется в понимании её мелких деталей. Мне кажется, что алгоритмы Z-Буферизации тут никоем образом не помогут. Нужно работать с нечто большим, а именно, с треугольниками. И по тому я думаю, что запросы о преградах будут хорошим решением (не факт, что лучшим, но всё же хорошим).

Learnopengl. Урок 4.1 — Тест глубины

Буфер глубины

В уроке, посвящённом системам координат, мы выполнили рендер трехмерного контейнера с использованием буфера глубины, что позволило предотвратить ошибочный вывод граней, находящихся позади других. В этом уроке мы пристальнее взглянем на буфер глубины (или z-буфер) и хранимые в нем значения, а также узнаем как конкретно проходит проверка находится ли фрагмент позади других.

Часть 2. Базовое освещение

Часть 3. Загрузка 3D-моделей


Буфер глубины также, как и буфер цвета (хранящий цвета всех фрагментов – видимое изображение), хранит определенную информацию для каждого фрагмента и, обычно, имеет размеры совпадающие с размерами буфера цвета. Буфер глубины создается автоматически оконной системой ОС и хранит значения в виде 16, 24 или 32 битных чисел с плавающей точкой. В большинстве систем по умолчанию создается буфер с точностью 24 бита.

При включенном тесте глубины OpenGL производит проверку глубины каждого обрабатываемого фрагмента относительно данных, хранимых в буфере. При прохождении теста содержимое буфера будет обновлено значением глубины обрабатываемого фрагмента, при провале теста – хранимое значение останется прежним, а фрагмент отбрасывается.

Тест глубины производится в экранном пространстве после выполнения фрагментного шейдера (и после теста трафарета, который будет рассмотрен в следующем уроке). Экранные координаты непосредственно связаны с параметрами окна просмотра, заданными функцией glViewport, и доступны через встроенную переменную GLSL gl_FragCoord в коде фрагментного шейдера. Компоненты x и y данной переменной представляют собой координаты фрагмента в окне просмотра (левый нижний угол окна имеет координаты (0, 0)). У gl_FragCoord также есть и третья компонента, которая собственно и содержит значение глубины фрагмента. Эта z-компонента используется для сравнения со значениями из буфера глубины.

Современные GPU практически все используют трюк, называемый ранним тестом глубины. Эта техника позволяет выполнить тест глубины до выполнения фрагментного шейдера. Если нам становится известно, что данный фрагмент никак не может быть виден (перекрыт другими объектами), то мы можем отбросить его до этапа шейдинга.
Фрагментные шейдеры довольно вычислительно тяжелы, потому стоит избегать их выполнения там, где это бессмысленно. У данной техники есть только одно ограничение: фрагментный шейдер не должен изменять значение глубины фрагмента. Это очевидно, ведь OpenGL в таком случае не сможет наперед определить значение глубины обрабатываемого фрагмента.

По умолчанию тест глубины отключен. Включим его:

Теперь, с включенным тестом глубины, OpenGL будет автоматически сохранять значения глубины для всех прошедших тест фрагментов и отбрасывать не прошедшие.

Включение теста глубины также требует очистки буфера от старых значений в каждом кадре. В знакомую функцию glClear добавляется новый флаг GL_DEPTH_BUFFER_BIT

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

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

Функция теста глубины

OpenGL позволяет переопределить оператор сравнения, используемый в тесте глубины, что дает нам тонкий контроль над тем, какие фрагменты стоит обработать, какие отбросить и в каких случаях буфер глубины будет обновлен. Оператор устанавливается через вызов функции glDepthFunc:

Функция принимает идентификатор оператора сравнения из данного списка:

По умолчанию используется GL_LESS, что подразумевает отбрасывание всех фрагментов, имеющих глубину большую или равную значению глубины, хранимому в буфере.

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

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

Вернув обратно оператор GL_LESS мы получим корректную сцену:

Вопрос точности значений глубины

Значения в буфере глубины ограничены интервалом [0.0, 1.0] и относительно них производится проверка z-компоненты всех объектов сцены с точки зрения наблюдателя. При этом z-компонента объекта в видовом пространстве может принять любое значение в интервале [zNear, zFar], который определяет ближнюю и дальнюю границу пирамиды проецирования (projection frustum). Для устранения этого несоответствия нам понадобится способ преобразования значений z-компоненты в видовом пространстве к интервалу [0.0, 1.0]. Первый, наивный, способ – простое линейное преобразование:

где zNear и zFar – значения параметров near и far, которые мы использовали при конструировании матрицы проекции, задающей пирамиду видимости (см. системы координат). Данная зависимость принимает как параметр значение z, лежащее внутри пирамиды видимости и преобразует его к интервалу [0.0, 1.0]. Соотношение между значением z и результирующим значением глубины можно увидеть на графике:

Обратите внимание, что все рассмотренные зависимости дают значение, стремящееся к 0.0 для близких объектов и стремящееся к 1.0 для объектов, лежащих вблизи дальней плоскости отсечения.

Однако, на практике линейный буфер глубины практически не используется. Для достижения качественного результата проецирования используется зависимость, пропорциональная величине 1/z. Результатом использования такой зависимости является высокая точность значений глубины для малых z и гораздо меньшая точность для больших z. Задумайтесь над смыслом такого поведения: действительно ли нам важна так же точность значений глубины для объектов, удаленных на тысячи условных единиц от наблюдателя, что и у детализированных объектов, прямо перед наблюдателем? Использование линейного преобразования не учитывает этот вопрос.

Поскольку нелинейное преобразование пропорционально величине 1/z, то для значений z в интервале [1.0, 2.0] мы получим значения глубины в интервале [1.0, 0.5], что уже покрывает половину точности типа float, обеспечивая огромную точность для малых z. Значения z из интервала [50.0, 100.0] будут обеспечены всего 2% от доступной точности типа float – но это как раз то, что нам нужно. Итак, новая зависимость, в том числе учитывающая и параметры zNear и zFar матрицы проекции:

Не переживайте, если вам не ясно, что конкретно подразумевает это выражение. Главное – запомнить, что значения, хранимые в буфере глубины, нелинейны в экранном пространстве (в видовом пространстве, до применения матрицы проецирования, они линейны). Значение 0.5 в буфере вовсе не означает, что объект находится посредине пирамиды видимости. На самом деле точка, которой соответствует эта глубина, довольно близка к ближней плоскости отсечения. На графике ниже приведена рассматриваемая зависимость нелинейного значения глубины от исходного значения z-компоненты:


Как видно, значения глубины сильно меняются для малых входных z, давая нам повышенную точность в области около ближней плоскости отсечения. Само выражение преобразования значений z (с точки зрения наблюдателя) внедрено в структуру матрицы проекции. Таким образом, когда мы переводим координаты вершин из видового пространства в пространство отсечения (clips space) и далее в экранное, мы применяем нелинейное преобразование значений z. Если вы хотите в деталях разобраться в механике работы матрицы проекции, то рекомендую эту замечательную статью.

Эффект нелинейности легко заметить при попытке визуализировать буфер глубины.

Визуальное представление значений буфера глубины.

Итак, в вершинном шейдере нам доступно значение глубины фрагмента через z-компоненту встроенной переменной gl_FragCoord. Если мы выведем это значение как значение цвета, то мы сможем визуализировать содержимое текущего буфера глубины:

Если вы попробуете запустить приложение, то, верней всего, все будет залито белым цветом, создавая впечатление, что все объекты имеют глубину 1.0 – максимально возможное значение. Отчего же мы не видим более темных участков, где глубина приближается к нулю?

Из предыдущего раздела мы помним, что в экранном пространстве значения буфера глубины нелинейны, т.е. для малых z точность велика, а для больших – мала. Значение глубины очень быстро возрастает с расстоянием в сцене, потому практически все вершины быстро достигают глубины близкой к 1.0. Если мы аккуратно подойдем поближе к одному из объектов, то в конце концов сможем различить потемнение их ближних частей с уменьшением значения z:

Здесь явно видно нелинейный характер значений глубины. У ближних объектов значение глубины изменяется значительно быстрее, чем у удаленных. Малейшее передвижение камеры меняет цвета от практически черных до чисто белого.

У нас, однако, есть возможность преобразовать нелинейные значения глубины фрагмента обратно в линейно распределенные. Для этого нам потребуется буквально обратить процесс проецирования вспять, но только для значений глубины. Первым шагом нам необходимо преобразовать значения глубины обратно из интервала значений [0.0, 1.0] в интервал [-1.0, 1.0] соответствующий нормализованным координатам устройства (NDC, normalized device coordinates) пространства отсечения. Затем выведем выражение, обратное нелинейному выражению (2), и применим его к полученному значению глубины. Результатом будет линейное значение глубины. Звучит вполне нам по силам, как вы считаете?

Итак, для начала переведем значение глубины в NDC:

Далее, полученное значение z преобразуем в линейное с помощью зависимости, обратной (2):

Напомню, что данное выражение получено для матриц проецирования, использующих выражение (2) для нелинейного преобразования значений глубины, также ограничивая их интервалом [zNear, zFar]. Повторно даю ссылку на статью, полную математических деталей внутреннего устройства матрицы проецирования. Также из статьи можно понять, откуда берется упомянутое выше выражение.

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

Поскольку линеаризованные значения глубины находятся между границами zNear и zFar, то бОльшая часть значений окажется больше 1.0 и будет выведена как чисто белый цвет. Поделив линейное значение глубины на величину zFar в коде функции main мы приближенно приводим его к интервалу [0.0, 1.0]. Это позволит нам наблюдать плавное возрастание яркости объектов сцены с их приближением к дальней плоскости пирамиды проекции, что гораздо нагляднее.

Запустив приложение в этот раз можно убедиться в линейном характере изменения значений глубины с расстоянием. Попробуйте побродить по сцене, дабы понаблюдать за изменениями:
Сцена практически полностью залита черным цветом, поскольку значения глубины линейно меняются от zNear = 0.1 к zFar = 100.0, которая, в данном случае, находится довольно далеко. А поскольку мы находимся рядом с ближней плоскости пирамиды проекции, то значения глубины и, соответственно, яркости весьма малы.

Артефакты ограниченной точности буфера глубины

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

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

Если засунуть камеру в один из контейнеров, что эффект предстанет во всей красе. Видно, как сквозь нижняя часть ящика постоянно проскакивают фрагменты плоскости пола, создавая раздражающий рваный узор: Z-fighting представляет собой распространенную проблему при использовании буфера глубины и, типично, более заметен для объектов удаленных (поскольку на удалении точность буфера снижается). Полностью избежать этого явления мы не можем, но в арсенале разработчика есть несколько подходов, позволяющих уменьшить или полностью избавиться от z-fighting в конкретной сцене.

Методы преодоления

Первый и, пожалуй, самый важным советом будет никогда не располагать объекты слишком близко друг к другу с риском наложения составляющих их треугольников. Добавляя небольшое, незаметное для пользователя, смещение между объектами вы обеспечите себе свободу от z-fighting’а. В нашем случае с плоскостью и контейнерами достаточно было бы просто сместить контейнеры в направлении положительной полуоси Y. Достаточно малое смещение будет незаметным, но достаточным для избавления от артефакта. Однако, данный метод требует ручной модификации сцены и тщательного тестирования для гарантии отсутствия проявлений z-fighting’а в сцене.

Другой подход заключается в задании ближней плоскости отсечения как можно дальше. Как выше было отмечено, значительная точность обеспечивается вблизи плоскости zNear. Потому, если мы отодвинем ближнюю плоскость от наблюдателя мы обеспечим большей точностью весь объем пирамиды видимости. Однако, стоит помнить, что излишнее смещение ближней плоскости может привести к заметному усечению объектов, находящихся вблизи. Так что данный подход требует некоторой доли проб и подгонки, дабы успешно выбрать значение zNear.

Третий метод просто предлагает использовать формат буфера глубины с большей точностью, за что придется расплачиваться долей производительности. В большинстве случаев используются буферы точностью 24 бита, но современные видеокарты позволяют использовать и точность в 32 бита для буфера глубины. Дополнительная точность позволит уменьшить эффект z-fighting’а, но будет стоить вам скорости выполнения.

Данные три техники избавления от z-fighting’а наиболее распространены и при этом легко реализуемы. Существуют и другие способы, более трудоемкие, но все так же не гарантирующие полного избавления от проблемы. Действительно, z-fighting типичная проблема, но при аккуратном применении перечисленных техник вам, вероятно, и вовсе не придется разбираться с проявлениями этого артефакта.

Илон Маск рекомендует:  Реальные примеры и инструменты
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL