1. 程式人生 > >Shader 學習筆記 20160501

Shader 學習筆記 20160501

控制Queue=Tranparent物體顯示順序(使用同一個Material)

  • 當多個物體使用一個Material的時候,不能直接改Material掛載的那個shader的 queue TAG,因為直接改的話會造成所有使用這個Material的Obj的queue都改掉了,也就是達不到我們期望的逐個控制顯示順序的目的了。
  • 這個事情可以給每一個Obj掛一個script,在script裡面用 curMaterial.renderQueue = queueValue 方法來更改這個Obj自己的renderQueue。這樣一搞瞬間想怎麼玩怎麼玩。
  • 這段code是shader的
Shader "Custom/GUI_my" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        //_Glossiness ("Smoothness", Range(0,1)) = 0.5
        //_Metallic ("Metallic", Range(0,1)) = 0.0
        _FadeValue("Fade Value", Range(0,1)) = 0.5
    }
    SubShader {
        //這裡比較重要,如果是渲染半透明物體,最好用Queue=Transparent,因為在Transparent
//render順序是從遠到近的,如果放在Opaque那裡,render順序就是從近到遠了(方便Cull看不見的 //Obj)。 //IgnorProjector表示,我們的半透明物體壓根不管Projector特效。原因是半透明一般是作為visual //effect或者UI使用,沒什麼機會受到Projector的影響的,除非你的設計需要它被影響到 Tags { "RenderType"="Opaque" "Queue" = "Transparent" "IgnoreProjector" = "True"} //啥也不用說,對於半透明物體,必須ZWrite Off
ZWrite Off //背面不渲染,意思就是camera從後面看的話,啥也沒有 Cull Back LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf UnlitGUI alpha novertexlights // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; float _FadeValue; struct Input { float2 uv_MainTex; }; //half _Glossiness; //half _Metallic; fixed4 _Color; inline half4 LightingUnlitGUI (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) { fixed4 c; c.rgb = s.Albedo; c.a = s.Alpha; return c; } void surf (Input IN, inout SurfaceOutput o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb * _Color.rgb; // Metallic and smoothness come from slider variables //o.Metallic = _Metallic; //o.Smoothness = _Glossiness; o.Alpha = c.a*_FadeValue; } ENDCG } FallBack "Diffuse" }
  • 掛在Obj上面的Script
using UnityEngine;
using System.Collections;


[ExecuteInEditMode]
public class RenderQueue : MonoBehaviour {

    public int queueValue = 2000;

    // Use this for initialization
    void Start () {

    }

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

        Material curMaterial = transform.GetComponent<Renderer>().sharedMaterial;

        if (curMaterial)
        {
            //if a material is found set the queue value
            //這裡最吊,居然改到的就是這個Obj自己的renderQueue,沒有改到別的Obj用同一個Material
            //奧妙何在? 難道是new了一個新的Material?!  可是上面明明是
            //transform.GetComponent<Renderer>().sharedMaterial 啊!!! 應該沒new吧
            //不管怎樣,從最終結果上看,的確每一個Obj都賦予了specific的renderQueue值,
            //我傾向於認為還是new了,只不過到底new的是整個Material還是隻是這個renderQueue
            //就不清楚了。。。
            curMaterial.renderQueue = queueValue;

        }
        else
        {
            //if a material is not found show a debug message
            Debug.LogWarning(transform.name + ": cannot find a material to set the render queue!");
        }
    }
}