首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络游戏 >

日照贴图 生成,ogrese 算法研究

2013-08-01 
光照贴图 生成,ogrese 算法研究ogrese 的光照贴图算法,如下.// 功能:计算地形的自投影void TerrainManager

光照贴图 生成,ogrese 算法研究
ogrese 的光照贴图算法,如下.


// 功能:计算地形的自投影
void TerrainManager::ComputeTerrainCaseShadows(float* lightMap, size_t width, size_t height, const Ogre::Vector3& lightDir)
{
const float HWidth = m_pData->GetWidth() - 1;
const float HHeight = m_pData->GetHeight()-1;
const float stepX = HWidth / width;
const float stepZ = HHeight / height;
const float invStepX = width / HWidth;
const float invStepZ = height / HHeight ;
size_t wid = (width + 1) * (height + 1);
float* flagMap = new float[wid];
memset(flagMap, 0, wid*sizeof(float));
wid = width + 1;
#ifdef _OPENMP
const float lightDirXMagnitude = fabs(lightDir.x);
const float lightDirZMagnitude = fabs(lightDir.z);
#pragma omp parallel for firstprivate( lightDirXMagnitude, lightDirZMagnitude, lightMap, flagMap, wid) schedule(static,4)
for(int m = 0; m < width; m++)
{
size_t *x, *z;
size_t i, j;
int dirX, dirY;
// that's because threading is really picky about sharing variables. the less you share, 
// the faster it goes.
if(lightDirXMagnitude > lightDirZMagnitude)
{
z = &i;
x = &j;

if(lightDir.x < 0)
dirY = -1;
else
dirY = 1;

if(lightDir.z < 0)
dirX = -1;
else
dirX = 1;
}
else
{
z = &j;
x = &i;

if(lightDir.x < 0)
dirX = -1;
else
dirX = 1;

if(lightDir.z < 0)
dirY = -1;
else
dirY = 1;
}
// if you decide to just do it single-threaded, 
// just copy the previous block back just above the for loop 

if(dirY < 0)
j = width - m - 1;
else
j = m;

Ogre::Vector3 rayPoint;// 射线上的测试点
float px, pz;// 等于 rayPoint * invStep
// calculate interpolated values


int x0, x1, z0, z1;
float du, dv;
float interpolatedHeight, interpolatedFlagMap;
float invdu, invdv;
float w0, w1, w2, w3;

float val;
const float epsilon = 0.5f;
size_t index;

for(size_t n = 0; n < width; ++n)
{
if(dirX < 0)
i = width - n - 1;
else
i = n;
// travel along the terrain until we:
// (1) intersect another point
// (2) find another point with previous collision data
// (3) or reach the edge of the map
rayPoint.x = (*x)*stepX;
rayPoint.z = (*z)*stepZ;

x0 = floor(rayPoint.x);
x1 = ceil(rayPoint.x);
z0 = floor(rayPoint.z);
z1 = ceil(rayPoint.z);
du = rayPoint.x - x0;
dv = rayPoint.z - z0;
invdu = 1.0 - du;
invdv = 1.0 - dv;
w0 = invdu * invdv;
w1 = invdu * dv;
w2 = du * invdv;
w3 = du * dv;
// compute interpolated height value from the heightmap direction below ray
rayPoint.y = w0 * m_pData->GetRawHeight(x0, z0) 
+ w1 * m_pData->GetRawHeight(x0, z1)
+ w2 * m_pData->GetRawHeight(x1, z0) 
+ w3 * m_pData->GetRawHeight(x1, z1);

// travel along ray
while (1)
{
rayPoint.x -= lightDir.x;
rayPoint.y -= lightDir.y;
rayPoint.z -= lightDir.z;
// check if we've reached the boundary
if (rayPoint.x < 0 || rayPoint.x >= HWidth || rayPoint.z < 0 || rayPoint.z >= HHeight)
{
flagMap[*z * wid + *x] = -1.0f;
break;
}
x0 = floor(rayPoint.x);
x1 = ceil(rayPoint.x);
z0 = floor(rayPoint.z);
z1 = ceil(rayPoint.z);

du = rayPoint.x - x0;
dv = rayPoint.z - z0;
invdu = 1.0 - du;
invdv = 1.0 - dv;
w0 = invdu * invdv;


w1 = invdu * dv;
w2 = du * invdv;
w3 = du * dv;
// compute interpolated height value from the heightmap direction below ray
interpolatedHeight = w0 * m_pData->GetRawHeight(x0, z0) 
+ w1 * m_pData->GetRawHeight(x0, z1)
+ w2 * m_pData->GetRawHeight(x1, z0) 
+ w3 * m_pData->GetRawHeight(x1, z1);

px = rayPoint.x * invStepX;
pz = rayPoint.z * invStepZ;
x0 = floor(px);
x1 = ceil(px);
z0 = floor(pz);
z1 = ceil(pz);

du = px - x0;
dv = pz - z0;
invdu = 1.0 - du;
invdv = 1.0 - dv;
w0 = invdu * invdv;
w1 = invdu * dv;
w2 = du * invdv;
w3 = du * dv;
// compute interpolated flagmap value from point directly below ray
interpolatedFlagMap = w0 * flagMap[z0 * wid + x0]
+ w1 * flagMap[z1 * wid + x0]
+ w2 * flagMap[z0 * wid + x1]
+ w3 * flagMap[z1 * wid + x1];

// check intersection with either terrain or flagMap
// if ipHeight < ipFlag check against flagMap value
if (interpolatedFlagMap > 0)
val = interpolatedHeight + interpolatedFlagMap;
else
val = interpolatedHeight;

if (rayPoint.y < val)
{
// point in shadow
flagMap[*z * wid + *x] = val - rayPoint.y;
index = *z * width + *x;
lightMap[index] = 1.0f;
break;
}
// check if pixel we moved to is unshadowed
// since the flagMap value is interpolated, we use an epsilon value to check
// if it's close enough to -1 to indicate non-shadow
if (interpolatedFlagMap < -1.0f+epsilon && interpolatedFlagMap > -1.0f-epsilon)
{
flagMap[*z * wid + *x] = -1.0f;
break;


}
}
}
}
//-------------------------
#else
// algorithm for ray traced shadow map as described here:
// http://gpwiki.org/index.php/Faster_Ray_Traced_Terrain_Shadow_Maps
size_t i, j;// 遍历像素点,0 - 光照图尺寸
int iDir, jDir;// 遍历像素点每次增量
size_t iSize, jSize;// 遍历像素点等于该值时结束循环
size_t *x, *z;// 指向 i 或 j 的指针

// based on the direction of light, decide in which order to traverse
// to speed up calculations
if (fabs(lightDir.x) > fabs(lightDir.z))
{
z = &i;
x = &j;
iSize = height;
jSize = width;
if (lightDir.x < 0)
{
j = jSize - 1;
jDir = -1;
}
else
{
j = 0;
jDir = 1;
}
if (lightDir.z < 0)
{
i = iSize - 1;
iDir = -1;
}
else
{
i = 0;
iDir = 1;
}
}
else
{
x = &i;
z = &j;
jSize = height;
iSize = width;
if (lightDir.x < 0)
{
i = iSize - 1;
iDir = -1;
}
else
{
i = 0;
iDir = 1;
}
if (lightDir.z < 0)
{
j = jSize - 1;
jDir = -1;
}
else
{
j = 0;
jDir = 1;
}
}

Ogre::Vector3 rayPoint;// 射线上的测试点
float px, pz;// 等于 rayPoint * invStep
// calculate interpolated values
int x0, x1, z0, z1;
float du, dv;
float interpolatedHeight, interpolatedFlagMap;
float invdu, invdv;
float w0, w1, w2, w3;

float val;
const float epsilon = 0.5f;
size_t index;
while (1)
{
while (1)
{
// travel along terrain until we:
// (1) intersect another point
// (2) find another point with previous collision data
// (3) reach the edge of the map
rayPoint.x = (*x)*stepX;


rayPoint.z = (*z)*stepZ;
x0 = floor(rayPoint.x);
x1 = ceil(rayPoint.x);
z0 = floor(rayPoint.z);
z1 = ceil(rayPoint.z);
du = rayPoint.x - x0;
dv = rayPoint.z - z0;
invdu = 1.0 - du;
invdv = 1.0 - dv;
w0 = invdu * invdv;
w1 = invdu * dv;
w2 = du * invdv;
w3 = du * dv;
// compute interpolated height value from the heightmap direction below ray
rayPoint.y = w0 * m_pData->GetRawHeight(x0, z0) 
+ w1 * m_pData->GetRawHeight(x0, z1)
+ w2 * m_pData->GetRawHeight(x1, z0) 
+ w3 * m_pData->GetRawHeight(x1, z1);
// travel along ray
while (1)
{
rayPoint.x -= lightDir.x;
rayPoint.y -= lightDir.y;
rayPoint.z -= lightDir.z;
// check if we've reached the boundary
if (rayPoint.x < 0 || rayPoint.x >= HWidth || rayPoint.z < 0 || rayPoint.z >= HHeight)
{
flagMap[*z * wid + *x] = -1.0f;
break;
}
x0 = floor(rayPoint.x);
x1 = ceil(rayPoint.x);
z0 = floor(rayPoint.z);
z1 = ceil(rayPoint.z);

du = rayPoint.x - x0;
dv = rayPoint.z - z0;
invdu = 1.0 - du;
invdv = 1.0 - dv;
w0 = invdu * invdv;
w1 = invdu * dv;
w2 = du * invdv;
w3 = du * dv;
// compute interpolated height value from the heightmap direction below ray
interpolatedHeight = w0 * m_pData->GetRawHeight(x0, z0) 
+ w1 * m_pData->GetRawHeight(x0, z1)
+ w2 * m_pData->GetRawHeight(x1, z0) 
+ w3 * m_pData->GetRawHeight(x1, z1);

px = rayPoint.x * invStepX;
pz = rayPoint.z * invStepZ;
x0 = floor(px);
x1 = ceil(px);
z0 = floor(pz);
z1 = ceil(pz);

du = px - x0;
dv = pz - z0;
invdu = 1.0 - du;


invdv = 1.0 - dv;
w0 = invdu * invdv;
w1 = invdu * dv;
w2 = du * invdv;
w3 = du * dv;
// compute interpolated flagmap value from point directly below ray
interpolatedFlagMap = w0 * flagMap[z0 * wid + x0]
+ w1 * flagMap[z1 * wid + x0]
+ w2 * flagMap[z0 * wid + x1]
+ w3 * flagMap[z1 * wid + x1];

// check intersection with either terrain or flagMap
// if ipHeight < ipFlag check against flagMap value
if (interpolatedFlagMap > 0)
val = interpolatedHeight + interpolatedFlagMap;
else
val = interpolatedHeight;

if (rayPoint.y < val)
{
// point in shadow
flagMap[*z * wid + *x] = val - rayPoint.y;
index = *z * width + *x;
lightMap[index] = 1.0f;
break;
}
// check if pixel we moved to is unshadowed
// since the flagMap value is interpolated, we use an epsilon value to check
// if it's close enough to -1 to indicate non-shadow
if (interpolatedFlagMap < -1.0f+epsilon && interpolatedFlagMap > -1.0f-epsilon)
{
flagMap[*z * wid + *x] = -1.0f;
break;
}
}
// update inner loop
j += jDir;
if (j >= jSize) // 因为j 是 size_t类型, 如果 j < 0, 那么j会变成一个极大值,所以不用判断 < 0的情况
break;
}
// reset inner loop starting point
if (jDir < 0)
j = jSize-1;
else
j = 0;
// update outer loop variable
i += iDir;
if (i >= iSize)
break;
}
#endif
delete[] flagMap; 
}


_OPENMP这个宏暂时没有定义,所以运行的是下面的#else的代码,
现在是 256*256的地形 生成了 一个2048*2048的贴图.很多地方不懂,请大家解释下每行代码的意思.谢谢了.
原理小弟略懂一二,但是这个代码,很多临时变量不是很懂 光照贴图 阴影贴图

lightmap
[解决办法]
你可以写成shader,然后再倒出贴图,这样会方便一些.
[解决办法]
对OGRE不了解,期待楼主继续研究日照贴图 生成,ogrese 算法研究

热点排行