Добрый день.
Прошу помощи в таком вопросе - как осуществить отрисовку только части объекта. Т.е. можно ли, например, разместить перед непрозрачным предметом какой-то невидимый объект, чтобы области им перекрываемые не отрисовывались?
Или такой способ в корне не верен и нужно смотреть в какую-то другую сторону? Если так, то прошу подсказать в какую.
Теоретически (я не пробовал) можно прям как говоришь. Шаг 1 - рисуем то, что должно быть видно всегда. Шаг 2 рисуем материалом который только заполняет буфер глубины. Шаг 3 - рисуем объекты в которых могут быть "дырки".
То есть если брать fallout 1-2 например то дырок там нет в предметах, полу и персонажах. А вот в стенках есть.
Можно так:
В render path добавляешь проход cull прямо перед проходом base:
<command type="scenepass" pass="cull" />
Тот объект, который будет "перекрывать" отрисовываешь вот таким материалом:
Materials/InvisibleOccluder.xml:
<material> <technique name="Techniques/InvisibleOccluder.xml" quality="0" loddistance="0" /> <parameter name="UOffset" value="1 0 0 0" /> <parameter name="VOffset" value="0 1 0 0" /> <parameter name="MatDiffColor" value="1 1 1 0" /> <parameter name="MatEmissiveColor" value="0 0 0" /> <parameter name="MatEnvMapColor" value="1 1 1" /> <parameter name="MatSpecColor" value="0 0 0 1" /> <parameter name="Roughness" value="0.5" /> <parameter name="Metallic" value="0" /> <cull value="ccw" /> <shadowcull value="ccw" /> <fill value="solid" /> <depthbias constant="0" slopescaled="0" /> <renderorder value="128" /> </material>
Техника Techniques/InvisibleOccluder.xm:
<technique vs="Unlit" ps="Unlit" vsdefines="NOUV" > <pass name="cull" blend="alpha" /> </technique>
По сути - ты заполняешь z-buffer объектом-окклудером, при этом не рисуя на экран.
После чего остальные объекты не пройдут z-test.
Метод не самый оптимальный, но вроде работает.
Спасибо. Но пока что-то не получается. Окклюдер действительно не видим. Но никакого отсечения не получается((( Пробовал ему render order меньше поставить - без изменений.
Если что - окклюдером пытаюсь сделать CustomGeometry.
Попробуй кубик чтоб наверняка
А точно render pass присутствует в выбранном render path?
Сделайте альфу ненулевой в материале, например
<parameter name="MatDiffColor" value="1 1 1 1" />
Вы должны увидеть окклудер
Кубик работает. Не совсем так как я ожидал, но работает
smb_z, я рендер pass для уверенности в Forward.xml добавил.
При не нулевой альфе:
- кубик виден
- CustomGeometry нет
CustomGeometry создается и меняется через BeginGeometry()/DefineVertex()/Commit()
ну проблема, видимо, в CustomGeometry. тут не подскажу, смотреть надо.
Вроде в примера было как с ней работать. Надо добиться что бы она работала с обычными материалами, а потом уже назначать ей InvisibleOccluder.
Кстати посмотри в сторону параметра cull. Может у тебя треугольники не в том порядке обходятся?
"Где были мои глаза? Елки-палки"
Действительно про cull я и забыл. Все в первом приближении заработало. Спасибо огромное!!!
Правда сейчас окклюдер вырезает все до бесконечности. А мне хотелось бы, чтобы фоновые (те что находятся еще дальше чем прорезаемый объект) предметы не вырезались.
Я так понимаю это уже на render order смотреть надо?
Нет, сейчас окклудер всегда рендерится первым, независимо от render order, т.к. он в отдельном пассе рисуется (render order влияет на сортировку в пределах одного пасса)
Поменяй
<pass name="cull" blend="alpha" />
на
<pass name="base" blend="alpha" />
и тогда да, можно регулировать порядок отрисовки с помощью render order.
После двух дней экспериментов вынужден признать, что, очевидно, я не понимаю чего-то фундаментального.
Цель моих экспериментов следующая - мне необходимо убирать часть объекта расположенного перед "экраном"
На верхнем рисунке "нулевая" сцена - зеленым цветом обозначен обрезаемый объект, синим -окклюдер, красным - экран.
В этом состоянии окклюдер не должен ничего обрезать, т.е. объект располагается перед экраном и все хорошо - как я понимаю, чтобы добиьтся этого, экран должен рисоваться первым.
На нижнем рисунке собственно ситуация с обрезкой - в результате поворота, часть зеленого объекта оказывается за окклюдером(выделена желтым, слева от пунктирной линии) и должна обрезаться.
Экран по прежнему не обрезается.
Для чего все это? Это мои эксперименты по дополненной реальности - экран действительно является экраном, на него транслируется изображение с камеры.
Техники для экрана и объекта я использовал стандартные, DiffAlpha
Итоги экспериментов:
Для окклюдера я пытался адаптировать приведенную выше в ветке технику используя pass="base". Когда для окклюдера используется такая техника:
<technique vs="Unlit" ps="Unlit" vsdefines="NOUV" > <pass name="base" depthwrite="true" depthtest="less" blend="alpha" /> </technique>
Происходит и обрезка экрана и вырезка "экрана".
Я пытался заменить depthtest на greater, чтобы с одной стороны запись в буфер производилась, но с другой сам окклюдер не отображался - в результате окклюдер не отображается, но и обрезка объекта больше не производится.
Я так подозреваю, что именно здесь, я что-то важное и не понимаю - но вот что?
>В этом состоянии окклюдер не должен ничего обрезать
ну вот на верхнем рисунке тебе окклюдер по идее как раз должен середину у зеленого вырезать (если смотреть со стороны красной плоскости, вниз )
на нижнем должна остаться только треугольная часть от зеленого, что отсечена вертикальной линией. (мб еще чутку с другого края)
>Для чего все это? Это мои эксперименты по дополненной реальности - экран действительно является экраном, на него транслируется изображение с камеры.
Я не понял тебе нужно реальной геометрий с камеры обрезать оверлейную AR-графику ?
ну если ты построил и знаешь реальные объемы обьектов с камеры, то почему бы тебе их просто не нарисовать грубой геометрией в самом начале кадра без всяких окклюдеров
они заполнят Z буффер
далее ты очищаешь Viewport (color/albedo) (Сlear можно юзать для RT и в середине RenderPath'a)
и рисуешь свою AR - геометрию (как обычно) с уже формированным Z буфером.
или я задачу не так понял?
Забыл указать направление:( Смотреть нужно снизу - через зеленый объект на экран.
Работает это так - изображение с камеры без изменений транслируется на экран. Это изображение дополняется зеленым объектом (который кстати полупрозрачный).На основе анализа изображения создается окклюдер (именно поэтому я выбрал CustomGeometry - форма окклюдера постоянно меняется)
Задачей этого окклюдера является обрезка тех частей зеленого объекта, которые по логике дополнения изображения на экране в настоящий момент являются лишними.
как я уже писал выше пробуй рендерить таким образом:
сначала свои окклюдеры как обычную геометрию, только лишь для того чтобы заполнить Z буффер
после прорисовки всех окклюдеров очищаешь viewport
первым делом рисуешь свой экран (красную плоскость) без теста и без записи в Z
затем переключаешься в обычный режим и рисуешь "зеленые объекты", их должно отсечь по Z от пасса с окклюдерами
примерно так RP и техники должны выглядеть
можешь даже вместо пассов(cull и screen) заюзать просто 2-render-ивент'а. И в программе, при получении сообщений рисовать уже используя низкоуровневый graphics...
Тема в архиве.