📄 tutorial_22.htm
字号:
return status;
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_22_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_22_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_22_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_22_files/l.png"><img src="Tutorial_22_files/l.png"></td>
<td valign="top" width="100%">下面是窗口大小变化函数,没有任何改变。
<p>接下来是绘制一个立方体的函数,它使用常规的方法绘制。</p></td><td background="Tutorial_22_files/r.png"><img src="Tutorial_22_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_22_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_22_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_22_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre>void doCube (void) {
int i;
glBegin(GL_QUADS);
<font color="#ffffaa">// 前面</font>
glNormal3f( 0.0f, 0.0f, +1.0f);
for (i=0; i<4; i++) {
glTexCoord2f(data[5*i],data[5*i+1]);
glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);
}
<font color="#ffffaa">// 后面</font>
glNormal3f( 0.0f, 0.0f,-1.0f);
for (i=4; i<8; i++) {
glTexCoord2f(data[5*i],data[5*i+1]);
glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);
}
<font color="#ffffaa">// 上面</font>
glNormal3f( 0.0f, 1.0f, 0.0f);
for (i=8; i<12; i++) {
glTexCoord2f(data[5*i],data[5*i+1]);
glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);
}
<font color="#ffffaa">// 下面</font>
glNormal3f( 0.0f,-1.0f, 0.0f);
for (i=12; i<16; i++) {
glTexCoord2f(data[5*i],data[5*i+1]);
glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);
}
<font color="#ffffaa">// 右面</font>
glNormal3f( 1.0f, 0.0f, 0.0f);
for (i=16; i<20; i++) {
glTexCoord2f(data[5*i],data[5*i+1]);
glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);
}
<font color="#ffffaa">// 左面</font>
glNormal3f(-1.0f, 0.0f, 0.0f);
for (i=20; i<24; i++) {
glTexCoord2f(data[5*i],data[5*i+1]);
glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);
}
glEnd();
}
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_22_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_22_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_22_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_22_files/l.png"><img src="Tutorial_22_files/l.png"></td>
<td valign="top" width="100%">现在到了OpenGL的初始化函数,它和前面的教程基本相同,只是添加了以下代码:</td>
<td background="Tutorial_22_files/r.png"><img src="Tutorial_22_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_22_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_22_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_22_files/br.png" height="28" width="28"></td></tr></tbody></table><font color="#aaffaa" size="3">
<pre> multitextureSupported=initMultitexture();
initLights();
</pre>
</font><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_22_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_22_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_22_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_22_files/l.png"><img src="Tutorial_22_files/l.png"></td>
<td valign="top" width="100%">这里我们完成了95%的工作,下面我们来解释上面提到的原理。 <p>开始理论讲解(凹凸映射)<br>
如果你安装了Powerpoint-viewer,下面是一个讲解凹凸映射原理的PPT,你可以下载后慢慢研究:<br>
<a href="http://www.owlei.com/DancingWind/Res/EmbossBumpMapping.ppt">凹凸映射 作者Michael I. Gold, nVidia 公司</a><br>
如果你没有安装Powerpoint-viewer,我把它转换为Html格式,现讲解如下:</p>
<p><strong><u>凹凸贴图</u></strong><br>
Michael I. Gold<br>
NVIDIA 公司</p>
<p><strong><u>凹凸贴图 </u></strong>
</p><p>真实的凹凸贴图是逐像素计算的
</p><ul>
<li>光照计算是按每个象素点的法向量计算的
</li><li>巨大的计算量
</li><li>更多的信息可以看: Blinn, J. Simulation of Wrinkled Surfaces. Computer Graphics.
12, 3 (August 1978), 286-292
</li></ul>
<p>凹凸贴图是在效果和精度之间的一个折中
</p><ul>
<li>只能对漫射光计算,不能使用反射光
</li><li>欺骗视觉的采样
</li><li>可能运行于当前的硬件上
</li><li>如果它看起来很好,就干吧
</li></ul>
<p><strong><u>漫射光的计算</u></strong> </p>
<p>C = (L*N)*Dl*Dm
</p><ul>
<li>L 顶点到灯之间的单位向量
</li><li>N 顶点的单位法向量
</li><li>Dl 灯光的漫射光颜色
</li><li>Dm 顶点材质的漫射属性
</li><li>凸值 逐像素改变N值
</li><li>凹凸映射 改变(L*N)的值
</li></ul>
<p><strong><u>近似的漫射因子 L*N</u></strong></p>
<p>纹理图代表高度场
</p><ul>
<li>[0,1] 之间的高度代表凹凸方程
</li><li>首先导出偏离度m
</li><li>m 增加/减少基础的漫射因子Fd
</li><li>(Fd+m) 在每一像素上近似等于 (L*N)
</li></ul>
<p><strong><u>偏移量m的导出</u></strong></p>
<p>偏移量m的近似导出
</p><ul>
<li>查找(s,t)纹理的高度H0
</li><li>查找(s+ds, t+dt)纹理的高度H1
</li><li>M近似等于H1-H0
</li></ul>
<p><u><strong>计算凹凸量</strong></u><font size="-1"><br>
<img src="Tutorial_22_files/image002.jpg" border="0" height="48" width="140"> <br>
<br>
1) 原始凸起(H0). <br>
<br>
<img src="Tutorial_22_files/image004.jpg" border="0" height="91" width="216"> <br>
<br>
2) 原始的凸起(H0)向光源移动一小段距离形成第二个凸起(H1)<br>
<br>
<img src="Tutorial_22_files/image006.jpg" border="0" height="48" width="173"> <br>
<br>
3) 用H1凸起减去H0凸起 (H1-H0)<br>
<br>
</font><b><u>计算灯光亮度</u></b><font size="-1"><br>
<br>
</font>计算片断的颜色Cf</p>
<ul type="disc">
<li>Cf = (L*N) x Dl x Dm</li>
<li>(L*N) ~ (Fd + (H1-H0))</li>
<li>Ct= Dm x Dl </li>
<li>Cf = (Fd + (H0-H1) x Ct</li>
<li>Fd等于顶点法线与灯光的向量的乘积</li>
</ul>
<b><u>上面就是全部么? 太简单了!</u></b><br> <br>
我们还没有完成所有的任务,还必须做以下内容:
<ul type="disc">
<li>创建一个纹理</li>
<li>计算纹理坐标偏移量ds, dt</li>
<li>计算漫射因子Fd</li>
<li>ds, dt ,Fd都从N和L导出</li>
<li>现在我们开始做一些数学计算</li>
</ul>
<b><u>创建纹理</u></b><br> <br>
保存纹理!
<ul type="disc">
<li>当前的多重纹理硬件只支持两个纹理</li>
<li>偏移值保存在alpha通道里</li>
<li>最大凸起值为 = 1.0</li>
<li>水平面值为 = 0.5</li>
<li>最小值为= 0.0</li>
<li>颜色存储在RGB通道中</li>
<li>设置内部颜色格式为RGBA8 !!</li>
</ul>
<b><u>计算纹理偏移量</u></b> <br> <br>
把灯光方向向量变换到一个笛卡尔坐标系中
<ul type="disc">
<li>顶点法线为z轴</li>
<li>从法线和视口的“上”向量导出坐标系</li>
<li>顶点法线为z轴</li>
<li>叉乘得到X轴</li>
<li>丢弃“上”向量,利用z,y轴导出x轴</li>
<li>创建3x3变换矩阵Mn</li>
<li>变换灯光方向向量到这个坐标系中</li>
</ul>
计算纹理偏移量<br> <br>
使用法向坐标系中的向量作为偏移量
<ul type="disc">
<li>L'= Mn x L</li>
<li>使用L’.x, L’.y 作为 ds, dt</li>
<li>使用 L’.z 作为漫射因子!</li>
<li>如果灯光方向接近垂直,则L’.x, L’.y 非常小</li>
<li>如果灯光方向接近水平,则L’.x, L’.y 非常大</li>
<li>L’.z小于零的含义?</li>
<li>灯光在法线的对面</li>
</ul>
在TNT上的实现<br> <br>
计算向量,纹理坐标
<ul type="disc">
<li>设置漫射因子</li>
<li>从纹理单元0取出表面颜色和H0值</li>
<li>从纹理单元1取出H1值</li>
<li>ARB_multitexture 扩展</li>
<li>混合纹理扩展 (TBD)<font size="-1"><br>
</font></li>
<li>混合0 alpha设置:</li>
</ul>
<ul type="disc">
<li>(1-T0a) + T1a - 0.5 </li>
<li>T1a-T0a 映射到[-1,1],但硬件把它映射到[0,1]</li>
<li>T1a为H1的值,T0a为H0的值</li>
<li>0.5 平衡损失的掐除值</li>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -