In Review
Prev | Chapter 13. Lies and Impostors | Next

## In Review

In this tutorial, you have learned the following:

- Impostors are objects who's geometric representation has little or no resemblance to what the viewer sees. These typically generate an object procedurally by cutting fragments out to form a shape, and then use normals to do lighting computations on the cut-out.

- Fragments can be discarded from within a fragment shader. This prevents the outputs from the shader from being written to the final image.

- Ray tracing can be employed by a fragment shader to determine the position and normal for a point. Those values can be fed into the lighting equation to produce a color value.

- Fragment shaders can change the depth value that is used for the depth test and is written to the framebuffer.

- Geometry shaders are a shader stage between the vertex shader and the rasterizer. They take a primitive as input and return one or more primitives as output.

### Further Study

Try doing these things with the given programs.

- Change the geometry impostor tutorial to take another vertex input: the material to use. The vertex shader should pass it along to the geometry shader, and the geometry shader should hand it to the fragment shader. You can still use `gl_PrimitiveID` as the way to tell the fragment shader. Regardless of how you send it, you will need to convert the value to an integer at some point. That can be done with this constructor-like syntax: `int(value_to_convert)`.

### Further Research

This is an introduction to the concept of impostors. Indeed, the kind of ray tracing that we did has often been used to render more complex shapes like cylinders or quadratic surfaces. But impostors are capable of much, much more.

In effect, impostors allow you to use the fragment shader to just draw stuff to an area of the screen. They can be used to rasterize perfect circles, rather than drawing line-based approximations. Some have even used them to rasterize Bézier curves perfectly.

There are other impostor-based solutions. Most particle systems (a large and vibrant topic that you should investigate) use flat-cards to draw pictures that move through space. These images can animate, changing from one image to another based on time, and large groups of these particle can be used to simulate various phenomena like smoke, fire, and the like.

All of these subjects are worthy of your time.

### GLSL Features of Note

discard

  This fragment shader-only directive will cause the outputs of the fragment to be ignored. The fragment outputs, including the implicit depth, will not be written to the framebuffer.

gl_VertexID

  An input to the vertex shader of type int. This is the index of the vertex being processed.

gl_FragDepth

  An output from the fragment shader of type float. This value represents the depth of the fragment. If the fragment shader does not use this value in any way, then the depth will be written automatically, using `gl_FragCoord.z`. If the fragment shader writes to it somewhere, then it must ensure that all codepaths write to it.

gl_PrimitiveID

  A geometry shader output and the corresponding fragment shader input of type int. If there is no geometry shader, then this value will be the current count of primitives that was previously rendered in this draw call. If there is a geometry shader, but it does not write to this value, then the value will be undefined.

gl_PrimitiveIDin

  A geometry shader input. It is the current count of primitives previously processed in this draw call.

`void EmitVertex(`

Available on in the geometry shader, when this function is called, all output variables previously set by the geometry shader are consumed and transformed into a vertex. The value of those variables becomes undefined after calling this function.

Prev | Up | Next
Purloined Primitives | Home | Glossary