FAQ

From OpenGL Wiki
Revision as of 16:20, 8 September 2009 by V-man (talk | contribs) (added Masking section. Corrected code for glGetError (or "How do I check for GL errors?))
Jump to: navigation, search

Welcome to the FAQ

What is OpenGL?

OpenGL stands for Open Graphics Library. It is an API for doing 3D graphics.
In more specific terms, it is an API that is used to "draw triangles on your scene". In this age of GPUs, it is about talking to the GPU so that it does the job of drawing. It does not deal with file formats. It does not open bmp, png and any image format. It does not open 3d object formats like obj, max, maya. It does not do animation. It does not handle keyboard, mouse and any input devices. It does not create a window, and so on.
All that stuff should be handled by an external library (GLUT is one example that is used for creating and destroying a window and handling mouse and keyboard).
GL has gone through several versions : 1.0, 1.1, 1.2, 1.2.1, 1.3, 1.4, 1.5, 2.0, 2.1, 3.0
At each versions, extensions of interest are introduced into the core. Usually, they are all ARB extensions.

Who maintains?

GL is created at SGI. Later on, the Architectural Review Board (ARB) controlled it which is a collection of major graphics companies.
Control was transfered to Khronos, which is another collection of major graphics companies. Their website is at http://www.khronos.org and they are specially known for OpenGL ES in which the ES means Embeded System (cellphones, PDA, consoles such as the Playstation 3 (PS3)) and other Open Spec APIs. You can find the list of companies at Khronos' website.

Open Source?

No, OpenGL doesn't have any source code. GL is a specification which can be found on this website. It describes the interface the programmer uses and expected behavior. OpenGL is Open Spec. Anyone can download the spec for free.
There is an implementation of GL that is Open Source and it is called Mesa3D http://www.mesa3d.org
It doesn't have the license to call itself OpenGL, but it does follow the spec very well.

Where can I download?

Just like the "Open Source?" section explains, GL is not a software product. GL is a specification.
Companies like nVidia and AMD/ATI use the spec to write their drivers, so OpenGL is in fact included in the drivers that they supply.
For laptop owners, you need to visit the manufacturer of your laptop and download the drivers from them.

Where can I download? #2

When you update your video driver, this is good enough for people who want to play games or run some application.
For programmers, installing drivers will not give you a gl.h file. It will not give you opengl32.lib. Those are files that come with your compiler (on Windows, your compiler might need opengl32.lib or perhaps opengl32.a).
Also, there are no updated gl.h and opengl32.lib file. These are stuck at GL 1.1 and will be forever. Read the Getting Started section to learn what you must do. http://www.opengl.org/wiki/Getting_started
Also, installing a video driver will not replace opengl32.dll. It is a system file and belongs to Windows. Only Microsoft may update it.
When you install a video driver, another file will be copied to your system (nvoglv32.dll in the case of nVidia) and the registry will be modified.
opengl32.dll will call into the real GL driver (nvoglv32.dll).

SDK

See this page
http://www.opengl.org/wiki/Getting_started#SDK
There isn't an official SDK from http://www.opengl.org however 3rd party individuals have made great websites and tutorials, companies like nVidia and ATI/AMD have made available many small projects that demonstrate GL features.
If you are new and want to understand what you must do, the 2 most important pages on this Wiki are : this FAQ page and also http://www.opengl.org/wiki/Getting_started

What platforms have GL?

Windows : 95 and above
Mac OSX : all versions
Linux : this depends on the distributions. Distros meant for desktop usage come with Gnome, KDE or some windows manager and OpenGL is either supplied as Mesa (software rasterizer) or they provide proper drivers.
FreeBSD : unknown
Cellphones, PDA, consoles such as the Playstation 3 (PS3) have OpenGL ES.
OpenGL ES is a subset of OpenGL. For example, it has VBO suppport but glBegin and glEnd have been removed.
Despite the fact that PS3 offers GL ES and Cg, most games don't use it. Instead, the companies use the more low level libraries available on that platform.

Which 3D API is better?

This question is asked by newcomers. They want to know whether they should chose OpenGL or DirectX.
It should be noted that GL can't be compared to DX since DX has additional features like DirectSound, DirectPlay, DirectInput, DirectMusic, DirectDraw, the DirectX Utility.
GL should be compared only to Direct3D.
If you need sound support, you can use FMod, Bass, OpenAL and others.
For a math library, there are many. For image loaders, there are many as well.
For a complete list, visit the Alternative Game Libraries forum at http://www.gamedev.net/community/forums

For D3D vs GL, there are many discussions on forums. This is one such example
http://www.gamedev.net/community/forums/topic.asp?topic_id=510845

In general, the more you know, the better, so it is recommended that you start with one or the other. Learning the other later on will be easy.

How Does It Work On Windows?

All Windows versions support OpenGL.
When you compile an application, you link with opengl32.dll (even on Win64).
When you run your program, opengl32.dll gets loaded and it checks in the Windows registry if there is a true GL driver. If there is, it will load it. For example, ATI's GL driver name starts with atioglxx.dll and nVidia's GL driver is nvoglv32.dll. The actual names change from release versions.
opengl32.dll is limited to 1.1. When you make a call like glBindTexture, it jumps to opengl32.dll and it checks if there is a driver. If there is, it calls the true driver bind function. There are many GL 1.1 functions such as glLoadMatrixf, glPushMatrix, glOrtho, glEnable, glTexEnvi.

For GL >=1.2 functions, you get a function pointer with wglGetProcAddress. Examples are glActiveTexture, glBindBuffer, glVertexAttribPointer. wglGetProcAddress returns an address from the real driver in these cases.

The above is just to inform you how it works under the hood. It has no impact on you as a programmer. It has no performance impact.
To compare with Direct3D, in direct3D, you get a COM object to something called the device. This COM object has a table of pointers for every function so that you can call d3ddevice->SetRenderState(). Again, there is no performance impact. GL and D3D don't have an advantage one over the other.
The only important thing to know is that opengl32.dll belongs to Microsoft. No one can modify it. You must not replace it. You must not ship your application with this file. You must not ship nvoglv32.dll or any other system file either.
It is the responsibility of the user to install the driver made available from Dell, HP, nVidia, ATI/AMD, Intel, SiS, and whatever.

Why is my GL version only 1.4? 1.3? 1.2?

When you install the driver for your video card, it provides the GL driver written specifically for it by the IHV.
The IHV might be Intel, nVidia, ATI/AMD, SiS, etc.
No, you can't get a higher GL version. That's simply the way it is.
This is a problem for people with integrated chipsets such as Intel. Intel's driver are terrible according to many forum users on this site and also other websites. It can't be considered a "gaming GPU".
You are best off developing and testing on something good like nVidia and ATI/AMD.
The alternative way is to use a software renderer such as Mesa which can be found at http://www.mesa3d.org but this is very slow.
This Wiki will get updated once Intel releases some descently stable drivers with at least GL 2.0.
Bottom line, integrated chipsets are only good for playing tic-tac-toe and reading websites such as this Wiki.

glTranslate, glRotate, glScale

Are these hardware accelerated?
No, there are no known GPUs that execute this. The driver computes the matrix on the CPU and uploads it to the GPU.
All the other matrix operations are done on the CPU as well : glPushMatrix, glPopMatrix, glLoadIdentity, glFrustum, glOrtho.
This is the reason why these functions are considered deprecated in GL 3.0. You should have your own math library, build your own matrix, upload your matrix to the shader.
A list of various libraries is at "Alternative Game Libraries" http://www.gamedev.net/community/forums/topic.asp?topic_id=291432
One such library is glhlib http://www.geocities.com/vmelkon/glhlibrary.html
It has a software matrix implementation.
Code example 1 :

 float mymatrix[16];
 glhLoadIdentityf2(mymatrix);
 glhPerspectivef2(mymatrix, 45.0, aspectRatio, zNear, zFar);  //The matrix is in mymatrix now. Do whatever you want with it

Code example 2 :

 float mymatrix[16];
 glhLoadIdentityf2(mymatrix);
 glhTranslatef2(mymatrix, 0.0, 0.0, 1.0);
 glhRotateAboutYf2(mymatrix, 45.0//YOU MUST CONVERT TO RADIANS);
 glhRotateAboutZf2(mymatrix, 45.0//YOU MUST CONVERT TO RADIANS);

YOU MUST CONVERT TO RADIANS means that instead of 45.0, you need to put 0.78539816. The library uses radians in general.
glhPerspectivef2 is a special exception.

Fixed function and modern GPUs

Modern GPUs no longer support fixed function. Everything is done with shaders. In order to preserve compatibility, the GL driver generates a shader that simulates the fixed function. It is recommended that all new modern programs use shaders. New users need not learn fixed function related operations of GL such as glLight, glMaterial, glTexEnv and many others.

How to render in pixel space

There are 2 ways to do it 1. Setup a certain projection matrix

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(0.0, WindowWidth, 0.0, WindowHeight, -1.0, 1.0);
 //Setup modelview to identity if you don't need GL to move around objects for you
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();

Notice that y axis goes from bottom to top because of the glOrtho call. You can swap bottom and top parameters if you want y to go from top to bottom. make sure you render your polygons in the right order so that GL doesn't cull them or just call glDisable(GL_CULL_FACE).

2. The second method is to use glWindowPos which ignores the projection and modelview matrices.
You can use glWindowPos2f or glWindowPos3f so perhaps the z component doesn't matter for you and you can set it to 0.0.
You can try glWindowPos2i, glWindowPos3i, glWindowPos2d, glWindowPos3d, glWindowPos2s, glWindowPos3s but that depends on what format the GPU supports. http://www.opengl.org/wiki/Common_Mistakes#Unsupported_formats_.231
glWindowPos basically changes the raster position. Then you would need to call glBitmap or glDrawPixels to render. Keep in mind that glBitmap or glDrawPixels are not recommended for rendering. It's always best to render polygons since that's what GPUs prefer.

Multi indexed rendering

You want to have an index array for each vertex attribute : vertex, normal, texcoord.
Perhaps you have 20 vertices, 35 normals, 20 texcoords and you have 3 index arrays.
Does GL support multi index rendering? No and this is because GPUs don't support it (nVidia, ATI, Intel).
There are of course exceptions such as certain consoles where multiple index arrays are supported by the GPU.

Anyway, you would have to duplicate some vertices and texcoords and yes, it will waste some memory.

Quite often, people asking this question are people who want to use the OBJ file format.

 v 1.52284 39.3701 1.01523
 v 36.7365 17.6068 1.01523
 v 12.4045 17.6068 -32.475
 and so on ...
 n 0.137265 0.985501 -0.0997287
 n 0.894427 0.447214 -8.16501e-08
 n 0.276393 0.447214 -0.850651
 and so on ...
 t 0.6 1
 t 0.5 0.647584
 t 0.7 0.647584
 and so on ...
 f 102//102//102 84//84//84 158//158//158 
 f 158//158//158 84//84//84 83//83//83 
 f 158//158//158 83//83//83 159//159//159 
 and so on ...

The lines that start with an f are the faces. As you can see, each vertex has 3 index, one for vertex, normal, texcoord.
The problem is that the OBJ format is ancient pre-GPU junk.
GPUs prefer 1 index list. They also prefer vertex, normal, texcoord to be interleaved rather than be in their own array. They prefer floating point format most of the time for vertex, normals, etc so that part the OBJ format got right. Faces should be in unsigned short format.
You should probably use your own file format instead of using OBJ.
For more info (as far as GL programming is concerned), Vertex arrays http://www.opengl.org/wiki/Vertex_Arrays
Vertex formats http://www.opengl.org/wiki/Vertex_Formats
VBO http://www.opengl.org/wiki/VBO
More about VBOs http://www.opengl.org/wiki/VBO_-_more

2 component textures

Formats such as GL_LUMINANCE4_ALPHA4, GL_LUMINANCE6_ALPHA2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE12_ALPHA4, GL_LUMINANCE12_ALPHA12, GL_LUMINANCE16_ALPHA16 are 2 component formats. The only way to know if the GPU actually supports it is to read the IHV manuals. For example, nVidia has a doc called nv_ogl_texture_formats.pdf at http://developer.nvidia.com that says that Gf6 supports GL_LUMINANCE16_ALPHA16.
Also, the GPU should be able to render to them in case FBO is supported.
There are other formats special to nVidia : GL_SIGNED_LUMINANCE8_ALPHA8, GL_HILO8, GL_HILO16, GL_FLOAT_RG16, GL_FLOAT_RG32.
Those tokens probably needs a _NV postfix and they should be defined in glext.h
Also visit http://www.opengl.org/registry to see which extensions define them.

Additional :
GL 3.0 introduces some new formats that the GPU must exactly support (it must not use another format of equal or higher capability)
GL_RG32F, GL_RG32I, GL_RG32UI, GL_RG16, and many others. See Required Texture Formats in the spec file.

Immediate mode, display lists, vertex arrays, VBO

Immediate mode means glBegin(), glVertex(), glEnd() and the related calls like glTexCoord, glNormal, glColor.
This method is outdated and slow.
Display lists and vertex arrays are also outdated now that VBO is available, since 2000.
There is very little reason to not use VBOs for everything however you should use them correctly in order to get good performance.
http://www.opengl.org/wiki/VBO
http://www.opengl.org/wiki/VBO_-_more
http://www.opengl.org/wiki/Vertex_Arrays
http://www.opengl.org/wiki/Vertex_Formats

glGetString(GL_VERSION)

This returns a string which may look something like "2.0.6914 WinXP SSE/SSE2/SSE3/3DNow!"
2.0 is the actual version number of GL supported. All the rest depends on what information the IHV wants to convey and is not part of the GL standard. 6914 would be the driver version. WinXP is the OS. SSE/SSE2/SSE3/3DNow! are CPU features that the driver can use in case it runs in software mode.
In glhlib http://www.geocities.com/vmelkon/glhlibrary.html
glhGetIntegerv(GLH_OPENGL_VERSION, version) can return the major and minor version. That is to say, version[0] would be an integer (2) and version[1] is an integer (0). This is a utility library similar to GLU to make programming easier.
Also note that at times glGetString(GL_VERSION) returns also the bus type used such as AGP or PCI or PCIEx.

glClear and glScissor

glScissor is one of the few functions that effect on how glClear operates. If you want to clear only a region of the back buffer, then call glScissor and also glEnable(GL_SCISSOR_TEST).
Alternatively, if you have used the scissor test and forgot to glDisable(GL_SCISSOR_TEST), then you might wonder why glClear isn't working the way you want to.

Masking

Pay attention to glColorMask, glStencilMask and glDepthMask. For example, if you disable depth writes by calling glDepthMask(FALSE), then all calls to glClear will not clear the depth buffer.

glGetError (or "How do I check for GL errors?)

OpenGL keeps a set of error flags, and each call to glGetError() tests and clears one of those flags. When there are no more error flags set, then glGetError() returns GL_NO_ERROR. So use a little helper function like this to check for GL errors:


  #include <stdio.h>
  #include <GL/gl.h>
  #include <GL/glu.h>

  int checkForGLErrors( const char *s )
  {
    int errors = 0 ;
    int counter = 0 ;

    while ( counter < 1000 )
    {
      GLenum x = glGetError() ;

      if ( x == GL_NO_ERROR )
        return errors ;

      fprintf( stderr, "%s: OpenGL error: %s [%08x]\n", s ? s : "", gluErrorString ( x ), errcnt++ ) ;
      errors++ ;
      counter++ ;
    }
  }

If there is no GL context, glGetError() would return an error code each time it is called since it is an error to call glGetError when there is no GL context. That is the reason why we have added counter < 1000.