Texture Mapping: Difference between revisions

From OpenGL Wiki
Jump to navigation Jump to search
mNo edit summary
Zyx 2000 (talk | contribs)
m Redirected page to Texture
 
(13 intermediate revisions by 2 users not shown)
Line 1: Line 1:
First, let's talk about texture types available.<br>
#REDIRECT [[Texture]]
<br>
GL has GL_TEXTURE_1D. You can ignore this and use GL_TEXTURE_2D instead.<br>
This has been part of GL since 1.0<br>
<br>
GL_TEXTURE_2D has width and height and usually the GPU stores this in memory in a format that is quick to access.<br>
For example, small blocks of the texture are stored in sequence so that cache memory works better.
This has been part of GL since 1.0<br>
<br>
GL_TEXTURE_3D has width and height and depth and usually the GPU stores this in memory in a format that is quick to access.<br>
Just like 2D, small blocks of the texture are stored in sequence so that cache memory works better but other techniques exist as well.<br>
This has been part of GL since 1.2<br>
<br>
GL_TEXTURE_CUBE_MAP has width and height and 6 faces. Kind of like 2D except it has 6 faces and texcoords work in a special way.<br>
This has been part of GL since 1.3<br>
<br>
GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_RECTANGLE_ARB are supported as extensions. For having non power
of 2 dimension 2D textures. Texcoords worked in a unusual way. From 0 to width for S. From 0 to height for the T.<br>
<br>
<br>
With GL 2.0, GL_TEXTURE_RECTANGLE becomes obsolete. You can make textures with any dimension, mipmap it, use any anisotropy supported,
use any texture wrap mode.<br>
<br>
<br>
== How to create a texture ==
<br>
Create a single texture ID<br>
  uint textureID;
  glGenTextures(1, &textureID);
<br>
You have to bind the texture before doing anything to it.<br>
  glBindTexture(GL_TEXTURE_2D, textureID);
<br>
Now you should define your texture properties. Any call sequence will work since GL is a state machine.<br>
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, TextureWrapS);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, TextureWrapT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter);
<br>
Some people make the mistake of not calling glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter); and
they get the default state GL_LINEAR_MIPMAP_NEAREST and they don't define the mipmaps, so <b>the texture is considered
incomplete</b> and you just get a white texture.<br>
<br>
If you will use mipmapping, you can either define them yourself by making many calls to glTexImage2D or let the GPU generate the mipmaps.<br>
Since current GPUs can generate it automatically with a box filter technique, you can call<br>
Mipmapping is usually good and increases performance.<br>
<br>
  glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
<br>
If you need anisotropy call<br>
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_ANISOTROPY_EXT, Anisotropy);
<br>
Anisotropy is an extension. It can drag down performance greatly and make your results look better. Use as less as possible.<br>
<br>
Define the texture with<br>
  glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, border, format, type, ptexels);
<br>
<br>
You need to make sure that your width and height are supported by the GPU.<br>
  int Max2DTextureWidth, Max2DTextureHeight;
  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Max2DTextureWidth);
  Max2DTextureWidth=Max2DTextureHeight;
  int MaxTexture3DWidth, MaxTexture3DHeight, MaxTexture3DDepth;
  glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &MaxTexture3DWidth);
  MaxTexture3DHeight=MaxTexture3DDepth=MaxTexture3DWidth;
  int MaxTextureCubemapWidth, MaxTextureCubemapHeight;
  glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &MaxTextureCubemapWidth);
  MaxTextureCubemapHeight=MaxTextureCubemapWidth;
  int MaxTextureRECTWidth, MaxTextureRECTHeight;
  glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &MaxTextureRECTWidth);
  MaxTextureRECTHeight=MaxTextureRECTWidth;
  int MaxRenderbufferWidth, MaxRenderbufferHeight;
  glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &MaxRenderbufferWidth);
  MaxRenderbufferHeight=MaxRenderbufferWidth;
<br>
<br>
Very old GPUs don't support border texels.<br>
Make sure the format is supported by the GPU else the drivers will convert into a proper format.<br>
Make sure the internal format is supported by the GPU (example : GL_RGBA8) else the driver will convert the texture for you.<br>
There is no way to query what formats the GPU supports but IHVs (nVidia, AMD/ATI) publish documents on what is supported.<br>
For example, it is very common for GL_RGBA8 to be supported but GL_RGB8 is not.<br>
You should also call glGetError to make you don't get an error message like running out of memory (GL_OUT_OF_MEMORY).<br>
<br>
The only thing left is calling glTexEnv but this isn't part of the texture state. It is part of the texture_environment, in other
words the texture unit.<br>
<br>
To use the texture, bind it to a texture unit with glBindTexture and don't forget to enable texturing with
glEnable(GL_TEXTURE_2D) and disable with glDisable(GL_TEXTURE_2D)
<br>
That's the basics of creating a texture and using it.<br>
<br>
== Just allocate memory for a texture ==
If you want to just allocate memory for the texture but you don't want to initialize the texels, then just give a NULL pointer to glTexImageXD. The GL specification doesn't say what values the texels will have.<br>
  uint textureID;
  glGenTextures(1, &textureID);
  glBindTexture(GL_TEXTURE_2D, textureID);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  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_RGBA8, 512, 512, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
 
== Copy the frame buffer to the texture ==
Don't use glCopyTexImage2D. This functions deletes the previous texture and reallocates therefore it is slow.<br>
Use glCopyTexSubImage2D instead, which just updates the texels.<br>
So, you need to render the scene to the backbuffer, don't call SwapBuffers, bind the texture and call glCopyTexSubImage2D
  RenderScene();
  glBindTexture(GL_TEXTURE_2D, textureID);
  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 512, 512);
  SwapBuffers();

Latest revision as of 21:05, 9 June 2011

Redirect to: