sometimes my meshes are black for large textures in a texture array, sometimes the textures render

Viewed 105

I'm trying to shade meshes I generated with a noise heightmap using an array of textures. With a smaller texture size (e.g. 512px*512px) everything works completely fine. However, if I use larger texture for example 1024px*1024px or 2048px*2048px, my meshes usually render black. Every now and then the textures will render correctly around 5% of the time, while around 20% of the time they will seem to render correctly for the first frame and then switch to black.

This issue seems to appear no matter how long my texture array is. (a size 1 array still causes the same behavior) I also see the same issue regardless of whether the images are JPGs or PNGs. I also tried a variety of different images as texture and reproduced the same problem. I have no errors or warnings in my console.

Below are simplified versions of the relevant code which also suffer from the same issue. This just additive blends the textures, but in the full version of the code, the height of the mesh is used to determine the texture(s) to use and the degree of blending between nearby textures. My code is based off of Sebastian Lague's procedural landmass generation youtube tutorial series, which only deals with 512px*512px textures.

The code that puts the texture array and layer number into the shader:

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;
    }
}

The shader itself:

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"
}

Here is a screenshot of then problem in action:

enter image description here

0 Answers
Related