Unity shader 笔记之迷雾效果

先看效果图:

Shader "Unlit/FogOfWar"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
	}
	CGINCLUDE
	#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;
	v2f vert (appdata v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);
		o.uv = TRANSFORM_TEX(v.uv, _MainTex);
		UNITY_TRANSFER_FOG(o,o.vertex);
		return o;
	}
			
	fixed4 frag (v2f i) : SV_Target
	{
		fixed4 col = tex2D(_MainTex, i.uv);
		
		return col;
	}
	ENDCG
	SubShader
	{
		Tags { "Queue" = "Transparent+20" }
		ZTest Off
		Blend SrcAlpha OneMinusSrcAlpha
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}
}
Shader "ImageEffect/AverageBlur"
{
	Properties		//变量定义
	{
		_MainTex ("Texture", 2D) = "black" {}	//主贴图
		
		_LastTex ("LastTexture", 2D) = "black" {}	//主贴图
		_BlurRadius("BlurRadius",float) = 1.3
		_LerpRate("LerpRate",float) = 0.05
	}
	CGINCLUDE
	#include "UnityCG.cginc"
	struct v2f
	{
		float4 pos:SV_POSITION;
		float2 uv:TEXCOORD0;
	};
	sampler2D _MainTex;		//基础颜色贴图输入
	float4 _MainTex_TexelSize;		//XX_TexelSize,XX纹理的像素相关大小width,height对应纹理的分辨率,
									//x = 1/width, y = 1/height, z = width, w = height
	float _BlurRadius;		//模糊采样半径
	float _LerpRate;
	sampler2D _LastTex;	
	v2f  vert (appdata_img v)
	{
		v2f  o;
		o.pos = UnityObjectToClipPos(v.vertex);
		o.uv=v.texcoord.xy;
		return o;
	}
	fixed4 frag2 (v2f i) : SV_Target		//frag片段函数 会对每一个像素点执行此函数 输入像素颜色等信息 输出最终该点颜色
	{
	
		fixed4 col = fixed4(0,0,0,0);	//初始化色彩为黑色
		float2 offset=_BlurRadius*_MainTex_TexelSize;
		half G[9]={		//设置卷积模板   此处是3*3的高斯模板
			1,2,1,
			2,4,2,
			1,2,1
		};
		for (int x=0;x<3;x++){	//进行3*3高斯模板的卷积(加权求平均值)
			for (int y=0;y<3;y++){
				col+=tex2D(_MainTex,i.uv+fixed2(x-1,y-1)*offset)*G[x*1+y*3];
			}
		}
		col=col/16;
		return col;
	} 	
	fixed4 frag (v2f i) : SV_Target		//frag片段函数 会对每一个像素点执行此函数 输入像素颜色等信息 输出最终该点颜色
	{
		fixed4 col = fixed4(0,0,0,0);	//初始化颜色为黑色 fixed4及四维向量 精度为fixed以此类推 

		fixed2 offset=_BlurRadius*_MainTex_TexelSize;	//用offset保存 半径对应贴图的uv偏移量

		for (int x=0;x<3;x++){			//循环遍历周围像素点
			for (int y=0;y<3;y++){
				col.a+=tex2D(_MainTex,i.uv+fixed2(x-1,y-1)*offset).a;	//全部加和
			}
		} 
		col.a=col.a/9;
		return col;		//因遍历周围9各像素点
	} 
	fixed4 lerpFrag (v2f i) : SV_Target		//frag片段函数 会对每一个像素点执行此函数 输入像素颜色等信息 输出最终该点颜色
	{
		half4 col1=tex2D(_MainTex,i.uv);
		half4 col2=tex2D(_LastTex,i.uv);

		return lerp(col2,col1,_LerpRate);		//因遍历周围9各像素点
	} 
	ENDCG
	SubShader
	{
		Cull Off ZWrite Off ZTest Always 
		Pass	//Pass 通道 主要是实现一些顶点和片段着色器功能
		{
			CGPROGRAM	//CG程序开始
			 //声明顶点着色器函数名字为vert
			#pragma vertex vert	
			 //声明片段着色器函数名字为frag
			#pragma fragment frag2
			ENDCG		 //CG程序结束
		}
		Pass
		{
			CGPROGRAM	//CG程序开始
			 //声明顶点着色器函数名字为vert
			#pragma vertex vert	
			 //声明片段着色器函数名字为frag
			#pragma fragment lerpFrag
			ENDCG		 //CG程序结束
		}
	}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FogOfWar
{
    public class FowFogRenderer : MonoBehaviour
    {
        public FowManager fowManager;
        public GameObject rendererPrefab;
        Material material;
        // Use this for initialization
        void Start()
        {
            var renderer= Instantiate(rendererPrefab, transform);
            renderer.transform.localPosition = Vector3.zero;
            renderer.transform.localScale = new Vector3(fowManager.FogSizeX/2, 1, fowManager.FogSizeY/2);
            material= renderer.GetComponentInChildren<Renderer>().material;
        }

        // Update is called once per frame
        void Update()
        {
            if (fowManager.map.FogTexture != null)
            {
                material.SetTexture("_MainTex", fowManager.map.FogTexture);
            }
           
        }
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FogOfWar
{
    public class InitMapByPhysics : MonoBehaviour
    {
        public FowManager fowManager;
        int[,] mapData;
        void Start()
        {
            PhysicsCheck();
        }
        public void PhysicsCheck()
        {
            mapData = new int[(int)(fowManager.FogSizeX / fowManager.MapTileSize), (int)(fowManager.FogSizeY / fowManager.MapTileSize)];
            for (int i = 0; i < mapData.GetLength(0); i++)
            {
                for (int j = 0; j < mapData.GetLength(1); j++)
                {
                    if (Physics.CheckBox(fowManager.GetV3(new int[] { i, j }), new Vector3(fowManager.MapTileSize - 0.02f, 0f, fowManager.MapTileSize - 0.02f)/2))
                    {
                        mapData[i, j] = 1;
                    }
                    else
                    {
                        mapData[i, j] = 0;
                    }
                }
            }
            fowManager.InitMap(mapData);
        }
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FogOfWar
{
    public class FowManager : MonoBehaviour
    {
        public static FowManager instance
        {
            get
            {
                return _instance;
            }
        }
        protected static FowManager _instance;
        public static void AddViewer(FowViewer viewer)
        {
            if (!_instance.viewerList.Contains(viewer))
            {
                _instance.viewerList.Add(viewer);
            }
            
        }
        public static void RemoveViewer(FowViewer viewer)
        {
            if (_instance.viewerList.Contains(viewer))
            {
                _instance.viewerList.Remove(viewer);
            }

        }

        public float FogSizeX=10;
        public float FogSizeY=10;
        public float MapTileSize = 1;
        public FOWMap map;
        public List<FowViewer> viewerList;
        public List<int[]> viewerPos;
        protected int[,] mapData;
        public float updateTime = 0.5f;
     
        // Use this for initialization
        void Awake()
        {
            if (_instance == null)
            {
                _instance = this;
            }
            else
            {
                Destroy(gameObject);
            }            
            viewerList = new List<FowViewer>();
            viewerPos = new List<int[]>();
            InvokeRepeating("NewFog", 0, updateTime);
        }
      
        public int[] GetPos(FowViewer viewer)
        {
            var x = (int)((viewer.transform.position.x - transform.position.x+FogSizeX/2) / MapTileSize); //点击的位置/格子尺寸
            var y = (int)((viewer.transform.position.z - transform.position.z+FogSizeY/2) / MapTileSize);
            return new int[] { x, y };
        }
        public Vector3 GetV3(int[] pos)
        {
            return new Vector3(pos[0] * MapTileSize, 0, pos[1] * MapTileSize)+new Vector3(MapTileSize/2,0,MapTileSize/2)+transform.position-new Vector3(FogSizeX/2,0,FogSizeY/2);
        }
        public void InitMap(int[,] mapData)
        {
            map = new FOWMap();
            map.InitMap(mapData);
            this.mapData = mapData;
            
        }
        public void NewFog()
        {
            if (map == null) return;
            map.FreshFog();
            viewerPos.Clear();
            foreach (var viewer in viewerList)
            {
                var pos = GetPos(viewer);
                viewerPos.Add(pos);//存的是所有格子位置
                map.ComputeFog(pos[0], pos[1], viewer.viewerRange / MapTileSize);//x y当前格子范围内的坐标都被点亮
            }
            Clickpoint(0, 0);
        }

        /// <summary>
        /// 点击触发
        /// </summary>
        /// <param name="viewx">角色世界x位置</param>
        /// <param name="viewz">角色世界z位置</param>
        public void Clickpoint(float viewx,float viewz)
        {
            if (map == null) return;
            var x = (int)((viewx - transform.position.x + FogSizeX / 2) / MapTileSize);
            var y = (int)((viewz - transform.position.z + FogSizeY / 2) / MapTileSize);
            viewerPos.Add(new int[] { x,y});
            map.ComputeFog(x,y, viewerList[0].viewerRange / MapTileSize);
        }

        public void LerpFog()
        {
            map.Lerp();
        }
        // Update is called once per frame
        void Update()
        {
           LerpFog();
        }
        private void OnDestroy()
        {
            map.Release();
        }
       
            
            
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseHitScreen : MonoBehaviour
{
    void Start()
    {
        
    }

    void Update()
    {   
        if (Input.GetMouseButtonDown(0))
        {
            //从摄像机发出射线的点
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                print("鼠标点击了物体"+hit.point);

            }
        }
    }
    
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值