2D Texture Array

So I’m trying to implement a 2D Texture Array to use to display the tiles in my 2D game.
I’ve setup a VBO, loaded in a shader program and I have been able to get to the point where I can display coloured quads on the screen with no problems at all. I’m now trying to get the texturing working.

I have an ImageLoader class that handles the conversion from Bitmap to GL Texture.

I have a 512x512 tileset, I split it into 32x32 chunks, and feed the resulting bytes into one long byte array. I’ve been able to use this same byte array in a 3D Texture but the 3D textures interpolated between layers so I was getting blending between transparent textures so I’m now trying 2D Texture Arrays.

Now, my problem is that I cant seem to get the texturing working no matter what I try. I’ve attached a picture of the output, It flickers and what you see in the picture is only there for a couple of milliseconds then disappears. Picture Here

Here’s a snippet from the texture generation, am I doing this right?(F.Y.I, it’s in C# so it may look different to what you are used to)


newTexture = GL.GenTexture();
TextureTarget target = TextureTarget.Texture2DArray;
GL.BindTexture(target, newTexture);

GL.TexParameter(
 target,
 TextureParameterName.TextureWrapS,
 (int)TextureWrapMode.ClampToEdge);

GL.TexParameter(target,
 TextureParameterName.TextureWrapT,
 (int)TextureWrapMode.ClampToEdge);

GL.TexParameter(
 target,
 TextureParameterName.TextureMinFilter,
 (int)TextureMinFilter.Linear);

GL.TexParameter(target,
 TextureParameterName.TextureMagFilter,
 (int)TextureMagFilter.Linear);

                GL.TexImage3D(target,0,PixelInternalFormat.Rgba,32, 32, counter,0,PixelFormat.Bgra,PixelType.UnsignedByte,byteArrayPointer);
   

When I’m rendering the VBO I bind the texture that GL gave me here,




GL.BindTexture(TextureTarget.Texture2DArray, this.TileSet.TextureID);


GL.EnableClientState(EnableCap.VertexArray);

GL.EnableClientState(EnableCap.ColorArray);

GL.EnableClientState(EnableCap.TextureCoordArray);

GL.BindBuffer(BufferTarget.ArrayBuffer, layerGraphicsCollection.VertexBufferObject);
GL.VertexPointer(2, VertexPointerType.Float, 0, IntPtr.Zero);

GL.BindBuffer(BufferTarget.ArrayBuffer, layerGraphicsCollection.ColourBufferObject);
GL.ColorPointer(4, ColorPointerType.UnsignedByte, 0, IntPtr.Zero);

GL.BindBuffer(BufferTarget.ArrayBuffer, layerGraphicsCollection.TextureBufferObject);
GL.TexCoordPointer(3, TexCoordPointerType.Float, 0, IntPtr.Zero);


GL.BindBuffer(BufferTarget.ElementArrayBuffer, layerGraphicsCollection.ElementBufferObject);


GL.DrawElements(BeginMode.Quads, layerGraphicsCollection.LayerVerticies.Indices.Length,

DrawElementsType.UnsignedInt, IntPtr.Zero);

GL.DisableClientState(EnableCap.VertexArray);

GL.DisableClientState(EnableCap.ColorArray);

GL.DisableClientState(EnableCap.TextureCoordArray);

Also my Fragment Shader looks like this


uniform sampler2DArray tex;


void main()
{
	
    vec3 coord;
    coord.x = gl_TexCoord[0].s;
    coord.y = gl_TexCoord[0].t;
    coord.z = 0.1; //testing
    vec4 color = texture2DArray(tex, coord.xyz);

    gl_FragColor = color;

}

It’s a 2D Game so my Vertex Storage Class looks something like this

LayerVerticies
Vector2[] vertices;
Vector3[] texcoords;
private int[] indicies;
private int[] colors;

There really isn’t that much on 2D Texture Arrays so I’m a bit stumped.

So I got it working by changing my FS code to this

uniform sampler2DArray base_texture;
varying vec3 texCoord;
void main()
{
vec4 base_color = texture2DArray(base_texture, texCoord);
gl_FragColor = base_color;

}

and my VS code to this
varying vec3 texCoord;
void main()
{
texCoord = vec3(gl_MultiTexCoord0);
gl_Position = ftransform();
}

but now I’m getting the same thing as if I were using texture atlases and 2d texture coordinates. I’m getting seams between my textures.

I specify my texture coordinates as (0.0, 1.0, n->maxTilesInTileset)

Does GL_REPEAT wrap mode help with the seams?

Let’s see a pic.

Zoom in so that each texel is approximately 2 pixels/texel (i.e. magnifying), and the textures are parallel to the screen. You aren’t using MIPmapping (as demonstrated by your minfilter = LINEAR), so any minified views will be an aliasy mess and not even worth looking at.

But CLAMP_TO_EDGE is the right wrap mode to use.

And how have you verified that your 2D texture slices look good when displayed side-by-side? Perhaps you are duplicating a texel on each edge between each two adjancent textures?

Here’s a picture of zoomed in with Linear filtering on.
Obviously when I run it in Nearest the seams are gone but it looks kind of ugly.
I’ve also attached a picture of the scene with nearest filtering on.

Well, you’re obviously not going to get any filtering across polygon edges unless you do something about it yourself.

The problem is likely that your texcoords run 0…1 in your quads, and once it gets to the edge, there’s nothing to “blend in” from one direction.

One approach is inset your texcoords by a texel so that when it gets within a pixel of the edge, it still has data to blend in. In other words, have your polygons actually not map to the edges of your texture, but one texel in.

I do have to comment though, it looks like your data doesn’t match up very well at the edges of textures. You might check that your textures are being constructed properly. They look like they might be close but not quite exactly where they should be. But you’re the expert on that. Maybe it’s just because the data’s so high frequency (noisy, high contrast).