Section A.7. Shading Language


A.7. Shading Language

The OpenGL Shading Language (commonly referred to as GLSL), added to OpenGL version 2.0, allows applications to replace portions of the rendering pipeline with vertex and fragment shadersprograms executed on a per-vertex and per-fragment basis that directly control the rendering process. The OpenGL Shading Language is the most revolutionary enhancement to OpenGL since its inception.

Applications replace portions of the OpenGL rendering pipeline with vertex and fragment shaders. Vertex shaders replace texture-coordinate generation; transformation of vertices, normals, and texture coordinates; and lighting operations. Fragment shaders replace texture mapping, fog, and color sum operations.

Applications for shaders are innumerable and still an area of active research. Shaders can be used to create rendering effects such as per-fragment lighting, animated and procedural texturing, geometric and image morphing, soft shadow effects including percentage closer filtering, non-Lambertian surfaces and bidirectional reflectance distribution functions (BRDFs), and bump mapping, not to mention any part of the fixed function OpenGL pipeline they replace, such as texture-coordinate generation, cube mapping, fog, and traditional per-vertex lighting.

To use the OpenGL Shading language, perform the following steps:

1.

Write vertex and fragment shader programs using the OpenGL Shading Language. Developers usually keep shader source in separate files, though they can be added as string constants in the application source itself.

2.

Load shader source into shader objects, and issue an OpenGL command to compile them.

3.

Combine shader objects into program objects, and link them.

4.

Set the linked program object shader executable in current state. Subsequent rendering operations are processed by the shader instead of the OpenGL fixed functionality pipeline.

5.

At render time, set appropriate values for any uniform variables used by the shader programs.

A.7.1. A Shader Example

Figure A-1 shows an image produced with a simple GLSL fragment shader. The shader reduces the texel color value by one-half if the texture coordinate falls within a circle centered at st (0.5, 0.5), producing a dark circle in the center of each face of a cube. The shader also implements the color sum operation to produce specular highlights with the secondary color.

Figure A-1. A cube rendered with a simple fragment shader.


Listing A-1 shows the fragment shader used to produce Figure A-1. Note that a vertex shader isn't required to produce this effect; the fixed function per-vertex operations compute the input values to the fragment shader.

Listing A-1. A simple OpenGL Shading Language fragment shader

 uniform sampler2D texMap; void main(void) {     vec4 color = texture2D( texMap, gl_TexCoord[0].st );     const vec2 tc = gl_TexCoord[0].st - .5;     if (tc.s*tc.s + tc.t*tc.t < .15)         color *= .5;     gl_FragColor = color * gl_Color + gl_SecondaryColor; } 

OpenGL produces fragments during rasterization of each face of the cube. To process these fragments with the fragment shader, the application must install a program object containing a fragment shader using the glUseProgram() command.

The fragment shader in Listing A-1 contains a single function, main(), which uses a single uniform variable, texMap. texMap uses the GLSL type sampler2D. Shaders use sampler types such as sampler2D to access textures in texture objects. The application needs to associate a texture object with a sampler2D uniform variable.

The shader uses some predefined variables. gl_TexCoord is an array of four-element vectors (vec4). Each element of gl_TexCoord is the interpolated strq texture coordinates for the current fragment. gl_Color and gl_SecondaryColor are the primary and secondary color values for the current fragment. With lighting enabled, the fixed function pipeline calculates lighting values per vertex. The rasterization stage interpolates these values, and effectively stores the results of ambient and diffuse lighting in gl_Color and specular lighting in gl_SecondaryColor. gl_FragColor is a fragment shader output variable and represents the final color of the fragment.

The first line of the shader obtains the texture color value corresponding to the s and t texture coordinates from the texMap sampler and stores the color in a four-element vector variable called color.

The next three lines of code check to see whether the s and t values have a squared distance less than 0.15 from the center (0.5, 0.5). If so, the shader multiplies color by 0.5, effectively dimming it by 50 percent.

The final line of code computes the final color value by modulating color with the fragment primary color and performing the color-sum operation by adding the secondary color. The code writes the result of this computation to gl_FragColor.

A.7.2. More Information

OpenGL® Shading Language (the orange book) is an excellent GLSL programming guide and reference. Note that in its current edition, the book documents the ARB extensions for use with GLSL rather than the OpenGL version 2.0 interface. There are significant differences between the two interfaces. Besides cosmetic command-name changes (glCreateShaderObjectARB() versus glCreateShader()), shader and program object identifiers are also different. The ARB extension defines a type GLhandleARB, whereas the version 2.0 interface uses the more traditional GLuint type for identifiers.

The OpenGL Shading Language (Kessenich 2004) is the formal GLSL specification, and can be downloaded for free as a PDF file from the OpenGL Web site. Finally, Section 2.15, "Vertex Shaders," and Section 3.11, "Fragment Shaders," of The OpenGL Graphics System document the OpenGL API for creating and using shaders.




OpenGL Distilled
OpenGL Distilled
ISBN: 0321336798
EAN: 2147483647
Year: 2007
Pages: 123
Authors: Paul Martz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net