PrtPerVertex Direct3D Sample |
This sample demonstrates how to use PrtEngine, a precomputed radiance transfer (PRT) simulator that uses low-order spherical harmonics (SH). The sample also demonstrates how to use these results to accomplish dynamic light transport using a dynamic lighting environment and a vs_1_1 vertex shader.
Source: | (SDK root)\Samples\Managed\Direct3D\PrtPerVertex |
---|---|
Executable: | (SDK root)\Samples\Managed\Direct3D\Bin\x86\csPrtPerVertex.exe |
PRT using low-order SH basis functions has a number of advantages over typical diffuse (N * L) lighting. Area light sources and global effects such as interreflections, soft shadows, self shadowing, and subsurface scattering can be rendered in real time after a precomputed light transport simulation. Clustered principal component analysis (CPCA) allows the results of the simulator to be compressed so the shader does not need as many constants or per-vertex data.
The basic idea is first to run a PRT simulator offline as part of the art content creation process and to save the compressed results for later real-time use. The light transport simulator models global effects that would typically be very difficult to do in real time. The real-time engine evaluates the lights in terms of SH basis functions and sums them up into a single set of SH basis coefficients describing the entire lighting environment. It then uses a vertex shader to arrive at the vertex's diffuse color by combining the compressed simulator results and the lighting environment. Because the offline simulator did the work of computing the interreflections and soft shadows, this technique is visually impressive, efficient, and can be used for real-time lighting.
The sample performs both the offline and real time portions of PRT. The startup dialog box asks the user which step to perform. The user can run the offline simulator or view a mesh using previously saved results from the PRT simulator. The offline step would typically be done in a separate tool, but this sample does both in the same executable file.
The first step is to run the offline per vertex PRT simulator in the PRTSimulator.cs source file. This code accepts a number of parameters to control the operation of the simulator, an array of meshes, and an array of SphericalHarmonicMaterial structures. One material is allowed per mesh, so each mesh is assumed to be homogenous. The simulator's input parameters and the members of the SH material structure are explained extensively by the sample dialog's tooltips. If you want to pass in more than one mesh, before you do so the meshes need to be transformed into the same coordinate space.
Most of the simulator input parameters do not affect how the results are used. In particular sample's Order parameter does affect how to use the results, specifying the order of SH basis functions that are used to approximate transferred radiance.
In addition to the Order parameter, the spectral parameter (spectralCB) also affects the results. If spectral simulation is chosen, there will be three color channels - red, green, and blue. However, sometimes it is useful to work just with one channel (when modeling shadows, for example). If you choose non-spectral simulation, you simply use the red channel when calling the SH functions, because the other channels are optional.
The simulator will run for a period of time, typically minutes, that depends on the complexity of the meshes, the number of rays, and simulation settings. The output is a GraphicsStream object that contains an internal header and an array of float values for each vertex of the mesh.
The float values for each vertex, called radiance transfer vectors, can be used by a vertex shader to transform source radiance into exit radiance. However, since there are Order2 transfer coefficients per channel, then with spectral and Order = 6 there would be 3 x 36 or 108 scalars per vertex. Fortunately, you can compress this large number of scalars with the CPCA algorithm. The number of coefficients per vertex will be reduced to the number of principal component analysis (PCA) vectors, and this number does not need to be large for good results. For example, four or eight usually yields good results. For example, if there are eight PCA vectors and Order = 6, then you will only need eight coefficients per vertex instead of 108. The number of PCA vectors must be less than Order2.
The equation to render compressed PRT data is:
where:
Parameter | Description |
---|---|
Rp | A single channel of exit radiance at vertex p and is evaluated at every vertex on the mesh. |
Mk | The mean for cluster k. This is an Order2 vector of coefficients. |
k | The cluster identifier (ID) for vertex p. |
L' | The approximation of the source radiance into the SH basis functions. This is an Order2 vector of coefficients. |
j | An integer that sums over the number of PCA vectors. |
N | The number of PCA vectors. |
wpj | The jth PCA weight for point p. This is a single coefficient. |
Bkj | The jth PCA basis vector for cluster k. This is an Order2 vector of coefficients. |
The sample's PRTMesh.cs source file collects all of the data needed for this equation and passes the appropriate data to a vertex shader that implements the equation, as follows:
int clusterBasisSize = (numberPcaVectors + 1) * numberCoefficients * numberChannels;Note that one is added to the number of PCA vectors to store the cluster mean. Also note that since both (Mk * L') and (Bkj * L') are constant, the sample calculates these values on the CPU and passes them as constants to the vertex shader. The sample stores this per-vertex data in the vertex buffer.
prtConstants = new float[ numberClusters * (4 + numberChannels * numberPcaVectors) ];This array is passed directly to the vertex shader with the Effect.SetValue method. Note that the vertex shader uses float4 because each register can hold four float values, so on the vertex shader side the array is of size:
int numberVConsts = numberClusters * (1 + numberChannels * numberPcaVectors / 4) + 4;Evaluating the lights, and calculating and setting the constant table, are rapid procedures that can be done once or more per frame, but for optimization purposes the sample only evaluates lighting effects when the lights are moved.
(SDK root)\Samples\Light Probes
For more detail about the math behind PRT, CPCA, and SH, see the following references:
Send comments about this topic to Microsoft. © Microsoft Corporation. All rights reserved.
Feedback? Please provide us with your comments on this topic.
For more help, visit the DirectX Developer Center