Unity Shader Bug

问题描述 投票:1回答:1

我正在使用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
        }
    }
}

以下是发生的事情的图像:enter image description here

我觉得需要某种填充来解决这个问题,但我不知道我需要什么样的填充。我觉得它与行有关,而且涉及某种浮点精度错误的问题:

// 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上放​​置一个偏移)它仍然会发生

任何帮助,将不胜感激

如果您有任何其他信息,请告诉我

c# unity3d shader
1个回答
2
投票

这里的问题是纹理的最低mip是在某些像素上获取的,显示为图片的平均值(灰色)。这样做的原因是mip级别是根据纹理坐标的导数计算的,当它们是连续的(在屏幕空间中)时会起作用,这不是你的情况,因为你每个像素都是模数。

您可以使用tex2Dgrad(https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-tex2dgrad)并使用ddx()和ddy()传递连续UV的衍生物来解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.