Rendering People and Clothing
http://developer.nvidia.com/object/doc_characters.html
http://www.virtualcinematography.org/
http://http.developer.nvidia.com/GPUGems/gpugems_ch16.html
http://graphics.cs.ucdavis.edu/~bcbudge/ecs298_2004/General_BSDFs_BSSDFs.ppt
http://www.macs.hw.ac.uk/texturelab/people/exchange_students/spence/
http://www.graphics.cornell.edu/pubs/2006/IM06.pdf
http://www.irit.fr/~Loic.Barthe/Publications/GI2007_Claustres_et_al.pdf
http://developer.nvidia.com/object/BRDFbased_Lighting.html
http://www.cs.ucl.ac.uk/staff/j.kautz/GameCourse/
http://developer.amd.com/media/gpu_assets/Oat-Wrinkles(Siggraph07).pdf
http://drp.disneyresearch.com/projects/cloth/
http://www.virtualcinematography.org/
http://http.developer.nvidia.com/GPUGems/gpugems_ch16.html
http://graphics.cs.ucdavis.edu/~bcbudge/ecs298_2004/General_BSDFs_BSSDFs.ppt
http://www.macs.hw.ac.uk/texturelab/people/exchange_students/spence/
http://www.graphics.cornell.edu/pubs/2006/IM06.pdf
http://www.irit.fr/~Loic.Barthe/Publications/GI2007_Claustres_et_al.pdf
http://developer.nvidia.com/object/BRDFbased_Lighting.html
http://www.cs.ucl.ac.uk/staff/j.kautz/GameCourse/
http://developer.amd.com/media/gpu_assets/Oat-Wrinkles(Siggraph07).pdf
http://drp.disneyresearch.com/projects/cloth/
Gamma Correctness
Technical Art
Tesselation
The Maths Of Lighting In A Nutshell
Where;
normal – normal of the pixel
tangent – tangent of the pixel
light – normalised light vector (pixel to light source)
eye – normalised eye vector (pixel to viewers eye)
wrap – a constant used to wrap the light around an object, produces a more natural softer lighting effect.
wrapNormaliser– 1.0 / (1.0 + wrap)
halfVect – half space of light and eye vector, = normalize(light + eye);
shift – a constant used to push the anistropic lighting away from the tangent towards the normal
power – specula power, higher the number the tighter the bright specula highlight
Lighting equations;
Diffuse
float ndot = dot(normal, light);
float amount = saturate(ndot);
Diffuse with wrap around
float ndot = dot(normal, light);
float amount = saturate(ndot + wrap) * ;
Back lighting
float ndot = dot(normal, light);
float amount = saturate(-ndot);
Back lighting with wrap around
float ndot = dot(normal, light);
float amount = saturate(-ndot + wrap) * wrapNormaliser;
Specular
float nhdot = saturate(dot(normal,halfVect);
float spec = pow(nhdot, power);
Fake Anistropic
float3 tn = normalize(tangent + shift * normal);
float thdot = dot(tn, halfVect);
float thsin = sqrt(1.0 - thdot * thdot);
float specular0 = pow(thsin, power);
Another Fake Anistropic That Avoids Using Tangents
Can be used to generate the crown like specular effect on hair without the problems associated with the tangents due to UV mapping directions.
float dotNH = dot(normal, halfVect);
float theta = acos(dotNH) + shift;
float alpha = cos(theta);
float specular = pow(alpha, power);
normal – normal of the pixel
tangent – tangent of the pixel
light – normalised light vector (pixel to light source)
eye – normalised eye vector (pixel to viewers eye)
wrap – a constant used to wrap the light around an object, produces a more natural softer lighting effect.
wrapNormaliser– 1.0 / (1.0 + wrap)
halfVect – half space of light and eye vector, = normalize(light + eye);
shift – a constant used to push the anistropic lighting away from the tangent towards the normal
power – specula power, higher the number the tighter the bright specula highlight
Lighting equations;
Diffuse
float ndot = dot(normal, light);
float amount = saturate(ndot);
Diffuse with wrap around
float ndot = dot(normal, light);
float amount = saturate(ndot + wrap) * ;
Back lighting
float ndot = dot(normal, light);
float amount = saturate(-ndot);
Back lighting with wrap around
float ndot = dot(normal, light);
float amount = saturate(-ndot + wrap) * wrapNormaliser;
Specular
float nhdot = saturate(dot(normal,halfVect);
float spec = pow(nhdot, power);
Fake Anistropic
float3 tn = normalize(tangent + shift * normal);
float thdot = dot(tn, halfVect);
float thsin = sqrt(1.0 - thdot * thdot);
float specular0 = pow(thsin, power);
Another Fake Anistropic That Avoids Using Tangents
Can be used to generate the crown like specular effect on hair without the problems associated with the tangents due to UV mapping directions.
float dotNH = dot(normal, halfVect);
float theta = acos(dotNH) + shift;
float alpha = cos(theta);
float specular = pow(alpha, power);
Satin or Silk Cloth faked using this anistropic effect
Normal Mapping.
We need to convert from tangent space to world space using the interpolated tangent, binormal and
normal, this new normal is in the same space as the interpolated normal and can
then be used for lighting calculations.
half3
GetNormal(half3 NM, half3 T, half3 B, half3 N)
{
return T * NM.x + B * NM.y + N * NM.z ;
}
Detail Map
Adds to the base normal map, a 2nd tiled normal map - ideally the 2nd normal map will use a 2nd set of UV
co-ordinates to provide the greatest control for the artist the example below just re-uses the first set.
half3 NM =
sample_tex2D_DXT5NM(NormalSampler, TNormalMap, UV0).rgb;
half2 NM2 =
sample_tex2D_DXT5NM(DetailNormalSampler, TDetailNormalMap, UV0 *
DetailNormalMapTilingFactor).rg;
NM.x += NM2.x;
NM.y +=
NM2.y;
N = GetNormal(NM, T, B,
N);
Blending Normal Maps
To Produce Wrinkles And
Creases
Expression1, Expression2,
Expression3 variables passed to shader to control each expression
component.
half3 NMBas = sample_tex2D_DXT5NM(NormalSampler,
TNormalMap, UV0).rgb; // Base Normal Map
half3 NMExp =
sample_tex2D_DXT5NM(NormalSamplerExp, TNormalMapExp, UV0).rgb; // Expression
Normal Mpa
half3 mask = sample_tex2D(DiffSamplerExp, TDiffuseAlphaMapExp,
UV0).rgb;
// Mask
expression areas, e.g. red = eyes, green = mouth, blue =
brow
half3 NMExpR = lerp(NMBas, NMExp, mask.r) -
NMBas;
half3 NMExpG = lerp(NMBas, NMExp, mask.g) - NMBas;
half3 NMExpB =
lerp(NMBas, NMExp, mask.b) - NMBas;
half3 NM = NMBas + lerp(0, NMExpR,
Expression1) + lerp(0, NMExpG, Expression2) + lerp(0, NMExpB,
Expression3);
N = GetNormal(NM, T, B, N);
We need to convert from tangent space to world space using the interpolated tangent, binormal and
normal, this new normal is in the same space as the interpolated normal and can
then be used for lighting calculations.
half3
GetNormal(half3 NM, half3 T, half3 B, half3 N)
{
return T * NM.x + B * NM.y + N * NM.z ;
}
Detail Map
Adds to the base normal map, a 2nd tiled normal map - ideally the 2nd normal map will use a 2nd set of UV
co-ordinates to provide the greatest control for the artist the example below just re-uses the first set.
half3 NM =
sample_tex2D_DXT5NM(NormalSampler, TNormalMap, UV0).rgb;
half2 NM2 =
sample_tex2D_DXT5NM(DetailNormalSampler, TDetailNormalMap, UV0 *
DetailNormalMapTilingFactor).rg;
NM.x += NM2.x;
NM.y +=
NM2.y;
N = GetNormal(NM, T, B,
N);
Blending Normal Maps
To Produce Wrinkles And
Creases
Expression1, Expression2,
Expression3 variables passed to shader to control each expression
component.
half3 NMBas = sample_tex2D_DXT5NM(NormalSampler,
TNormalMap, UV0).rgb; // Base Normal Map
half3 NMExp =
sample_tex2D_DXT5NM(NormalSamplerExp, TNormalMapExp, UV0).rgb; // Expression
Normal Mpa
half3 mask = sample_tex2D(DiffSamplerExp, TDiffuseAlphaMapExp,
UV0).rgb;
// Mask
expression areas, e.g. red = eyes, green = mouth, blue =
brow
half3 NMExpR = lerp(NMBas, NMExp, mask.r) -
NMBas;
half3 NMExpG = lerp(NMBas, NMExp, mask.g) - NMBas;
half3 NMExpB =
lerp(NMBas, NMExp, mask.b) - NMBas;
half3 NM = NMBas + lerp(0, NMExpR,
Expression1) + lerp(0, NMExpG, Expression2) + lerp(0, NMExpB,
Expression3);
N = GetNormal(NM, T, B, N);