using UnityEngine; using UnityEngine.UI; /**************************************************** 文件:FogOfWar.cs 作者:https://afoolzwt.github.io/ 邮箱: 848832649@qq.com 日期:#CreateTime# 功能:Nothing *****************************************************/ publicclassFogOfWar : MonoBehaviour { public RawImage fogRawImage;
///<summary> /// 迷雾的像素密度,由多少个点组成. ///</summary> public Vector2Int fogDensity = new Vector2Int(100, 100);
private Texture2D fogTexture;
public Transform cubeTrans; public MeshCollider planeMesh; private Vector2 planeOriginPoint; private Vector2 worldSize; privatevoidStart() { fogTexture = new Texture2D(fogDensity.x, fogDensity.y); fogRawImage.texture = fogTexture;
worldSize = new Vector2(planeMesh.bounds.size.x, planeMesh.bounds.size.z); //将plane的坐标减去它尺寸的一半,即可得到它的左下角的坐标 planeOriginPoint = new Vector2(planeMesh.transform.position.x - worldSize.x * 0.5f, planeMesh.transform.position.z - worldSize.y * 0.5f);
InitShape(); InitFog();
EliminateFog(); }
privatevoidInitFog() { int pixelCount = fogDensity.x * fogDensity.y; //将迷雾的默认颜色设置为黑色 Color[] blackColors = new Color[pixelCount]; for (int i = 0; i < pixelCount; i++) { blackColors[i].a = 127.5f/255; } fogTexture.SetPixels(blackColors); fogTexture.Apply(); }
///<summary> /// 消除形状的长宽 ///</summary> public Vector2Int beEliminatedShapeSize = new Vector2Int(8, 6);
private Vector2Int[] shapeLocalPosition;
///<summary> /// 初始化视野形状 ///</summary> privatevoidInitShape() { int pixelCount = beEliminatedShapeSize.x * beEliminatedShapeSize.y; shapeLocalPosition = new Vector2Int[pixelCount];
int halfX = Mathf.FloorToInt(beEliminatedShapeSize.x * 0.5f); int remainX = beEliminatedShapeSize.x - halfX; int halfY = Mathf.FloorToInt(beEliminatedShapeSize.y * 0.5f); int remainY = beEliminatedShapeSize.y - halfY;
int index = 0; for (int y = -halfY; y < remainY; y++) { for (int x = -halfX; x < remainX; x++) { shapeLocalPosition[index] = new Vector2Int(x, y); index++; } } }
privatevoidEliminateFog() { Vector2 cubePos = new Vector2(cubeTrans.position.x, cubeTrans.position.z);
Debug.Log(cubePos.x + cubePos.y);
//相对假定原点的距离比例,因为是世界坐标,两个点相减有可能是负数,texture中不存在负数的坐标,所以转化为正数. Vector2 originDistanceRatio = (cubePos - planeOriginPoint) / worldSize; originDistanceRatio.Set(Mathf.Abs(originDistanceRatio.x), Mathf.Abs(originDistanceRatio.y)); //距离比例乘以密度,即可知道cube相当在texture中的点即可计算出来 Vector2Int fogCenter = new Vector2Int(Mathf.RoundToInt(originDistanceRatio.x * fogDensity.x), Mathf.RoundToInt(originDistanceRatio.y * fogDensity.y)); for (int i = 0; i < shapeLocalPosition.Length; i++) { int x = shapeLocalPosition[i].x + fogCenter.x; int y = shapeLocalPosition[i].y + fogCenter.y; //因为消除迷雾的形状是比cube的位置还要大的,在最边缘的时候,消除的像素点的坐标会超出texture范围,所以超出部分忽略. if (x < 0 || x >= fogDensity.x || y < 0 || y >= fogDensity.y) continue;
///<summary> /// The fastest form of visibility updates -- radius-based, no line of sights checks. ///</summary> voidRevealUsingRadius (IFOWRevealer r, float worldToTex) { // Position relative to the fog of war Vector3 pos = (r.GetPosition() - mOrigin) * worldToTex; float radius = r.GetRadius() * worldToTex - radiusOffset;
// Coordinates we'll be dealing with int xmin = Mathf.RoundToInt(pos.x - radius); int ymin = Mathf.RoundToInt(pos.z - radius); int xmax = Mathf.RoundToInt(pos.x + radius); int ymax = Mathf.RoundToInt(pos.z + radius);
int cx = Mathf.RoundToInt(pos.x); int cy = Mathf.RoundToInt(pos.z);
for (int y = 0; y < textureSize; ++y) { int yw = y * textureSize; int yw0 = (y - 1); if (yw0 < 0) yw0 = 0; int yw1 = (y + 1); if (yw1 == textureSize) yw1 = y;
yw0 *= textureSize; yw1 *= textureSize;
for (int x = 0; x < textureSize; ++x) { int x0 = (x - 1); if (x0 < 0) x0 = 0; int x1 = (x + 1); if (x1 == textureSize) x1 = x;
int index = x + yw; int val = mBuffer1[index].r;
val += mBuffer1[x0 + yw].r; val += mBuffer1[x1 + yw].r; val += mBuffer1[x + yw0].r; val += mBuffer1[x + yw1].r;
val += mBuffer1[x0 + yw0].r; val += mBuffer1[x1 + yw0].r; val += mBuffer1[x0 + yw1].r; val += mBuffer1[x1 + yw1].r;
///<summary> /// Update the specified texture with the new color buffer. ///</summary> voidUpdateTexture () { if (!enableRender) { return; }
if (mTexture == null) { // Native ARGB format is the fastest as it involves no data conversion mTexture = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false);