zoukankan      html  css  js  c++  java
  • Wang Tile的Shader简易实现

    在使用大面积的平铺纹理时,会导致重复感较强的贴图呈现在画面中。我们可以通过许多方法进行优化,WangTile就是其中一种。

    WangTile(王浩瓷砖)方法通过对每条边标记颜色,并在平铺时将相同颜色的边拼接在一起,最终铺满整个平面。

    参考《GPU Gems2》中的做法,但这里使用一组预先设定好的可循环组合值,以及一个4x4的瓷砖纹理。

    4x4纹理图:

    假设y坐标朝向为从下到上,x坐标朝向为从左到右,则索引(0,0)表示数字16的色块,索引(2,3)表示数字3的色块,以此类推。

    这里首先配置好可循环的组合,他们的x轴和y轴不同的序列为:

    X_seq: 1, 2, 2, 3, 0, 1, 3, 1, 2, 3, 0, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3
    Y_seq: 0, 1, 2, 3, 0, 1, 3, 1, 2, 3, 1, 2, 2, 2, 3, 0, 1, 3, 0, 1, 3

    这个序列可以给不同的瓷砖贴图重复使用,我们把这个作为数组传入Shader,数组长度写死为21,其Shader如下:

    Shader "Unlit/WangTileTesGPU"
    {
        Properties
        {
            _TileTex("Tile Texture", 2D) = "white" {}
        }
        SubShader
        {
            Tags { "RenderType"="Opaque" }
            LOD 100
    
            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;
                };
    
                sampler2D _TileTex;
    
                uniform float _WangTile_X_Seq[21];
                uniform float _WangTile_Y_Seq[21];
    
    #define MAIN_TEX_TILE_SIZE half2(21, 21)
    #define TILE_TEX_SIZE half2(4, 4)
    
                v2f vert (appdata v)
                {
                    v2f o = (v2f)0;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = v.uv;
                    return o;
                }
    
                fixed4 SampleTile(half2 uv, half2 index, half2 mainTexTileTexSize, half2 tileTexSize)
                {
                    float xIndex = _WangTile_X_Seq[index.x % 21] / tileTexSize.x;
                    float yIndex = _WangTile_Y_Seq[index.y % 21] / tileTexSize.y;
    
                    half2 large_uv = frac(uv * mainTexTileTexSize);
                    half2 sub_uv = large_uv / tileTexSize;
    
                    return tex2D(_TileTex, half2(xIndex, yIndex) + sub_uv, ddx(uv), ddy(uv));
                    //使用ddx,ddy参数去除接缝问题
                }
    
                fixed4 frag (v2f i) : SV_Target
                {
                    half2 sub_uv_index = floor(i.uv * MAIN_TEX_TILE_SIZE);//Index: 1,2,3,4...
    
                    return SampleTile(i.uv, sub_uv_index, MAIN_TEX_TILE_SIZE, TILE_TEX_SIZE);
                }
                ENDCG
            }
        }
    }

    传入数组的csharp脚本如下:

    public class WangTileGPU : MonoBehaviour
    {
        public Material mat;
    
    
        void Start()
        {
            float[] index_x_loop = new float[] { 1, 2, 2, 3, 0, 1, 3, 1, 2, 3, 0, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3 };
            float[] index_y_loop = new float[] { 0, 1, 2, 3, 0, 1, 3, 1, 2, 3, 1, 2, 2, 2, 3, 0, 1, 3, 0, 1, 3 };
    
            mat.SetFloatArray("_WangTile_X_Seq", index_x_loop);
            mat.SetFloatArray("_WangTile_Y_Seq", index_y_loop);
        }
    }

    最终效果:

    带贴图的效果(未做连续处理):

  • 相关阅读:
    scrapy爬虫爬取小姐姐图片(不羞涩)
    scrapy爬虫登录edusrc查看漏洞列表
    代码审计【根据功能点定向审计】BugFree ZSWin重装案例
    645-2007协议解析
    最近总结
    防爆zigbee模块
    物联网卡余额管理软件更新
    激光+紫外催化控制器
    modbus转edp协议
    modbus转mqtt工具
  • 原文地址:https://www.cnblogs.com/hont/p/12732570.html
Copyright © 2011-2022 走看看