我正在使用Unity着色器,它可以在一个平面上显示多个不同的图块。 Unity将浮点数组传递给着色器,其中包含一个tile ID列表和一个4x4 tile图,对于mostpart,它可以完美地工作,但是有一个小问题。
我附上了这个现象的图像,在瓷砖的接缝处你可以看到灰线。我打开了瓷砖遮罩来减轻问题,因此更容易看到。
以下是着色器代码:
Shader "Unlit/TileMap" { Properties { // Texture configuration _DiffuseTex("Diffuse", 2D) = "white" {} _MaskTex("Mask", 2D) = "black" {} _MapWidth("Map Width", int) = 0 _MaskMapWidth("Mask Mask Width", int) = 0 _WorldWidth("World Width", int) = 0 // Global illumination modifiers _GlobalLumosity("Global Lumosity", Range(0, 1)) = 1 _GlobalHue("Global Hue", Color) = (1, 1, 1, 1) } SubShader { Tags { "Queue"="Transparent" "RenderType"="Transparent" } LOD 200 ZWrite On Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma target 4.0 #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 _DiffuseTex; float4 _DiffuseTex_ST; sampler2D _MaskTex; float4 _MaskText_ST; uint _ID; uint _MapWidth; uint _MaskMapWidth; uint _WorldWidth; half _GlobalLumosity; float4 _GlobalHue; float _allIDs[16]; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _DiffuseTex); return o; } fixed4 frag (v2f i) : SV_Target { float mapSizeModif = 1.0f / _MapWidth; float maskMapSizeModif = 1.0f / _MaskMapWidth; float worldSizeModif = 1.0f / _WorldWidth; // float lightness = tex2D (_MaskTex, i.uv * _MapWidth); float lightness = 1.0f; uint index = (int) (floor(i.uv.x * _WorldWidth) + (floor(i.uv.y * _WorldWidth) * _WorldWidth)); i.uv.x = i.uv.x % worldSizeModif; i.uv.y = i.uv.y % worldSizeModif; uint id = (uint) _allIDs[index]; i.uv.x += mapSizeModif * (id % _MapWidth); i.uv.y += mapSizeModif * floor (((float)id) / _MapWidth); fixed4 col = tex2D (_DiffuseTex, i.uv); col *= _GlobalLumosity; col *= _GlobalHue; col.a = lightness; return col; } ENDCG } } }
我觉得需要某种填充来解决这个问题,但我不知道我需要什么样的填充。我觉得它与行有关,而且涉及某种浮点精度错误的问题:
// Convert position into localised scaling
i.uv.x = i.uv.x % worldSizeModif;
i.uv.y = i.uv.y % worldSizeModif;
这是设置磁贴信息的MonoBehaviour控制器:
void Update() {
propBlock.SetFloatArray("_allIDs", new float[16] { 1, 1, 3, 2, 1, 1, 2, 2, 1, 3, 2, 1, 1, 2, 1, 1 });
renderer.SetPropertyBlock(propBlock);
}
我认为它可能是瓷砖之间的简单纹理流血,但是,即使强迫它,以便没有瓦片流失是可能的(通过在UV上放置一个偏移)它仍然会发生
任何帮助,将不胜感激
如果您有任何其他信息,请告诉我
这里的问题是纹理的最低mip是在某些像素上获取的,显示为图片的平均值(灰色)。这样做的原因是mip级别是根据纹理坐标的导数计算的,当它们是连续的(在屏幕空间中)时会起作用,这不是你的情况,因为你每个像素都是模数。
您可以使用tex2Dgrad(https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-tex2dgrad)并使用ddx()和ddy()传递连续UV的衍生物来解决这个问题。