深入探索透视纹理映射（下）

718人阅读 评论(0)

-潘宏
-
2010年5月5日

-本人水平有限，疏忽错误在所难免，还请各位数学高手、编程高手不吝赐教
-email:
popyy@netease.com

仿射纹理映射错在什么地方?

double x, y, xleft, xright;

double s, t, sleft, sright, tleft, tright, sstep, tstep;

for(y = y0; y < y1; ++y)

{

xleft = y和左边的直线方程来求出左边的x

xright = y和右边的直线方程来求出右边的x

sleft = (y – y0) * (s1 – s0) / (y1 – y0) + s0;

sright = (y – y0) * (s2 – s0) / (y2 – y0) + s0;

tleft = (y – y0) * (t1 – t0) / (y1 – y0) + t0;

tright = (y – y0) * (t2 – t0) / (y2 – y0) + t0;

sstep = (sright – sleft) / (xright – xleft);

tstep = (tright – tleft) / ( xright – xleft);

for(x = xleft, s = sleft, t = tleft; x < xright;

++x, s += sstep, t += tstep)

{

帧缓冲像素[x, y] = 纹理[s, t];

}

}

sstep = (sright – sleft) / (xright – xleft);

tstep = (tright – tleft) / ( xright – xleft);

透视纹理映射的数学推导

double x, y, xleft, xright; // 插值xy，左右线段x

double oneoverz_left, oneoverz_right; // 左右线段1/z

double oneoverz_top, oneoverz_bottom; // 上下顶点1/z

double oneoverz, oneoverz_step;   // 插值1/z以及扫描线1/z步长

double originalx, originaly, originalz; // 空间中的原始xyz

double s, t; // 要求的原始st

for(y = y0; y < y1; ++y)

{

xleft = y和左边的直线方程来求出左边的x

xright = y和右边的直线方程来求出右边的x

oneoverz_top = 1.0 / z0;

oneoverz_bottom = 1.0 / z1;

oneoverz_left = (y – y0) * (oneoverz_bottom – oneoverz_top) / (y1 – y0) + oneoverz_top;

oneoverz_bottom = 1.0 / z2;

oneoverz_right = (y – y0) * (oneoverz_bottom – oneoverz_top) / (y2 – y0) + oneoverz_top;

oneoverz_step = (oneoverz_right – oneoverz_left) / (xright – xleft);

for(x = xleft, oneoverz = oneoverz_left; x < xright;

++x, oneoverz += oneoverz_step)

{

originalz = 1.0 / oneoverz;

originalx = -x * originalz / N;

originaly = -y * originalz / N;

originalxoriginaly以及originalz在空间中通过线性插值找到相应的st

帧缓冲像素[x, y] = 纹理[s, t];

}

}

originalxoriginaly以及originalz在空间中通过线性插值找到相应的st

double x, y, xleft, xright; // 插值xy，左右线段x

double oneoverz_left, oneoverz_right; // 左右线段1/z

double oneoverz_top, oneoverz_bottom; // 上下顶点1/z

double oneoverz, oneoverz_step;   // 插值1/z以及扫描线步长

double soverz_top, soverz_bottom; // 上下顶点s/z

double toverz_top, toverz_bottom; // 上下顶点t/z

double soverz_left, soverz_right; // 左右线段s/z

double toverz_left, toverz_right; // 左右线段t/z

double soverz, soverz_step; // 插值s/z以及扫描线步长

double toverz, toverz_step; // 插值t/z以及扫描线步长

double s, t; // 要求的原始st

for(y = y0; y < y1; ++y)

{

xleft = y和左边的直线方程来求出左边的x

xright = y和右边的直线方程来求出右边的x

oneoverz_top = 1.0 / z0;

oneoverz_bottom = 1.0 / z1;

oneoverz_left = (y – y0) * (oneoverz_bottom – oneoverz_top) / (y1 – y0) + oneoverz_top;

oneoverz_bottom = 1.0 / z2;

oneoverz_right = (y – y0) * (oneoverz_bottom – oneoverz_top) / (y2 – y0) + oneoverz_top;

oneoverz_step = (oneoverz_right – oneoverz_left) / (xright – xleft);

soverz_top = s0 / z0;

soverz_bottom = s1 / z1;

soverz_left = (y – y0) * (soverz_bottom – soverz_top) / (y1 – y0) + soverz_top;

soverz_bottom = s2 / z2;

soverz_right = (y – y0) * (soverz_bottom – soverz_top) / (y2 – y0) + soverz_top;

soverz_step = (soverz_right – soverz_left) / (xright – xleft);

toverz_top = t0 / z0;

toverz_bottom = t1 / z1;

toverz_left = (y – y0) * (toverz_bottom – toverz_top) / (y1 – y0) + toverz_top;

toverz_bottom = t2 / z2;

toverz_right = (y – y0) * (toverz_bottom – toverz_top) / (y2 – y0) + toverz_top;

toverz_step = (toverz_right – toverz_left) / (xright – xleft);

for(x = xleft, oneoverz = oneoverz_left,

soverz = soverz_left, toverz = toverz_lef,t

x < xright; ++x, oneoverz += oneoverz_step,

soverz += soverz_step, toverz += toverz_step)

{

s = soverz / oneoverz;

t = toverz / oneoverz;

帧缓冲像素[x, y] = 纹理[s, t];

}

}

推广到视口

（1）最终投影点x、y和1/z是线性关系

（2）最终投影点x、y和s/z、t/z是线性关系

下一个要证明的就是从CVV通过视口变换，进入到视口中的图元点，是否也可以使用这个算法。其实稍微想一下就知道，视口变换本身就是一个线性变换（请参考上一篇文章的视口变换一节），因此对于上面推导出的CVV中的投影点

《Perspective Texture Mapping》导读

C落入了N-1像素上，而D落在N像素上，但根据位置关系，C和D都应该属于N纹理像素上。这就需要把小数纹理坐标转换成整数纹理坐标的约定。两个约定方式

（1）       固定z的直线方法：找到多边形的一个特殊方向，在这个方向上，所有投影后的片元的z值都相等。这样就在一个非轴对齐的扫描线上进行纹理坐标线性插值（DOOM使用的就是这个方法）。

（2）       用二次曲线去逼近上述图形。

（3）       用分段仿射纹理映射的方法。对每一行扫描线，取固定长度线段用仿射方式作近似，可以达到一个非常逼近上述图形的曲线。

http://www.chrishecker.com/Miscellaneous_Technical_Articles

0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：704163次
• 积分：8928
• 等级：
• 排名：第2215名
• 原创：37篇
• 转载：984篇
• 译文：0篇
• 评论：48条
最新评论