Archive for June, 2010

Register assignment in HLSL

Sunday, June 27th, 2010

When you are manually assigning shader constants to registers (using a ‘register’ keyword), those registers are also taken out of the automatic assignment pool.
This means that constants that don’t have explicit registers will never overlap with ones that do even if latter are not used in the shader.
And so code like this:
float4 c0 : register(c0);
float4 c1 : register(c2);
float4 c2;
float4 main():POSITION
{
    return c2;
}

Will compile into this:
vs_2_0
mov oPos, c1

This is a pretty small thing, but still quite convenient and useful to know.

Spherical Harmonics in games

Saturday, June 19th, 2010

Here is everything you really need to know about spherical harmonics to use them in games:

0. Spherical Harmonics are not scary at all :)
1. An Efficient Representation for Irradiance Environment Maps
2. Spherical Harmonics in Actual Games
3. Spherical Harmonic Lighting: The Gritty Details
4. DirectX SDK samples contain all the C++ and HLSL code that you might need to get started.

C++ code to calculate shader constants for evaluation on GPU:
IrradianceVolume\PRTMesh.cpp, CPRTMesh::ComputeSHIrradEnvMapConstants()

HLSL code to evaluate SH for a given normal:
IrradianceVolume\SHIrradianceEnvMap.fx

Also, DirectX SDK comes with a bunch of functions to get you going quickly. For example there is D3DXSHProjectCubeMap(), which generates spherical harmonic coefficients from a given cubemap.

PS: There one thing to keep in mind, though: SH are not the only option for storing lighting information. One great alternative is Valve’s Ambient Cube (page 28), which gives quality somewhere between 2-band and 3-band SH.