地形阴影渲染
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
地形阴影贴图快速计算
时间:2007-12-05来源:作者:图腾收集发布人:admin 点击:97次
关键字:迅雷快车Baidu贴图地形阴影计算快速目录 1 引言 2 算法描述 3 算法实现 4 光照贴图 5 颜色部件原文:Fast Computation of Terrain Shadow Maps 译者:Dreams Woo1、引言(Introduction)地形渲染是一个覆盖内容非常广的主题。本文将集中介绍对地形的光照和阴影的渲染。在下图中,你将看到这一技术的
目录
1 引言
2 算法描述
3 算法实现
4 光照贴图
5 颜色部件
原文:Fast Computation of Terrain Shadow Maps
译者:Dreams Woo
1、引言(Introduction)
地形渲染是一个覆盖内容非常广的主题。本文将集中介绍对地形的光照和阴影的渲染。在下图中,你将看到这一技术的应用效果。
2、算法描述(Algorithm description)
本法则实际上非常简单,对于每一个栅格点,我们选择从灯光坐标点发出的光线到地图的交点。由于只选择射线L下面的点因此非常快。如下图1:
让我们了解下面的符号:
A = 目标点
B = 灯光位置的投影坐标(vector B = vector(sun_pos.x, 0, sun_pos.z));
C = 灯光位置坐标;
L = 光线矢量(L = A - C);
P = 光线经过路线的所有投影点;
X(P) = 投影点P在光线矢量上的坐标(用于单独计算LERP)。
点P用来参与从点A到点B之间的2D线计算。对于任意点P,假如在高度图中它的值大于点X(P)的Y值,那么就选择他。这样我们就知道光线L与高度图相交,那么点A的光照值就等于
‘ambient_color_value’,接着我们就可以处理下一个目标点。
假如所有的P类型的点都测试完没有发现交点,那么点A的光照值就使用下面的公式:
Illum(A) = ambient_color_value + (L dot N)
值的范围为[0,1]。
3、算法实现(Algorithm implementation)
假如上面的运算你还不明白,下面的代码将帮助你。最重要的函数是intersect_map。这个函数检查目标点是否被遮挡。测试光线是否与高度图有相交。这个函数调用高度图中每一个点。当发现一个交点时,就停止测试,接着测试下一个(如下图2中的点)。就象我在运算法则描述中的那样,假如目标点没有被遮挡,它的光照值使用上面的公式。
函数genLightmap用于产生光照图。它测试和照亮高度图中所有点。
注重:假如你使用下面的代码,你应当知道法线被从每个部件是FLOAT类型压缩为一个字节。
int intersect_map(const vector3& iv,const ray& r,Image* hm,float fHeightScale)
{
int w,hits;
float d,h,D;
vector3 v,dir;
v = iv + r.direction;
w = hm->w;
hits = 0;
while (!(( v.x >= w-1 ) || ( v.x <= 0 ) || ( v.z >= w-1 ) || ( v.z <= 0 )))
{
// length of lightdir's projection
D =
Magnitude(vector3(v.x,0,v.z)-vector3(r.origin.x,0,r.origin.z));
d = Magnitude(iv-v); // light direction
h = iv.y + (d*r.origin.y) / D; // X(P) point
if (hm->data[ifloor(v.z)* w + ifloor(v.x)] * fHeightScale > h)
{
// check if height in point P is bigger than point X's height
hits++; // if so, mark as hit, and skip this work point.
break;
};
dir = r.direction;
dir.y = 0;
v += Normalize(dir); // fetch new working point };
return hits;
};
Image* genLightmap(char* normal,Image* hm,vector3 fSunDir,int w,float fAmbient)
{
int i,j,hits;
float f,dot;
vector3 n,fVertex;
Image* lmap;
ray r;
float fHeightScale = 10.0f / 255.0f;
lmap = new Image(w,w,1);
if (!lmap)
{
printf("(!) Error: cannot alloc lightmap!\n");
return 0;
};
for (j=0; j { for (i=0; i { fVertex.x = i; fVertex.y = hm->data[j*w+i] * fHeightScale; fVertex.z = j; f = fAmbient; r.origin = fVertex + fSunDir * 2000.0f; r.direction = fSunDir; if (!intersect_map(fVertex,r,hm,fHeightScale)) { // checks current working point for intersection // computing the lighting equation n.x = (float)(normal[3*(j*w+i)+0]); n.y = (float)(normal[3*(j*w+i)+1]); n.z = (float)(normal[3*(j*w+i)+2]); f += 0.5f*(1.0f+DotProduct(Normalize(n),Normalize(fSunDir))); if (f>1.0f) f = 1.0f; }; dot = f * 255.0f; lmap->data[j*w+i] = (unsigned char)dot; }; }; return lmap; };