2. What Is an Extension?
An OpenGL extension is really just that; an
extension to the OpenGL standard. In fact, just
like OpenGL, each extension is recorded in a
specification document. This document
describes, in detail, some extra functionality that
allows you to render faster, in better quality or
more easily. Extensions allow graphics card
vendors to quickly provide access to the most
cutting-edge features of their chipsets, without
waiting for updates to the OpenGL specification.
3. Extension Naming
PREFIX_extension_name
Prefix is the vendor name.
Name Strings
glGetStringi()
the name string for an extension is the extension name prefixed
by GL_, WGL_ (for Windows extensions), GLX_ (for X
extensions), or GLU_ (for extensions to the GLU library).
4. Functions and Tokens
Extensions can add new functions, new tokens
each function is prefixed by a lower case ‘‘gl’’
the rest of the function name uses a capital letter at the
beginning of each word
Ex : glFunctionNameARB()
token :is a constant or enumerant such as
GL_TEXTURE_2D or GL_FLOAT
should be all capital letters, with spaces replaced by
underscores and prefixed with GL_
Ex: GL_SOME_NEW_TOKEN_ARB
6. Obtaining a Function’s Entry
Point
You need to link to them dynamically at runtime
Querying the graphics drivers for a function pointer to the
function you want to use. This is platform specific, but the
general idea is the same on all platforms.
7. Steps
First, you must declare a pointer to a function .
Next, you call a platform- specific function to find the
address of the function you want, and assign it to the
function pointer
If the function pointer is NULL after this call, then the
extension that provides the function is not available.
8. Steps cont.
PFNGLGETSTRINGIPROC is the typedef for the function
pointer type
On Windows, we use the wglGetProcAddress() function for this
(on X you would use glXGetProcAd- dress())
PROC wglGetProcAddress(LPCSTR lpszProcName);
Code ex:
glGetStringi=(PFNGLGETSTRINGIPROC)wglGetProcAddress("
glGetStringi");
if (glGetStringi != NULL) { //We can use glGetStringi
}
9. Extensions on Windows
on the Windows platform, you must use
extensions to access any functionality
after OpenGL 1.1
10. Finding Supported Extensions
You can get available extensions by using glGetStringi()
and passing GL_EXTENSIONS as the first parameter.
11. WGL Extensions
There are some extensions that are specific to the
Windows system
wglGetExtensionsStringARB()
const char* wglGetExtensionsStringARB(HDC hdc);
This function differs from glGetStringi() in that it returns the
extension strings as a space-delimited list.
12. Defining Tokens
#define GL_HALF_FLOAT_NV 0x140B
Notice that we prefix the GL_ to the constant defined in
the specification to match the naming convention of the
other tokens.
15. The main functionality
deprecated
Color Index mode
OpenGL shading language versions 1.10 and 1.20 (now replaced with 1.30) n Immediate
mode
Fixed-function vertex processing
Matrix stacks
Client vertex arrays
Rectangles
Raster position
Non-sprite points
Wide lines and line stipple
Quadrilateral and polygon primitives
Separate polygon drawing mode
Polygon stipple
Pixel drawing
Bitmaps
Texture wrap mode—GL_CLAMP
Display lists
The selection buffer
The accumulation buffer
Alpha test
Attribute stacks
Evaluators
Unified extension string
16. Most of the above functionality is
now implemented using shaders,
and some parts (such as the
matrix stack) can be
implemented in separate libraries
17. What Is GLSL?
GLSL or the OpenGL Shading
Language is used to write
programs that run on the GPU
18. Main types of shaders
Vertex shaders: which operate on every vertex sent to the
graphics card.
Fragment (also known as pixel) shaders: which operate
on every pixel to be rasterized.
You effectively replace whole sections of the pipeline.
19.
20. Vertex Shaders
Vertex shaders are programs that operate on each vertex that is
sent to the graphics card by a rendering command such as
glDrawArrays()
The responsibility of this shader to calculate the final position of
the vertex.
Calculate per-vertex attributes such as colors
Vertex shader only knows about a single vertex at a time
It is not possible to extract information on neighboring vertices.
The only output that is required by a vertex shader is the
position
21. You will need to manually handle the following:
Vertex transformation (using modelview and projection
matrices)
Texture coordinate generation
Lighting calculations
Color application
Normal transformation
22. Fragment Shaders
It is the job of the fragment shader to calculate the final
output color of a pixel that will be stored in the frame
buffer
23. With Fragment shader you must handle the following
parts:
Computing per-pixel colors
Applying textures
Calculating per-pixel fog
Applying per-pixel lighting
24. The GLSL Language
There have been three versions of GLSL since its
introduction
1.10
1.20
1.30
25. Shader Structure
A GLSL shader must contain at least a single function
called main().
Any output that the shader generates is passed via
variables which have a qualifier of out
Variables that are passed into or out of a shader must be
declared in global scope
27. Variables
GLSL variables obey rules of scope
Global scope (at the top of the shader)
Variable can exist across more than one shader (program
scope)
28. Data Types
GLSL is a statically typed language
GLSL also has some other base types specific to shader
programming (vectors, matrices).
29.
30. initialize a variable (int i = 0;)
vectors and matrices are made up of multiple components
These elements can be addressed individually by adding a
period (.) to the variable name and then using the component
name to select a component
Matrix components are accessed using the array-style notation
(mat4[column][row])
you can define arrays of variables in GLSL
vec3 array[3];
The length of an array can be determined later in the shader by
using the built-in length()
float array[3];
int arrayLength = array.length();
31. Structures
struct Light { vec3 color;
vec3 position };
Light firstLight;
firstLight.color = vec3(0.0, 1.0, 2.0);
It is illegal to nest a structure declaration inside another structure
struct B {
struct A { //Invalid!
int a; };
};
32. perfectly fine for a structure to contain an instance of another
structure
struct A { int a; } struct B {
A a; // OK.
};
33. Operators
On types such as vectors that are made up of several
components
the operators work on a component-by-component basis
The one exception is multiplications involving matrices,
which work using standard linear algebra rules.
38. Uniforms
A variable with a uniform qualifier has its value passed
into the shader from the application and remains constant
between the shader stages
Uniforms cannot be the target of an assignment inside the
shader
They can be accessed by all stages of the shader
program if the variable is declared identically in each
shader
glUniform*()
39. Vertex Attributes
A vertex attribute is a regular global variable marked with
the in qualifier in a vertex shader.
glVertexAttribPointer()
40. Statements
GLSL contains the same flow control statements that you
find in C and C++.
It is not legal to define a variable inside an if statement
41. Constructors
GLSL data types have built-in constructors that can be used to
create new variables initialized with data
Not only to initialize new variables, but also to copy data from a
variable of one type to another
out vec4 ourColorOutput;
void main(void)
{
vec3 color = vec3(1.0, 0.0, 0.0); //A 3-element vector initialized with a
constructor
//A constructor is used to copy the data to a 4-element vector
ourColorOutput = vec4(color, 1.0); }
42.
43. Swizzling
Some constructors allow you to pass in more than one type of
argument to construct an object of the sum of their components
vec4 fourVec(1.0, 2.0, 3.0, 4.0);
vec3 threeVec = vec3(fourVec.y, fourVec.z, fourVec.w);
vec4 fourVec(1.0, 2.0, 3.0, 4.0);
vec3 threeVec = fourVec.yzw;
Swizzling works on all vector types, and you can use any
combination of component names from the same name set
(xyzw, rgba, or stpq)
44. Defining Functions
Function declarations differ from C in that each parameter
may include one of the following qualifiers: in, out, inout,
or const (whereas C only has const).
Functions in GLSL can be overloaded.
45. Built-in Functions
Some of these functions are simple convenience functions
you could write yourself
Others provide access to hardware functionality which is
impossible to recreate manually
46. Using Shaders
To use GLSL programs in your code, you need to use the C API
functions that were promoted to core in OpenGL 2.0.
1. Create the shader objects—This will normally consist of creating
a program object and two shader objects (fragment and vertex).
2. Send the source to OpenGL—The source for each shader is
associated with the corresponding shader objects.
3. Compile the shaders.
4. Attach the shaders to the program object.
5. Link the program.
6. Bind the program ready for use.
7. Send any uniform variables and vertex attributes. 8. Render the
objects that use the program.
47. Creating GLSL Objects
The first thing to do to prepare our GLSL program for use
is to generate the objects that hold the state of the
program in OpenGL
There are two types of object :
shader objects
program objects
48. program objects
hold infor- mation relating to the GLSL program as a
whole.
GLuint glCreateProgram(void); //To create the program
objects
49. shader objects
hold the source code and data belonging to the vertex or
fragment shaders
glCreateShader() //To create the shader objects.
GLuint glCreateShader(GLenum type);
Currently, the type parameter can be either
GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
50. shader objects
To send the shader source code to OpenGL
void glShaderSource(GLuint shader, GLsizei count, const
GLchar **string, const GLint *length);
count is the number of strings in this array
length is an array that stores the character length of the strings
in the string array
If length is NULL, all strings in the array are assumed to be null-
terminated
To compile shaders
void glCompileShader(GLuint shader);
51. shader objects
To find out whether compilation of the shader was
successful
void glGetShaderiv(GLuint shader, GLenum pname, GLint
*params);
EX:
GLint result;
glGetShaderiv(shaderObject, GL_COMPILE_STATUS,
&result);
52.
53. To attach shader
void glAttachShader(GLuint program, GLuint shader);
//If you attempt to attach the same shader to the program
twice, OpenGL generates a GL_INVALID_OPERATION error
To detach shader
void glDetachShader(GLuint program GLuint shader);
54. Ready to link the GLSL
program
Linking may fail for a number of reasons:
One of the shader objects hasn’t compiled successfully.
The number of active attribute variables has exceeded the
number supported by the OpenGL implementation.
The number of supported or active uniform variables has been
exceeded.
The main function is missing from one of the attached shaders.
An output variable from the vertex shader is not declared
correctly in the fragment shader.
A function or variable reference cannot be resolved.
A global variable shared between stages is declared with
different types or initial values.
55. You link a program by using the following function:
void glLinkProgram(GLuint program);
To retrieve infor- mation on a program object, you use
glGetProgramiv()
void glGetProgramiv(GLuint program, GLenum pname, GLint
*params);
56.
57. To enable a GLSL program
void glUseProgram(GLuint program);
This will bind and enable the program
Any primitives sent to OpenGL while the program is
enabled will use the attached shaders for rendering
If you pass 0 as the program parameter, then shader will
be disabled.
58. Sending Data to Shaders
Passing Data to Uniforms
Passing Data to Vertex Attributes
59. Passing Data to Uniforms
Each GLSL implementation has a limited number of
locations to store uniform variables
The GLSL implementation determines which uniform goes
in which location
Before you can send data to a uniform, you must first find
out its location
GLuint glGetUniformLocation(GLuint program, const GLchar*
name);
60. To send the data to Uniform :
void glUniform{1|2|3|4}{f|i}(GLint location, TYPE v); void
glUniform{1|2|3|4}ui(GLint location, TYPE v);
void glUniform{1|2|3|4}{f|i}v(GLint location, GLuint count, const
TYPE *v); void glUniform{1|2|3|4}uiv(GLint location, GLuint count,
const TYPE *v);
count is the number of values in the array
v is a pointer to an array containing the data
void glUniformMatrix{2|3|4}fv(GLint location, GLuint count,
GLboolean trans- pose, const GLfloat *v);
void glUniformMatrix{2x3|3x2|2x4|4x2|3x4|4x3}fv(GLint location,
GLuint count, GLboolean transpose, const GLfloat *v);
Transpose: If you have stored your data in column-major order then
you need to pass GL_FALSE to transpose; otherwise, pass
GL_TRUE.
61. Passing Data to Vertex
Attributes
Attributes in GLSL are variables that are defined in the
vertex shader with the in qualifier
You can either let OpenGL determine which location to
store the attribute or you can specify it manually
OpenGL determine which location :
GLint glGetAttribLocation(GLuint program, const GLchar*
name);
the program needs to have been linked for this function to
work.
62. Specify the location of the attributes yourself :
void glBindAttribLocation(GLuint program, GLuint index,
const GLchar* name);
Calls to glBindAttribLocation() should be made before
linking the GLSL program
Attribute zero is special and should always be used for the
vertex position.
63. send the data to the attribute using glVertexAttribPointer():
void glVertexAttribPointer(GLuint index, GLint size,
GLenum type, GLboolean normalized, GLsizei stride,
const GLvoid *pointer);
index is the location of the attribute
size indicates the number of components per element (this can
be between one and four)
Type GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,
GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGN ED_INT,
GL_FLOAT, or GL_DOUBLE.
normalized flag is true then data will be converted to a floating-
point value between -1.0 and 1.0 (for signed values) or 0.0 and
1.0 for unsigned values
stride specifies the offset in bytes between attributes in the array
pointer is a pointer to the array of data to send to the attribute
using VBOs (which you should be!), this should be an integer
offset in bytes into the currently bound buffer.
64. Vertex attributes must be enabled before rendering
void glEnableVertexAttribArray(GLuint index);
The attributes can be disabled with :
void glDisableVertexAttribArray(GLuint index);
65. Calculating Vertex
Transformations
// First multiply the current vertex by the modelview matrix
vec4 pos = modelview_matrix * vec4(a_Vertex, 1.0);
// Then multiply the result by the projection matrix
gl_Position = projection_matrix * pos;
66. Applying Colors
two-step process.
vertex shader, you must read the input attribute that
contains the color for the vertex. You must pass this to
your fragment shader using an out variable
the color will be interpolated before the input to the
fragment shader
In the fragment shader, you can pass this color directly out
as the final color, or you can perform some logic to
change the color
67. Handling Your Own Matrices
The Kazmath Library
One feature that the library provides is its own matrix
stack
Notes de l'éditeur
To get a list of all extensions supported by the OpenGL implementation, you must iterate from 0 to NUM_EXTENSIONS – 1 calling glGetStringi() each time with the new index. But how big is NUM_EXTENSIONS? To find out, you need to pass GL_NUM_EXTENSIONS to glGetIntegerv()
Note:For a variable to exist between shaders, it must be declared with the correct qualifiers in both shaders (e.g., in and out)