2008年10月31日星期五

陰影映射

完成了紋理投影後,製作基本陰影映射就如吃生一樣容易。




// Pixel shader

varying vec3 normal, lightDir, halfVector;
varying vec2 colorCoord;
varying vec4 shadowCoord;
uniform sampler2D colorTex;
uniform sampler2DShadow shadowTex;

// Light intensity inside shadow
const float shadowIntensity = 0.5;

// Should be supplied as uniform
const float shadowMapPixelScale = 1.0 / float(2048);
const int pcfSize = 1; // The pcf filtering size, 0 -> 1x1 (no filtering), 1 -> 3x3 etc

void main(void)
{
vec4 diffuse = gl_FrontLightProduct[0].diffuse;
vec4 specular = gl_FrontLightProduct[0].specular;
vec4 ambient = gl_FrontLightProduct[0].ambient;
vec3 n = normalize(normal);
float NdotL = max(dot(n, lightDir), 0.0);

diffuse *= NdotL;
vec3 halfV = normalize(halfVector);
float NdotHV = max(dot(n, halfV), 0.0);
specular *= pow(NdotHV, gl_FrontMaterial.shininess);

// Get the shadow value, let the hardware perform perspective divide,
// depth comparison and 2x2 pcf if supported.
// float shadowValue = shadow2DProj(shadowTex, shadowCoord).r;

// Perform PCF filtering
float shadowValue = 0.0;
for(int i=-pcfSize; i<=pcfSize; ++i) for(int j=-pcfSize; j<=pcfSize; ++j)
{
vec4 offset = vec4(i * shadowMapPixelScale, j * shadowMapPixelScale, 0, 0);
shadowValue += shadow2DProj(shadowTex, shadowCoord + offset).r;
}
shadowValue /= (2 * pcfSize + 1) * (2 * pcfSize + 1);

float shadowSpecularFactor = shadowValue == 0 ? 0 : 1;
float shadowDiffuseFactor = min(1.0, shadowIntensity + shadowValue);

gl_FragData[0] = shadowSpecularFactor * specular +
(ambient + shadowDiffuseFactor * diffuse) * vec4(texture2D(colorTex, colorCoord).xyz, 1);
}


當然,還有許多的陰影技術可以嘗試;我比較臨感興趣的有:


相關文章

沒有留言:

發佈留言