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

-潘宏
-
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

#### 深入探索透视纹理映射

2016-07-21 23:48:28

#### 软件光栅器六之透视纹理映射

2016-12-01 01:39:16

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

2014-03-29 02:07:35

#### 纹理映射的两种方式

2010-08-09 15:36:00

#### 探索吧！深入理解探索式软件测试

2017年11月08日 2.49MB 下载

#### [读书笔记] 深入探索C++对象模型-第一章《关于对象》

2016-08-21 21:14:18

#### GLSL实现多重纹理映射(例子取自glsl橙皮书第10章)

2010-11-17 17:31:00

#### 《深入探索Android热修复技术原理》—— 带书签版本

2017年07月14日 26.32MB 下载

#### 向量几何在游戏中的应用

2008年09月22日 103KB 下载

#### 深度探索C++对象模型 中文 高清完整PDF版

2014年03月12日 23.45MB 下载