Graphics Reference
In-Depth Information
In the geometry shader, we first declare that the maximum number of vertices will be 3,
since we are only generating one triangle primitive with each invocation. In addition, we
declare that we want 2 instances of each primitive to be created with the instance function
attribute. To process the primitive being sent to the geometry shader, we begin by initial-
izing the order and direction variables that will be used to determine if we are processing
the front or back paraboloid. This is determined by the id input attribute, which is the SV_
GSInstancelD system value semantic. We choose the paradigm such that when the id is 0,
we are working on the front paraboloid, while a value of 1 indicates that we are working
on the back paraboloid. 3 If we are working on the back paraboloid, we simply switch the
ordering of the vertices by swizzling its components, and we then set the direction variable
to -1. Then the input primitive vertices are only accessed using the order variable, which
allows for a simple way to choose the right winding order. 4
The next step is to loop through each of the vertices of the primitive and perform
the paraboloid projection on them. This is done by calculating a projFactor, which is
essentially the z-component of the vector to the vertex (which was generated in the vertex
shader) multiplied by the direction variable, and added to 1. The multiplication by the di-
rection variable will convert the negative half-space into the positive half-space when we
are processing the back paraboloid. Then, the addition of 1 is actually performing the addi-
tion of the view vector from Equation (13.7). Since we are working in the paraboloid basis,
the incident vector (or view vector) is (0,0,1), so adding it to the vertex direction vector is
the same as adding 1 to its z-component. We then use the resulting proj Factor to divide
the x and y components, which produces the output location within the paraboloid map.
The available range of the results of these components provides values that vary between
(-1,1) for both the x- and the y -coordinates, which fits nicely into the clip space positions
that must be provided for the rasterizer stage.
Another useful point to consider is that any vertices that exist in the other half-space
(when the positive z -valued vertices are being processed in the negative half-space, and
vice-versa), they will end up with a negative depth value. We can see this by considering
the two possible cases. When geometry exists in the positive half-space around the parabo-
loid basis and we are processing the positive half-space paraboloid map, then the vertices'
z-values will be positive and will be rasterized, while any geometry in the negative half
space will be culled. In the opposite case, we are processing the negative half space. The
direction variable is used to change any negative z-values to positive values, and the vertex
3 The terms front and back here only refer to the orientation of the paraboloids, which is determined by the view
matrix that is passed into the vertex shader. The paraboloid maps themselves can be viewed from any angle,
regardless of their orientation, so the choice of basis can be made in whatever way is convenient. Many imple-
mentations choose to use a world-space-aligned orientation to simplify the implementation, but we include the
transformation in the vertex shader for flexibility in choosing the basis.
4 Since the built-in vector data types can be accessed with array-like syntax, we can swizzle the components
of the vector with the member syntax (xyz -> xzy) and then use the vector variable like an array (order[0],
order[l], and so forth).
Search WWH ::




Custom Search