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

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

СообщениеДобавлено: 03 окт 2019, 08:42
vexpmon
Всем привет!
Собрал в конструкторе шейдер для 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 - то все нормально

Помогите разобраться в чем проблема плиз

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

СообщениеДобавлено: 03 окт 2019, 15:05
DbIMok
думаю проблема в том, что material и его UI это разные сущности. если вы меняете что-то через UI, оно "знает", что что-то происходило с материалом. если работаете с материалом напрямую, то нет

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

СообщениеДобавлено: 03 окт 2019, 18:40
waruiyume
Выглядит как говно, но как умею:
Синтаксис:
Используется 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.