概述
Begin
这个冬天积雪的屏幕特效,从效果上看还是不错的。
实现的原理还是挺简单的。首先获取到屏幕像素的深度纹理信息,得到每个像素的法线。利用法线的Y值得到积雪的程度。然后把积雪贴图和原本的贴图进行混合。
获取屏幕像素的深度纹理
屏幕特效的实现都需要有一个cs脚本和shader 文件。
在cs脚本上,设定好摄像机获取深度纹理
void OnEnable() {
GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
}
然后需要在shander 文件中定义变量 ,和把屏幕坐标的法线转换为世界坐标的法线。
sampler2D _CameraDepthNormalsTexture;
fixed4 frag (v2f i) : SV_Target
{
half3 normal;
float depth;
float2 uv =float2(i.uv.x, i.uv.y);
DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture, uv), depth, normal);
normal = mul( (float3x3)_CamToWorld, normal);
}
完整代码实现
1 屏幕特效基类,来自 Unity shader 入门精要 这本书的。主要是检测硬件是否支持屏幕特效。
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
public class PostEffectsBase : MonoBehaviour {
// Called when start
protected void CheckResources() {
bool isSupported = CheckSupport();
if (isSupported == false) {
NotSupported();
}
}
// Called in CheckResources to check support on this platform
protected bool CheckSupport() {
if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false) {
Debug.LogWarning("This platform does not support image effects or render textures.");
return false;
}
return true;
}
// Called when the platform doesn't support this effect
protected void NotSupported() {
enabled = false;
}
protected void Start() {
CheckResources();
}
// Called when need to create the material used by this effect
protected Material CheckShaderAndCreateMaterial(Shader shader, Material material) {
if (shader == null) {
return null;
}
if (shader.isSupported && material && material.shader == shader)
return material;
if (!shader.isSupported) {
return null;
}
else {
material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
if (material)
return material;
else
return null;
}
}
}
绑定到摄像机的脚本。
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class SnowImageEffectScript_Simple : PostEffectsBase {
public Shader shader;
private Material _material = null;
public Material material {
get {
_material = CheckShaderAndCreateMaterial(shader, _material);
return _material;
}
}
public Texture2D SnowTexture;
public Color SnowColor = Color.white;
[Range(0, 1)]
public float _SnowButtom = 0f;
[Range(0, 10)]
public float _SnowScale = 1f;
void OnEnable() {
GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
}
void OnRenderImage (RenderTexture src, RenderTexture dest) {
if (material != null) {
// set shader properties
_material.SetMatrix("_CamToWorld", GetComponent<Camera>().cameraToWorldMatrix);
_material.SetColor("_SnowColor", SnowColor);
_material.SetFloat("_SnowButtom", _SnowButtom);
_material.SetFloat("_SnowScale", _SnowScale);
_material.SetTexture("_SnowTex", SnowTexture);
Graphics.Blit(src, dest, material);
} else {
Graphics.Blit(src, dest);
}
}
}
屏幕特效的shader
Shader "Hidden/SnowImageEffectShader_Simple"
{
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 = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
sampler2D _CameraDepthNormalsTexture; //深度纹理
float4x4 _CamToWorld;
//摄像机空间 到 世界空间的变换
sampler2D _SnowTex;
half4 _SnowColor;
fixed _SnowButtom;
// 积雪的阈值设置
fixed _SnowScale;
fixed4 frag (v2f i) : SV_Target
{
half3 normal;
float depth;
float2 uv =float2(i.uv.x, i.uv.y);
//获取像素的世界坐标空间的法线
DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture, uv), depth, normal);
normal = mul( (float3x3)_CamToWorld, normal);
//计算积雪阈值
half snowAmount = normal.g * _SnowScale;
if(snowAmount < _SnowButtom)
{
snowAmount=0;
}
//原本的贴图采样
half3 snowColor = tex2D(_SnowTex, uv) * _SnowColor;
half4 col = tex2D(_MainTex, i.uv);
return lerp(col,
half4(snowColor,1), snowAmount);
}
ENDCG
}
}
}
参考
http://blog.theknightsofunity.com/make-it-snow-fast-screen-space-snow-shader/
《 Unity Shader 入门精要》
最后
以上就是健壮铅笔为你收集整理的Unity 屏幕特效 冬天积雪的全部内容,希望文章能够帮你解决Unity 屏幕特效 冬天积雪所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复