碧血红天的HomePage

U3d杂谈 — 实现一个简单的战争迷雾

对于很多探索和对抗类型的游戏,都会存在战争迷雾的机制。我这里实现了一个简单的战争迷雾的效果。算是一个抛砖引玉的作用。如何想把迷雾做的更好,还的再上面使劲优化,不过现在这样可以起到一个学习作用。

基本思想

使用程序纹理,实时绘制当前行走过的轨迹,把能看见的区域存再r通道中。由于计算纹理像素的过程有些耗时,采用异步的方法计算。视野的区域和渐变通过一个纹理来实现。

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using UnityEngine;

public class ProgressTexture : MonoBehaviour
{
    public int width = 32;
    public int height = 32;


    public Texture2D genTexture;
    //赋值上视野纹理,可以通过纹理控制视野的渐变效果
    public Texture2D colorTexture;

    private int colorW;
    private int colorH;

    public Transform fog;
    public Material mat;

    public Transform role;
    public Transform dimian;
    public float radius;

    float dimianW;
    float dimianH;
    float roleX;
    float roleY;
    private Color32[] colors;
    private Color32[] rcolors;

    Thread t;
    // Start is called before the first frame update
    void Start()
    {
        rcolors = colorTexture.GetPixels32();
        
        colorW = colorTexture.width;
        colorH = colorTexture.height;

        dimianW = dimian.position.x * 2;
        dimianH = dimian.position.z * 2;
        roleX = role.position.x;
        roleY = role.position.z;
        mat = fog.GetComponent<MeshRenderer>().material;
        genTexture = new Texture2D(width, height);
        colors = new Color32[width * height];


        mat.SetTexture("_VisibleTex", genTexture);

        //计算颜色
        t = new Thread( new ThreadStart(this.ThreadJob));
        t.IsBackground = true;
        t.Start();
    }

    private void OnDestroy()
    {
        t.Abort();
    }


    void ThreadJob()
    {
        while(true)
        {
            DrawTexture();
            Thread.Sleep(1 / 60);
        }

    }
    void Update()
    {
        roleX = role.position.x;
        roleY = role.position.z;
      
        genTexture.SetPixels32(colors);
        //如何不会用到mipMap 使用genTexture.Apply(false)会节省很多消耗
        genTexture.Apply();
    }

    void DrawTexture()
    {
        //图像以位置坐标是反向的 所以需要1-
        int XEnd = (int)((1 - ((roleY - radius) / dimianH)) * width);
        XEnd = Mathf.Min(XEnd, width);
        int XStart = (int)((1 - (roleY + radius) / dimianH) * width);
        XStart = Mathf.Max(XStart, 0);
        int YEnd = (int)((1 - (roleX - radius) / dimianW) * height);
        YEnd = Mathf.Min(YEnd, height);
        int YStart = (int)((1 - (roleX + radius) / dimianW) * height);
        YStart = Mathf.Max(YStart, 0);

        int h = XEnd - XStart;
        int w = YEnd - YStart;
        for (int i = XStart; i < XEnd; ++i)
        {
            for(int j = YStart; j < YEnd; ++j)
            {
                int index = i * width + j;
                float a = (float)(i - XStart) / h;
                float b = (float)(j - YStart) / w;
                int col = (int)(a * colorW);
                int row = (int)(b * colorH);
                //采集视野纹理的像素值
                int index2 = (int)(Mathf.Max(row,0 )* colorW + Mathf.Max(col,0));
                if(colors[index].r < rcolors[index2].r)
                {
                    colors[index].r = rcolors[index2].r;
                }
                
            }
        }
        
    }
}

在Shader中,我们只需要把雾的颜色像素的透明度与当前程序纹理的r通过做相减。

Shader "Custom/Fog"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _VisibleTex("VisibleTex",2D) = "black" {}
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always
        Blend SrcAlpha OneMinusSrcAlpha
        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 _VisibleTex;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                //我这里全置黑了,为了方便看
                col.rgb = fixed3(0.1, 0.1, 0.1);

                fixed4 f = tex2D(_VisibleTex, i.uv);
                col.a = max(col.a - f.r,0);
                return col;
            }
            ENDCG
        }
    }
}

最后展示的效果如下:

下面附上我的资源和代码:

87 评论

  1. โปร สล็อต pg slot จากเว็บสล็อตออนไลน์ PG-SLOT.GAME ที่ยกเกมสล็อตออนไลน์จากค่ายดังมาอย่างหลากหลายค่ายเกม เช่น pg slot jili joker และอื่นๆอีกมากมายในเว็บเดียว มาแรง 2022

  2. เว็บไซต์ สล็อต ค่ายเว็บดังพร้อมสร้างความตื่นเต้นในทุกๆครั้งที่สปินยิ่งกว่าถูกรางวัล pg slot- th.com ปรับปรุงให้เกมมีความเที่ยงธรรม แก่คนที่เข้ามาสปินทำให้เข้ารางวัลได้ง่ายๆ

  3. This paragraph is genuinely a fastidious one it helpps new
    the web viewers, who are wishing in favor of blogging.

    Also visit my web-site :: buy propecia uk online

  4. clomid and nolvadex If you re having an acute respiratory attack and your inhaler doesn t work, it could be a dangerous situation

发表评论