PDA

View Full Version : opengl es texture!



davie
07-09-2010, 05:19 AM
Hi there,
In OpenGL ES, the width and height of a picture that used for texture must be two to the power of n. In my program i need draw a lot of pictures and some of them are not two to the power of n. Then how to use these pictures? Thanks a lot!

ZbuffeR
07-09-2010, 05:43 AM
First you have to know that the power-of-two limitation does not forces width and height to be the same. Depending on the case, it can help reduce the overhead.ie, 32*128 is valid POT.
Then you can just fill in the non-power-of-two part you have and only use texcoords within this rectangle, instead of the full 0-1 range.
Ex, for 30*100 NPOT picture on a 32*128 POT texture, use texcoords :
xmin=0, xmax=30/32.0
ymin=0, ymax=100/128.0

davie
07-10-2010, 03:13 AM
Hi ZbuffeR,
Thanks for your reply!

"First you have to know that the power-of-two limitation does not forces width and height to be the same. Depending on the case, it can help reduce the overhead.ie, 32*128 is valid POT."
yes, i know that the width and height of a picture for texture can not be the same.

"Then you can just fill in the non-power-of-two part you have and only use texcoords within this rectangle, instead of the full 0-1 range.
Ex, for 30*100 NPOT picture on a 32*128 POT texture, use texcoords :
xmin=0, xmax=30/32.0
ymin=0, ymax=100/128.0"

How to do what you said? ie, if i have a 30*100 picture and read its data into a buffer(a buffer of 30*100*BYTES_PER_PIXEL length, ie, BYTE* pBuffer = new BYTE[30*100*BYTES_PER_PIXEL];), then pass 32,128 and pBuffer to the third, fouth and last parameter of the function glTexImage2D. Does this make a right texture? Thanks a lot!

BTW: if a 30*140 picture, its texture should be 32*256?

ZbuffeR
07-12-2010, 02:03 AM
That is the idea, but you will have to play with GL_PACK_ROW_LENGTH and provide all the rows (even if the last ones are undefined) to avoid GL trying to read past your array. See the documentation about glPixelStorei (http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml)
It is simpler if you can fill in yourself 30*100 in a 32*128 block, and send the 32*128 data to OpenGL.

EDIT: scratch that, even simpler is to glTexImage2D on a NULL pointer, with 32*128, then glTexSubImage2D the part of interest.
Just keep in mind the default GL alignment is 4 bytes, so you might have to do this for byte alignment :
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);

And yes : for a 30*140 picture, its texture should be 32*256.

davie
07-13-2010, 01:54 AM
Hi ZbuffeR,

Thanks for your help! But i still have some questions.

I have a 400*240 picture and want to draw it at the position (0,0,400,240) of my screen. First i read the picture into a buffer(the pointer pData in the following codes points to this buffer), then i try the following:

1. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
when doing this, my program stops and seems to be dead.

so i try the second method as follow:

2.

BYTE *pBuf = new BYTE[512*256*iChannel];
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, pBuf);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 480, 240, GL_RGB, GL_UNSIGNED_BYTE, pData);
delete [] pBuf;
pBuf = NULL;

This works ok! but there is a problem when i draw this texture to the screen.
because the picture is 400*240, so i draw it to the RECT(0,0,400,240) of my screen, but i found
the picture doesnt occupy all the rect, the right and lower place is black! How to solve this problem?
Thanks a lot!

davie
07-13-2010, 04:13 AM
Can anybody help me? Thanks!

ZbuffeR
07-13-2010, 06:16 AM
1) of course this can not work, as I explained above.
2) perfect.

Did you use custom texcoords as I explained even earlier ?
xmin=0, xmax=400/512.0
ymin=0, ymax=240/256.0

What code do you use to draw on screen ? Quad, vertex, texturecoord, etc ? Please show your code.

davie
07-13-2010, 08:14 AM
Hi ZbuffeR,

Thanks very much!

"Did you use custom texcoords as I explained even earlier ?
xmin=0, xmax=400/512.0
ymin=0, ymax=240/256.0"

Sorry, i dont know when and where to use this. Can i pass them as parameters to some functions?

Sorry for i have no code on hand, but i remember a little, it is something like this:

glBindTexture(...);
glVertexPointer(...);
glTexCoord(...);
glDrawArrays(...);

Thans again!

BTW: I will show my code more complete, but it need some hours later for i am not at my office now.

davie
07-13-2010, 06:06 PM
Hi ZbuffeR,

My full codes are as follow:


void OpenGL::LoadTexture(BYTE* pData, int iWidth, int iHeight, int iChannel, unsigned int* texture)
{
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, *texture);

glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

int width = ldexp(1, ceil(log(iWidth)/log(2)));
int height = ldexp(1, ceil(log(iHeight)/log(2)));
if (iChannel == 2)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iWidth, iHeight, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pData);
}
else if (iChannel == 3)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iWidth, iHeight, GL_RGB, GL_UNSIGNED_BYTE, pData);
}
else if (iChannel == 4)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iWidth, iHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);
}
}

void OpenGL::GlDrawIcon(const RECT& rect, unsigned int texture, int z)
{
glTranslatex(0, 0, Int2Fixed(z));

GLshort vertices[12];
GetVerticesFromRect(vertices, rect);
glTexCoordPointer(2, GL_FIXED, 0, m_texcoords);
glVertexPointer(3, GL_SHORT, 0, vertices);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glTranslatex(0, 0, Int2Fixed(-z));
}

m_texcoords[0] = m_texcoords[1] = m_texcoords[3] = m_texcoords[4] = 0;
m_texcoords[2] = m_texcoords[5] = m_texcoords[6] = m_texcoords[7] = ONE;

Thanks!

davie
07-13-2010, 06:45 PM
Hi,

Another thing i need clarify:

First, i make a 512*256 texture with a 480*240 picture.

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 480, 240, GL_RGB, GL_UNSIGNED_BYTE, pData);

Second, i draw it on screen.
if i draw the texture at the (0,0,512,256) region of the screen, then the picture is fully in the region (0,0,480,240).
and the (481,0,512,256) and (0,241,512,256) regions both are black(have no picture data), so i want these black areas dont show on my screen.

if i draw the texture at the (0,0,480,240) region of the screen,
then the picture is fully in a region (0,0,x,y), and the (x+1,0,480,240) and (0,y+1,480,240) regions both are black. This time the picture is not shown with its original size(480*240), it is been resized(size reduced).

I search this problem with google, many people have no idea with it and some people think it cannt be figured. They think that using pictures with width and height be the power of 2 is the only solution. I dont know whether thet are right.

Now i have no idea, any help and suggestions would be appreciated!

davie
07-13-2010, 08:05 PM
if there are no good ideas, i have to break down a 480*240 picture to 12 pictures, with width and height as follow:

256*128 128*128 16*128
256*64 128*64 16*64
256*32 128*32 16*32
256*16 128*16 16*16

ZbuffeR
07-14-2010, 03:53 AM
You already have all the information you need.
If you post 3 messages while us europeans are asleep, please be patient enough to have an answer :)

Here :


m_texcoords[0] = m_texcoords[1] = m_texcoords[3] = m_texcoords[4] = 0;
m_texcoords[2] = m_texcoords[5] = m_texcoords[6] = m_texcoords[7] = ONE;

Fix your texture coordinates, as I already explained 2 times here, instead of using the 0;1 range, use 0;(float)iWidth/width for width and 0;(float)iHeight/height.

That way you will only see the desired part of the texture, without black borders.


I search this problem with google, many people have no idea with it and some people think it cannt be figured. They think that using pictures with width and height be the power of 2 is the only solution. I dont know whether thet are right.
Indeed they are WRONG.

davie
07-14-2010, 05:20 AM
Hi ZbuffeR,

Thanks very much! It's ok now! :)