先看效果图:
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);
}
}
}
}