How can I access shader variables from script?

ぃ、小莉子 提交于 2019-12-24 21:46:39

问题


The shader:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Outlined/Silhouetted Diffuse" {
     Properties {
         _Color ("Main Color", Color) = (.5,.5,.5,1)
         _OutlineColor ("Outline Color", Color) = (0,0,0,1)
         _Outline ("Outline width", Range (0.0, 0.03)) = .005
         _MainTex ("Base (RGB)", 2D) = "white" { }
     }

 CGINCLUDE
 #include "UnityCG.cginc"

 struct appdata {
     float4 vertex : POSITION;
     float3 normal : NORMAL;
 };

 struct v2f {
     float4 pos : POSITION;
     float4 color : COLOR;
 };

 uniform float _Outline;
 uniform float4 _OutlineColor;

 v2f vert(appdata v) {
     // just make a copy of incoming vertex data but scaled according to normal direction
     v2f o;
     o.pos = UnityObjectToClipPos(v.vertex);

     float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
     float2 offset = TransformViewToProjection(norm.xy);

     o.pos.xy += offset * o.pos.z * _Outline;
     o.color = _OutlineColor;
     return o;
 }
 ENDCG

     SubShader {
         Tags { "Queue" = "Transparent" }

         // note that a vertex shader is specified here but its using the one above
         Pass {
             Name "OUTLINE"
             Tags { "LightMode" = "Always" }
             Cull Off
             ZWrite Off
             ZTest Always
             ColorMask RGB // alpha not used

             // you can choose what kind of blending mode you want for the outline
             Blend SrcAlpha OneMinusSrcAlpha // Normal
             //Blend One One // Additive
             //Blend One OneMinusDstColor // Soft Additive
             //Blend DstColor Zero // Multiplicative
             //Blend DstColor SrcColor // 2x Multiplicative

 CGPROGRAM
 #pragma vertex vert
 #pragma fragment frag

 half4 frag(v2f i) :COLOR {
     return i.color;
 }
 ENDCG
         }

         Pass {
             Name "BASE"
             ZWrite On
             ZTest LEqual
             Blend SrcAlpha OneMinusSrcAlpha
             Material {
                 Diffuse [_Color]
                 Ambient [_Color]
             }
             Lighting On
             SetTexture [_MainTex] {
                 ConstantColor [_Color]
                 Combine texture * constant
             }
             SetTexture [_MainTex] {
                 Combine previous * primary DOUBLE
             }
         }
     }

     SubShader {
         Tags { "Queue" = "Transparent" }

         Pass {
             Name "OUTLINE"
             Tags { "LightMode" = "Always" }
             Cull Front
             ZWrite Off
             ZTest Always
             ColorMask RGB

             // you can choose what kind of blending mode you want for the outline
             Blend SrcAlpha OneMinusSrcAlpha // Normal
             //Blend One One // Additive
             //Blend One OneMinusDstColor // Soft Additive
             //Blend DstColor Zero // Multiplicative
             //Blend DstColor SrcColor // 2x Multiplicative

             CGPROGRAM
             #pragma vertex vert
             #pragma exclude_renderers gles xbox360 ps3
             ENDCG
             SetTexture [_MainTex] { combine primary }
         }

         Pass {
             Name "BASE"
             ZWrite On
             ZTest LEqual
             Blend SrcAlpha OneMinusSrcAlpha
             Material {
                 Diffuse [_Color]
                 Ambient [_Color]
             }
             Lighting On
             SetTexture [_MainTex] {
                 ConstantColor [_Color]
                 Combine texture * constant
             }
             SetTexture [_MainTex] {
                 Combine previous * primary DOUBLE
             }
         }
     }

     Fallback "Diffuse"
 }

And after attached the shader to a material on a cube I want now to control the Outline width in csharp script so I also attached a script empty for now to the cube:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Outline : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}

For example I want to change the Outline width value using time or startcoroutine.

If the Outline width range values are 0.0, 0.03 then I want to change this values automatic from 0 to 0.03 using time or startcoroutine.

Update:

This is working using Update for changing the _Outline value:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Outline : MonoBehaviour
{
    public float width;

    private Renderer rend;
    private float currentWidth;

    private void Start()
    {
        rend = GetComponent<Renderer>();
        currentWidth = rend.material.GetFloat("_Outline");
    }

    private void Update()
    {
        SetOutLineWidth(width);
    }

    public void SetOutLineWidth(float width)
    {
        rend.material.SetFloat("_Outline", width);
    }
}

But now how can I use startcoroutine to change the _Outline value automatic nonstop from 0.0 to 0.03 and back from 0.03 to 0.0 ?


回答1:


You have two options.

  1. and the simplest: store your oscillating value in the script (modify, then call material.SetFloat() with the new value).

  2. Material.GetFloat()




回答2:


Not Sure If You Still Need It But Here Is My Solution, only different is the variable name for width outline

using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class BlinkingHighlight : MonoBehaviour {

        public Renderer rend;

        float initialWidth = 0f;
        float EndWidth = 0.025f;

        float waitTime = 0.5f;

        public bool TestBlinking = false;
        bool BlinkingCycleComplete = false;

        void Start() {
            rend = GetComponent<Renderer> ();
        }

        public IEnumerator Blinking(){
            //Debug.Log ("Blinking");
            BlinkingCycleComplete = true;
            rend.material.SetFloat ("_OutlineWidth", initialWidth);
            yield return new WaitForSeconds(waitTime);
            rend.material.SetFloat ("_OutlineWidth", EndWidth);
            yield return new WaitForSeconds(waitTime);
            BlinkingCycleComplete = false;
        }

        void Update() {
            if (TestBlinking == true && BlinkingCycleComplete == false) {
                StartCoroutine (Blinking ());
            } else if (TestBlinking == false) {
                rend.material.SetFloat ("_OutlineWidth", initialWidth);
            }
        }
    }


来源:https://stackoverflow.com/questions/48472332/how-can-i-access-shader-variables-from-script

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!