Jump to content
  • Advertisement
Sign in to follow this  
Yours3!f

copy raw texture data from one to another

This topic is 2568 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm trying to speed up my font rendering using only one texture and vbo, so I packed the characters into a container, and now I want to store the raw image data of each character in the container texture.

So this is how I load in the characters' raw image data:

unsigned int w = ftface->glyph->bitmap.width;
unsigned int h = ftface->glyph->bitmap.rows;
unsigned int tex_width = next_powa2 ( ftface->glyph->bitmap.width );
unsigned int tex_height = next_powa2 ( ftface->glyph->bitmap.rows );

//for each character
the_font->characters[d].data = new GLubyte[tex_width * tex_height * channels]; //data --> GLubyte* []

for ( unsigned int e = 0; e < tex_height; e++ ) //go through each row
{
for ( unsigned int f = 0; f < tex_width; f++ ) //and each column
{
if ( f >= w || e >= h )
{
the_font->characters[d].data[channels * ( f + e * tex_width ) ] = 0;
the_font->characters[d].data[channels * ( f + e * tex_width ) + 1] = 0;
}
else
{
// I use GL_LUMINANCE_ALPHA as the incoming format, so it should be white + transparency
the_font->characters[d].data[channels * ( f + e * tex_width ) ] = 255;
the_font->characters[d].data[channels * ( f + e * tex_width ) + 1] = ftface->glyph->bitmap.buffer[f + w * e];
}
}
}


So when the raw image data of each character is loaded I pack them into the container, and try to copy the raw image data of each character into the bigger container texture:

GLubyte* data = new GLubyte[final_tex.width * final_tex.height * 2]; // 2 because we still use GL_LUMINANCE_ALPHA

for (int c = 0; c < char_ptr.size(); c++) //for each character
{
//if it is good
if (char_ptr[c]->w > 0 && char_ptr[c]->h > 0 &&
char_ptr[c]->w <= 256 && char_ptr[c]->h <= 256 &&
char_ptr[c]->x <= final_tex.width - char_ptr[c]->w && char_ptr[c]->y <= final_tex.height - char_ptr[c]->h)
{
for (int h = 0; h < char_ptr[c]->h; h++) //go through each row
{
for (int w = 0; w < char_ptr[c]->w; w++) //and each column
{
int origin = 2 * (char_ptr[c]->x + (char_ptr[c]->y + h) * final_tex.width); // this is where each row is located in the big texture
int place = 2 * w; //this represents the position of each byte in one row
int place2 = 2 * (w + h * char_ptr[c]->w); //the position of each byte in the original image (the character)

data[origin + place] = char_ptr[c]->data[place2];
data[origin + place + 1] = char_ptr[c]->data[place2 + 1];
}
}
}
}

//and finally upload the texture
final_tex.create();
final_tex.bind();
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, final_tex.width, final_tex.height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data );


so when I draw the texture I get a grey rectangle, and if alpha blending is enabled it disappears ( alpha = 0 )
so I suppose that there's something wrong with copying the image data... any ideas?

Best regards,
Yours3lf

Share this post


Link to post
Share on other sites
Advertisement
I don't feel like trying to debug your code, but I could provide you with a template for copying a small bitmap into a big bitmap that is uncomplicated and is reasonably fast:
(havn't tried to compile it)


int src_h = char_h;
int src_w = char_w;
int src_stride = charwidth*pixelsize;
char* src = charmap;
int dst_stride = bufferwidth*pixelsize;
char* dst = buffer + charpos.x + charpos.y*dst_stride;


for(int y = src_h; y > 0; y--) {
for(int x = src_w; x > 0; x--) {
*dst++ = *src++;
*dst++ = *src++; //as many times as bytes in the pixel
}
dst += dst_stride;
src += src_stride;
}



ofcourse you would like to use more efficient adressing modes then byte moves, but then you need to think a little bit more, I'll leave that as an exercise ;)

(the backward loops thing is a silly ARM optimization, its hardcoded in my brain :P)

Share this post


Link to post
Share on other sites

I don't feel like trying to debug your code, but I could provide you with a template for copying a small bitmap into a big bitmap that is uncomplicated and is reasonably fast:
(havn't tried to compile it)


int src_h = char_h;
int src_w = char_w;
int src_stride = charwidth*pixelsize;
char* src = charmap;
int dst_stride = bufferwidth*pixelsize;
char* dst = buffer + charpos.x + charpos.y*dst_stride;


for(int y = src_h; y > 0; y--) {
for(int x = src_w; x > 0; x--) {
*dst++ = *src++;
*dst++ = *src++; //as many times as bytes in the pixel
}
dst += dst_stride;
src += src_stride;
}



ofcourse you would like to use more efficient adressing modes then byte moves, but then you need to think a little bit more, I'll leave that as an exercise ;)

(the backward loops thing is a silly ARM optimization, its hardcoded in my brain :P)


sorry for the late reply, I've been experimenting :)

I looked at the code you posted and I think I do the same but without pointers... Now it should work nevertheless...
So I tried to put one character ( ? ) into the big texture:

int channels = 2;
for(int y = 0; y < characters[63].h; y++)
{
for(int x = 0; x < characters[63].w; x++)
{
int place = channels * (x + y * characters[63].w);
data[place] = characters[63].data[place];
data[place + 1] = characters[63].data[place + 1];
}


but it wasn't much success :(

then I tried to at least color the big texture all-white:

int channels = 2;

for(int y = 0; y < final_tex.width; y++)
{
for(int x = 0; x < final_tex.height; x++)
{
int place = channels * (x + y * final_tex.width);
data[place] = 255;
data[place + 1] = 255;
}
}

but this failed too... it appears on screen as if alpha was 0.5 or something like that and the color on the texture too, and I don't know why...

here's how I try to render it on screen:

glDisable ( GL_DEPTH_TEST );
glEnable ( GL_BLEND );
glDisable(GL_CULL_FACE);

glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

the_font.the_shader.bind();

event::get()->get_resize()->set_orthographic ( 0.0f, objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT, 0.0f, -1.0f, 1.0f );

the_font.the_shader.pass_m4x4 ( objs::get()->ppl.get_projection_matrix(), "m4_p" );
the_font.the_shader.pass_int ( 0, "texture0" );

objs::get()->mvm.push_matrix();
objs::get()->mvm.translate_matrix(mymath::vec3f(100, 100, 0));
the_font.the_shader.pass_m4x4 ( objs::get()->ppl.get_model_view_matrix(), "m4_mv" );
objs::get()->mvm.pop_matrix();

//render fontmap
the_font.final_tex.bind();

glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0);
glVertex2f(0, 0);

glTexCoord2f(1, 0);
glVertex2f(the_font.final_tex.width, 0);

glTexCoord2f(1, 1);
glVertex2f(the_font.final_tex.width, the_font.final_tex.height);

glTexCoord2f(1, 1);
glVertex2f(the_font.final_tex.width, the_font.final_tex.height);

glTexCoord2f(0, 1);
glVertex2f(0, the_font.final_tex.height);

glTexCoord2f(0, 0);
glVertex2f(0, 0);
glEnd();

the_font.the_shader.unbind();

glEnable(GL_CULL_FACE);
glDisable ( GL_BLEND );
glEnable ( GL_DEPTH_TEST );

event::get()->get_resize()->set_perspective();


If I don't enable blending then I get an all-grey texture... see the screenshots

Share this post


Link to post
Share on other sites
omg I'm so stupid, I always forget the texture wrap modes.... <_<

final_tex.create();
final_tex.bind();
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_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_RGBA, final_tex.width, final_tex.height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data );


so now painting the big texture all-white works, but copying the characters' raw image data to it still doesn't work...

Share this post


Link to post
Share on other sites
Are you trying to copy image pixels from first GL texture (src) to second (dst)? If yes, you can create FBOs (for src and dst images) and then blit (glBlitFramebufferEXT) (at the end, delete FBOs if you don't need them any more).




Best wishes, FXACE.

Share this post


Link to post
Share on other sites

Are you trying to copy image pixels from first GL texture (src) to second (dst)? If yes, you can create FBOs (for src and dst images) and then blit (glBlitFramebufferEXT) (at the end, delete FBOs if you don't need them any more).




Best wishes, FXACE.




no :)

I'm trying to copy raw image data loaded from a font to a bigger array of raw image data. Then I upload that data as a texture to the gpu and draw it.

Share this post


Link to post
Share on other sites
ok I finally got it :)
the copying algorithm was correct, I just messed up drawing it... I still don't know what went wrong rendering the big texture, but I decided to use some deprecated OGL rendering to make sure I'm drawing it right, and it turned out I didn't...
so here's the screenshot of the font(map? :) ), as you can see most of the characters are rendered correctly, but there are some glitches... I think those are the ones that should be rotated (there are some which are rotated to save space...) but it seems all-right for now :rolleyes:

Thanks for the help guys :)

Share this post


Link to post
Share on other sites

yeah see picture :) I can render the characters one-by-one...


Ah, didn't see the text in the thumbnails and never clicked them, thought I saw the important bits anyway (obv. I didn't)
Glad you fixed it :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!