# 【王浩瓷砖】

用于解决地图上平铺纹理重复度太高的显示问题。

美术纹理的规范必须满足下图所示:

  1. 包含16种边缘组合可能性

  2. 两个子瓷砖的绿色与绿色能够无缝对接,红色与红色边缘无缝对接。

Markdown 图片

平铺原理:

全屏显示

效果预览:

全屏显示

# 生成随机平铺纹理

根据平铺规则使用工具生成指定尺寸的平铺纹理。

该纹理每个像素记录 1~16 之间的值,用于表示贴图中的指定的子瓷砖。

Markdown 图片

(因为每个像素能表示的单通道颜色为256种,只使用了前16,所以输出的平铺纹理看起来像全黑,仔细看可以看看微弱的灰度杂点)

使用生成的平铺数据贴图时需要注意:

  1. 设置 Filter 为 null。
  2. 取消勾选 srgb 选项。
  3. 不能压缩。

本人使用Godot编写的平铺数据图生成工具,下方地址可下载Godot4.2项目源码:

度盘:https://pan.baidu.com/s/1IZUZ8MySY8Mjo2iqyyqRmg?pwd=vp66 (opens new window)

使用工具需要先确定图片储存边长为多少个子格子。

例如一张1024X1024的王浩瓷砖纹理图,设定为显示1平方米的面积,那么一个子格子纹理就是0.25平方米。

那么512X512的平铺纹理代表512X512个子格子,算出无重复平铺为128平方米。所以显示 地面的Quad 需要把x和y缩放设置为128。

# 算法实现

Shader "vp/WangTileMapShader"
{
    Properties
    {
        _tileTex("tileTex", 2D) = "white" {}
        _tillingX("tillingX", Float) = 1
        _tillingY("tillingY", Float) = 1
        // 生成的固定随机图,注意不能压缩,不能是srgb,不能使用Filter
        _genTileTex("genTileTex", 2D) = "white" {}
        _pixelX("genTileTexPixelX", Float) = 512
        _pixelY("genTileTexPixelY", Float) = 512
    }
    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;
            };

            uniform sampler2D _tileTex;
            uniform float _tillingX;
            uniform float _pixelX;
            uniform sampler2D _genTileTex;
            SamplerState sampler_genTileTex;
            uniform float _tillingY;
            uniform float _pixelY;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                half4 finalColor;

                // 用于采样生产的固定随机值
                float2 maskUV = float2((i.uv.x * _tillingX) , (i.uv.y * _tillingY));
                // 固定随机值 在 0~15 整数之间
                float maskVal = ((tex2D(_genTileTex, maskUV).r * 255.0) - 1.0);

                float _tileX = 4;
                float _tileY = 4;

                // 偏移
                float addX = floor(fmod(maskVal, _tileX));
                float addY = floor((maskVal / _tileY));
                float2 finalUV = (float2(((frac(((i.uv.x * _tillingX) * _pixelX)) / _tileX) + ((1.0 / _tileX) * addX)) , ((frac(((i.uv.y * _tillingY) * _pixelY)) / _tileY) + ((1.0 / _tileY) * addY))));

                finalColor = tex2D(_tileTex, finalUV);
                return finalColor;
            }
            ENDCG
        }
    }
}

参考自CSDN阿赵3d:Wang tile(王浩瓷砖)算法解决贴图平铺重复问题 (opens new window)