Передать параметр в шейдер

Шейдеры и все-все-все.

Передать параметр в шейдер

Сообщение vexpmon 03 окт 2019, 08:42

Всем привет!
Собрал в конструкторе шейдер для UI элемента
https://yadi.sk/d/J4YksreegkH67A
GX/UI/Selector
У него есть enum параметр селектор в который передается значение от 0 до 3
Если значение больше 0 - то подсвечивается необходимая текстура Icon , при 0 - иконки не подсвечиваются
Значение в шейдер передаю следующей строкой
Синтаксис:
Используется csharp
Header.GetComponent<Image>().material.SetFloat("_Selector", 2);

где Header ссылка GameObject - элемент UI Image
Программно на материале значение меняется, но сам шейдер не срабатывает - иконка не подсвечивается
Если же выбераю вручную на метриале в Editor'e - то все нормально

Помогите разобраться в чем проблема плиз
Аватара пользователя
vexpmon
UNец
 
Сообщения: 30
Зарегистрирован: 15 авг 2014, 21:29

Re: Передать параметр в шейдер

Сообщение DbIMok 03 окт 2019, 15:05

думаю проблема в том, что material и его UI это разные сущности. если вы меняете что-то через UI, оно "знает", что что-то происходило с материалом. если работаете с материалом напрямую, то нет
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > Telegram чат @unity3d_ru (4200+) > Telegram канал @unity_news (1500+) > Telegram тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 5936
Зарегистрирован: 31 июл 2009, 14:05
Откуда: RU.61
  • Сайт

Re: Передать параметр в шейдер

Сообщение waruiyume 03 окт 2019, 18:40

Выглядит как говно, но как умею:
Синтаксис:
Используется csharp
using System;
using UnityEngine;

[ExecuteInEditMode]
public class ShaderFeatureSet : MonoBehaviour
{
    private Material mat;
    [SerializeField, HideInInspector]
    private Material oldMaterialP;

    public shader_feature activeFeature;
    //shader_feature _SELECTOR_I0 _SELECTOR_I1 _SELECTOR_I2 _SELECTOR_I3
    public enum shader_feature
    {
        _SELECTOR_I0, _SELECTOR_I1, _SELECTOR_I2, _SELECTOR_I3
    }

    void OnValidate()
    {
        if (!mat)
        {
            var ren = GetComponent<Renderer>();
            if(!oldMaterialP)
            {
                oldMaterialP = ren.sharedMaterial;
                mat = Instantiate(ren.sharedMaterial);
                ren.sharedMaterial = mat;
            }
            else
            {
                mat = Instantiate(oldMaterialP);
                ren.sharedMaterial = mat;
            }
            if (!mat)return;
        }

        foreach (var n in Enum.GetNames(typeof(shader_feature)))
        {
            if (!mat.IsKeywordEnabled(n) && activeFeature.ToString() == n)
                mat.EnableKeyword(n);
            else
                mat.DisableKeyword(n);
        }
    }

    void OnDisable()
    {
        if (mat)
        {
            DestroyImmediate(mat);
            GetComponent<Renderer>().sharedMaterial = oldMaterialP;
        }
    }
}
 

Вообще рабочая часть эта:
Синтаксис:
Используется csharp
foreach (var n in Enum.GetNames(typeof(shader_feature)))
        {
            if (!mat.IsKeywordEnabled(n) && activeFeature.ToString() == n)
                mat.EnableKeyword(n);
            else
                mat.DisableKeyword(n);
        }


И да, в билд попадут только те shader_feature, которые активированы на материале во время сборки билда. Чтобы активировать куски кода в рантайме, нужно юзать multicompile(не помню как в Амплифи оно называется) или обычный if.
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 5301
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону


Вернуться в Shader Lab

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1