Where: Room 1.05 in CSSE
and online (active in consultation hour)
Try to complete this lab during the lab session and, if
you fall behind, complete it in
your own time.
lab2
folder to lab3
lab3
folder - but still go back and read
the code in the lab 2 and lab 1 folders as needed. You can even
copy code fragments over to this weeks code.
An example of really a lot of points:
glDrawArrays
. Take a copy of the code (C++ and GLSL) for Q1 and
change it so that, instead of the uniform variable time
,
the sin and cos of the angle are calculated in the C++
program and passed as uniform float
variables
sinAngle
and cosAngle
to the vertex shader.
Make and run this program. (You may not actually see much difference in performance, but it's generally good to avoid recalculating things, and this change is also a step towards the general approach to transformations in OpenGL via matrices.)
cos
tells you how much the original (x or y) coordinate affects the same coordinate when rotated. sin
tells you how much the original (x or y) coordinate affects the other coordinate when rotated.
(It's negative in the line for the x coordinate above because the y-axis when rotated clockwise moves towards
the negative x-direction.)
Suppose we want to separately say how much x affects x, x affects y, y affects x and y
affects y. Then we'll have 4 separate numbers - arrange these in a 2 by 2 matrix and
pass them to the shader instead of the sin and cos values. (Start with a copy of your
code prior to experimenting with scaling.)
Hint: you can construct and pass the 2 by 2 matrix via:
mat2 multipliers_mat = mat2( vec2(cos(angle), -sin(angle)), vec2(sin(angle), cos(angle)) ); glUniformMatrix2fv( multipliers, 1, GL_TRUE, multipliers_mat );
This requires that multipliers
be a global variable set via
glGetUniformLocation
during initialisation to link to a
uniform mat2
variable in the vertex shader which
replaces sinAngle
and cosAngle
.
Similarly, replace the uses of sinAngle
and cosAngle
with:
multipliers[0][0]
for the x multiplier affecting the x coordinate,
multipliers[0][1]
for the y multiplier affecting the x coordinate
(replacing also the -ve since instead it's in the matrix),
multipliers[1][0]
for the x multiplier affecting the y coordinate,
multipliers[1][1]
for the y multiplier affecting the y coordinate,
multipliers *
vPosition.xy
. Verify
that the code works the same when you put the following in the vertex shader: gl_Position.xy = multipliers * vPosition.xy;
Example image with different scaling for the multipliers affecting the x and y coordinates. (And optional colour.):
Hint: the x coordinates
should stay constant, and the y and z coordinates should rotate in the same way as
the x and y coordiantes did in the previous parts.
Note: the z coordinate will actually have no effect, for now, but later it will
when we also do hidden surface removal and perspective projection.
Without perspective
projection (we have an orthographic projection), it means that far objects
occupy just as much of the screen as close ones. This gives a less realistic
3D effect, although it does accurately model the situation where the viewer
is distant relative to the size of the objects, and orthographic projections
are generally prefered for technical drawing in engineering and architecture.
Hint: The z-coordinates passed to the vertex shader should always be zero.
Hint: The coordinate that isn't being rotated should have 1 in the matrix for its effect on itself, and zeros for the effects on itself by the other coordinates, as well as zeros for its effects on the other coordinates. For the coordinates that are being rotated it should do similarly to the 2D rotations above.
Unzip this so that you have lab3-soln
under your labs-examples
folder, then build using make as usual.