首页 > 解决方案 > 有时我的网格对于纹理数组中的大纹理是黑色的,有时纹理渲染

问题描述

我正在尝试使用纹理数组对使用噪声高度图生成的网格进行着色。使用较小的纹理尺寸(例如 512px*512px),一切正常。但是,如果我使用更大的纹理,例如 1024px*1024px 或 2048px*2048px,我的网格通常会呈现黑色。不时地,纹理将在大约 5% 的时间内正确渲染,而在大约 20% 的时间里,它们似乎在第一帧正确渲染,然后切换为黑色。

无论我的纹理数组有多长,这个问题似乎都会出现。(大小为 1 的数组仍然会导致相同的行为)无论图像是 JPG 还是 PNG,我也会看到相同的问题。我还尝试了各种不同的图像作为纹理并重现了相同的问题。我的控制台中没有错误或警告。

以下是相关代码的简化版本,它们也存在同样的问题。这只是添加混合纹理,但在完整版本的代码中,网格的高度用于确定要使用的纹理以及附近纹理之间的混合程度。我的代码基于 Sebastian Lague 的 procedural landmass generation youtube 教程系列,该教程仅处理 512px*512px 纹理。

将纹理数组和层号放入着色器的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

[CreateAssetMenu()]
public class TextureData : UpdatableData {
    const int textureSize = 2048;
    const TextureFormat textureFormat = TextureFormat.RGB565;

    public Layer[] layers;

    public void UpdateMeshHeights(Material material, float minHeight, float maxHeight) {
        material.SetInt("layerCount", layers.Length);
        Texture2DArray texturesArray = GenerateTextureArray(layers.Select(x => x.texture).ToArray());
        material.SetTexture("baseTextures", texturesArray);
    }

    Texture2DArray GenerateTextureArray(Texture2D[] textures) {
        Texture2DArray textureArray = new Texture2DArray(textureSize, textureSize, textures.Length, textureFormat, true);
        for (int i=0; i < textures.Length; i++) {
            textureArray.SetPixels(textures[i].GetPixels(), i);
        }
        textureArray.Apply();
        return textureArray;
    }

    [System.Serializable]
    public class Layer {
        public Texture2D texture;
    }
}

着色器本身:

Shader "Custom/Terrain" {
    SubShader {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
            #pragma surface surf Standard fullforwardshadows
            #pragma target 3.0

            int layerCount;
            UNITY_DECLARE_TEX2DARRAY(baseTextures);

            struct Input {
                float3 worldPos;
                float3 worldNormal;
            };

            float3 triplanar(float3 worldPos, float scale, float3 blendAxes, int textureIndex) {
                float3 scaledWorldPos = worldPos / scale;
                float3 xProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.y, scaledWorldPos.z, textureIndex)) * blendAxes.x;
                float3 yProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.z, textureIndex)) * blendAxes.y;
                float3 zProjection = UNITY_SAMPLE_TEX2DARRAY(baseTextures, float3(scaledWorldPos.x, scaledWorldPos.y, textureIndex)) * blendAxes.z;
                return xProjection + yProjection + zProjection;
            }

            void surf (Input IN, inout SurfaceOutputStandard o) {
                float3 blendAxes = abs(IN.worldNormal);
                blendAxes /= blendAxes.x + blendAxes.y + blendAxes.z;

                for (int i = 0; i < layerCount; i++) {
                    float3 textureColor = triplanar(IN.worldPos, 1, blendAxes, i);
                    o.Albedo += textureColor;
                }
            }
        ENDCG
    }
    FallBack "Diffuse"
}

以下是实际问题的屏幕截图:

在此处输入图像描述

标签: unity3dgraphicsshadertextures

解决方案


推荐阅读