Skip to main content
GameDev.net gamedev.net
🔒 Locked

256x256pixel textures

Started by Harrism Jan 23, 2006 at 6:09 PM 48 replies 5.4k views
Original Post
Harrism
Harrism
I want to be able to map a texture of 640x480 onto a square. Currently I can only do it if the texture is 256x256 if it's a pixel bigger I can't. Why? Can't put it any simplier, how can I get around this? or is there a reason for this restriction? I havent tried a smaller image, but all the textures on NeHe seem to all be 256x256. Thankyou
meisawesome
meisawesome
Normal graphic hardware requires that textures are a power of 2.

So width and height should each be 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, ...

Even though i've heard that some graphic hardware supports textures that arent a power of 2, I think that you should still have a power of 2.
Harrism
Harrism
What if I said I wanted it to be a backdrop. Say I was writing a simple opengl program to display any chosen bitmap. (a bit pointless but the princible is the same)
M2tM
M2tM
You can actually use any power of 2 texture size (though there may be an upper and lower bound to that, I'm not sure what they are offhand.)

So 256x256, 512x512, 1024x1024 are all valid.

To display a 640x480 texture on a 640x480 quad you can bind by these texture coordinates assuming a 1024x1024 sized texture:

top left: 0, 0
bottom right: (640/1024) which is.625, (480/1024) which is .46875


example (note, I'm just using 2d coordinates, but the glTexCoord2d function is the important part anyway):
glBegin( GL_QUADS );
glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
glTexCoord2d((640.0/1024.0),0.0); glVertex2d(640.0,0.0);
glTexCoord2d((640.0/1024.0),(480.0/1024.0)); glVertex2d(640.0,480.0);
glTexCoord2d(0.0,(480.0/1024.0)); glVertex2d(0.0,480.0);
glEnd();
_____"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Alkiem
Alkiem
Which kind of texture do you use? if it is GL_TEXTURE_2D, width and height must be a power of 2. So you need to create a 1024*512 texture containing your 640*480 texture, and then use the appropriate normalized texture coordinates ie 640/1024 and 480/512. You waste memory but graphic cards handle it very fast. If you don't want to waste memory, you can use GL_TEXTURE_RECTANGLE_ARB, and then it is possible to use non power of 2 size, but it will be slower than with GL_TEXTURE_2D (don't forget to use non normalized texture coordinates ie 640 and 480). There is also GL_TEXTURE_NON_POWER_OF_TWO_ARB but i don't know the differences.

[edit]
I was a little too slow to answer :S.
Harrism
Harrism
I just tried the exact code you wrote. It just gave me a white shape. I also tried merging it with mine same thing happened. The image is only displayed it seems if the saved bitmap is 256x.
gold
gold
OpenGL 2.0 relaxes the requirement for textures to be power of two. On earlier implementations you can use the ARB_texture_rectangle extension for this functionality, with the caveat that rectangle textures cannot be mipmapped. If you only want to render it as a background image, this should not be an issue.

Edit - Mr Bunny beat me to the punch. The non_power_of_two extension is standard in GL 2.0.
M2tM
M2tM
try one that is 512x512 with your working 256x256 code. It should work. After you get that working, try a 1024x1024 one. Then after that try changing the values of the texture binding to (0, 0), (.5, .5) which should result in half the texture appearing over the whole quad.

Alkiem, I don't believe 1024x512 is a valid texture size for OpenGL. I think it's got to be both a power of 2 AND square.
_____"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
gold
gold
OpenGL has no requirement that textures be square, even before NPOT. I know a certain graphics chip with that restriction, but that piece of hardware is quite obsolete now.
Harrism
Harrism
'GL_ARB_texture_rectangle' : undeclared identifier

Somehow I don't think that should be occurring.

#include
#include
#include
#include
#include /* GLU extention library */
#include
M2tM
M2tM
Alright, my bad. I read a source that said it had to be square as well, and it included a check in it's texture loader to make certain the texture was square as well. That's where my confusion comes from.
_____"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
gold
gold
Quote:
Original post by Harrism
'GL_ARB_texture_rectangle' : undeclared identifier

Somehow I don't think that should be occurring.

#include
#include
#include
#include
#include /* GLU extention library */
#include


You need glext.h, a collection of all the extension enumerants and prototypes not included in Microsoft's gl.h.

Harrism
Harrism
I'm afraid the same problem occurs, a white rectangle is placed on the screen.

glEnable(GL_ARB_texture_rectangle);
...
glBindTexture(GL_ARB_texture_rectangle, texture[0]);

I'm afraid the same problem is occuring [a white rectangle], as to trying the other identifiers, they aren't included in any of the headers and I get unknown idenfitier again.

I've checked to make sure the bitmap is being loaded and placed into memory fine. If it couldn't find it I would know about it. However it will refuse to load up a 256x image as it did before with GL_ARB_texture_rectangle.

It's wonderful I'm being black listed as a microsoft calibrator ;-)
gold
gold
Umm... where to start.

The target is GL_TEXTURE_RECTANGLE_ARB, not GL_ARB_texture_rectangle. The latter is just a preprocessor macro to indicate the presence of the extension in the header file, i.e.

#ifdef GL_ARB_texture_rectangle
...
#endif

You need to use the target for TexImage, BindTexture and Enable. You also need to test for the presence of the extension via glGetString(GL_EXTENSIONS).

gold
gold
Oh yeah... and you also need to use unnormalized texture coordinates with TEXTURE_RECTANGLE. Instead of addressing the texels as (0, 1), specify texcoords as (0, size) where in your case the size is (0, 640) in S and (0, 480) in T.

For some light reading, check out the extension spec.
Harrism
Harrism
if(glGetString(GL_TEXTURE_RECTANGLE_ARB)){
return 0;
}
else {
return 1;
}

Returns 1. I've already beaten you to the rest of it. I'd quite happily say GL_TEXTURE_RECTANGLE_ARB is there. Your opinion may differ. Cube is still imageless. Copy and paste the code? It's pretty much simplist copy and paste code itself anyway. Just something to get working so I can have a look at.
gold
gold
Quote:
Original post by Harrism
if(glGetString(GL_TEXTURE_RECTANGLE_ARB)){
return 0;
}
else {
return 1;
}

Returns 1.


I cannot explain this... it should return NULL and set an error!

You need to query GL_EXTENSIONS and search for the substring "GL_ARB_texture_rectangle".

Here is a tutorial on querying extensions.
benjamin bunny
benjamin bunny
You should think about using an extension loading library. Writing all that function loading code manually isn't really necessary anymore (although for these extensions you probably only need the constants). Speaking of which, I released a new version of GLee a couple of hours ago if you're interested [smile].

If you're using GLee, you can test for arb_texture_rectangle with

if (GLEE_ARB_texture_rectangle)

if it returns true you can just go ahead and use the extension.
Harrism
Harrism
Here's the code, I'm getting tired for one night, if someone's nice I'll have something to wake up to, if not i should be more awake to deal with this. It's pretty much copy and paste code anyway. Ben looking through playing, unfortunately still no luck. Nite :-) You know what it's like.

/**********************************************************************//********************************************************************//* Example 3: A fully interactive 3D world with OpenGL              *//********************************************************************/#include <windows.h>#include <stdio.h>#include <gl\gl.h>#include <gl\glut.h>#include <gl\glu.h> /* GLU extention library */#include <gl\glaux.h>#include <gl\glext.h>										// Header File For The Glaux Libraryvoid init(void);void display(void);void keyboard(unsigned char, int, int);void resize(int, int);void drawcube(int, int, int);int is_depth; /* depth testing flag */GLuint	texture[2];											// Font Texture Storage SpaceAUX_RGBImageRec *LoadBMP(char *Filename)			        // Loads The Bitmap Images{		FILE *File=NULL;								    // File Handle		if (!Filename)										// Make Sure A Filename Was Given		{			return NULL;									// If Not Return NULL		}		File=fopen(Filename,"r");							// Check To See If The File Exists		if (File)											// Does The File Exist?		{			fclose(File);									// Close The Handle			return auxDIBImageLoad(Filename);				// Load The Bitmap And Return A Pointer		}		return NULL;										// If Load Failed Return NULL}int LoadGLTextures()										// Load Bitmaps And Convert To Textures{        int Status=FALSE;									// Status Indicator		int		loop1;												// Generic Loop1        AUX_RGBImageRec *TextureImage[2];					// Create Storage Space For The Textures        memset(TextureImage,0,sizeof(void *)*2);			// Set The Pointer To NULL        if ((TextureImage[0]=LoadBMP("c:/BITMAPS/SCREEN0/screen0.bmp")))	// Load Background Image        {			Status=TRUE;									// Set The Status To TRUE			glGenTextures(2, &texture[0]);					// Create The Texture			for (loop1=0; loop1<1; loop1++)					// Loop Through 2 Textures			{				glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture[loop1]);				glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 3, TextureImage[loop1]->sizeX, TextureImage[loop1]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop1]->data);				glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);				glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR);			}			for (loop1=0; loop1<1; loop1++)					// Loop Through 2 Textures			{				if (TextureImage[loop1])					// If Texture Exists					{					if (TextureImage[loop1]->data)			// If Texture Image Exists					{						free(TextureImage[loop1]->data);	// Free The Texture Image Memory					}					free(TextureImage[loop1]);				// Free The Image Structure				}			}		}	return Status;											// Return The Status}int main (int argc, char **argv){	glutInit(&argc, argv);	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);	glutInitWindowSize(640, 480);	glutInitWindowPosition(40, 40);	glutCreateWindow("The Cube World");	init();	glutDisplayFunc(display);	glutKeyboardFunc(keyboard);	/* this time we're going to keep the aspect ratio	constant by trapping the window resizes */	glutReshapeFunc(resize);  	glutMainLoop();	return 0;}void init(void){		if (!LoadGLTextures())							// Jump To Texture Loading Routine ( NEW )	{	//	return FALSE;							// If Texture Didn't Load Return FALSE ( NEW )	}	glEnable(GL_TEXTURE_RECTANGLE_ARB);						// Enable Texture Mapping ( NEW )	glShadeModel(GL_SMOOTH);		glClearColor(0.0, 0.0, 0.0, 0.0);	glEnable(GL_DEPTH_TEST);	is_depth = 1;	glMatrixMode(GL_MODELVIEW);}void display(void){	if (is_depth)		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	else		glClear(GL_COLOR_BUFFER_BIT);	/* draw the floor */	//example (note, I'm just using 2d coordinates, but the glTexCoord2d function is the important part anyway):	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture[0]);				// Select Our Texture	//glBegin( GL_QUADS );	//glTexCoord2f(0.0f,0.0f);							glVertex3f(-64.0f, -64.0f,  1.0f);	//glTexCoord2f((640.0f/1024.0f),0.0f);				glVertex3f( 64.0f, -64.0f,  1.0f);	//glTexCoord2f((640.0f/1024.0f),(480.0f/1024.0f));	glVertex3f( 64.0f,  70.0f,  1.0f);	//glTexCoord2f(0.0f,(480.0f/1024.0f));				glVertex3f(-64.0f,  70.0f,  1.0f);	//glEnd();	glBegin(GL_QUADS);				glTexCoord2d(0, 640); glVertex2i(-64.0f, -64.0f);	// Bottom Left Of The Texture and Quad		glTexCoord2d(0, 640); glVertex2i( 64.0f, -64.0f);	// Bottom Right Of The Texture and Quad		glTexCoord2d(0, 480); glVertex2i( 64.0f,  70.0f);	// Top Right Of The Texture and Quad		glTexCoord2d(0, 480); glVertex2i(-64.0f,  70.0f);	// Top Left Of The Texture and Quad	glEnd();	glutSwapBuffers();}void keyboard(unsigned char key, int x, int y){	/* This time the controls are:		  "a": move left	  "d": move right	  "w": move forward	  "s": move back	  "t": toggle depth-testing	*/	switch (key)	{	case 'a':	case 'A'://		glTranslatef(5.0, 0.0, 0.0);		break;	case 'd':	case 'D'://		glTranslatef(-5.0, 0.0, 0.0);		break;	case 'w':	case 'W':		glTranslatef(0.0, 0.0, 5.0);		break;	case 's':	case 'S':		glTranslatef(0.0, 0.0, -5.0);		break;	case 't':	case 'T':		if (is_depth)		{			is_depth = 0;			glDisable(GL_DEPTH_TEST);		}		else		{			is_depth = 1;			glEnable(GL_DEPTH_TEST);		}	}	display();}void resize(int width, int height){	if (height == 0) height = 1;		glMatrixMode(GL_PROJECTION);	glLoadIdentity();	/* note we divide our width by our height to get the aspect ratio */	gluPerspective(45.0, width / height, 1.0, 400.0);	/* set initial position */	glTranslatef(0.0, -5.0, -150.0);	glMatrixMode(GL_MODELVIEW);}/**********************************************************************/

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.