CS 381 Fall 2010 > Lecture Notes for Thursday, October 14, 2010 |
I will be discussing how to deal with shaders
using a collection of utility functions by O. Lawlor
(modified by G. Chappell).
These simplify the process of compiling & linking
shaders.
You can find these in any of the shader-using applications
posted on the web page (e.g.,
useshader.cpp
).
The functions are public domain; do anything you want with them.
There is no standard filename extension for GLSL code.
Some people use “.glsl
”.
I will use “...vertex.txt
”
& “...fragment.txt
”.
GLSL code is compiled at application runtime. A pair of compiled shaders (1 vertex shader & 1 fragment shader) is stored in a program object. To do:
makeProgramObjectFromFiles
.
glUseProgramObjectARB
.
glUseProgramObjectARB
sets a GL state:
from now on all data sent through the pipeline
will be processed using the given shaders,
until another such call is made.glUseProgramObjectARB(0)
.
See
useshader.cpp
for a C++ application that uses shaders.
In order to execute it, you will need separate text files
holding the shader source,
as well as a machine with programmable graphics hardware,
and the GLEW package installed.
See
plain_shaders.zip
for examples of shaders.
These shaders are intended for use with
useshader.cpp
.
Pre-declared OpenGL-related variables, types, and constants are named as
gl_CamelCase
(e.g. gl_ModelViewProjectionMatrix
).
Note that, in GLSL, model/view is two words.
Struct members are camelCase
(e.g. spotDirection
).
Unfortunately, there are no consistent naming conventions
for other built-in GLSL functions and types.
However, all are either
lowercase
(e.g., inversesqrt
)
or camelCase
(e.g., lessThanEqual
).
float
,
int
,
bool
.struct
, as in “C”.vec4
is 4-vector of float
s.
Similarly vec2
, vec3
.
Use ivec4
, etc., for int
s,
and bvec4
, etc., for bool
s.
mat4
is 4×4 matrix of float
s.
Similarly, mat3
.
Lots of other options available, but these two are the ones
we use most.Vector types have very nice syntax. Component access using the bracket operator and three kinds of dot notation:
// The 4 lines below are equivalent, for v of type vec4 v[0], v[1], v[2], v[3] v.x, v.y, v.z, v.w v.r, v.g, v.b, v.a // think colors: Red, Green, Blue, Alpha v.s, v.t, v.p, v.q // based on standard names for texture coords
Multiple letters can follow a dot.
v1.xz = v2.zy; // Above is equivalent to: v1.x = v2.z; v1.z = v2.y;
Also:
v1.xy = v1.yx; // Swap 1st 2 components of v1
Can also do fancy initialization.
vec3 w1; vec4 w2 = vec4(w1.yxz, 1.0);
C++-style constructor syntax is not available.
vec3 a(1.,2.,3.); // NO! vec3 a = vec3(1.,2.,3.); // Yes
There are implicit conversions from simple to vector types.
For example, converting a float
with value 2.1
to a vec3
will result in the vector
<2.1, 2.1, 2.1>.
Some example code:
vec3 u = 1.; // Same as vec3 u = vec3(1., 1., 1.); vec3 v = u - 2.; // Save as vec3 v = u - vec3(2., 2., 2.);
vec3
-vec4
Conversion
If you do just about anything with a location in space
(other than multiplying a 4 × 4 matrix by it
or setting gl_Position
equal to it),
then it needs to be a vec3
.
But, of course, OpenGL provides positions as vec4
values.
We can convert as follows:
// Convert vec4 -> vec3 vec4 opengl_vertex; vec3 my_vertex = opengl_vertex.xyz / opengl_vertex.w; // Convert vec3 -> vec4 vec4 opengl_vertex_again = vec4(my_vertex, 1.0);
As in “C”:
if
...else
,
also while
, etc.,
break, continue, function calls.
Execution begins at function main
,
which should take no parameters and return void
.
Additional keywork: discard
.
This is legal only in a fragment shader.
It means to toss out this fragment,
so that it does not go on to the framebuffer.
const
. Compile-time constant.
const int x = foo();
”
is NOT standard-conforming.
(However, some compilers will accept it.)attribute
. Applied to globals in a vertex shader.
Means per-vertex input from application.uniform
. Applied to globals in a vertex or fragment shader.
Means per-primitive input from application.varying
. Applied to globals in
both vertex and fragment shaders.
Means output from vertex shader and input to fragment shader.
Value for each fragment is computing by linear interpolation.
Using attribute
and uniform
values is tricky,
since you have to do something in both the shader
and the application.
We will discuss these later.
However, using
varying
values is easy.
Simply declare a global variable, with same type and name,
using the varying
qualifier,
in both the vertex and fragment shaders.
// In vertex shader varying vec3 myPos; // In fragment shader varying vec3 myPos;
Note that
a position in space, communicated as a varying
,
should be a vec3
, not a vec4
.
Convert between the two as described above.
See
vary_shaders.zip
for shaders that use varying
.
These shaders are intended for use with
useshader.cpp
.
Some pre-declared variables.
gl_Vertex
. Is attribute of type vec4
.
Params to glVertex*
command.gl_ModelViewMatrix
,
gl_ProjectionMatrix
,
glModelViewProjectionMatrix
.
Are uniforms of type mat4
.gl_FrontColor
, gl_Color
.
Varying of type vec4
.
Former is output of vertex shader.
Latter is input to fragment shader.
(There is also gl_BackColor
,
but it is ignored by default.
Later we will discuss this further.)gl_Position
. Varying of type vec4
.
The vertex shader must set this.gl_FragColor
. Type vec4
.
Output of the fragment shader.Some built-in functions.
log
, exp
, etc.radians(d)
, degrees(r)
. Conversions.s*v
, m*v
, m*m
.
Various multiplications: scalar mult of vectors,
matrix-vector product, matrix-matrix product.dot(u,v)
, cross(u,v)
.
Products of vectors.length(v)
, distance(u,v)
,
normalize(u,v)
. Vector operations.mix(x,y,t)
. Linear interpolation.reflect(v,n)
. Reflection.
n
is normal vector of surface.
Also refract
.A short general review of the first half of the course was done.
ggchappell@alaska.edu