浅谈 Unity3D 的 RenderQueue

突然发现换了阿里云的空间就支持 wp的 中文链接了,好赞。。

言归正传,今天做了一个 光晕的效果, 参考的是Nehe 的Opengl教程, 以前一直没做过这个东西就有点好奇,做完后,发现效果特别赞,又简单,但是遇到了 RenderQueue 的一些bug,记录一下。

unity3d_overlay2

有人肯定会说Unity3d 自身可以创建 LensFlare 效果,为什么还要自己搞,我看了下,貌似 LensFlare必须绑定到 Light 上才有效果,而且准备素材的时候很麻烦,简单的黑白图调色都不行,还是自己写吧。

再说说 Nehe教程中判断 某点 是否在视野内, 是通过获取相机的视椎体,然后监测某点是否在视椎体的6个平面内。。。 感觉这个真麻烦,直接将 点 通过 mvp 矩阵转换到屏幕空间,然后判断该点坐标是否 x,y > 0 && x,y < 1 即可。 好吧,又跑题了。。。 u3d_overlay_1

如图,编写了一个Shader, RenderQue=”Overlay” ZWrite Off ZTest Off
发现在场景有其他 GameObject 的地方,图片都能正确的挡住它们,但是当背景为天空盒的时候,确被天空盒挡住了, 根据常识理解这不应该, 天空盒应该是在实体层渲染的, 不应该会挡住, 然后在 Shader 中就算改成 Overlay+99999 也是毫无效果。。。


请不要无脑复制转载本文, 由 dreamfairy 原创, 转载请注明出处 本文地址 http://www.dreamfairy.cn/blog/2016/05/25/%e6%b5%85%e8%b0%88-unity3d-%e7%9a%84-renderqueue/
Shader就是这个咯


Shader "Unlit/Overlayer2"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Color("Color", Color) = (1,1,1,1)
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" "Queue"="Overlay+99999"}
		//Blend SrcAlpha One
		ZWrite Off
		ZTest Off

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float4 _Color;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// sample the texture
				fixed a = tex2D(_MainTex, i.uv).r;
				fixed4 col = fixed4(_Color.rgb * a, a);
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
}

于是上 u3d 的官网论坛逛逛,发现一群老外在那边喊 ZTest Always 啊, ZWrite On 啊。。
拜托,如果开启了 ZTest Always 的话,就会影响到UI的层级关系了,因为UI总是 ZTest Always保持最上的, 一个场景特效的问题应该在场景内解决, ZWrite On 更不行了,会导致半透明部分遮挡的天空盒部分无法渲染。

然后写了个 Debug Scrpit做测试,看看RenderQueue 是多少。

using UnityEngine;
using System.Collections;

public class GetQueue : MonoBehaviour {
	public int Queue;
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
		Renderer renderer = this.gameObject.GetComponent<Renderer> ();
		Queue = renderer.sharedMaterial.renderQueue;
	}
}

看完居然是后,发现 Queue 居然不是 4000(Overlay)+99999.. 好吧,你赢咯.
百思不得其解的情况下,我给材质重设了一次Shader, 再次启动居然ok了。。。 绕了好大一圈。。。
改了Shader居然不会刷新,必须手动设置一次, 关了Unity 重开都不会刷新。。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注