|
|
|
|
Тени и способы их реализации
| |
Yandersen | Дата: Чт, 23 Апр 2009, 23:27 | Сообщение # 1 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Без теней игра будет выглядеть нереалистично и "не на уровне" в наше время, так что если мы хотим написать движок сами, то рано или поздно должны решить проблему построения теней. Помозгуем?.. Добавлено (23 Апр 2009, 23:27) --------------------------------------------- Геометрические расчёты могут быть разными; это может быть идеальным решением, но рисуем мы не вручную, а юзаем графическую библиотеку (OpenGL, я полагаю). Значит, строить тени мы обязаны её средствами. Что есть наложение теней в принципе? Это затемнение тех пикселов (соответствующих определённым точкам в сцене), которые заслонены от источника света (будем считать его точечным) находящимися в сцене поверхностями (треугольники, полигоны...). А как определить, заслонён ли пиксел от светильника какой-либо из поверхностей, попал ли он в тень от неё? Это значит проверить, не находится ли проверяемый пиксел внутри объёма тени, которая в случае треугольника выглядит как усечённая треугольная пирамида, верхнее основание которой - треугольник поверхности, а нижнее - либо отсутствует (в теории), либо расположено где-то на огромном удалении от источника света и верхнего основания (ну, что такое пирамида - все знают, надеюсь, что такое усечённая пирамида - тоже "слышали"). Чем можно решить проблему? У меня фраза "наложение теней" вызывает ассоциации с "буфер маски", "буфер-накопитель"... Везде приводят примеры с ними, но такие какие-то завёрнутые, с кучей ручной невнятной геометрии и вообще, трудно-представимые в универсальном случае, где отрисовать нужно больше нескольких треугольников... Кто может что-нить сказать по поводу теней? Надумки, догадки? А может, доступные для понимания решения?
[Беженец со Скаев]
|
|
| |
smt005 | Дата: Пт, 24 Апр 2009, 12:37 | Сообщение # 2 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| http://wingman.org.ru/ Реализация карт теней с использованием GLSL шейдеров http://www.gamedev.ru/code/articles/ShadowMapGLSL
|
|
| |
Yandersen | Дата: Сб, 25 Апр 2009, 01:27 | Сообщение # 3 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Могу предположить, что спихиваешь литру, с которой сам не разобрался. Я, вообще, считаю, что самое трудное - разбираться в чужих трудах. Я не осилил. Зато плодовито позаседал в какадрамуарии и родил там свою идею. Может, велосипед изобретаю (как обычно, эх...), но может сработать. Желаю поделиться манаизлияниями, в общем. Начал я топик с басни про теневой объём, представляющий из себя усечённую пирамиду (совсем не обязательно треугольную - основанием, т.е. тенеотбрасывающей поверхностью может быть любой полигон). Как отрисовать такую пирамиду тени - дело техники и простейших коротких геометрических вычислений. Про это забудем пока - будем считать, что у нас уже есть функция, умеющая рисовать длиннющую пирамиду тени за полигоном, координаты вершин которого даны. Вот, для наглядности, пример (темная полупрозрачная байда - пирамида тени, отбрасываемая на серую кривую поверхность треугольником , расположенным за картинкой сверху): Ну, собсесно гря, осталось отсечь рисование пустого объёма тени. Попробуем разобраться, что нужно отсечь (какие пикселы теневой пирамиды не рисовать). Очевидно, что задние поверхности пирамиды рисовать незачем, а также те из передних, через которые проглядывают задние. Вот тогда получим нормальную спроецированную тень на объекте. Техника. Как это сделать - немного мутно, но решение прощупывается... Во-первых, чтобы предотвратить рисование как лицевых, так и обратных граней одновременно, нужно включить соответствующую настройку OpenGL, которая предотвращает отрисовку задних сторон примитивов (тех, что к наблюдателю изнанкой повёрнуты): glEnable(GL_CULL_FACE); ИМХО, эта полезная для производительности опция должна быть включена всегда. Чтобы рисуя теневую пирамиду явно задавать, какая из её поверхностей будет отрисована (передняя или задняя), достаточно выбрать: glCullFace(GL_BACK); //Не рисовать изнанки (выставлено по-умолчанию). или glCullFace(GL_FRONT); //Не рисовать лицевые грани И такая пиксельная логика: 1) сперва отрисовываем всю сцену, как обычно 2) Для каждого полигона модели, призванной отбросить тень, делаем вот что: "Рисуем" задние грани теневой пирамиды каждого полигона. "Рисуем" не значит, что рисуем в кадр (не фигачим по самой картинке), т.е. цвета пикселов не меняем пока, но всё же метим пикселы, куда нужно было рисовать (короче, пишем только в буфер трафарета). Секрет в том, что при рисовке передней стороны теневой пирамиды (которая как раз должна частично наложиться на поверхность и затемнить её), рисуются лишь те её пикселы, которые не легли на пикселы задней грани (это значит, между ними находится тенируемая поверхность). Такая вот идея. Довтыкнуть надо только, как с буфером трафарета работать...
[Беженец со Скаев]
Сообщение отредактировал Yandersen - Сб, 25 Апр 2009, 01:35 |
|
| |
smt005 | Дата: Сб, 25 Апр 2009, 12:31 | Сообщение # 4 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Quote (Yandersen) Могу предположить, что спихиваешь литру, с которой сам не разобрался. Я забыл что ты не на Visual C++ делаешь. В wingman.org.ru некоторые примеры разобрал, например работа с Vertex Arrays. Сейчас читаю про шейдеры, для представления. Потом планирую разобраться с тенями, после чего можно будет приступить к шейдерам. И уже после этого пробовать делать тении с помощью GLSL. Quote (Yandersen) Я, вообще, считаю, что самое трудное - разбираться в чужих трудах. Поддерживаю и то что ты сейчас написал, это не мои труды. , поэтому я попытаюсь разобрать в том что делают професссионалы(предпологаю). Заметка, в wingman.org.ru есть пример с камерой, так вот, он походу там изобрёл не велосипед а мотоцикл, причем работающий на бананах. Поэтому я сделал простенькую функцию, которая наверно ничуть не уступает в практичности и при этом проста.
|
|
| |
Yandersen | Дата: Вс, 26 Апр 2009, 00:14 | Сообщение # 5 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Мой способ работает! Наметал по-черновому код, всё получилось, тень отрабатывает, как задумано: Мои объяснения выше оказались немного неверными, но в общем и целом, алгоритм построения теней будет похож. Я смогу их сделать. Осталось только функции написать, оформить, доработать алгоритм и гуд. Потом набросаю какую-нить сцену и движущейся в ней отбрасывающий тень объект, чтобы показать отрисовку теней в динамике. Сразу скажу, что на производительность мой метод давить будет не очень сильно. Вообще, тени - операция ресурсозатратная, так что в любом случае... [Ушёл молиццо Святой Компилляции]Добавлено (26 Апр 2009, 00:14) --------------------------------------------- З.Ы.: минус моего метода - границы тени будут резкие. Но зато идеально ровные, без квадратиков, как на текстуре мелкого размера, растянутой на весь экран.
[Беженец со Скаев]
|
|
| |
smt005 | Дата: Вс, 26 Апр 2009, 00:23 | Сообщение # 6 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Потом объясни как сделать тень, очень подробно. А то все примеры которые я видел, наворочены до безобразия.
|
|
| |
Yandersen | Дата: Вс, 26 Апр 2009, 10:55 | Сообщение # 7 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Хм, а я бы не сказал, что мой способ очень прост... Но он на 80% состоит из игры с буфером трафарета (stencil buffer). Так что сперва советую прочесть и понять всё насчёт этого. Из документации могу перечислить материалы по функциям, которые я юзал для игры с тенями: glClearStencil - функция, с помощью которой можно задать, какое значение будет присваиваться всем пикселам буфера трафарета при вызове glClear(GL_STENCIL_BIT); glStencilMask - запретить или разрешить писание в буфер трафарета (write-protection on/off); glStencilFunc - настраивает функцию, с помощью которой производится тест рисуемых пикселов на шанс быть отрисованными. Буфер трафарета, как и буфер глубины (depth-buffer / z-buffer) используется для отсеивания отдельных пикселов (буфер глубины нужен для теста на удалённость от наблюдателя; буфер трафарета точного назначения не имеет, но в зависимости от выбранного алгоритма может применяться для разных нужд); glStencilOp - настраивает функцию (настройка алгоритма её действий), которая изменяет значения пикселов буфера трафарета в зависимости от результатов теста глубины (glDepthFunc) и теста буфера трафарета (glStencilFunc). Ну, ещё я юзал glDepthMask и glColorMask, которые аналогично glStencilMask защищают от записи / разрешает писать в буфер глубины / в буфер кадра (цвета). Не знаю, как тебе, но мне было достаточно документации, чтобы разобраться, бо у мну с инглишем чудненько плюс много наработок и заготовок кода, которые при лёгком менянии соответствующих участков кода позволяют наблюдать результ действия исследуемых функций. Когда разберёшься с этими функциями, тряси меня на сказку по их использованию для построения теней. Если чё-то будет невнятно, тряси (только не насчёт glStencilFunc - её я сам не совсем понял, но кой-как применил всё-таки).
[Беженец со Скаев]
Сообщение отредактировал Yandersen - Вс, 26 Апр 2009, 10:59 |
|
| |
smt005 | Дата: Вс, 26 Апр 2009, 17:59 | Сообщение # 8 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Попытался разобраться, не понятно, видимо мало знаний. Давай лучше объясняй. Может после того как объяснишь, я смогу разбираться с этими функциями.
|
|
| |
Yandersen | Дата: Вт, 28 Апр 2009, 21:02 | Сообщение # 9 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Оки, ну держись... Ты знаешь, как работает glClearColor? С её помощью "задаётся цвет фона". Точнее, с помощью этой функции ты задаёшь, какое значение цветовых компонент (RGBA) присваивать ВСЕМ пикселам буфера цвета, когда ты "чистишь кадр" перед отрисовкой сцены с помощью функции glClear(GL_COLOR_BUFFER_BIT). Точно также работает glClearStencil - задаёт значение, которое будет присвоено всем пикселам буффера трафарета при его очистке, glClear(GL_STENCIL_BUFFER_BIT). Также работает и glClearDepth, межпрочим, но её мне юзать не приходилось пока. glStencilMask аналогична glDepthMask и glColorMask. Просто защищают буфер от записи. Объясню на примере последней: void glColorMask(bool,bool,bool,bool); Если при рисовании примитивов нужно запретить писание, к примеру, красной составляющей цвета, то перед началом рисовки пропиши: glColorMask(false,true,true,true); В таком случае, если, к примеру, пиксел-кандидат-на-рисование имеет цвет {1,1,1,1} (т.е. белый, непрозрачный), то после писания его в буфер кадра красная компонента отсеится и пиксел станет бирюзовым {0,1,1,1}. В отличие от четырёхкомпонентного буфера цвета, буферЫ глубины и трафарета включают лишь одну компоненту (depth (float, 32bit) и stencil (char, 8bit), соответственно), так что функции glDepthMask и glStencilMask требуют лишь одного переключателя. glStencilFunc похожа на glDepthFunc и glAlphaFunc. Про все расскажу. В общем, эти функции настраивают условия, при которых пикселу будет разрешено быть отрисованным. К примеру, если мы зададим: glAlphaFunc(GL_GREATER, 0); то пикселы будут рисоваться только при условии, что их альфа-компонента цвета больше нуля. Т.е. полностью прозрачные пикселы отсеиваются. Казалось бы, "так они ведь всё равно не будут видны, так зачем их отсеивать?" Фигли. В буфере цвета не отобразятся, но в буфер глубины всё равно писаться будут. Эдакие фантомы - сами не видны, но если попробовать нарисовать что-нить за ними, то и проявяться. Так, к примеру, можно создать особый эффект маскировки глайдера, которая имитирует окружающую среду (ландшафт), но не может имитировать другие глайдеры, к примеру. Для этого отключим альфа-функцию: glDisable(GL_ALPHA_TEST); или, что аналогично (пикселы будут проходить тест всегда, при любых значениях альфа компоненты): glAlphaFunc(GL_ALWAYS, 0); Первым делом отрисуем ландшафт, и окружение, как обычно, затем - фантомный глайдер, присваивая альфа-компоненте цветов всех его вершин значение нуля. Тогда вершины будут абсолютно прозрачными и в буфер цвета не пройдут, т.е. картинку не изменят. После этого можно отрисовать все остальные глайдеры. Так, глайдеры, перекрытые фантомом, будут пропадать, поскольку не пройдут тест буфера глубины, в котором фантом оставил свой невидимый след. Кстати, намного проще и с тем же эффектом, можно просто перед отрисовкой глайдера запретить писать в буфер цвета: glColorMask(false,false,false,false); И рисовать глайдер, как обычно. Хотя, даже больше: мы можем для повышения производительности ещё и отключить просчёт освещения, бо в буфер цвета всё равно глайдер-фантом не пройдёт, а наша цель - заполнить буфер глубины. Теперь glDepthFunc. Аналогично работает, только в отличие от альфа-функции сравнивает глубину пиксела-кандидата не с указанным тобою константным значением, а прямо со значением глубины оответствующего пиксела, уже находящегося в буфере глубины. Так, с её помощью производится "сортировка" объектов по удалению от наблюдателя. Т.е. функция помогает скрыть те части рисуемых примитивов, которые перекрыты ближайшими к наблюдателю. Хочу особо отметить два варианта этой функции: glDepthFunc(GL_LESS); //Разрешает рисовать пиксел только в случае, если он ближе к наблюдателю, чем тот, что уже в буффере и glDepthFunc(GL_LEQUAL); //В отличие от предыдущей, разрешает рисовать пиксел ещё и в случае, когда его глубина равна глубине пиксела, уже находящемуся в буффере. Мне больше нравится второй вариант, бо он даёт возможность "смешивать" совпадающие поверхности - к примеру, так можно наносить отметины, рисуя поверхность второй раз, но уже полупрозрачную и с текстурой отметины. glStencilTest - также проверяет, пропускать ли пиксел на отрисовку. Тоже имеет свой набор алгоритмов. К примеру, если установить функцию трафарета так: glStencilFunc(GL_NOTEQUAL,0,1); мы отсеим пикселы, у которых значение в буфере трафарета равно нулю. Рисуясь, примитивы могут писаться в буфер цвета, глубины, а также трафарета. Причём, как они будут писаться в буфер трафарета, какие изменения в нём будут производить, мы можем контролировать и задавать с помощью функции: void glStencilOp(GLenum fail , GLenum zfail , GLenum zpass); Три её аргумента - это названия алгоритмов, которые будут применены к пикселам-кандидатам в зависимости от условий (результатов теста функций глубины и трафарета). Итак: 1) "fail" - что делать, если функция теста трафарета (glStencilFunc) требует запретить отрисовку этого пиксела. Возможные варианты действий: GL_KEEP - "ну и хер с ним", едем дальше, ничё не предпринимаем; GL_ZERO - метит этот пиксел в буфере трафарета ноликом; GL_REPLACE - пишет в буфер трафарета число, которое мы задавали ещё в glStencilFunc (func,ref,mask); GL_INCR - увеличивает значение в буффере трафарета на 1 (stencil++); GL_DECR - уменьшает значение в буффере трафарета на 1 (stencil--); GL_INVERT - "переворачивает" бит (нолик в единичку или единичку в нолик); 2) "zfail" - что делать, если завалился тест на глубину, хотя тест трафарета прошёл. Варианты те же. 3) "zpass" - оба теста прошли успешно. Что делать? Варианты те же. С этими функциями теперь пнятненько? Добавлено (28 Апр 2009, 21:02) --------------------------------------------- smt005, имею желание задекларировать тебя какашкой. Я, памаишь, пол-дня расписывал тебе полотно, старался тут, а ты игноришь, будто тебе поф. Хоть бы вопрос какой задал, если чё не понятно, или пнул бы насчёт "поехали дальше - как сами тени-то делал?". А то сначала "объясняй", а потом - вот. Нехорошо, ата-та!
[Беженец со Скаев]
Сообщение отредактировал Yandersen - Вс, 26 Апр 2009, 23:34 |
|
| |
smt005 | Дата: Вт, 28 Апр 2009, 21:52 | Сообщение # 10 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Ну блин извини, мне сейчас некогда, прочитал но не вникал, поэтому и нет вопросов. Как решу свои житейские проблемы и начну опять програмить, тогда и будут вопросы.
|
|
| |
Yandersen | Дата: Ср, 29 Апр 2009, 13:43 | Сообщение # 11 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| К тому времени я уже допишу класс Shadower'а и всё задокументирую... Кстати, нашёл в инете какую-то статейку, в которой были общие принципы построения теней в OpenGL, так там как раз мой способ упомянался, причём очень положительно. Так что я всё ж велосипед изобрёл, как обычно.
[Беженец со Скаев]
|
|
| |
Yandersen | Дата: Чт, 30 Апр 2009, 01:32 | Сообщение # 12 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Написал класс Shadower'а для построения теней. Работает, но ещё долизывать буду. В общем, для создания теней вырисовывается необходимым алгоритм, при котором сцена должна быть перерисована дважды - первый раз обычным способом, для рисования картинки без учёта теней; затем просчёт теней заключается в передаче классу Shadower'а данных о примитивах (принимаются только полигоны) - координаты вершин, в результате чего строятся невидимые пирамиды тени, в конечном итоге приводящие к заполнению Stencil-буффера единичками там, где объекты затенены; и последний этап - второе рисование сцены обычным способом, но с включённым тестом Stencilя и предварительной настройкой общих параметров освещения, что приведёт к перерисовыванию сцены лишь в затенённых местах, но в режиме теневого освещения, что даст идеальный реалистичный эффект. Пока - вот первый скриншот:
[Беженец со Скаев]
|
|
| |
smt005 | Дата: Чт, 30 Апр 2009, 10:28 | Сообщение # 13 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Потом следать какое нибудь сглаживание маски и будут нерезкие тени.
|
|
| |
Yandersen | Дата: Чт, 30 Апр 2009, 14:10 | Сообщение # 14 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Quote (smt005) Потом следать какое нибудь сглаживание маски и будут нерезкие тени. Нет такой фичи, к сожалению - маска (трафарет,Stencil?) - позволяет логически вкл/выкл рисовку отдельных пикселов, но не модифицирует способ их рисования. По моему способу, как я вчитал, делают несколько кадров, микросдвигая светильник каждый раз, а потом смешивают полученные картинки. Говорят, хорошо получается. Но мне итак картинка нравится. Кстати, как и предупреждали, обнаружился баг при нахождении наблюдателя внутри теневого объёма - при этом все тени "инверсируются" - там, где должна быть тень, её нет, а везде, где должен быть свет - тень. Решить баг просто - как они написали, просто очищать буфер трафарета не нулями, а единицами, чтобы инверсировать всё обратно, но встаёт вопрос просчёта положения наблюдателя при рисовке каждой тени... Пока же, просчёт теней предельно нересурсоёмок - при передаче просчётчику теней очередного полигона тенирующей модели немного простой математики вовлекается перед началом рисовки теневого объёма (вычисляется направление света в текущей системе координат), а при передаче каждой новой вершины полигона всего лишь два раза вызывается glVertex: glVertex3f(x, y, z); glVertex3f(x+LightDirX, y+LightDirY, z+LightDirZ); Т.е. способ идеален как раз для сложных поверхностей, имеющих много вершин, а не только для простых треугольников. Учитывая, что просчёт света и текстурирование на этом этапе отключено, быстродействие способа просчёта теней этим методом налицо.
[Беженец со Скаев]
Сообщение отредактировал Yandersen - Чт, 30 Апр 2009, 14:11 |
|
| |
smt005 | Дата: Пт, 01 Май 2009, 20:01 | Сообщение # 15 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Quote (Yandersen) Нет такой фичи, к сожалению Может шейдерами попробывать? На wingman.org.ru вроде всё понятно и подробно описано про GLSL, но я сам на практике ещё не использовал.............
|
|
| |
Yandersen | Дата: Вт, 23 Июн 2009, 03:07 | Сообщение # 16 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Quote (smt005) Yandersen, если не сложно, напиши пожалуйста как сделать тени, ОЧЕНЬ подробно, каждый шаг... Я сейчас занимаюсь движком - физика, отображение моделей и т.д. и пока не хочется отвлекаться на саму графику, но когда нибудь время прийдёт. И только ты пока разобрался в тени. Хорошо, что заранее спросил - возможно, "мой" способ построения теней придётся вшивать в движок ещё с настроек GL-окна. //---------------- Пока без технических подробностей - тока принцип. Допустим, тенируЮЩий объект - треугольник с известными координатами, источник света - нелокализованный, направление лучей известно (координаты вектора направления света). Для того, чтобы что-то изучить, надо это видеть. Будем рисовать тень. Если отрисовать тень, отбрасываемую этим треугольником, то она как будет выглядеть? Как треугольная призма бесконечной длины (ну, не совсем бесконечной, конечно, - придётся ограничить). Допустим, длина тени – 1000. Направление света – вектор единичной длины. Чтобы одеть на треугольник юбку тени, необходимо вычислить три координаты её дальнего основания. При наших условиях это предельно просто – сложить координаты треугольника с координатами вектора света (домноженными на 1000). Этого достаточно, чтобы отрисовать полупрозрачным чёрным цветом (0.f,0.f,0.f,0.5f) юбку-тень, являющуюся боковой поверхностью теневой призмы. Во: Оки. А теперь посмотрим, что будет, если подпихнуть под тень какую-нить поверхность: Поизучаем результат. Ведь наша конечная цель какая – рисовать тень там, где она должна быть. А где, и как это определить? Сконцентрируемся на 3-х помеченных зонах, на которых видны фрагменты отрисованной боковой поверхности теневой пирамиды. Понятно, что тень нам нужна лишь в зоне 3, на подсунутой под треугольник поверхности, строго под треугольником. Но в чём суть отличия при рисовании теневой юбки? А? Ну? ... В общем, в зонах 1 и 2 (между ними различий нет) задняя и передняя грани теневой юбки наложились одна на другую, но в зоне 3 была отрисована лишь передняя грань, а задняя, скрытая под тенируЕМой поверхностью, не была растеризована! Т.е. там, где нам нужна тень, поверхность юбки была отрисована лишь 1 раз, а там, где тень не нужна – два. Это и есть ключ! Ну а дальше – дело техники (игра с буфером трафарета). Это чуть позже. Теория понятна?
[Беженец со Скаев]
|
|
| |
smt005 | Дата: Вт, 23 Июн 2009, 20:50 | Сообщение # 17 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Думаю, этот метод не очень хороший для высокополигонального "мира".
|
|
| |
Yandersen | Дата: Ср, 24 Июн 2009, 00:13 | Сообщение # 18 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Quote (smt005) Думаю, этот метод не очень хороший для высокополигонального "мира". Мдя... Вообще-то, треугольник был взят для простоты примера. В действительности метод применим для любого выпуклого (а может и для любого вообще!) n-угольника (полигона). Добавлено (24 Июн 2009, 00:13) --------------------------------------------- И метод был бы идеален, если бы не пролетал в случае, когда наблюдатель находится внутри юбки тени. Как решить эту проблему, всё ещё не знаю. Тени тогда инверсируются...
[Беженец со Скаев]
Сообщение отредактировал Yandersen - Ср, 24 Июн 2009, 00:08 |
|
| |
smt005 | Дата: Ср, 24 Июн 2009, 01:23 | Сообщение # 19 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Quote (Yandersen) n-угольника (полигона) Я имел в виду сложный объект на сложную "поверхность". Как с производительностью?
|
|
| |
Yandersen | Дата: Ср, 24 Июн 2009, 02:04 | Сообщение # 20 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Кажысь, допираю... что-то череп трещит... Добавлено (24 Июн 2009, 02:01) ---------------------------------------------
Quote (smt005) Я имел в виду сложный объект на сложную "поверхность". Как с производительностью? Если идти в технические дебри, то о "на что-то" не говорим вообще. Есть только тенируЮЩий объект, но субъект - буффер кадра. Как я уже говорил, производительность будет определятся так: FPS упадёт в два раза, бо рисоваться кадр будет дважды - первый раз без теней, а второй раз - перерисован только там, где в буфере трафарета помечена зона тени. Сколько времени будет потрачено на просчёт теней, зависит лишь от количества тенируЮЩих объектов, которые будут переданы на обработку.Добавлено (24 Июн 2009, 02:04) --------------------------------------------- В принципе, вторую рисовку кадра можно и не делать, а просто нашлёпнуть полупрозрачную чёрную пелену на отмеченные участки.
[Беженец со Скаев]
|
|
| |
smt005 | Дата: Ср, 24 Июн 2009, 15:11 | Сообщение # 21 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| То что написал понятно, идём дальше. Ты в матрицах OpenGL и математических, разбираешся ? Во всех примера о тени, используются матрицы, но я в них ничего не могу понять, следовательно не могу разобраться в построении тени.
|
|
| |
Yandersen | Дата: Чт, 25 Июн 2009, 14:21 | Сообщение # 22 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Quote (smt005) Ты в матрицах OpenGL и математических, разбираешся ? С модельно-видовой - да. Как минимум просчёт вектора направления света для текущей модельно-видовой матрицы я в своём тенепостроителе осуществляю.Quote (smt005) Во всех примера о тени, используются матрицы, но я в них ничего не могу понять, следовательно не могу разобраться в построении тени. Кстати, а ссылочками не покормишь? Мне интересно, как гуру проблему решают. Я тут вчера, вроде, справился с тенями окончательно и написал функции по их рисованию (для полигональных примитивов - треуги, квады и полигоны). Ещё надо проверить работу, набросав в сцену объектов сложной формы, и тогда поделюсь. Пока что интерфейс тенепостроителя получается такой: (0): при создании окна не забыть отвести 8 бит под stencil-буфер! (01): перед рисовкой кадра всегда придётся чистить stencil-биты впридачу к битам цвета и глубины! (02): тест буфера трафарета должен быть всегда включён (не уверен на 100%, ещё подумаю). Функцию по настройке параметров OpenGL, соответствующую моим требованиям и накопленному опыту, дам. 1: рисуем сцену, забыв о тенях. 2: включаем режим рисования теней ( "glsEnterShadowsMode();" ). 3: для всех объектов, тени от которых желаем пометить, для каждого их полигона, из которых они состоят, рисуем в буфере трафарета тень с помощью функций: glsBeginShadow(); glsVertex3fv(...); ... glsVertex3fv(...); glsEndShadow(); К примеру, если вершины полигона такие: float a[3] = {...}; float b[3] = {...}; float c[3] = {...}; float d[3] = {...}; float e[3] = {...}; То рисовка тени от него ничем не отличается от рисовки его самого методом glBegin-glEnd, только названия функций чуть иные: glsBeginShadow(); glsVertex3fv(a); glsVertex3fv(b); glsVertex3fv©; glsVertex3fv(d); glsVertex3fv(e); glsEndShadow(); 4: когда все необходимые полигоны сцены отложили свои тени в буфер трафарета, выходим из режима тенирования ( "glsExitFromShadowsMode();" ). 5: тушим свет и рисуем сцену снова (тут уж обязательно тест трафарета должен быть включён, бо тени помечены лишь в нём, позволяя теперь рисовать лишь в затенённых участках). Пока заголовочный файл с функциями построения теней не дам, бо ещё не закончил. Плюс считаю необходимым осуществить поддержку GL_TRIANGLE_STRIP, что сложнее. Но заголовочным файлом с настройками OpenGL поделюсь (см. в прикреплении). Вроде, я его уже выкладывал... Там описаны функции по инициализации окна, но внимание прошу обратить на функцию "SetupMySettings()" (запускаемую не раньше, чем 3D-окно создано - это важно!). Этих параметров рекомендую придерживаться. Разве что "glDisable(GL_COLOR_MATERIAL);" можно сменить на "glEnable(GL_COLOR_MATERIAL);", если хотите юзать функцию glColor.
[Беженец со Скаев]
|
|
| | |
Yandersen | Дата: Пт, 26 Июн 2009, 14:07 | Сообщение # 24 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Ну, тогда мой метод - "метод теневых объёмов". Жаль его подробно не описали. Блин, не всё так просто оказалось... Теперь рисовка тени не зависит от положения наблюдателя, зато если два объекта кидают тень на третий, то перекрываясь, две тени аннигилируют друг друга! Я сломаю свой микромоск...
[Беженец со Скаев]
|
|
| |
smt005 | Дата: Пт, 26 Июн 2009, 14:46 | Сообщение # 25 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Забудь про "метод теневых объёмов", это прошлый век, сейчас пора "буфера глубины". Добавлено (26 Июн 2009, 14:44) --------------------------------------------- Приимущества "буфера глубины" - сложность объектов никак не влияет на производительность, минус только в том, что требует больше памяти чем "метод теневых объёмов". Но уже давно, оперативы достаточно, даже в М1 используется "буфера глубины". Я даже не припомню игру этого века, которая использовала бы "метод теневых объёмов". Добавлено (26 Июн 2009, 14:46) --------------------------------------------- Принцип работы с "буфер глубины" (ссылки я тебе дал) я понял, если ты не поня, могу объяснить.
|
|
| |
smt005 | Дата: Вс, 28 Июн 2009, 20:27 | Сообщение # 26 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Сделал я тени!!! Правдя не всё понимаю вполне, но использовать могу. Проверьте обязательно прогу: Какая тень, чёрная или полупрозрачная ? Какая видеокарта ? W, S - поднимать полигоны и опускать. A, D - двагать верхний полигон R, F - дважение камеры.
|
|
| |
Микс | Дата: Вс, 28 Июн 2009, 20:34 | Сообщение # 27 |
1 Поколение
Группа: Основной состав
Сообщений: 80
Статус: Offline
| Требует файл meno00.bmp
|
|
| |
Yandersen | Дата: Пн, 29 Июн 2009, 02:30 | Сообщение # 28 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Quote (smt005) Но уже давно, оперативы достаточно, даже в М1 используется "буфера глубины". Я даже не припомню игру этого века, которая использовала бы "метод теневых объёмов". DOOM 3. И любая другая гуля, где тени имеют ровные чёткие границы. В примере Микса стопудово этот метод, кстати.Quote (smt005) Приимущества "буфера глубины" - сложность объектов никак не влияет на производительность, минус только в том, что требует больше памяти чем "метод теневых объёмов". Угу. Только тени выглядят убого-квадратировано, а ещё какие-то необходимые для этого метода функции не входят в стандартный комплект OpenGL. Quote (smt005) Проверьте обязательно прогу Хотелось бы, да вот архив даже не открываеццо... Итак, я всё же жму на теневые объёмы, бо это наиболее реально-представимая, а оттого мне более приятная, байда. Покопался в нете (скажу честно, наши ресурсы не идут ни в какое сравнении с забугорными), изучил вопрос. Заодно полностью врубился в работу буфера трафарета (головоломка ещё та). В общем, есть два подвида метода теневых объёмов, отличающихся скоростью-качеством. Рисовка кадра идёт в обоих случаях в 3 этапа: 1) рисуем сцену, забыв о тенях. Просто тупо рисуем; 2) просчитываем тени в буфере трафарета; 3) темним светило и снова рисуем кадр, только с проверкой буфера трафарета, в результате чего перерисованы будут лишь те зоны, где в трафарете помечены тени. Два подвида, один из которых придуман мной ( ) отличаются 2-м этапом, т.е. способом просчёта затененных участков кадра. Оба требуют построения объёмной закрытой фигуры, представляющей собой теневой объём. Это призма (юбка, надетая на тенирующий полигон, закрытая с обоих концов). Принципы основываются вот на чём: если пиксел кадра внутри теневой фигуры, он затенён, иначе - освещён. В буфере трафарета помечаются те пикселы, которые попали внутрь как минимум одного теневого объёма. Я не буду пудрить мозги техническими моментами, расскажу в общем и вкратце. Распространнённый общепринятый метод требует 2-х проходов, т.е. строить и рисовать пирамиды теней нужно 2 раза при рисовке кадра. Всё отличие - настройки OpenGL перед каждым из циклов. Этот метод строит тени правильно, но если в каком-то участке одна на одну наложатся 256 и более теней - начнутся мильгания (пропадание произвольных теней), связанные с тем, что большинство видюх пока что поддерживают лишь 8-битный буфер трафарета. Это единственный вариант провала 2-х-проходного метода. Я же изобрёл 1-проходный метод (тени просчитываются, соответственно, в 2 раза быстрее) и требующий всего 3-бита буфера трафарета (будет работать на любой видюхе), но проваливающийся тогда, когда наблюдатель находится внутри тени (тень пропадает). Оба метода всунуты в тестовую прогу в прикреплении. Странно, что размер ехе-шника получился всего немногим больше 100 кб, так что боюсь чтоб пошло... Перемещение вверх-вниз-влево-вправо на стрелках, вперёд-назад колёсиком мыши, зажав левую кнопку мыши - вертеть камеру, кнопкой S переключать алгоритмы (разница заметна лишь при вхождении в невидимый объём тени).
[Беженец со Скаев]
|
|
| |
smt005 | Дата: Пн, 29 Июн 2009, 03:27 | Сообщение # 29 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Вот это тпроверьте. Добавлено (29 Июн 2009, 03:27) ---------------------------------------------
Quote (Yandersen) Только тени выглядят убого-квадратировано Смотря как настроеш, в моей демке чёткие тени.Quote (Yandersen) ещё какие-то необходимые для этого метода функции не входят в стандартный комплект OpenGL. Я только OpenGL библиотеками пользовался. Если хочеш тратить время на способ который сейчас нигде не используется, делай, потом сравнить можно будет.
|
|
| |
Yandersen | Дата: Пн, 29 Июн 2009, 04:22 | Сообщение # 30 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| smt005, не работает твоя демка, перпроверь ехешник - не верится в 65кБ размера. И не жми уж такие крохи, ради Святой Компилляции!!!
[Беженец со Скаев]
|
|
| |
Микс | Дата: Пн, 29 Июн 2009, 06:13 | Сообщение # 31 |
1 Поколение
Группа: Основной состав
Сообщений: 80
Статус: Offline
| Приложение Шамана не работает. Ибо нет у меня vcl60.bpl Приложение smt005 работает. Тень у верхнего полигона чёрная, у среднего - нету. Но, если поднести его к южному краю нижнего полигона, то появляется чёрная тень с треугольниками на границе.
|
|
| |
smt005 | Дата: Пн, 29 Июн 2009, 13:13 | Сообщение # 32 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Забыл написать, Yandersen, прога работает, как ты и говорил. Quote (Yandersen) И не жми уж такие крохи Привычка. Quote (Микс) среднего - нету. Подними полигоны с помощью кнопки W. Этот полигон на уровне с нижним, это проявление так называемого "файтинга полигонов". Quote (Микс) Приложение Шамана не работает. Ибо нет у меня vcl60.bpl А ещё жаловался что в OpenGL чегото нет. Quote (Микс) не работает твоя демка Какая ошибка? Как раньше, "неправильно настроенно приложение" ?
|
|
| |
smt005 | Дата: Пн, 29 Июн 2009, 13:33 | Сообщение # 33 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Во что должно получиться.
|
|
| |
Yandersen | Дата: Пн, 29 Июн 2009, 13:46 | Сообщение # 34 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Quote (smt005) Какая ошибка? Как раньше, "неправильно настроенно приложение" ? Угу...
[Беженец со Скаев]
|
|
| |
Yandersen | Дата: Пн, 29 Июн 2009, 14:08 | Сообщение # 35 |
1 Поколение
Группа: Доверенные
Сообщений: 196
Статус: Offline
| Перекомпилил. Добавлено (29 Июн 2009, 14:08) ---------------------------------------------
Quote (Yandersen) Заодно полностью врубился в работу буфера трафарета Это главное, что я получил при освоении метода теневых объёмов. А вообще, чессгря, если метод smt005 действительно даст хорошие результы, то поддержу алгоритм, не требующий ковыряний в графических данных и не зависящий от способов отрисовки сцены. Так что раз ты...Quote (smt005) Сделал я тени!!! Правдя не всё понимаю вполне, но использовать могу. ... и...Quote (smt005) Принцип работы с "буфер глубины" (ссылки я тебе дал) я понял, если ты не поня, могу объяснить. То поделись, плиз, кодом (хотя бы ключевыми строками) и объясни своими словами теорию, плиз, когда время будет, оки?
[Беженец со Скаев]
|
|
| |
Frozen_Light | Дата: Пн, 29 Июн 2009, 15:42 | Сообщение # 36 |
4 Поколение
Группа: Доверенные
Сообщений: 194
Статус: Offline
| Ыгы. Который до сих тормозит на всех видеокартах аж до 7го жирафа.
Я полон оптимизма. Человечество преодолело законы морали, почему бы ему не преодолеть законы физики?
|
|
| |
PA3UJIb | Дата: Пн, 29 Июн 2009, 16:03 | Сообщение # 37 |
1 Поколение
Группа: Основной состав
Сообщений: 105
Статус: Offline
| Quote (Frozen_Light) Который до сих тормозит на всех видеокартах аж до 7го жирафа. у мну на Радике9600 не тормозило, в разрешении 800х640 и минимальными настройками Quote (Yandersen) Перекомпилил. Все прекрасно работает. Quote (smt005) Во что должно получиться. Тоже все отлично. А вот по качеству теней, мне Шамановские больше нравяццо.
|
|
| |
smt005 | Дата: Пн, 29 Июн 2009, 16:59 | Сообщение # 38 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Quote (PA3UJIb) А вот по качеству теней, мне Шамановские больше нравяццо. Что именно не нравиться в "моём" способе? В данном примере чёткость тени сравнима с чёткостью в прмере Yandersenа, разрешение самого экрана только маленькое. А то что она чёрная, так это не конечный результат реализации тени. Quote (Yandersen) То поделись Вот код, хотя ты скорее всего без поллитра не разберёшся сам. Кучу всякого говна скачал где описывается реализация тени и нифига не понимал пока не скачал книгу. OpenGL суперкнига, Ричард С. Райт-мл. и Бенджамин Липчак. http://lib.kruzzz.com/download/7593/design/graph/OpenGL_Right.djvu
|
|
| |
Микс | Дата: Пн, 29 Июн 2009, 19:14 | Сообщение # 39 |
1 Поколение
Группа: Основной состав
Сообщений: 80
Статус: Offline
| 2 smt005 Вот, что нашёл поиском. http://www.gamedev.ru/flame/forum/?id=79361 Походу, некоторым людям надо скачать Microsoft Visual C++ 2008 Redistributable Package. У меня-то самого Microsoft Visual C++ 2008 Express Edition стоит. Добавлено (29 Июн 2009, 19:14) --------------------------------------------- MSPDB80.DLL MSVCR90D.DLL Вот, что нужно.
|
|
| |
smt005 | Дата: Пн, 29 Июн 2009, 19:43 | Сообщение # 40 |
Admin
Группа: Администраторы
Сообщений: 936
Статус: Offline
| Yandersen, попробуй кинуть библиотени о которых Микс говорит.
|
|
| |
|
|