154
edits
Changes
→This Week
: Uniform data
<syntaxhighlight lang="cpp">
#define MLIGHTS 4
#define POINT_LIGHT 0
#define SPOT_LIGHT 1
#define DIRECTIONAL_LIGHT 2
// Types
//
// Light holds the data for a single static light in world space
//
struct Light {
int type; // POINT_LIGHT, SPOT_LIGHT, DIRECTIONAL_LIGHT
float3 ambient;
float3 diffuse;
float3 specular;
float3 direction; // in world space
float3 position; // in world space
float3 attenuation; // .xyz for 1.0f/ (.x + .y * d + .z * d * d)
float3 spot; // .x = cos(phi/2), .y = cos(theta/2), .z = falloff
float range; // where attenuation becomes 0
};
// Material holds the reflectivity properties of the material
//
struct Material {
float4 ambient;
float4 diffuse;
float4 specular;
float power;
};
// Uniform Data (constant for the stream of vertices)
//
// Geometry
float4x4 viewProjection; // view * projection transformation
float4x4 world; // world transformation
float4 viewPoint; // camera viewpoint for specular calcs
float3 heading; // camera heading for specular calcs
int noLights; // no of static lights
Light light[MLIGHTS]; // static lights
bool lightOn[MLIGHTS]; // light switch
// Uniform Data (constant for a stream of fragments)
//
float4 ambient; // global ambient light - always on
Material material; // material reflectivity
bool texOn; // texture switch
texture texMap;
sampler2D tex = sampler_state {
texture = <texMap>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = MIRROR;
AddressV = MIRROR;
};
</syntaxhighlight>
: Varying Data - simple unlit objects
<syntaxhighlight lang="cpp">
//-------------------------------- Simple Unlit Objects -----------------------
//
// UnlitInput holds the original data for a vertex in the stream
//
struct UnlitVSInput {
float3 position : POSITION; // position in local space
float3 normal : NORMAL; // normal in local space
float2 texCoord : TEXCOORD0; // texture coordinates
};
// UnlitOutput holds the transformed data for the vertex
//
struct UnlitVSOutput {
float4 position : POSITION; // position in homogeneous clip space
float2 texCoord : TEXCOORD; // texture coordinates
float3 normal : TEXCOORD1; // lighting normal in world space
float3 toViewer : TEXCOORD2; // direction to viewer in world space
float3 toLight[MLIGHTS] : TEXCOORD3; // light vector
};
// UnlitFSInput holds the input data for a single fragment of the stream
//
struct UnlitFSInput {
float2 texCoord : TEXCOORD0; // texture coordinate at this fragment
float3 normal : TEXCOORD1; // lighting normal in world space
float3 toViewer : TEXCOORD2; // direction to viewer in world space
float3 toLight[MLIGHTS] : TEXCOORD3; // direction from fragment to light i
};
</syntaxhighlight>
: Vertex Shader
<syntaxhighlight lang="cpp">
// unlitVShader transforms vertex and lighting data for simple unlit objects
//
UnlitVSOutput unlitVShader(UnlitVSInput input) {
UnlitVSOutput output; // result returned by this function
// Transform the vertex coordinates to homogeneous clip coordinates
//
// A more efficient algorithm would accept the world*view*projection
// tranformation as one uniform matrix and avoid the 2-stage product
// This will require a bit of restructuring of the application code.
//
output.position = mul(float4(input.position, 1.0), world); // local to world
output.position = mul(output.position, viewProjection); //... to clip
// Determine the vector from this vertex to the viewer
output.toViewer = viewPoint.xyz - input.position;
// Determine the vector from this vertex to light source i in local space
// (assumes that light position and direction are specified in local space)
for (int i = 0; i < noLights; i++)
if (light[i].type == DIRECTIONAL_LIGHT)
output.toLight[i] = - light[i].direction;
else
output.toLight[i] = light[i].position - input.position;
// pass the normal and texture coordinates along unaltered
//
output.normal = input.normal;
output.texCoord = input.texCoord;
return output;
}
</syntaxhighlight>
: Fragment Shader
<syntaxhighlight lang="cpp">
// This fragment shader processes lighting for noLights lights in object space// and returns a pixel colour//float4 unlitFShader(UnlitFSInput input) : COLOR { float4 output; // result returned by this function float3 normal; // normal to the fragment float3 toViewer; // from fragment to the camera float3 toLightSource; // from fragment to current light source // lighting contribution accumulators float3 ambientLight = ambient.xyz; float3 diffuseLight = (float3)0; float3 specularLight = (float3)0; // lighting calculation factors float diffuseFactor, reflectFactor, distance, factor; float attenuationFactor, spotFactor, rho; // normalize the fragment input normal = normalize(input.normal); toViewer = normalize(input.toViewer); // perform calculations for each light in turn for (int i = 0; i <noLights && i < MLIGHTS; i++) { if (lightOn[i]) { // diffuse and reflection factors toLightSource = normalize(input.toLight[i]); diffuseFactor = saturate(dot(normal, toLightSource)); reflectFactor = saturate(dot(normalize(2 * diffuseFactor * normal - toLightSource), toViewer)); /syntaxhighlight>/ attenuation if (light[i].type != DIRECTIONAL_LIGHT) { distance = length(input.toLight[i]); if (distance <syntaxhighlight langlight[i].range) { attenuationFactor ="cpp">light[i].attenuation.x +< light[i].attenuation.y * distance + light[i].attenuation.z * distance * distance; attenuationFactor = 1.0f / attenuationFactor; } else attenuationFactor = 0.0f; } else attenuationFactor = 1.0f; //syntaxhighlight>spot if (light[i].type == SPOT_LIGHT) { rho = saturate(dot(toLightSource, normalize(-light[i].direction))); if (rho <syntaxhighlight lang="cpp">light[i].spot.x) spotFactor = 0.0f; else if (rho <= light[i].spot.y) spotFactor = pow(abs( (rho - light[i].spot.x)/syntaxhighlight><syntaxhighlight lang (light[i].spot.y - light[i].spot.x)), light[i].spot.z); else spotFactor = 1.0f; } else spotFactor = 1.0; factor = attenuationFactor * spotFactor; // accumulate ambient, diffuse, and specular elements of light i ambientLight += factor * light[i].ambient.xyz; diffuseLight += factor * diffuseFactor * light[i].diffuse.xyz; specularLight += factor * light[i].specular.xyz * pow(reflectFactor, material.power); } } // apply material reflectivity to each accumulated element of light // to obtain the colour of the lit fragment // output.xyz = saturate(material.ambient.xyz * ambientLight) + saturate(material.diffuse.xyz * diffuseLight) + saturate(material.specular.xyz * specularLight); output.w ="cpp">material.diffuse.w; // sample the texture< //syntaxhighlight><syntaxhighlight lang if (texOn) output *="cpp">tex2D(tex, input.texCoord); return output;}
</syntaxhighlight>
=== To Do ===
=== Resources ===