PDA

View Full Version : Unexpected Behavior: PBO atlas texture copy



Athlete
11-15-2015, 03:57 PM
Hi, I'm using PBO texture uploads for a couple of years now - code is working fine. Now I wanted to change my multi PBO, multi Texture approach to using a singular texture as a 2D Atlas.

When I copy one tile into the texture though, I get the result that the copied tile has reduced in height and is copied multiple times in width instead.

This is my scenario:

atlas texture: 5760x1080
tile: 1920x1080

result: attached

original: attached

It looks like the texture is filling a row of a 3x3 array instead of just one tile of a 1x3 array.. the issues scales with the atlas size:
1920x1080 atlas -> no error (tile size = atlas size)
3840x1080 atlas -> expected: 1x2, but actually: 2x2
5760x1080 atlas -> expected: 1x3, but actually: 3x3
and so on..

Any clues?

Code:




int m_textureWidth = 5760;
int m_textureHeight = 1080;
int m_atlasSize = m_textureWidth*m_textureHeight*3;
int m_tileSize = 1920*1080*3;
GLuint* m_textureIds;
GLuint* m_pboIds;
unsigned char* m_pBuf = .. contains the image bytes ..

void InitAtlasTexture()
{
m_textureIds = new GLuint[1];
glGenTextures(1, m_textureIds);

glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_BGR, m_textureWidth, m_textureHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);

glBindTexture(GL_TEXTURE_2D, 0);
}

void InitPBO()
{
m_pboIds = new GLuint[1];
glGenBuffers(1, m_pboIds);

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pboIds[0]);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, m_atlasSize, 0, GL_MAP_WRITE_BIT);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}

bool CopyTexture()
{
GLubyte* ptr = NULL;
ptr = (GLubyte*)glMapNamedBufferRange(m_pboIds[0], 0, m_atlasSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_INVALIDATE_RANGE_BIT);

if (ptr)
{
memcpy(ptr, m_pBuf, m_tileSize);

glUnmapNamedBuffer(m_pboIds[0]);
}
else
{
return false;
}

glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, m_pboIds[0]);
glTextureSubImage2D(m_textureIds[0], 0, 0, 0, m_textureWidth, m_textureHeight, GL_BGR, GL_UNSIGNED_BYTE, 0);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);

return true;
}

void Render()
{
//..just the snipet thats important here:

float left = 0.0;
float right = 1.0;
float top = 1.0;
float bottom = 0.0;

glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textureIds[0]);

glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(left, bottom);
glVertex3f(-width/2.0, -height/2.0, 0.0f);

glTexCoord2f(right, bottom);
glVertex3f(width/2.0, -height/2.0, 0.0f);

glTexCoord2f(left, top);
glVertex3f(-width/2.0, height/2.0, 0.0f);

glTexCoord2f(right, top);
glVertex3f(width/2.0, height/2.0, 0.0f);
glEnd();

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

GClements
11-16-2015, 01:43 AM
When I copy one tile into the texture though, I get the result that the copied tile has reduced in height and is copied multiple times in width instead.



glTexImage2D(GL_TEXTURE_2D, 0, GL_BGR, m_textureWidth, m_textureHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);
...
glTextureSubImage2D(m_textureIds[0], 0, 0, 0, m_textureWidth, m_textureHeight, GL_BGR, GL_UNSIGNED_BYTE, 0);

You're telling it to fill the entire width of the texture. It should be



glTextureSubImage2D(m_textureIds[0], 0, 0, 0, m_textureWidth/3, m_textureHeight, GL_BGR, GL_UNSIGNED_BYTE, 0);


Except that there should probably a variable which holds the tile width rather than using m_textureWidth/3.

Athlete
11-16-2015, 07:08 AM
Thank you so much! I knew it was something simple :)