First, set your textures to GL_NEAREST, and turn of mip-mapping if you have that on. You have to section the big image. Downsize it by half, section it, downsize, section etc. Because pixels on the edge need to be sampled/averaged with what they are touching. And at the seems, the pixels don't get to take into account their neighbors pixels. Your issue looks a little bit more of an issue than that though.
Hi,
Thanks for your response. I went over my code to make sure that all the parameters are set correctly, and for as far as I can see they are.
Here is the bit that generates and sends a clipped texture to the GPU:
void applyTexture( unsigned char* data, int w, int h, int n)
{
if( data != NULL ){
/* Generate a texture name and bind the current texture */
glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);
/* Replace the color of the object, shading is done in shaders */
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/* Specify texture mapping parameters */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
/* Load the texture into GPU memory */
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
data);
/* Unbind the texture to prevent it from appearing on unexpected objects */
glBindTexture(GL_TEXTURE_2D, 0);
}
}
So from the QuadTree, when I generate 4 new quads, I also clip the texture up into 4 pieces, and send one piece to each of the children. They then just call this method on the grid VB object, and the VB object is rendered as follows:
void render(){
/*
* Draw the object
*/
if(mTexture != 0)
{
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, mTexture );
}
/* Use the shader */
glUseProgram(shader_id);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
/*
* Bind the VBO
*/
glBindBuffer(GL_ARRAY_BUFFER, mVboObject);
glVertexPointer(3,GL_FLOAT,mVertexStride,0);
glTexCoordPointer(2, GL_FLOAT, mTextureStride, (GLvoid*)(sizeof(float)*6));
glPushMatrix();
glDrawArrays(GL_TRIANGLES, 0, mNumVertices);
glPopMatrix();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if(mTexture != 0){
glFlush();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}
Also, my texture clipping code is as follows:
unsigned char * QuadNode::getTextureRegion(unsigned char* data, int width, int height, int startX, int startY)
{
int nLength = (width/2) * (height/2);
int halfWidth = width / 2;
int addWidth = width / 2;
unsigned char *newData = new unsigned char[nLength];
int currentIndex = 0;
int dataIndex = 0;
for(int i = startX + startY * width; dataIndex < nLength; i++)
{
if(currentIndex >= halfWidth)
{
currentIndex = 0;
i += addWidth;
}
newData[dataIndex] = data;
currentIndex++; dataIndex++;
}
return newData;
}
unsigned char* QuadNode::correctData(unsigned char* data, int width, int height)
{
int horizontal = height / 2;
int vertical = width / 2;
unsigned char* nData = data;
for(int i = 0; i < width; i++)
{
nData[horizontal * width + i] = data[horizontal * width + i];//(data[horizontal * width + i] +
//data[(horizontal+1) * width + i]) / 2;
nData[(horizontal-1) * width + i] = nData[horizontal * width + i];
}
for(int i = 0; i < height; i++)
{
nData[width*i + vertical - mHmN] = (data[width*i + vertical - mHmN]);
nData[width*i + (vertical - mHmN) + 1] = (data[(width*i + vertical - mHmN) + 1]);
nData[width*i + (vertical - mHmN) + 2] = 255;// (data[(width*i + vertical - mHmN) + 2]);
nData[width*i + (vertical - mHmN) + 3] = (data[(width*i + vertical - mHmN) + 3]);
nData[width*i + vertical] = nData[width*i + vertical - mHmN];
nData[width*i + vertical + 1] = nData[(width*i + vertical - mHmN) + 1];
nData[width*i + vertical + 2] = nData[(width*i + vertical - mHmN) + 2];
nData[width*i + vertical + 3] = nData[(width*i + vertical - mHmN) + 3];
}
return nData;
}
Where correctTexture is called
before getTextureRegion. I have tested the approach by setting the values as equal to 255 on blue or red, and rendering the result using the fragment shader. The colours are correctly on the two aligned edges, hence why I'm presuming that interpolation is the culprit.