ECE4893A/CS4803MPG: Multicore and GPU Programming for Video Games
Homework #3: Now You Are Thinking with Shaders
Due: Wednesday, Nov. 7 at 23:59:59 (via T-square)
Late policy: The homework will be graded out of 80 points. We will
accept late submissions up to Friday, Nov. 9 at 23:59:59; however,
for every day that is it is overdue (including weekend days),
we will subtract 20 points from the total.
(We understand that sometimes multiple assignments hit at once, or other
life events intervene, and hence you have to make some tough choices. We’d
rather let you turn something in
late, with some points off, than have a “no late assignments
accepted at all”
policy, since the former encourages you to still do the assignment
and learn something from it, while the latter just grinds down your soul.)
homework will guide you through a series of tasks that explore various
creative possibilities of shader programming. Each task will involve modifying
code from the “XNAShader” demo on the class website. Some of the problems
build off of the same base code,
so you will probably want to be working on a copy of the code, since
these problems are not meant to be cumulative, e.g., Problem 3 has you add
a spotlight effect to one of the programs, and Problem 5 has you add a pulsing
mesh effect to the same program, but Problem 5 isn’t intended to also have
a spotlight effect in addition to the pusling.
As you work through the problems, paste your code and screenshots into
a single Microsoft Word document.
You only need to provide
the parts of code that you modify; i.e. you don’t necessarily have to paste
in an entire function. Include enough information so
that I can tell what functions
the code you show is included in, perhaps including a few lines of code before or
after to provide context.
You may use something that isn’t
Microsoft Word as long as it can output PDF files.
1) Modify the “TwoShadingTeapot”
demo — both the per-vertex (Gourard style)
and the per-pixel (Phong style) shaders — to
employ a simple form of
shading. Gooch shading attempts to mimic some
techniques that artists use,
particularly in technical illustrations, where
the goal is to convey information, and not necessarily be “photorealistic.”
Instead of the usual diffuse lighting,
select vertex color by linearly interpolating between blue (0,0,1)
and yellow (1,1,0) according to the formula (1+L.N)/2, where L is the light
direction, N is the surface normal, and the period indicates a dot
product. Note this formula varies between 0 and 1; 0 should give blue,
1 should give yellow. Note that unlike with usual diffuse shading, surfaces
will be visible (as blue) even if no light impacts it. Please deactivate
(however you wish) the specular and ambient components of the lighting.
(If you dig into
Gooch’s paper, you will see that what I have described and ask you to
implement is the simplest and most jarring form of Gooch shading; the paper
discusses combing this with the usual diffuse shading term and other
interesting tricks. You need not
do any of that here, but you may find it interesting reading).
Take a screenshot that shows both teapots. Try to use
a screenshot that clearly shows the difference in quality between
per-vertex and per-pixel lighting.
2) Modify the “NoLightCubeHLSL” demo to implement a simple form
of “depth cueing.”
Like Gooch shading, depth cueing is a nonphotorealistic technique that
may help CAD designers when, for instance, viewing complex wireframe models
(although here we’re not using wireframe models). Here, we will make
parts of the cube that are further away appear darker than those that
are close. Instead of just
painting the texture, found from tex2D(textureSample,input.TexCoord),
multiply it by a depthFactor originally
calculated in the vertex shader by a line like:
output.depthFactor = max(0,min(1,(e-output.Position.z)/(e-s)));
where e and s
representing the starting and ending coordinate of
the depth cueing effect (i.e. anything beyond e is not seen, anything
closer than s looks the same).
Note my use of the word “originally” above — we want to do this computation
in the vertex shader, and then have the hardware automatically interpolate
these depth factors for us and pass these interpolated values on to the pixel
shader. So you’ll need to add another line to the VertexShaderOutput
structure, that “hijacks” a register such as
TEXCOORD1 to pass this information along.
Normally e and s would be passed in from
the main application through variables, but to keep things simple,
you can “hard code” these into your shader code.
Experiment with values of e and s for your particular scene to get
a good illustration of the depth cueing effect; you will want to experiment
with using the up and down keys to move the cube away and towards you, and
probably try e and s values in the 1 to 8 range, with
e greater than s.
Take a screenshot that clearly shows the depth cueing effect.
(If you look
at the C# code you’ll see there’s commands for slowing down the spin rate
of the cube,
which may be useful in setting this up.)
3) Make the “OneLightTeapotHLSL” demo moodier by
incorporating a spotlight effect.
In particular, see
the “Spotlight Effect” slide in the “Lighting & Rasterization” lecture.
multiply the intensity from the max(dot(normal,light),0)
calculation already given
in the code by this spotlight term.
For a spotlight, we
need to think of it as pointed in a particular direction; we’ll assume the
spotlight is always pointed at (1,0,0) in world coordinate space,
so the spotlight is aimed a little to the side. (In this
assignment, for simplicity,
you can “hard code” the
spotlight aim point into your shader code; the right software engineering
thing to do would be to include this information in the Lights class, but
that’s overkill for what we need here.)
In the spotlight formula in the lecture slides, the vectors must be normalized,
so you’ll need to do another call to normalize. Choose a power sufficiently
high that the spotlight effect is quite dramatic. I found that I had to use
a very high power, on the order of three digits!
Take a screenshot that clearly shows the spotlight effect.
4) Modify “OneLightCubeHLSL” to make the texture wave in a strange
Instead of just using input.TexCoord
in the texture lookup in the pixel shader,
you should first add a time-varying function of the form
A*sin(B*input.TexCoord.y)*sin(C*time) to the the xcoordinate of
the ycoordinate of input.TexCoord.
You will need to declare time as a uniform extern variable
in your shader code and set it to something like
gameTime.TotalGameTime.Milliseconds in your Draw() method.
the deformation in x is determined by the y coordinate, and the deformation
in y is determined by the x coodinate.
A and D control the amount of
B and E sort of set the distance
between “deformation valleys”,
C and F control the speed. Pick A to be
different than D, B to be different than E, and C to be different than F.
(These parameters can be “hard coded” into your shader code.)
You will need to experiment a lot with those settings
to get something interesting and useful.
When you run it, you should see the picture morph in strange oscillatory
ways. Experiment with various values of the parameters.
Take a screenshot that illustrates the wavy effect.
5) Modify “OneLightTeapotHLSL” so that the teapot is a creepy pulsating
staypuff marshmellow teapot.
OK, what in the world do I mean by that? Here we’ll pass in a time
variable as in Problem 5, but instead of varying the texture coordinates,
we will vary the vertex positions. Before the line that performs the
gWVP transformation, put in a line like this:
input.Position += A * input.Normal * (1+sin(B*time))
This will make each vertex bulge out along the direction of its normal in a
creepy pulsating staypuff marshmellow teapot sort of way. Experiment with
A and B (you can “hard code” these) until you get something that you think look
awesome. (As an aside, it’s also fun to drop the “1+” in the equation above,
which will cause the teapot to kind of implode in on itself during the sine
Take a screenshot of the awesomeness; make sure the screenshot shows some
Not a problem, but an interesting aside: Check out Section 8.4.4
on Valves’ “Half Lambert Diffuse” lighting in this paper on
in Valve’s Source Engine.
Deliverables: Assemble your HLSL code and screenshots in an orderly
fashion into a single Microsoft
Word document or PDF file (using whatever tools you wish to create a PDF).
For each problem above, give the code, then give the screenshot. You only
need to show code for shaders that you modified; i.e. if you had to modify
the vertex shader but not the fragment shader, you need only show the vertex
shader (and vice-versa).
Include “HW3” and as much
as possible of your full name in the
filename, e.g., HW3_Aaron_Lanterman.doc. (The upload
procedure should be reasonably self explanatory once
you log in to T-square.)
Be sure to finish sufficiently in
advance of the deadline that you will
be able to work around any troubles
T-square gives you to successfully
submit before the deadline. If you have
trouble getting T-square to work,
please e-mail your compressed
file to Prof. Lanterman at firstname.lastname@example.org,
with “MPG HW #3” and your full
name in the header line;
use this e-mail submission as a last resort if T-square isn’t working.
You are welcome to discuss
high-level implementation issues
with your fellow students,
but you should avoid actually looking at
one another student’s
code as whole, and
under no circumstances should you be copying
any portion of another student’s code.
However, asking another student to
focus on a few lines of your code discuss
why a you are getting a particular
kind of error is reasonable.
Basically, these “ground rules” are
intended to prevent a student from
“freeloading” off another student,
even accidentally, since they
won’t get the full yummy nutritional
educational goodness out of the assignment if they do.
code from homeworks done in previous years is strictly prohibited.