You might be interested in my OpenGL notes.
What is GLSL?
The newer versions of OpenGL (later than 2.0) support (and may even insist upon) using a shading language. This is a completely separate and specialized programming language used to create "shaders". These shaders are sent to the rendering engine (usually the hardware managed by the GPU) where they are compiled and used to modify how the rendering process is accomplished. I think of these so called shaders as simply the programs that run on that other computer you’re hopefully using, the GPU. While somewhat flexible, GLSL is a language that is very focused on the tasks needed to be done by a GPU. It is to the GPU hardware what JavaScript is to a web browser.
There are a few kinds of shaders:
Helpful Tips
Here’s a way to get Vim to highlight GLSL.
Here is an astonishingly good resource that allows composing different shader experiments in a web sandbox with the ability to output the code to Cpp.
Different Shaders
The following are the valid types of shaders as implied by the enum
parameter to the glCreateShader()
function.
- GL_VERTEX_SHADER
-
This seems to be applied to the geometry of the objects being rendered. I’m not sure really what exactly it does except to ostensibly "shade" vertices.
- GL_GEOMETRY_SHADER
-
This is a less used kind of shader (it’s optional) that is often not even listed in pipeline diagrams. It’s only officially been in OpenGL since version 3.2. Maybe it is used to get effects like hair or fur or plant parts, things which move around the basic points of an object but which are mostly visual. Or maybe it’s designed to distort the view port as in the Oculus Rift’s required barrel distortion. I don’t know yet. New information: It has access to all the vertices in a primitive. The outputs of the vertex shader would be the inputs for the geometry shader and the outputs of the geometry shader can be the inputs for the fragment shader. One application would be to plot the surface normals of a bunch of triangles.
- GL_FRAGMENT_SHADER
-
This seems to be applied to regions of pixels as opposed to geometric coordinates. This seems to happen once the geometry is established and entire regions (which I think are what fragments are) are rendered to screen pixels. Need to make the entire scene sunny or gloomy? Then this is the shader to concentrate on.
- GL_COMPUTE_SHADER
-
No idea.
- GL_TESS_CONTROL_SHADER
-
No idea. Presumably "tess" is for tessellation.
- GL_TESS_EVALUATION_SHADER
-
No idea.
See glCreateShader() for the official details.
Functions For Shader Setup
These are the functions generally needed to set up a rendering pipeline’s shaders in roughly right order:
General Syntax
GLSL is pretty similar to C stylistically. Commenting is the same. The statements end in a semi-colon. Types are strictly declared.
Variable Types
Since the GLSL is a full working programming language, it has a selection of usable data types.
- bool
-
Can be
true
orfalse
. Specify with:bool ok= false
- int
-
Signed integer. Specify with:
int temp= 68
- uint
-
Unsigned integer. Specify with:
uint speed= 70u
- float
-
Floating point. Specify with:
float ratio= 3.5f
- bvec2,bvec3,bvec4
-
Vector of booleans.
bvec2=(true,false)
- ivec2,ivec3,ivec4
-
Vector of integers.
- uvec2,uvec3,uvec4
-
Vector of unsigned integers.
- vec2,vec3,vec4
-
Vector of floats.
Storage Qualifiers
The variables can be declared with storage qualifiers. The main one is
uniform
for values passed in from the client which will not change
in the shader. There are in
and out
which governs variables that
are coming from another or going to another processing stage, i.e.
another shader. You can also specify variables with const
if they’re
specific to the shader program and are not going to change during the
its operation. There are also in centroid
, out centroid
, and
inout
but these seem exotic. I’ve also seen varying
in programs
used as a storage qualifier.
With vector types, you can do something called "swizzling" which looks like:
avectype.x= 1.0f;
avectype.yz= (2.0f,3.0f);
doubled= avectype * 2.0f;
The vector type subcomponents are xyzw
or rgba
or stpq
for
working on geometry, colors, or textures respectively. BTW, nobody
seems to know what the letters stpq
stand for.
GLSL Built-In Functions
Can one define GLSL functions? I don’t know that yet. There are quite a few handy functions available to use right away in GLSL. In some ways it’s kind of convenient to be able to count on your graphics hardware to know how to do the normal graphics things without calling special libraries in your program. Here are some available functions:
-
radians(), degrees()
-
sin(), asin(), sinh(), asinh()
-
cos(), acos(), cosh(), acosh()
-
tan(), atan(), tanh(), atanh()
-
pow(), exp(), exp2()
-
log(), log2()
-
sqrt(), inversesqrt()
-
length(vec), distance(v1,v2), normalize(vec)
-
dot(v1,v2), cross(v1,v2), faceforward()
-
reflect() refract()
-
matrixCompMult(), outerProduct()
-
transpose(), determinant(), inverse()
-
lessThan(vec), greaterThan(vec)
-
lessThanEqual(), greaterThanEqual()
-
equal(), notEqual()
-
any(vec) [or], all(vec) [and], not(vec)
-
abs(), sign(), floor(), trunc(), round(), ceil(), fract()
-
mod(), modf()
-
min(), max(), clamp()
-
mix(), step(), smoothstep()
-
isnan(), isinf()
-
floatBitsToInt(), floatBitsToUint(), intBitsToFloat(), uintBitsToFloat()
User Defined Functions and Control Structures
It looks like you can program your own functions in GLSL. The syntax is very much like C.
GLSL seems to support if
, else if
, and else
constructions and
they look exactly like C’s.
Although less common, I’ve seen for
loops working fine too. They too
are exactly like C.
There is also a preprocessor which can do some of the things the C preprocessor its syntax is based on can do.
Here is an example that shows a function definition, local variables,
a for
loop, and if
syntax:
// Comments look like this. #ifdef GL_ES precision mediump float; #endif #define CUTOFF 0.001 float shadow(vec3 x1, vec3 x2){ float s= 0.0; float p= 0.0; for(int i= 0; i < 25; i++) { p= myHelper(x1 + x2 * s); if (p < CUTOFF){ return 0.5; } s += p; } return 1.0; }