History: CelShading.cg
Source of version: 2 (current)
Copy to clipboard
{CODE(wrap="1", colors="c++")}//
// The maximum number of lights per-object. Decrease this value if you need some extra performance.
//
// If you change this, then you must enter 'CelShading.program' and change the '$numLights'
// variable to match this definition.
#define NUM_LIGHTS 6
//
// Vertex program
float4 main_vp(
float4 iPos : POSITION,
float3 iNorm : NORMAL,
float2 iUV : TEXCOORD0,
out float3 oPos : TEXCOORD0,
out float3 oNorm : TEXCOORD1,
out float2 oUV : TEXCOORD2,
uniform float4x4 worldViewProj ) : POSITION
{
oPos = iPos.xyz;
oNorm = iNorm;
oUV = iUV;
return mul(worldViewProj, iPos);
}
//
// Colored surface fragment program
float4 main_fp(
float3 iPos : TEXCOORD0,
float3 iNorm : TEXCOORD1,
float3 iUV : TEXCOORD2,
uniform float3 eyePosition,
uniform float4 ambientColor,
uniform float4 diffuseColor,
uniform float4 specularColor,
uniform float4 emissiveColor,
uniform float shininess,
uniform float3 ambientLight,
// Light params
uniform float4 lightDiffuse[NUM_LIGHTS],
uniform float4 lightSpecular[NUM_LIGHTS],
uniform float4 lightPosition[NUM_LIGHTS],
uniform float4 lightAttenuation[NUM_LIGHTS],
// Texture params
uniform sampler1D diffuseRamp : register(s0),
uniform sampler1D specRamp : register(s1) ) : COLOR
{
float4 surfaceColor = float4(ambientLight,1)*ambientColor;
float4 specularSurface = 0;
for (int i = 0; i < NUM_LIGHTS; i++)
{
float3 norm = normalize(iNorm);
//
// Calculate light vector and distance
float3 lightVec = 0;
if (lightPosition[i].w == 1)
lightVec = lightPosition[i].xyz - iPos*lightPosition[i].w;
else
lightVec = lightPosition[i].xyz;
float lightDist = length(lightVec);
lightVec = normalize(lightVec);
//
// Calculate the direction in-between the light direction and the camera's direction.
float3 eyeVec = normalize(eyePosition - iPos);
float3 halfDir = normalize(lightVec + eyeVec);
//
// Calculate luminosity based on light attenuation
float luminosity = 1.f;
if(lightAttenuation[i].x > lightDist && lightPosition[i].w == 1)
luminosity = 1.f /
( lightAttenuation[i].y + lightAttenuation[i].z*lightDist +
lightAttenuation[i].w*(lightDist*lightDist) );
//
// Get diffuse component based on the dot product of the normal and the light direction,
// multiplied by the luminosity component.
float diffComponent = max(dot(norm, lightVec), 0)*luminosity;
//
// Get specular component based on the dot product of the normal and the half-camera-light
// direction, multiplied by the luminosity component.
float specComponent = pow(max(dot(norm, halfDir), 0), shininess)*luminosity;
float diffuse = tex1D(diffuseRamp, diffComponent).r;
float specular = tex1D(specRamp, specComponent).r;
surfaceColor += diffuse*diffuseColor*lightDiffuse[i];
specularSurface += specular*lightSpecular[i]*specularColor;
}
return emissiveColor + surfaceColor + specularSurface;
}
//
// Decal + Specular Mapping fragment program
float4 mainDecal_fp(
float3 iPos : TEXCOORD0,
float3 iNorm : TEXCOORD1,
float3 iUV : TEXCOORD2,
uniform float3 eyePosition,
uniform float4 ambientColor,
uniform float4 diffuseColor,
uniform float4 specularColor,
uniform float4 emissiveColor,
uniform float shininess,
uniform float3 ambientLight,
// Light params
uniform float4 lightDiffuse[NUM_LIGHTS],
uniform float4 lightSpecular[NUM_LIGHTS],
uniform float4 lightPosition[NUM_LIGHTS],
uniform float4 lightAttenuation[NUM_LIGHTS],
// Texture params
uniform sampler1D diffuseRamp : register(s0),
uniform sampler1D specRamp : register(s1),
uniform sampler2D decalTex : register(s2)) : COLOR
{
float4 surfaceColor = float4(ambientLight,1)*ambientColor;
float4 specularSurface = 0;
float4 texColor = tex2D(decalTex, iUV);
for (int i = 0; i < NUM_LIGHTS; i++)
{
float3 norm = normalize(iNorm);
//
// Calculate light vector and distance
float3 lightVec = 0;
if (lightPosition[i].w == 1)
lightVec = lightPosition[i].xyz - iPos*lightPosition[i].w;
else
lightVec = lightPosition[i].xyz;
float lightDist = length(lightVec);
lightVec = normalize(lightVec);
//
// Calculate the direction in-between the light direction and the camera's direction.
float3 eyeVec = normalize(eyePosition - iPos);
float3 halfDir = normalize(lightVec + eyeVec);
//
// Calculate luminosity based on light attenuation
float luminosity = 1.f;
if(lightAttenuation[i].x > lightDist && lightPosition[i].w == 1)
luminosity = 1.f /
( lightAttenuation[i].y + lightAttenuation[i].z*lightDist +
lightAttenuation[i].w*(lightDist*lightDist) );
//
// Get diffuse component based on the dot product of the normal and the light direction,
// multiplied by the luminosity component.
float diffComponent = max(dot(norm, lightVec), 0)*luminosity;
//
// Get specular component based on the dot product of the normal and the half-camera-light
// direction, multiplied by the luminosity component.
float specComponent = pow(max(dot(norm, halfDir), 0), shininess)*luminosity;
float diffuse = tex1D(diffuseRamp, diffComponent).r;
float specular = tex1D(specRamp, specComponent).r;
surfaceColor += diffuse*diffuseColor*lightDiffuse[i];
specularSurface += specular*lightSpecular[i]*specularColor;
}
return texColor*(emissiveColor + surfaceColor) + specularSurface;
}
//
// Decal + Specular Mapping fragment program
float4 mainDecalSpec_fp(
float3 iPos : TEXCOORD0,
float3 iNorm : TEXCOORD1,
float3 iUV : TEXCOORD2,
uniform float3 eyePosition,
uniform float4 ambientColor,
uniform float4 diffuseColor,
uniform float4 specularColor,
uniform float4 emissiveColor,
uniform float shininess,
uniform float3 ambientLight,
// Light params
uniform float4 lightDiffuse[NUM_LIGHTS],
uniform float4 lightSpecular[NUM_LIGHTS],
uniform float4 lightPosition[NUM_LIGHTS],
uniform float4 lightAttenuation[NUM_LIGHTS],
// Texture params
uniform sampler1D diffuseRamp : register(s0),
uniform sampler1D specRamp : register(s1),
uniform sampler2D decalTex : register(s2),
uniform sampler2D specMap : register(s3)) : COLOR
{
float4 surfaceColor = float4(ambientLight,1)*ambientColor;
float4 specularSurface = 0;
float4 texColor = tex2D(decalTex, iUV);
float4 specMapColor = tex2D(specMap, iUV);
for (int i = 0; i < NUM_LIGHTS; i++)
{
float3 norm = normalize(iNorm);
//
// Calculate light vector and distance
float3 lightVec = 0;
if (lightPosition[i].w == 1)
lightVec = lightPosition[i].xyz - iPos*lightPosition[i].w;
else
lightVec = lightPosition[i].xyz;
float lightDist = length(lightVec);
lightVec = normalize(lightVec);
//
// Calculate the direction in-between the light direction and the camera's direction.
float3 eyeVec = normalize(eyePosition - iPos);
float3 halfDir = normalize(lightVec + eyeVec);
//
// Calculate luminosity based on light attenuation
float luminosity = 1.f;
if(lightAttenuation[i].x > lightDist && lightPosition[i].w == 1)
luminosity = 1.f /
( lightAttenuation[i].y + lightAttenuation[i].z*lightDist +
lightAttenuation[i].w*(lightDist*lightDist) );
//
// Get diffuse component based on the dot product of the normal and the light direction,
// multiplied by the luminosity component.
float diffComponent = max(dot(norm, lightVec), 0)*luminosity;
//
// Get specular component based on the dot product of the normal and the half-camera-light
// direction, multiplied by the luminosity component.
float specComponent = pow(max(dot(norm, halfDir), 0), shininess)*luminosity;
float diffuse = tex1D(diffuseRamp, diffComponent).r;
float specular = tex1D(specRamp, specComponent).r;
surfaceColor += diffuse*diffuseColor*lightDiffuse[i];
specularSurface += specular*lightSpecular[i]*specularColor;
}
return texColor*(emissiveColor + surfaceColor) + specMapColor*specularSurface;
}{CODE}