Страница 1 из 1

Replecement shader

СообщениеДобавлено: 20 июл 2016, 01:19
kripto289
Пытаюсь разобраться с replacement shader на камере.
Кто-нибудь в курсе как это работает? Так и не разобрался. Буду очень рад простому примеру.

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 01:46
waruiyume
Страницу справки починили http://docs.unity3d.com/Manual/SL-Shade ... ement.html (собственно ничего не добавишь).
В прошлый раз когда я тута заходил там было пусто.
Очень наглядный демо проект юнитеков https://www.assetstore.unity3d.com/en/#!/content/5145(искать его пришлось с собаками, комментах пишут, что он не 100% рабочий, но думаю, что копипастить из него можно и сейчас.)

Ещё один пример, в нём с помощью Replecement shader создаётся маска для объектов, в шейдере которых указан определённый тег.

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 09:19
kripto289
waruiyume писал(а):Страницу справки починили http://docs.unity3d.com/Manual/SL-Shade ... ement.html (собственно ничего не добавишь).
В прошлый раз когда я тута заходил там было пусто.
Очень наглядный демо проект юнитеков https://www.assetstore.unity3d.com/en/#!/content/5145(искать его пришлось с собаками, комментах пишут, что он не 100% рабочий, но думаю, что копипастить из него можно и сейчас.)

Ещё один пример, в нём с помощью Replecement shader создаётся маска для объектов, в шейдере которых указан определённый тег.

Справка это первое что я открываю.
Мне не понятен сам процесс. Вот например что есть эта строка? " maskCamera.RenderWithShader(maskShader, "RenderType");"
Выбираются все объекты с RenderType? Wat? Какой смысл от такого свойства, если все шейдера имеют RenderType? Как рендирить только определённые сабшейдеры? Например с тегом "renderType"="blabla"?
За ссылки спасибо, буду разбираться.

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 12:56
waruiyume
Дык, там же ниже есть пример.
Допустим, у Вас на сцене есть объекты с "RenderType"="Opaque" и "RenderType"="blabla"
При отрисовке с заменой, сабшейдеры объектов на сцене "заменяются" сабшейдерами из шейдера который передаётся в первом параметре. Во втором параметре, фактически, указывается переменная, которая должна совпасть в сабшейдере на сцене и сабшейдере эффекта.
Синтаксис:
Используется glsl
Shader "EffectShader" {
     SubShader {
         Tags { "RenderType"="Opaque" }
         Pass {
             //рисовать с красной заливкой
         }
     }
     SubShader {
         Tags { "RenderType"="blabla" }
         Pass {
             //рисовать кислотный трип
         }
     }
 ...
 }
 

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 14:38
kripto289
waruiyume писал(а):Дык, там же ниже есть пример.
Допустим, у Вас на сцене есть объекты с "RenderType"="Opaque" и "RenderType"="blabla"
При отрисовке с заменой, сабшейдеры объектов на сцене "заменяются" сабшейдерами из шейдера который передаётся в первом параметре. Во втором параметре, фактически, указывается переменная, которая должна совпасть в сабшейдере на сцене и сабшейдере эффекта.
Синтаксис:
Используется glsl
Shader "EffectShader" {
     SubShader {
         Tags { "RenderType"="Opaque" }
         Pass {
             //рисовать с красной заливкой
         }
     }
     SubShader {
         Tags { "RenderType"="blabla" }
         Pass {
             //рисовать кислотный трип
         }
     }
 ...
 }
 

Во втором параметре renderWithShader как раз совпадает "RenderType" с обоими сабшейдерами выше. Судя по справке выше, он заменит первое вхождение. А если я хочу заменить только 2-ой сабшейдер? Что мне писать?
У меня не было бы проблем, если бы все писали "renderWithShader(shader, "blabla")", тогда ясно что он заменяет. Ну или так "renderWithShader(shader, "RenderType=blabla")",

Вообще мне кажется я не той дорогой иду. У меня есть некий объект с шейдером (у которого определённый тег, блабла например), и мне надо что бы камера с RenderTarget не отрисовывала этот объект. Юзать слои не могу, так как их нельзя создать в рантайме. Получится ли у меня с заменой шейдера игнорить отрисовку, если я пропишу аддитивный шейдер с 0 альфой?

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 14:49
waruiyume
Получится ли у меня с заменой шейдера игнорить отрисовку, если я пропишу аддитивный шейдер с 0 альфой?

Нет, такое сделать не получится, поскольку, будут отрисованы только заменённые, т.е. Вам придётся дублировать все используемые шейдеры, что, явно, крайне затруднительно.
В смысле, нельзя создавать рантайм, всегда же есть 32 слоя, и ни больше ни меньше сделать слоёв не получится?

Может просто задефайнить в шейдере участок который будет делать discard или возвращать цвет с нулевой альфой, и включать ключевое слово при надобности?

А вообще, не проще вырубить рендерер?

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 16:03
kripto289
waruiyume писал(а):
Получится ли у меня с заменой шейдера игнорить отрисовку, если я пропишу аддитивный шейдер с 0 альфой?

Нет, такое сделать не получится, поскольку, будут отрисованы только заменённые, т.е. Вам придётся дублировать все используемые шейдеры, что, явно, крайне затруднительно.
В смысле, нельзя создавать рантайм, всегда же есть 32 слоя, и ни больше ни меньше сделать слоёв не получится?

Может просто задефайнить в шейдере участок который будет делать discard или возвращать цвет с нулевой альфой, и включать ключевое слово при надобности?

А вообще, не проще вырубить рендерер?

Расскажу суть.
У меня есть шейдер с искажениями. Он должен работать как на ПК, так и на мобилках.
Примерно такой констуркции
Subshader {
GrabPass{}
Pass{}
}

Дефайнами я не могу закрыть секцию grabpass. (которая глючит на мобилках). Lod не пойдёт (у меня куча разных шейдеров, как их все выбрать? по какому признаку?)
Опустим этот момент. Я делаю костыль - я создаю второй шейдер без grabpass. Вместо текстуры из бэкбуфера я рендерю в renderTarget и передаю как текстуру в шейдер.
Возникает проблема, ибо камера захватывает объект. Выходит рекурсивная картинка.
Для игнорирования я не могу использовать слои. Код переносимый, а слои перенести нельзя. Более того, если не объекте висит несколько материалов среди которых мой, то слой закроет отрисовку всех остальных материалов. (тот же эффект льда на скинед поверхности например, уже не создать).
Слои кстати можно создавать только в редакторе, и я даже не представляю как они переносятся в другой проект с другим кол-вом слоёв. Там ведь сравнение слоёв побитовое и всё полетит к чертям?

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 16:24
waruiyume
Слои кстати можно создавать только в редакторе

Слои нельзя создавать в принципе, ни в редакторе, ни в рантайме, можно только назначить им имя. Если у слоя не имени это не значит, что слой не существует.

Ну, так не используйте GrabPass, разве нельзя отрендерить с цену в OnPrerender в текстуру, предварительно выключив ненужные рендереры?

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 16:50
kripto289
waruiyume писал(а):
Слои кстати можно создавать только в редакторе

Слои нельзя создавать в принципе, ни в редакторе, ни в рантайме, можно только назначить им имя. Если у слоя не имени это не значит, что слой не существует.

Ну, так не используйте GrabPass, разве нельзя отрендерить с цену в OnPrerender в текстуру, предварительно выключив ненужные рендереры?

Как выключить рендеры не юзая слои? Так?

public void OnPreRender ()
{
this.renderer.enabled = false;
}
public void OnPostRender ()
{
this.renderer.enabled = true;
}
Но ведь объект не будет рендириться вообще. А если висит 2 материала, то мне надо рендирить объект только с 1 материалом. Как вариант, если не юзать несколько материалов на меше, пойдёт.
Заменой шейдера сами сказали что не выйдет. Я не работал с камерами и постэффектами, пока это для меня тёмный лес.

Можно ли такое провернуть стенсил буфером:?

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 17:05
waruiyume
Так:
Синтаксис:
  1. void OnPreRender ()//Вызывается только для камеры 
  2.    ВыключитьТоЧтоНеНужно(); 
  3.    ОтрендеритьКамеруВтекстуру(); 
  4.    ВключитьНенужноеОбратно(); 

В этом случае фокус в дефайнами должен сработать, GrabPass же не будет использоваться.

Можно ли такое провернуть стенсил буфером:?

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

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 17:33
kripto289
waruiyume писал(а):Так:
Синтаксис:
  1. void OnPreRender ()//Вызывается только для камеры 
  2.    ВыключитьТоЧтоНеНужно(); 
  3.    ОтрендеритьКамеруВтекстуру(); 
  4.    ВключитьНенужноеОбратно(); 

В этом случае фокус в дефайнами должен сработать, GrabPass же не будет использоваться.

Можно ли такое провернуть стенсил буфером:?

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

О точно, вообще не подумал что я могу не только объект вырубать, а но и манипулировать его материалами и дефайнами. Спасибо!

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

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 18:11
waruiyume
Найдите все рендереры Object.FindObjectsOfType, а потом отсейте по шейдеру из используемых материалов.

Replacement шейдер всё равно игнорирует значения ключей.

Вы чего-то путаете.

Re: Replecement shader

СообщениеДобавлено: 20 июл 2016, 21:24
kripto289
waruiyume писал(а):Найдите все рендереры Object.FindObjectsOfType, а потом отсейте по шейдеру из используемых материалов.

Replacement шейдер всё равно игнорирует значения ключей.

Вы чего-то путаете.

Всё я разобрался как это работает. Теперь понятно как юнити рендирит forward base и всякие другие проходы.
Спасибо за помощь!