如何在 Unity 中创建一个可以显示由许多小图像组成的纹理的着色器

所以我想做的是从 SQL 表加载卫星图像并将它们包裹在一个球体周围以创建一个地球仪。我知道我已经加载了所覆盖的图像,我只是不确定如何使我的着色器以正确的方向显示图像。

我访问了 Unity 论坛并从 Unity 文档中查看了此代码

使用链接的着色器代码和我在论坛上收到的帮助,这是我最终得到的代码:

Properties

    {

        _MainTexArray("Tex", 2DArray) = "" {}

        _SliceRange("Slices", Range(0,32)) = 6

        _UVScale("UVScale", Float) = 1

        _COLUMNS("Columns", Range(0, 5)) = 1

        _ROWS("Rows", Range(0, 5)) = 1

        _CELLS("Cells", Range(0, 32)) = 16

    }

        SubShader

        {

            Pass

            {

                CGPROGRAM

                #pragma vertex vert

                #pragma fragment frag

                // texture arrays are not available everywhere,

                // only compile shader on platforms where they are

                #pragma require 2darray


                #include "UnityCG.cginc"


                struct v2f

                {

                    float3 uv : TEXCOORD0;

                    float4 vertex : SV_POSITION;

                };


                float _SliceRange;

                float _UVScale;


                v2f vert(float4 vertex : POSITION)

                {

                    v2f o;

                    o.vertex = UnityObjectToClipPos(vertex);

                    o.uv.xy = (vertex.xy + 0.5) * _UVScale;

                    o.uv.z = (vertex.z + 0.5) * _SliceRange;

                    return o;

                }

                float _COLUMNS; //Columns and rows only go between 0 and 1

                float _ROWS;

                float _CELLS;

                UNITY_DECLARE_TEX2DARRAY(_MainTexArray);        

                half4 frag(v2f i) : SV_Target

                {

                    float3 uv = float3(i.uv.x * _CELLS, i.uv.y * _CELLS, 0);

                    uv.z = floor(i.uv.x / _COLUMNS) * floor(i.uv.y / _ROWS);

                    return UNITY_SAMPLE_TEX2DARRAY(_MainTexArray, uv / _CELLS); 

                }

                ENDCG

            }

        }


HUX布斯
浏览 139回答 1
1回答

慕妹3242003

如果您可以对照片数组进行索引,以便有效地获得地球的等距柱状投影,则可以尝试使用着色器代码的修改形式Farfarer Unity论坛复制并稍作修改如下:Shader "Custom/Equirectangular" {    Properties{        _MainTexArray("Tex", 2DArray) = "" {}        _COLUMNS("Columns", Int) = 2        _ROWS("Rows", Int) = 2    }        SubShader{            Pass {                Tags {"LightMode" = "Always"}                CGPROGRAM                    #pragma vertex vert                    #pragma fragment frag                    #pragma require 2darray                    #include "UnityCG.cginc"                    struct appdata {                       float4 vertex : POSITION;                       float3 normal : NORMAL;                    };                    struct v2f                    {                        float4    pos : SV_POSITION;                        float3    normal : TEXCOORD0;                    };                    v2f vert(appdata v)                    {                        v2f o;                        o.pos = UnityObjectToClipPos(v.vertex);                        o.normal = v.normal;                        return o;                    }                    UNITY_DECLARE_TEX2DARRAY(_MainTexArray);                    int _ROWS;                    int _COLUMNS;                    #define PI 3.141592653589793                    inline float2 RadialCoords(float3 a_coords)                    {                        float3 a_coords_n = normalize(a_coords);                        float lon = atan2(a_coords_n.z, a_coords_n.x);                        float lat = acos(a_coords_n.y);                        float2 sphereCoords = float2(lon, lat) * (1.0 / PI);                        return float2(sphereCoords.x * 0.5 + 0.5, 1 - sphereCoords.y);                    }                    float4 frag(v2f IN) : COLOR                    {                        float2 equiUV = RadialCoords(IN.normal);                        float2 texIndex;                        float2 uvInTex = modf(equiUV * float2(_COLUMNS,_ROWS), texIndex);                        int flatTexIndex = texIndex.x * _ROWS + texIndex.y;                        return UNITY_SAMPLE_TEX2DARRAY(_MainTexArray,                                float3(uvInTex, flatTexIndex));                    }                ENDCG            }        }    FallBack "VertexLit"}您还需要使用texArr = new Texture2DArray(256, 256, textures.Length, TextureFormat.RGBA32, false, true);代替texArr = new Texture2DArray(256, 256, textures.Length, TextureFormat.RGBA32, true, false); 如果我将此脚本附加到球体上,它对我有用:Material myMat;public List<Texture2D> texes;IEnumerator Start(){    yield return null;    myMat = GetComponent<Renderer>().material;    Texture2DArray texArr = new Texture2DArray(256, 256, 9,             TextureFormat.RGBA32, false, true);    texArr.filterMode = FilterMode.Bilinear;    texArr.wrapMode = TextureWrapMode.Clamp;    for (int i = 0 ; i < texes.Count ; i++)    {        texArr.SetPixels(texes[i].GetPixels(), i, 0);    }    texArr.Apply();    myMat.SetTexture("_MainTexArray", texArr);}并在texes中按顺序添加这些纹理:并将行和列设置为 3,它会产生不错的结果:如果启用双线性过滤,纹理边界处仍然存在一些伪影。但这些文物必须放大得很近才能看到。由于双线性过滤缺乏相邻像素,它们大多显示为混合不当或丢失像素:当然,这个示例没有正确平铺,因此沿着一条经线有明显的接缝:由于此设置需要来自球体的法线,因此这只适用于法线接近球体的物体。因此,例如,它无法在平面上正确渲染。
打开App,查看更多内容
随时随地看视频慕课网APP