Shadowmapped shadows are often aliased. To make shadow edges smoother, interpolate shadow values between shadow map texels.

One way to reduce the "shadow acne" artifact is to render the backfaces of objects into the shadow rather than front faces. This will prevent front faces from self-shadowing (except in very thin objects). Implement this for a whistle.

Come up with another whistle and implement it. A whistle is something that extends the use of one of the things you are already doing. It is part of the basic model construction, but extended or cloned and modified in an interesting way. Ask your TAs to make sure this whistle is valid.

Implement Loop Subdivision for closed, watertight meshes. The skeleton for this bell is already set up in meshprocessing.cpp. For an extra whistle, detect boundary edges on non-watertight meshes and subdivide those appropriately. For an additional bell, add the ability to label a vertex or edge as extraordinary (i.e. preserved on the subdivided mesh) and change the subdivision weights accordingly.

Render a flat mirror in your scene. As you may already know, OpenGL has no built-in reflection capabilities. To simulate a mirror, you'll want to reflect the world about the mirror's plane and then draw the reflected world, before doing the regular scene drawing pass. Use the stencil buffer to make sure that the reflected geometry is clipped inside the boundaries of the mirror. The stencil buffer is similar to a Z buffer and is used to restrict drawing to certain portions of the screen.  See Scott Schaefer's site for more information. In addition, the NeHe game development site has a detailed tutorial.

Build a complex shape as a set of polygonal faces, using triangles (either the provided primitive or straight OpenGL triangles) to render it. Examples of things that don't count as complex: a pentagon, a square, a circle. Examples of what does count: dodecahedron, 2D function plot (z = sin(x2 + y)), etc. Note that using the dodecahedron primitive (or other primitives apart from triangles) does not meet this requirement.

Implement a smooth curve functionality. Examples of smooth curves are here. These curves are a great way to lead into swept surfaces (see below). Functional curves will need to be demonstrated in some way. One great example would be to draw some polynomial across a curve that you define. Students who implement swept surfaces will not be given a bell for smooth curves. That bell will be included in the swept surfaces bell. Smooth curves will be an important part of the animator project, so this will give you a leg up on that.

Implement one or more non-linear transformations applied to a triangle mesh. This entails creating at least one function that is applied across a mesh with specified parameters. For example, you could generate a triangulated sphere and apply a function to a sphere at a specified point that modifies the mesh based on the distance of each point from a given axis or origin. Credit varies depending on the complexity of the transformation(s) and/or whether you provide user controls (e.g., sliders) to modify parameters.

Heightfields are great ways to build complicated looking maps and terrains pretty easily. Implement a heightfield to generate terrain in an interesting way. You might try generating fractals, or loading a heightfield from an image (i.e., allowing the user to design the height of the terrain by painting the image in an image editor and importing it).

Add a lens flare.  This effect has components both in screen space and world space effect.    For full credit, your lens flare should have at least 5 flare "drops", and the transparency of the drops should change depending on how far the light source is from the center of the screen.  You do not have to handle the case where the light source is occluded by other geometry (but this is worth an extra whistle).

x2 Implement shadow-mapping for directional lights. There are many steps to this, but you can refer to the point light shadowmapping code for help:
  1. Look for directional lights in the prerender pass (Scene::RenderPrepass()).
  2. Associate a GLRenderableTexture with each of your directional lights; the equivalent uses of GLRenderableCubemap for point light shadowmaps are in GLRenderer::RenderEnvMaps() and GLRenderer::SetUniforms()
  3. .
  4. Use an orthographic projection of the scene along the direction of the light. This will involve deciding on an orientation of your orthographic projection, and determining the bounds of the scene so that the scene fits into your texture.
  5. Add in the directional light shadowmap as well as any variables defining the orientation as built-in uniforms, and pass them into your shaders as appropriate (bottom of GLRenderer::SetUniforms.
  6. In your Blinn-Phong shader, look up the appropriate ray in the shadowmap to determine shadowing.
x2

Add a function in your model file for drawing a new type of primitive. The following examples will definitely garner two bells; if you come up with your own primitive, you will be awarded one or two bells based on its coolness. Here are three examples:

  • Swept surfaces (this is worth 3 bells) -- given two curves, sweep one profile curve along the path defined by the other. These are also known as "generalized cylinders" when the profile curve is closed. This isn't quite as simple as it may first sound, as it requires the profile curve to change its orientation as it sweeps over the path curve. See this page for some uses of generalized cylinders. This document may be helpful as well, or see the parametric surfaces lecture from a previous offering of this class. You would most likely want to use the same type of curve files as the surface of revolution does. An example would be sweeping a circle along a 2d curve to generate a paper clip.

x2

(Variable) Use some sort of procedural modeling (such as an L-system) to generate all or part of your character. Have parameters of the procedural modeler controllable by the user via control widgets. In a previous quarter, one group generated these awesome results.

x3

Implement projected textures.  Projected textures are used to simulate things like a slide projector, spotlight illumination, or casting shadows onto arbitrary geometry.  Check out this demo and read details of the effect at glBase, and SGI.

x3

Another way to implement real-time shadows is by creating extra geometry in the scene to represent the shadows, based on the silhouettes of objects with respect to light sources. This is called shadow volumes. Shadow volumes can be more accurate than shadow maps, though they can be more resource-intensive, as well. Implement shadow volumes for the objects in your scene. For an extra bell, make it so that shadows work correctly even when your camera is located within a shadow volume.

x3

One difficulty with hierarchical modeling using primitives is the difficulty of building "organic" shapes. It's difficult, for instance, to make a convincing looking human arm because you can't really show the bending of the skin and bulging of the muscle using cylinders and spheres. There has, however, been success in building organic shapes using metaballs. Implement your hierarchical model and "skin" it with metaballs. Hint: look up "marching cubes" and "marching tetrahedra" --these are two commonly used algorithms for volume rendering. For an additional bell, the placement of the metaballs should depend on some sort of interactically controllable hierarchy. Try out a demo application.

Metaball Demos: These demos show the use of metaballs within the modeler framework. The first demo allows you to play around with three metaballs just to see how they interact with one another. The second demo shows an application of metaballs to create a twisting snake-like tube. Both these demos were created using the metaball implementation from a past CSE 457 student's project.

Demo 1: Basic Texture Mapped Metaballs
Demo 2: Cool Metaball Snake