v2f vert(v2in v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); half2 texCoord = v.texcoord; half2 deltaTexCoord = texCoord - _ScreenLightPos.xy; deltaTexCoord *= 1.0f / 8 * _Density; texCoord -= deltaTexCoord; o.uv0 = texCoord; texCoord -= deltaTexCoord; o.uv1 = texCoord; texCoord -= deltaTexCoord; o.uv2 = texCoord; texCoord -= deltaTexCoord; o.uv3 = texCoord; texCoord -= deltaTexCoord; o.uv4 = texCoord; texCoord -= deltaTexCoord; o.uv5 = texCoord; texCoord -= deltaTexCoord; o.uv6 = texCoord; texCoord -= deltaTexCoord; o.uv7 = texCoord; return o; }
struct v2f { float4 pos : POSITION; float2 uv0 : TEXCOORD0; float2 uv1 : TEXCOORD1; float2 uv2 : TEXCOORD2; float2 uv3 : TEXCOORD3; float2 uv4 : TEXCOORD4; float2 uv5 : TEXCOORD5; float2 uv6 : TEXCOORD6; float2 uv7 : TEXCOORD7; };
传入值的结构体v2in
struct v2in { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; };
half4 frag(v2f i) : COLOR { half illuminationDecay = 1.0f; half4 color = tex2D(_MainTex, i.uv0)*illuminationDecay; illuminationDecay *= _Decay; color += tex2D(_MainTex, i.uv1)*illuminationDecay; illuminationDecay *= _Decay; color += tex2D(_MainTex, i.uv2)*illuminationDecay; illuminationDecay *= _Decay; color += tex2D(_MainTex, i.uv3)*illuminationDecay; illuminationDecay *= _Decay; color += tex2D(_MainTex, i.uv4)*illuminationDecay; illuminationDecay *= _Decay; color += tex2D(_MainTex, i.uv5)*illuminationDecay; illuminationDecay *= _Decay; color += tex2D(_MainTex, i.uv6)*illuminationDecay; illuminationDecay *= _Decay; color += tex2D(_MainTex, i.uv7)*illuminationDecay; color /= 8; return half4(color.xyz * _Exposure, 1); }
illuminationDecay光照衰减,_Decay是我们外部可控衰减
_Exposure增加亮度
Shader "Custom/god ray 2 blend" { Properties{ _MainTex("Base (RGB)", 2D) = "" {} _GodRayTex ("God (RGB)", 2D) = ""{} _Alpha("_Alpha", Float) = 0.5 } // Shader code pasted into all further CGPROGRAM blocks CGINCLUDE #include "UnityCG.cginc" struct v2in { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; }; struct v2f { float4 pos : POSITION; float2 uv : TEXCOORD0; }; sampler2D _MainTex; sampler2D _GodRayTex; uniform float _Alpha; v2f vert(v2in v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.texcoord; return o; } half4 frag(v2f i) : COLOR { half4 color = tex2D(_MainTex, i.uv) + tex2D(_GodRayTex, i.uv)*_Alpha; //half4 color = tex2D(_MainTex, i.uv); return color; } ENDCG Subshader{ Tags{ "Queue" = "Transparent" } Pass{ ZWrite Off BindChannels { Bind "Vertex", vertex Bind "texcoord", texcoord0 Bind "texcoord1", texcoord1 } Fog{ Mode off } CGPROGRAM #pragma fragmentoption ARB_precision_hint_fastest #pragma vertex vert #pragma fragment frag ENDCG } } Fallback off } // shader
代码如下:
using UnityEngine; using System.Collections; [ExecuteInEditMode] public class godRay2 : MonoBehaviour { public Transform lightpos; public Shader curShader; public Shader curShaderblend; private Material curMaterial; private Material curMateriaBlend; public Vector4 ScreenLightPos = new Vector4(0, 0, 0, 0); public float Density = 0.01f; public float Decay = 0.5f; public float Exposure = 0.5f; public float Alpha = 1; public RenderTexture tempRtA = null; public RenderTexture tempRtB = null; private Vector3 lightScreenPos; #region Properties Material material { get { if (curMaterial == null) { curMaterial = new Material(curShader); curMaterial.hideFlags = HideFlags.HideAndDontSave; } return curMaterial; } } Material materialBlend { get { if (curMateriaBlend == null) { curMateriaBlend = new Material(curShaderblend); curMateriaBlend.hideFlags = HideFlags.HideAndDontSave; } return curMateriaBlend; } } #endregion void Start() { if (!SystemInfo.supportsImageEffects) { enabled = false; return; } if (!curShader && !curShader.isSupported) { enabled = false; } } void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture) { if (curShader != null) { lightScreenPos = Camera.main.WorldToScreenPoint(lightpos.position); if (lightScreenPos.z > 0 && lightScreenPos.x > 0 && lightScreenPos.x < camera.pixelWidth && lightScreenPos.y > 0 && lightScreenPos.y < camera.pixelHeight) { material.SetVector("ScreenLightPos", new Vector4(lightScreenPos.x / camera.pixelWidth, lightScreenPos.y / camera.pixelHeight, 0, 0)); // material.SetVector("ScreenLightPos", ScreenLightPos); material.SetFloat("Density", Density); material.SetFloat("Decay", Decay); material.SetFloat("Exposure", Exposure); materialBlend.SetFloat("Alpha", Alpha); CreateBuffers(); Graphics.Blit(sourceTexture, tempRtA, material); Graphics.Blit(tempRtA, tempRtB, material); Graphics.Blit(tempRtB, tempRtA, material); Graphics.Blit(tempRtA, tempRtB, material); Graphics.Blit(tempRtB, tempRtA, material); materialBlend.SetTexture("_GodRayTex", tempRtA); Graphics.Blit(sourceTexture, destTexture, materialBlend, 0); // Graphics.Blit(tempRtA, destTexture, material, 0); } else { Graphics.Blit(sourceTexture, destTexture); } } else { Graphics.Blit(sourceTexture, destTexture); } } void CreateBuffers() { if (!tempRtA) { tempRtA = new RenderTexture(Screen.width / 4, Screen.height / 4, 0); tempRtA.hideFlags = HideFlags.DontSave; } if (!tempRtB) { tempRtB = new RenderTexture(Screen.width / 4, Screen.height / 4, 0); tempRtB.hideFlags = HideFlags.DontSave; } } void OnDisable() { if (curMaterial) { DestroyImmediate(curMaterial); } } }
本shader有几个缺点,在比较暗的场景不要使用,因为光源处不亮,所以效果不好,Ray的质量不高,从例子就可以看出来,Ray很不清晰,此处可以和Unity ImageEffect的Sun shafts作比较
最后放上两组效果
林中闪耀的光芒