Home Technical Talk

Problem with HLSL Terrain Shader(Texture 2D Array)

polycounter lvl 14
Offline / Send Message
SpeCter polycounter lvl 14
Hi,
I use the HLSL function Texture2D.Load do retrieve texture information.
These informations are 3 Texture Indicies, 3 Texture blend weights and 3 texture tiling vaulues.

Now if 2 different texture indicies are blended which have different texture tiling values there are some kind of gridlines showing and i don´t know why.

Here are some images showing the problem:
terrainbuggitter.PNG

And from a nearer perspective:
terrainbuggitternah.PNG

Here is the HLSL code:
Texture2DArray<float4> SplatTextureArray : register(t1);
Texture2D<float4> BlendTexture : register(t2);

float2 GetBlendValAndWorldTextureSize(float val)    
{                                                       
    float2 ret;                                         
    ret.x = frac(val) * 10;             // blend weight auslesen        
    ret.y = 512.f / floor(val);         // UV Multiplier um die Wiederholung der Textur zu bestimmen            
                            
    return ret;                                         
}                                                       
                                                                        
uint3 GetIndices(uint indices)                          
{                                                       
    uint3 retval;                                       
                                                    
    retval.x = indices & 256;                   
    retval.y = (indices>>8) & 256;              
    retval.z = (indices>>16) & 256;         
                                                                    
    return retval;                                      
}

float4 GetColour(int3 index, SamplerState splattexturarraystate, float2 uv)                                                         
{                                                                                                                                   
    float4 blendinfo = BlendTexture.Load(index & 255);                                                          
    uint3 indices = GetIndices((uint)blendinfo.w);                                                                                  
                                                                                                                                                    
    float2 blend = GetBlendValAndWorldTextureSize(blendinfo[0]);                                                                    
    float4 result = SplatTextureArray.Sample(splattexturarraystate, float3(uv * blend.y, indices[0]));                              
                                                                                                                                                    
    [unroll]                                                                                                                        
    for(uint i = 1; i < 3; ++i)                                                                                                     
    {                                                                                                                               
        blend = GetBlendValAndWorldTextureSize(blendinfo[i]);                                                                       
                                                                                                                                            
        if(blend.x)                                                                                                                 
        {                                                                                                                           
            result = lerp(result, SplatTextureArray.Sample(splattexturarraystate, float3(uv * blend.y, indices[i])), blend.x);      
        }                                                                                                                           
    }                                                                                                                               
                                                                                                                                                
    return result;                                                                                                                  
}

float4 TerrainFragmentShader(TerrainVSOutput inputval, uniform SamplerState splattexturarraystate : TEXUNIT1) : SV_TARGET
{                                                                                                                                   
    float2 uv = inputval.sPosition.xz / 511;                                                                        
                                                                                                                                                    
    int3 index = int3((int2)(frac(inputval.sTexCoords) * 256), 0);                                                  
                                                                                                                                                    
    float4 tl = GetColour(index, splattexturarraystate, uv);                                                                        
    float4 tr = GetColour(index + int3(1, 0, 0), splattexturarraystate, uv);                                                        
    float4 bl = GetColour(index + int3(0, 1, 0), splattexturarraystate, uv);                                                        
    float4 br = GetColour(index + int3(1, 1, 0), splattexturarraystate, uv);                                                        
                                                                                                                                                    
    float2 lf = frac(inputval.sTexCoords * 256);                                                                        
    float4 result = lerp(lerp(tl, tr, lf.x), lerp(bl, br, lf.x), lf.y);


    return result;                                                                                                                  
}

If i take out the "* blend.y" part it doesn´t show up but then i can´t use different tiling values for the textures.
The value in blend.y should be right, because i already tested if it got the right value and colored it red if it isn´t(which shows nothing) if i test it the error doesn´t show up btw.

If someone has an idea or knows what the problem it, your help would be appreciated.

Replies

  • Ben Cloward
    Options
    Offline / Send Message
    Ben Cloward polycounter lvl 18
    Does it still happen if you take out the frac function? I've seen weird things like that happen right on the boundaries where the value hits a whole number and frac rolls it around again.
  • SpeCter
    Options
    Offline / Send Message
    SpeCter polycounter lvl 14
    Tried that already(on every frac) and it doesn´t help( int3 index = int3((int2)(frac(inputval.sTexCoords) * 256), 0); doesn´t have any frac anymore in a newer version)
  • SpeCter
    Options
    Offline / Send Message
    SpeCter polycounter lvl 14
    I found another way to "fix" it, if i use texture2dlod instead of sample(meaning no mips) it won´t show these lines two. Limiting the mips doesn´t seem to help either.
  • JamesWild
    Options
    Offline / Send Message
    JamesWild polycounter lvl 8
    We were messing around with some materials that stepped the UVs to make blocky surfaces and saw the exact same thing. It's caused by the mipmap algorithm spotting that the UVs jump a long way at the border and using a lower mipmap level on it. I don't think there's a huge amount you can do other than hard splitting the terrain.
  • SpeCter
    Options
    Offline / Send Message
    SpeCter polycounter lvl 14
    JamesWild wrote: »
    We were messing around with some materials that stepped the UVs to make blocky surfaces and saw the exact same thing. It's caused by the mipmap algorithm spotting that the UVs jump a long way at the border and using a lower mipmap level on it. I don't think there's a huge amount you can do other than hard splitting the terrain.

    Thanks for mentioning that it´s a mipping issue, we got it to work ;)

    We just did this:
    float2 dx = ddx(uv);
    float2 dy = ddy(uv);
    
    if(blend.x)
    result = lerp(result, SplatTextureArray.SampleGrad(splattexturarraystate, float3(uv * blend.y, indices[0]), dx * blend.y, dy * blend.y), blend.x);
    
Sign In or Register to comment.