| |
|
|
||||
![]() |
||||||
| |
|
|||||
|
A Non-Integer Power Function on the Pixel Shader Applications
This instruction loads dest with src1 or src2 depending whether src0 is positive or not. If we consider this instruction with values of src1 = 1 and src2 = 0, we obtain the function illustrated at Figure 7.
Since the conditional instructions can only take one of two values, they often produce jaggy-edge artifacts. In fact, some neighboring pixels end up having very different colors because they sit on the threshold of the condition. To overcome this problem, we can use the function illustrated at Figure 8. We call such a function a smooth conditional because it smoothly and rapidly goes from one value to the other as some threshold is crossed.
The function illustrated in Figure 8 corresponds to the following mathematical formula:
This formula can be computed on the pixel shader using the code of Listing 12. This code is similar to the one of Listing 9. The difference is that it uses two extra cmp instructions, one for the absolute value and one for the condition x>0. Also, note that the last mul has a _x2 multiply instruction modifier although it should be considered as a 4 in the Multiplier table when generating A' and B'. This is done in order to account for the multiplicative factor in the term 0.5 (1 - |x|)n appearing in the formula.
Listing
12. Code to perform a smooth conditional function We can use the above code to build a smooth conditional selection between two arbitrary values src1 and src2. To do so, we simply add a lrp instruction at the end of the previous pixel shader. This linear interpolation is made to map 0 to src1 and 1 to src2. The result is a function that mimics the standard cmp in a smooth fashion. The presented
code requires a lot of instructions; however we can co-issue them if we
want the smooth conditional to act only on the alpha channel. Moreover,
the simplified asymmetric shape of Figure 9 often constitutes a good enough
smooth conditional for x>0. Given that the input x is
saturated (greater or equal to 0) then this function can be expressed
as 1-(1-x)n.
Other variations
on the smooth conditional pixel shader code allows for various other arithmetic
tests. In fact, the simple power function xn can be
considered as the smooth conditional for x>1. So let's see how we can build a pixel shader that equals 1 for pixels within some radius r of a point P and smoothly goes to 0 for pixels outside this radius. First, for each vertex, we'll require a vector R that joins point P to the vertex. This vector needs to be scaled so that its length equals 1 for a vertex that is exactly at distance r from P. We place the vector P in texture coordinates 0. We will directly use this vector, therefore no texture needs to be bound to stage 0. We then select the approximation exponent m for the power function used in the smooth conditional. In the presented example, we take m = 4. The multiply instruction modifier _x4 was used with each instruction. Since we use a fixed exponent n for the shader, we place A' and B' in constant registers c0 and c1. The pixel
shader of Listing 13 uses this technique to apply a simple diffuse lighting
equation to all pixels within some radius of a given point. The diffuse
color is placed in interpolated color v0,
texture 1 contains the decal texture to apply and texture 2 holds an extra
diffuse light map. A constant ambient factor is stored in constant register
c2. More complex effects
could use the pixel shader same trick in order to limit themselves to
a volume. Also, more complex volumes could be devised by applying some
per vertex or per pixel process on P. ps.1.0
add
r0.rgb, v0, t2 ;
Compute diffuse lighting by adding v0 and t2
Listing
13. Code to perform volume bounded pixel shader lighting Phong Shading One of the
major problems of per pixel lighting resides in computing the specular
component of the final color. This component is due to the reflection
of the light itself on a shiny material. It is easy to see that the reflection
of a point light on a perfectly shiny sphere is a single point. Unfortunately,
very few surfaces are perfectly shiny. To account for non-perfect reflections,
sometimes called dull reflection, Phong (and Warnock before him) introduced
a very popular model. This model relies on the use of a power function
where the exponent depends on the shininess of the material. We will now show how, using the power function algorithm exposed earlier, we can perform realistic per pixel Phong shading including a normal map, a color diffuse texture map, a color specular texture map, and a shininess map. Phong
Equation with Blinn Half-Vector Before we
can express this equation, we need to detail the variables that are needed.
First, the shading depends upon the light direction, described by unitary
vector L. We also need to know the surface normal at the shading
point, noted N. Finally, we need to use some vector to compute
the specular component. Like it is often the case for per pixel shading,
we do not directly use the Phong equation. Instead we take the Blinn half-vector
H, that is the unitary vector falling directly between the view
direction V and the light direction L. Figure 10 illustrates
these vectors.
When using normal mapping, we distinguish between the perturbed normal used for lighting, noted N' and the real surface normal noted N. The scalar values that are needed for the computation are the ambient, diffuse and specular coefficients noted respectively MAmbc, MDiffc, and MSpecc for the material, and LAmbc, LDiffc, and LSpecc for the light. Here the index c is R, G or B to indicate one of the color components. The shading equation can now be written as:
Expressing
the Inputs First, we suppose that the light ambient, diffuse and specular coefficients do not vary from one pixel to the next. This means that the algorithm proposed cannot handle slide-projectors or other kinds of textured lights. We also suppose that the material ambient coefficients do not vary arbitrarily from pixel to pixel. Instead, these are linked to the material diffuse coefficients using the equation MAmbc = KAmbc *MDiffc, with KAmbc constant within the shader. The equation states that the ambient color is always the same as the diffuse color up to some constant. This is not a very limiting assumption since this relationship between material ambient and diffuse coefficients is often witnessed in practice. The three coefficients MDiffc and exponent n can vary from pixel to pixel and therefore need to be expressed in a four-component, 2D texture map. Recall that we do not store n directly, instead we place the corresponding value A' in the texture's fourth component. Coefficients MSpecc can also vary at each pixel and can be placed in a separate three-component, 2D texture. These coefficients act as a color gloss map, effectively an extension of the traditional single-component specular gloss map. The perturbed normal N' is expressed as a tangent-space normal map. We therefore use a 2D texture map containing color-encoded normalized vectors that can be accessed using a single 2D texture look-up. We refer the reader to other real-time shading texts to learn more on tangent space normal maps. To effectively use a tangent-space normal map in our lighting equation, we need to have a normal map representation of the light vector L and halfway vector H. As discussed earlier, the halfway vector needs to be renormalized per pixel; otherwise important visual artifacts will occur when the power function is applied. We therefore interpolate H through a texture coordinate and use a cube map look-up to renormalize it. A renormalization cube map, as illustrated in Figure 11, contains a color-encoded vector in each texel corresponding to the unitary vector pointing in the direction of that texel.
Once the light vector is only used in linear computations, not renormalizing it has almost no impact on the visual result. Therefore, we skip per pixel renormalization in order to make the best usage out of our texture resources. This means that we can store the light vector L in an interpolated color.
|
||||||||||||||||||||||||||||||||||||||||
|
|