PDA

View Full Version : texture Array + integer uvw weird behavior



lamigo
10-04-2014, 07:41 AM
Probably something very basic I am missing on this one, but I have been stuck for a while and some help would be appreciated;
I am drawing a 2d textured quad in a 2D hud. The texture is stored in a texture array, made exclusively of orange and black pixels. I am sending u, v and w coordinates as shorts. w is the index in the texture array. u,v coordinates are multiplied by 512 before being sent, and divided back by 512 in glsl.
When I display a small percentage of the texture on my quad with a small uv range, I get orange and black pixels as expected, and I see enough of it to be sure it is the right texture. But when I play with a bigger uv range , I am starting to see an overlay superimposed on the textured quad that gets more opaque to the point where I don't see my texture anymore. Sometimes, the overlay is plain white, sometimes snowy, sometimes it looks like a piece of an image I was looking at in Firefox an hour ago! Obviously something is not initialized, but what? I am only using one texture stage in that trivial shader and not doing fog, The texture is GL_RGB so no alpha.
If I force the uv in the pixel shader with constant values, I get a plain square that is either orange or black as expected.
I also forced the texture slot to zero in the shader to make sure I am not halfway between 2 slots.


This is the very simple shader used to draw the quad


#version 330
#extension GL_EXT_texture_array : enable

#ifdef VERTEX //------------------------------

layout(location = 0) in vec3 in_Position;
layout(location = 1) in ivec4 in_UV;
out vec4 gl_Position;
smooth out vec3 uvw;

void main()
{
gl_Position = vec4(in_Position.xy, 0.0, 1.0); // only using xy here
vec2 uv = in_UV.st / 512.0;
uvw = vec3( uv, 0 ); // forcing w=0 as a test
}

#endif //----------------------------------------

#ifdef FRAGMENT //----------------------------

smooth in vec3 uvw;
out vec3 color;
uniform sampler2DArray gSampler;

void main()
{
color = texture2DArray( gSampler, uvw ).rgb;
}

#endif //-------------------------------------------


And a few relevant pieces


typedef struct
{
float x,y,z;
u16 u,v,w,notused;
s8 nx, ny, nz;
u8 material;
} GN_Vertex;

// draw quad routine
void Texture::display( int numSlot, float x0, float y0, float x1, float y1 )
{
u16 tabIdx[6] = {0,1,2, 0,2,3 };

this->use();
shader->use();
shader->setUniform( "gSampler", 0 );
vtxQuad[0].x = vtxQuad[3].x = x0;
vtxQuad[1].x = vtxQuad[2].x = x1;
vtxQuad[0].y = vtxQuad[1].y = y0;
vtxQuad[2].y = vtxQuad[3].y = y1;
vtxQuad[0].u = vtxQuad[0].v = vtxQuad[1].v = vtxQuad[3].u = 0;
vtxQuad[1].u = vtxQuad[2].u = vtxQuad[2].v = vtxQuad[3].v = 412; // changing that number to reveal bug
vtxQuad[0].w = vtxQuad[1].w = vtxQuad[2].w = vtxQuad[3].w = numSlot;
meshQuad->sendVertices( vtxQuad, 0, 4 );
meshQuad->sendIndices( tabIdx, 6 );
meshQuad->draw( GN_TRIANGLE, GN_FILL );
}

void Mesh::sendVertices( GN_Vertex *vtx, int nbVtx )
{
glBindVertexArray( vao_ );
glBindBuffer(GL_ARRAY_BUFFER, vbo_ );

if( !vtx ) mode_ = GL_STREAM_DRAW;
glBufferData(GL_ARRAY_BUFFER, nbVtx*sizeof(GN_Vertex), vtx, mode_ );

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, 0); // positions

glEnableVertexAttribArray(1);
glVertexAttribIPointer(1, 4, GL_SHORT, 24, (GLvoid*)12); // texture coords

glBindVertexArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0 );

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}



void Mesh::draw( Primitive primitive, int state, int nbIdx )
{
gl.setDrawState( state );
glBindVertexArray( vao_ );

glDrawElements( tabPrimitive[primitive], nbIdx, GL_UNSIGNED_SHORT, (void*)0);
glBindVertexArray(0);
}

lamigo
10-05-2014, 02:51 AM
Problem solved.
I forgot I was using tri linear filtering on that texture. My texture array init was allocating a complete mipmap chain, while my RTT was only filling the first one. So trilinear was blending my base texture with the higher uninitialised mipmap progressively bringing ghost junk.