OpenGL Shading Language

From OpenGL.org
Revision as of 19:28, 22 August 2009 by Alfonse (Talk | contribs) (Adding infobox.)

Jump to: navigation, search
OpenGL Shading Language
Core in version 4.5
Core since version 2.0
ARB extension GL_ARB_shader_objects, GL_ARB_vertex_shader, GL_ARB_fragment_shader, GL_ARB_shading_language_100

The OpenGL Shading Language (GLSL) is a high level shading language with a C-like syntax. It was approved by OpenGL Architecture Review Board (ARB) for programming OpenGL compliant programmable hardware, thus giving developers more control of the graphics pipeline at the lowest level.

Background

The first forms of programmable GPUs appeard with the nVidia TNT series and with them came the nVidia register combiners (NV_register_combiners) for programming them. Though register combiners were not strictly a programming language they did give the programmer more freedom in terms of manually setting up the fragment end of the pipeline and doing cool effects, that were previously achieved in software for educational purposes and were too slow to be commercially viable.

Later on more support for fragment pipeline setup was provided in the form of NV_register_combiners2, NV_texture_shader, NV_texture_shader2 and NV_texture_shader3.

NVidia, later on came up with vertex programs (NV_vertex_program) with their Geforce 3 series. Vertex programs were much more convenient and provided the programmers with an assembly language for programming the GPU and loading those programs via an API.

Over the years different efforts from different IHVs (Independent Hardware Vendors) were combined and finally resulted in ARB_vertex_program (approved by ARB in June, 2002) and ARB_fragment_program (approved by ARB in September, 2002), and ATI was the first IHV to support them with their Radeon 9700 card.

In the meantime 3DLabs had been considering options to "overhaul" the OpenGL API, dubbed OpenGL 2.0. This was supposed to be the first major revision of the API since OpenGL 1.1 back in the mid-90s. This was necessary because they were competing with, what was becoming an extremely popular API for games, DirectX 9.0 from Microsoft. Alongwith other proposals, one of the major component was a high level shading language that would provide the programmer with a high level syntax for programming the GPU. Dubbing it OpenGL Shading Language (GLSL) the proposal was presented to ARB and was finally accepted in June 2003 (OpenGL 1.5). New extensions (ARB_shading_language_100, ARB_shader_objects, ARB_vertex_shader, ARB_fragment_shader) were introduced which gave birth to GLSL 1.00 in June, 2003.

In September, 2004 (SIGGRAPH) OpenGL 2.0 specifications were released by the ARB with GLSL 1.10 as the shading language (a few modifications from GLSL 1.00).

Details

Data types

The OpenGL Shading Language Specification defines 22 basic data types, some are the same as used in the C programming language, while others are specific to graphics processing.

  • void – used for functions that do not return a value
  • bool – conditional type, values may be either true or false
  • int – a signed integer
  • float – a floating point number
  • vec2 – a 2 component floating point vector
  • vec3 – a 3 component floating point vector
  • vec4 – a 4 component floating point vector
  • bvec2 – a 2 component Boolean vector
  • bvec3 – a 3 component Boolean vector
  • bvec4 – a 4 component Boolean vector
  • ivec2 – a 2 component vector of integers
  • ivec3 – a 3 component vector of integers
  • ivec4 – a 4 component vector of integers
  • mat2 – a 2X2 matrix of floating point numbers
  • mat3 – a 3X3 matrix of floating point numbers
  • mat4 – a 4X4 matrix of floating point numbers
  • sampler1D – a handle for accessing a texture with 1 dimension
  • sampler2D – a handle for accessing a texture with 2 dimensions
  • sampler3D – a handle for accessing a texture with 3 dimensions
  • samplerCube – a handle for accessing cube mapped textures
  • sampler1Dshadow – a handle for accessing a depth texture in one dimension
  • sampler2Dshadow – a handle for accessing a depth texture in two dimensions

Apart from these built-in data types, user defined data types in the form of C structs are also supported. Refer to the GLSL specifications.

Operators

GLSL provides many built-in operators for built-in data types. There is no need for the programmer to manually write overloaded operators (which is not supported anyway). Built-in common math operators like assignment, comparison, equality etc. are provided. Logical operators like logical and and or are also supported. Bitwise operators, although a part of the language (reserved tokens), are currently not supported as part of the GLSL 1.10 specifications. GLSL 1.20 specifications, however, promise a support for these operators. Refer to the official GLSL specifications for more details.

Control Structures

All sorts of C like control structures like if-else statements and loops are supported. Note that goto is not supported. Refer to the official GLSL specifications for more details.

Functions

Functions are also supported in GLSL. User-defined functions are supported and the standard GLSL library (GLSL stdlib) provides many built-in functions for performing mathematical and other graphics operations. This gives IHVs, the liberty to perform hardware specific optimizations for built-in functions.

Compiling and Executing

GLSL shaders are not standalone applications. Like all other shading languages they require a host application to load and execute them. All major languages like C, C++, C#, Delphi, Java, VB and many others support OpenGL and therefore the host application can be written in any of these languages. GLSL shaders are simple text programs and the host application uses OpenGL API to compile and execute these shaders on the graphics hardware.

GLSL compiler is provided by the driver, which does not require the application to pre-compile the GLSL code into assembly. High level GLSL code can be compiled directly by the driver using OpenGL API calls. The compiled code can then be uploaded to the hardware. Refer to GLSL specifications for more information.

Caveats and Common Problems

Vendor specific compiler, has its pros and cons. Vendors can have their own assembly and the compiler compiles GLSL code to that assembly. They can also have vendor specific optimizations both in the compiler and the code generation, depending on their hardware. However, non-standard GLSL compilers from vendors can result in non-portable GLSL code e.g. a shader compiled using compiler from Vendor A may not compile on a compiler from Vendor B if it contains some non-standard syntax that was allowed by Vendor A's compiler and not supported by Vendor B. Non-standard, does not necessarily mean a subset of the standard, it can easily be the superset of the standard, allowing high(er) level syntax, not supported by the standard.

To remedy this problem 3DLabs released GLSLvaidate that is a standalone fully GLSL standard compliant compiler which can compile and check your code for syntax errors. A shader compiled with GLSLvalidate is guaranteed to be GLSL standard compliant and should compile on any driver supporting the minimal GLSL syntax.

A sample trivial GLSL Vertex Shader

void main(void)
{
    gl_Position = ftransform();
    //The above is for GLSL 1.00, 1.10, 1.20
    //Below, is for GLSL 1.30
    //Define your own uniforms!!!
    //Define your own vertex attribute!!!
    //gl_Position = ProjectionModelviewMatrix * AttrVertex;
}

The minimal job a fully working vertex shader must do is pass on a vertex position by transforming it from object coordinates to eye coordinates using the modelview matrix, and to clip coordinates by transformation with the projection matrix. Here is such a minimal shader:

void main(void)
{
    gl_Position = gl_ProjectionMatrix*gl_ModelViewMatrix*gl_Vertex;
    //The above is for GLSL 1.00, 1.10, 1.20
    //Below, is for GLSL 1.30
    //Define your own uniforms!!!
    //Define your own vertex attribute!!!
    //gl_Position = ProjectionModelviewMatrix * AttrVertex;
}

A sample trivial GLSL Fragment Shader

void main(void)
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

The minimal fragment shader must set the gl_FragColor. If you just want to pass on the fragment color without modifying it, then the minimalist example would look like this:

void main(void)
{
    gl_FragColor = gl_FrontColor;
    //For GLSL 1.30, do not use gl_FrontColor. Define your own varying variable
}

References

See also

External links