最近想在游戏项目中实现一套天气系统,看到这个文章自己做了一下实现发现不对不知道是不是因为我升级u3d至5.5的原因总是报错主要两个错误:
1、摄像机反转,摄像机的显示和shader执行后的是上下翻转的出现这个情况我的解决方法是将Rendering Path从Deferred设置为Legacy Deferred就ok了。
2、return lerp(col, snowColor, snowAmount);这句话会有一个错误Shader error in 'Jamesloo/ScreenSpaceSnow': cannot implicitly convert from 'const half3' to 'half4' at line 86 (on d3d11) 修改办法是将half3 col = tex2D(_MainTex, i.uv); 改为half4 col = tex2D(_MainTex, i.uv);即可。
奉上源码:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class ScreenSpaceSnow : MonoBehaviour
{
public Camera m_Cam;
public Texture2D SnowTexture;
public Color SnowColor = Color.white;
public float SnowTextureScale = 0.1f;
[Range(-1, 1)]
public float BottomThreshold = 0f;
[Range(-1, 1)]
public float TopThreshold = 1f;
private Material _material;
void OnEnable()
{
// dynamically create a material that will use our shader
_material = new Material(Shader.Find("Jamesloo/ScreenSpaceSnow"));
// tell the camera to render depth and normals
GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
}
void OnRenderImage(RenderTexture src, RenderTexture dest)
{
// set shader properties
//_material.SetMatrix("_CamToWorld", GetComponent<Camera>().cameraToWorldMatrix);
//m_Cam.ResetWorldToCameraMatrix
_material.SetMatrix("_CamToWorld", m_Cam.worldToCameraMatrix);
_material.SetColor("_SnowColor", SnowColor);
_material.SetFloat("_BottomThreshold", BottomThreshold);
_material.SetFloat("_TopThreshold", TopThreshold);
_material.SetTexture("_SnowTex", SnowTexture);
_material.SetFloat("_SnowTexScale", SnowTextureScale);
// execute the shader on input texture (src) and write to output (dest)
Graphics.Blit(src, dest, _material);
}
}
创建脚本绑定至你的场景主摄像机。
Shader "Jamesloo/ScreenSpaceSnow"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
sampler2D _CameraDepthNormalsTexture;
float4x4 _CamToWorld;
sampler2D _SnowTex;
float _SnowTexScale;
half4 _SnowColor;
fixed _BottomThreshold;
fixed _TopThreshold;
half4 frag (v2f i) : SV_Target
{
half3 normal;
float depth;
DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture, i.uv), depth, normal);
normal = mul((float3x3)_CamToWorld, normal);
// find out snow amount
half snowAmount = normal.g;
half scale = (_BottomThreshold + 1 - _TopThreshold) / 1 + 1;
snowAmount = saturate((snowAmount - _BottomThreshold) * scale);
//find out snow color
float2 p11_22 = float2(unity_CameraProjection._11, unity_CameraProjection._22);
float3 vpos = float3((i.uv * 2 - 1) / p11_22, -1) * depth;
float4 wpos = mul(_CamToWorld, float4(vpos, 1));
wpos += float4(_WorldSpaceCameraPos, 0) / _ProjectionParams.z;
half4 snowColor = tex2D(_SnowTex, wpos.xz * _SnowTexScale * _ProjectionParams.z) * _SnowColor;
// get color and lerp to snow texture
half4 col = tex2D(_MainTex, i.uv);
//return col;
return lerp(col, snowColor, snowAmount);
}
ENDCG
}
}
}
如果不明白实现的原理可以参考原文http://blog.theknightsofunity.com/make-it-snow-fast-screen-space-snow-shader/
最终效果图
Bottom Threshold = -1
Bottom Threshold = 0