Howto:Shader programming in FlightGear
|This article is a stub. You can help the wiki by|
This is meant to become an introduction to shader programming in FlightGear, for the time being (03/2010), this is work in progress, please feel free to ask questions or suggest topics.
Your help in improving and updating this article is appreciated, thanks!
Tutorials about GLSL Programming in general are collected at GLSL Shader Programming Resources for a quick reference, please see: http://www.khronos.org/files/opengl-quick-reference-card.pdf.
GLSL (OpenGL Shading Language) is the official OpenGL shading language and allows you to write programs, so called "shaders" that are uploaded and executed on the GPU (processor of the graphics card).
GLSL, also known as GLslang, is a high level shading language based on the C programming language. It was created to give developers more direct control of the graphics pipeline without having to use assembly language or hardware-specific languages.
With the recent advances in graphics cards, new features have been added to allow for increased flexibility in the rendering pipeline at the vertex and fragment level. Programmability at this level is achieved with the use of fragment and vertex shaders.
GLSL is a C-like hi-level language to create OpenGL fragment (pixel) and vertex shaders. To make it simple, a shader is a program that is loaded on the GPU and called for every vertex or pixel: this gives programmers the possibility to implement techniques and visual effects and execute them faster. In modern games lots of shaders are used: lights, water, skinning, reflections and much more.
To really understand shaders, you should have a knowledge about the rendering pipeline; this helps to understand where and when the shaders act in the rendering process. In general, you must know that vertex are collected, processed by vertex shaders, primitives are built, then are applied colors, textures and are also called fragment shaders; finally it comes to the rasterization and the frame is put on the buffer.
Some benefits of using GLSL are:
- Cross platform compatibility on multiple operating systems, including Linux, Mac OS and Windows.
- The ability to write shaders that can be used on any hardware vendor’s graphics card that supports the OpenGL Shading Language.
- Each hardware vendor includes the GLSL compiler in their driver, thus allowing each vendor to create code optimized for their particular graphics card’s architecture.
While GLSL has a C-Like syntax, it introduces new types and keywords. To get a detailed view of the language, please see the GLSL specification you can find on http://www.opengl.org/documentation/glsl/
The OpenGL Shading Language provides many operators familiar to those with a background in using the C programming language. This gives shader developers flexibility when writing shaders. GLSL contains the operators in C and C++, with the exception of pointers. Bitwise operators were added in version 1.30.
Similar to the C programming language, GLSL supports loops and branching, including if, else, if/else, for, do-while, break, continue, etc.
User defined functions are supported, and a wide variety of commonly used functions are provided built-in as well. This allows the graphics card manufacturer the ability to optimize these built-in functions at the hardware level if they are inclined to do so. Many of these functions are similar to those found in the math library of the C programming language such as exp() and abs() while others are specific to graphics programming such as smoothstep() and texture2D().
GLSL shaders are not stand-alone applications; they require an application that utilizes the OpenGL API. A shader is a program, to be run it must be loaded, compiled and linked. Actually each vertex and fragment shader must have one entry point (the main function) each, but you can create and link more shaders.
GLSL shaders themselves are simply a set of strings that are passed to the hardware vendor’s driver for compilation from within an application using the OpenGL API’s entry points. Shaders can be created on the fly from within an application or read in as text files, but must be sent to the driver in the form of a string.
GLSL has explicit ties to the OpenGL API - to the extent that much of the OpenGL 'state' (eg which light sources are bound, what material properties are currently set up) is presented as pre-defined global variables in GLSL.
There are two types of shaders in GLSL: vertex shaders and fragment shaders.
So, shaders generally go around in pairs - one shader (the "Vertex shader") is a short program that takes in one vertex from the main CPU and produces one vertex that is passed on to the GPU rasterizer which uses the vertices to create triangles - which it then chops up into individual pixel-sized fragments. The other shader (the "Fragment shader" - also known (incorrectly) as the "Pixel shader") take one pixel from the rasterizer and generates one pixel to write or blend into the frame buffer.
The vertex shader runs from start to end for each and every vertex that's passed into the graphics card - the fragment process does the same thing at the pixel level. In most scenes there are a heck of a lot more pixel fragments than there are vertices - so the performance of the fragment shader is vastly more important and any work we can do in the vertex shader, we probably should.