# 【王浩瓷砖】
用于解决地图上平铺纹理重复度太高的显示问题。
美术纹理的规范必须满足下图所示:
包含16种边缘组合可能性
两个子瓷砖的绿色与绿色能够无缝对接,红色与红色边缘无缝对接。
平铺原理:
效果预览:
# 生成随机平铺纹理
根据平铺规则使用工具生成指定尺寸的平铺纹理。
该纹理每个像素记录 1~16 之间的值,用于表示贴图中的指定的子瓷砖。
(因为每个像素能表示的单通道颜色为256种,只使用了前16,所以输出的平铺纹理看起来像全黑,仔细看可以看看微弱的灰度杂点)
使用生成的平铺数据贴图时需要注意:
- 设置 Filter 为 null。
- 取消勾选 srgb 选项。
- 不能压缩。
本人使用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
}
}
}