8 min read

(For more resources related to this topic, see here.)

Quick start – using GLEW

You have now installed GLEW successfully and configured your OpenGL project in Visual Studio to use it. In this article, you will learn how to use GLEW by playing with a simple OpenGL program that displays a teapot. We will extend this program to render the teapot with toon lighting by using shader programs. To do this, we will use GLEW to set up the OpenGL extensions necessary to use shader programs. This example gives you a chance to experience GLEW to utilize a popular OpenGL extension.

Step 1 – using an OpenGL program to display a teapot

Consider the following OpenGL program that displays a teapot with a light shining on it:

#include <GL/glut.h>
void initGraphics()
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
const float lightPos[4] = {1, .5, 1, 0};
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void onResize(int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(40, (float) w / h, 1, 100);
glMatrixMode(GL_MODELVIEW);
}
void onDisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0,
0.0, 0.0, 1.0,
0.0, 1.0, 0.0);
11
Instant GLEW
glutSolidTeapot(1);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutCreateWindow("Teapot");
initGraphics();
glutDisplayFunc(onDisplay);
glutReshapeFunc(onResize);
glutMainLoop();
return 0;
}

Create a new C++ console project in Visual Studio and copy the above code into the source file. On compiling and running this code in Visual Studio, you will see a window with a grey colored teapot displayed inside it as shown in the screenshot below:

Let us briefly examine this OpenGL program and try to understand it. The main function shown below uses the GLUT API to create an OpenGL context, to create a window to render in and to set up the display function that is invoked on every frame. Instead of GLUT, you could also use other cross-platform alternatives such as the OpenGL Framework (GLFW) library or the windowing API of your platform.

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutCreateWindow("Teapot");
initGraphics();
glutDisplayFunc(onDisplay);
glutReshapeFunc(onResize);
glutMainLoop();
return 0;
}

Here, the call to glutInit creates an OpenGL context and the calls to glutInitDisplayMode, glutInitWindowSize, and glutCreateWindow help create a window in which to render the teapot. If you examine the initGraphics function, you can see that it enables lighting, creates a light at a given position in 3D space, and sets the background color to white. Similarly, the onResize function sets the size of the viewport based on the size of the rendering window. Passing a pointer to the onResize function as input to glutReshapeFunc ensures that GLUT calls onResize every time the window is resized. And finally, the onDisplay function does the main job of setting the camera and drawing a teapot. Passing a pointer to the onDisplay function as input to glutDisplayFunc ensures that GLUT calls onDisplayfunction every time a frame is rendered.

Step 2 – using OpenGL extensions to apply vertex and fragment shaders

One of the most common uses of GLEW is to use vertex and fragment shader programs in an OpenGL program. These programs can be written using the OpenGL Shading Language (GLSL). This was standardized in OpenGL 2.0. But, most of the versions of Windows support only OpenGL 1.0 or 1.1. On these operating systems, shader programs can be used only if they are supported by the graphics hardware through OpenGL extensions.

Using GLEW is an excellent way to write portable OpenGL programs that use shader programs. The program can be written such that shaders are used when they are supported by the system, and the program falls back on simpler rendering methods when they are not supported. In this section, we extend our OpenGL program to render the teapot using toon lighting. This is a simple trick to render the teapot using cartoonish colors.

We first create two new text files: one for the vertex shader named teapot.vert and another for the fragment shader named teapot.frag. You can create these files in the directory that has your OpenGL source program.

Copy the following code to the teapot.vert shader file:

varying vec3 normal, lightDir;
void main()
{
lightDir = normalize(vec3(gl_LightSource[0].position));
normal = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = ftransform();
}

Do not worry if you do not know GLSL or cannot understand this code. We are using this shader program only as an example to demonstrate the use of OpenGL extensions. This shader code applies the standard transformations on vertices. In addition, it also notes down the direction of the light and the normal of the vertex. These variables are passed to the fragment shader program which is described next.

Copy the following code to the teapot.frag shader file:

varying vec3 normal, lightDir;
void main()
{
float intensity;
vec3 n;
vec4 color;
n = normalize(normal);
intensity = max(dot(lightDir, n), 0);
if (intensity > 0.97)
color = vec4(1, .8, .8, 1.0);
else if (intensity > 0.25)
color = vec4(.8, 0, .8, 1.0);
else
color = vec4(.4, 0, .4, 1.0);
gl_FragColor = color;
}

Again, do not worry if you do not understand this code. This fragment shader program is executed at every pixel that is generated for display. The result of this program is a color, which is used to draw that pixel. This program uses the light direction and the normal passed from the vertex shader program to determine the light intensity at a pixel. Based on the intensity value, it picks one of three possible shades of purple to color the pixel.

By employing these shader programs, the teapot is rendered in toon lighting like this:

However, to get this output our OpenGL program needs to be modified to compile and load these shader programs.

Step 3 – including the GLEW header file

To be able to call the GLEW API, you need to include the glew.h header file in your OpenGL code. Make sure it is placed above the include files of gl.h, glext.h, glut.h, or any other OpenGL header files. Also, if you include glew.h, you don’t really need to include gl.h or glext.h. This is because GLEW redefines the types and function declarations that are in these OpenGL header files.

#include <GL/glew.h>
#include <GL/glut.h>

Step 4 – initializing GLEW

GLEW should be initialized before calling any of its other API functions. This can be performed by calling the glewInit function. Ensure that this is called after an OpenGL context has been created. For example, if you are using GLUT in your OpenGL program, call glewInit only after a GLUT window has been created. The code shown below initializes GLEW:

GLenum err = glewInit();
if (GLEW_OK != err)
{
printf("GLEW init failed: %s!n", glewGetErrorString(err));
exit(1);
}
else
{
printf("GLEW init success!n");
}

The call to glewInit does the hard work of determining all the OpenGL extensions that are supported on your system. It returns a value of GLEW_OK or GLEW_NO_ERROR if the initialization was successful; otherwise, it returns a different value. For example, if glewInit is called before an OpenGL context was created, it returns a value of GLEW_ERROR_NO_GL_VERSION.

You can find out the cause of a GLEW error by passing the return value of glewInit to the function glewGetErrorString as shown above. This returns a human-readable string that explains the error.

Step 5 – checking if an OpenGL extension is supported

New or enhanced functionality in the OpenGL API is provided by the means of an extension. This typically means that new data types and API functions are added to the OpenGL specification. Details of the name and functionality of any extension can be found in the OpenGL.

In our example, we want our OpenGL program to be able to use GLSL vertex and fragment shaders. This functionality has been provided using extensions that are named GL_ARB_vertex_shader and GL_ARB_fragment_shader. These extensions provide functions to create shader objects, set the shader source code, compile it, link it, and use them with an OpenGL program. Some of the functions provided by this extension are listed below:

glCreateShaderObjectARB();
glShaderSourceARB();
glCompileShaderARB();
glCreateProgramObjectARB();
glAttachObjectARB();
glLinkProgramARB();
glUseProgramObjectARB();

To be able to use these functions in our OpenGL program, we first check if the extension is enabled in our system. Depending on the graphics hardware and drivers on your system, not every OpenGL extension might be available and usable on your system. For example, most versions of Windows support only OpenGL 1.0 or 1.1. The drivers supplied by graphics hardware vendors, such as NVIDIA or AMD for example, might support more recent versions of OpenGL and OpenGL extensions.

Every OpenGL extension has a name of the form GL_VENDOR_extension_name. The VENDOR may be NV, ATI, APPLE, EXT, ARB, or any such supported vendor name. An extension created by a single vendor is called a vendor-specific extension. If it is created by many vendors, it is called a multivendor extension. If many users find an extension to be a good enhancement, it is promoted to an ARB-approved extension. Such extensions might be integrated into future versions of OpenGL as a core feature.

To check for an extension using GLEW, you check if a global boolean variable named GLEW_VENDOR_extension_name is set to true. These variables are defined and their values are set when you initialize GLEW using glewInit. So, to test if vertex and fragment shaders are supported, we add the following code:

if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
{
printf("No GLSL supportn");
exit(1);
}

In this example, we exit the program if these extensions are not supported. Alternatively, you could write the program so that it switches to a simpler or alternate rendering method if the extension you want is not supported.

Summary

This article provided you the details to use GLEW with OpenGL code using a simple example of teapot rendering.

Resources for Article :


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here