参考资料:
book:[计算机图形学]
book:[DirectX9.03D游戏开发编程基础-13摄像机]
http://wenku.baidu.com/view/a08bf9ee4afe04a1b071decc.html(绕任意轴旋转)
http://wenku.baidu.com/view/700512d5360cba1aa811da70.html(视口矩阵)
http://blog.csdn.net/popy007/article/details/1797121(投影矩阵)
http://blog.csdn.net/popy007/article/details/4091967(投影矩阵)
http://blog.csdn.net/popy007/article/details/5556639(纹理映射)
http://blog.csdn.net/popy007/article/details/5570803(纹理映射透视纠正)
http://hi.baidu.com/tinya/blog/item/37f0ffdeea8dd85ecdbf1a6b.html
http://www.chrishecker.com/Miscellaneous_Technical_Articles
http://blog.csdn.net/popy007/article/details/5556639
http://zoomquiet.org/res/scrapbook/ZqFLOSS/data/20100709102006/
5.20 搭建应用程序框架(api画点)
5.20 向量和矩阵定义
5.20 顶点定义
5.20 三角形定义
5.20 WVP矩阵变换
5.20 vp空间变换
5.21 直线绘制(画线)
5.21 三角形填充(画面)
5.21 数据结构调整(调整数据结构定义,方便计算。)
5.22 blinn-phong光照模型(光照)
5.22 模型定义(渲染Cube)
5.23 模型空间到世界空间的变换(仿射变换基础实现)
5.23 gouraud着色(渐变填充)
5.23 贴图定义(暂时用png贴图)
5.23 纹理映射
5.24 透视纠正
5.24 接口修正(从基于三角形的,改成基于顶点的,再考虑批量处理顶点和面检索相关,为裁剪打基础)
5.24 背面剔除(定义摄像机的朝向)
5.24 CVV裁剪
5.24 vp裁剪
***5.25 隐藏面消除(Z-buffer) [有效率问题,暂时关闭了]
5.25 摄像机操作
5.28 建立SVN仓库
5.28 排查uv错位
5.28 2D直线裁剪算法[不行,即使裁剪了,确定新线段的方法也过于复杂,可能想错了](使用插值所有像素点的cvv坐标,判断-1,1范围内的点)
5.28 排查矩阵相关计算错误---1、vec4*mat44写错了,实现的是列主矩阵计算。
5.29 排查矩阵相关计算错误---2、vp矩阵[1,1]写错了,多取了一次反;
5.29 排查背面剔除错误(背面剔除需要在透视除法之后再做)
5.29 整理基础数据结构,由class改为struct。
5.29 增加TestUnit的UI
***5.29 非常近的时候,uv计算会出错[]
5.30 增加profile工具,查性能问题
5.30 Profile数据组织
5.30 Profile数据显示
5.31 加profile,分析具体性能问题(绘制640*480个点效率低下)
5.31 引入ddraw surface做对照试验[没弄好,先弄GDI的方式吧].
5.31 修改GDI方式画点的流程,写入内存块,然后整体拷贝到rendertarget。(因为这里有个lock显存的问题)(290ms)
6.01 让ddraw surface可用,完成对照组。(200ms,比gdi稍微快一点)
6.01 提高绘制点的效率(采用锁一辈子离屏表面的方式,效率从200ms-->57ms)
6.01 修正颜色值错误
6.01 优化填充三角面时的数据结构(效率上没明显变化,数据量太少,最多480)
6.01 优化贴图采样(减少了22ms)
***6.01 优化线性插值(减少是减少了,13ms,但是结果不正确)
关于透视投影纹理映射我有几个问题:
1、在视口空间做的uv插值计算的结果,怎么能对应到某个像素点呢?一个是(x(float),y(int))这个点得出的uv, 一个是vp空间里光栅化的点(x(int),y(int));
2、假设直接视为这个uv就为光栅化的像素的uv坐标,那行扫描的时候,整行的像素的uv坐标全部关于x线性插值吗?感觉这也不对啊,难道是关于1/z?
3、(理解的对不对?)计算出一个像素点的uv坐标之后([0,1]),乘以贴图的尺寸,从而转换到贴图空间,这时要偏(-0.5,-0.5),用于uv坐标和屏幕坐标对齐[疑惑4],然后就是贴图采样点事情了?
4、如果要-0.5, 那假设有个像素的u坐标为0.0,转换到贴图空间后还是0.0, 当-0.5之后,如果贴图采用环绕寻址方式,岂不是对应的不是0图素的颜色值,而是9.5(贴图宽度为10)图素的颜色值了?
5、采用-0.5偏移的计算体系里,使用的是上取整,所以应该是10这个颜色值? 如果是下取整,岂不是9了,和0差的更远了啊?
6、(理解的对不对?)找出uv坐标对应的图素之后,使用贴图采样算法,比如取左右2个点做3点平均/上下左右4个点做5点平均吗?
7、这就是所谓的2x采样,4x采样?
8、如果像素点的u坐标为0.0,采用哪个图素?0号还是10号呢? 如果是1.0呢?
顶点数据里有uv, 这个是在生产阶段就有的,美术称为称展uv。
uv在顶点做 wvp /w vp 变换的时候,值不变。一直带到光栅化步骤
插值可得出每像素的uv,根据这个uv计算贴图图素,再和光照颜色*,得出最终颜色。
c#的赋值,真晕人
我的矩阵坏了...x 朝左...貌似变成右手坐标系了。
正在学习矩阵推导,准备修好它
使用的是应该是dx文档里的矩阵。不知道为什么会这样。
[ 2012-05-25 ]
kun(小龙) 00:38:30
我知道哪错了,我把摄像机的 right,up,look 和 观察坐标系的uvn 搞混了。 也就是把观察坐标系各轴向(uvn)在世界坐标系里的表达(U(x,y,z),V(x,y,z),N(x,y,z))搞混了,实际上我还没定义摄像机的朝向,只是定义了uvn在xyz坐标下的表达。
所以让我以为 look是朝向的时候, 我让它朝屏幕里面看..就是unit_z, 结果把整个观察坐标系反向了,相当于绕Y轴旋转了180度,而我的投影矩阵是按左手坐标系推导的,所以投影过来的东西都反了。
)
kun(小龙) 00:42:11
uvn在xyz坐标下的表达==>uvn单位向量在xyz坐标下的表达.
kun(小龙) 09:16:19
裁剪是个大坑啊.....
一些穿过frumst的面或者直线,如果不在3D空间做裁剪,会被投影,就像投影到虚投影面上一样。这时再做2D裁剪,已经来不及了。必须在CVV那步处理好,确保所有参与计算的顶点的坐标都在 -1,1 之间,不然就会出虚投影(我自己的叫法)的问题。
一个3个顶点都在CVV外面的三角面大概(没仔细算)最多能被cvv裁出6个顶点,需要用这些顶点再构成三角面,同时保持和原三角面的法向量一致。如果是gouraud着色,同时还需要插值出新顶点的光照颜色。
e... 这样的话2D裁剪岂不是没用了。。所以肯定我哪有错...但是虚投影肯定存在。
也许是这样:如果一个面,或者线段,有顶点落在了虚frusmt(frusmt的反向延长体)的空间内,就必然得计算新顶点,不然就让它投影,交给2D去做。因为2D更好算。
==,好像还和裁剪平面有关系。
我用的是最最基本的逐点判断法做2D裁剪,就是看是不是在窗口内。
结论刚才试出来了:
在view空间(还没变换成cvv的那个),如果有点在eye的后方(n轴),就必须做3D裁剪,否则会出虚投影问题。
我的做法是,在cvv里,判断下z值,如果z<-1,就不要这个点了---超级简陋的3D裁剪。
kun(小龙) 09:16:40
结果正确。摄像机随便移动也不会出现虚投影了。
kun(小龙) 10:13:49
还有个问题,我的cube在屏幕边缘变形严重...应该哪有问题
kun(小龙) 10:14:13
就好像不是线性的一样。
kun(小龙) 10:18:40
cube这东西贴了纹理后,不做遮挡面消除没法看....各种穿插
kun(小龙) 10:18:47
眼睛都花了..
kun(小龙) 12:18:23
各种坑啊...贴图出来的纹理很诡异.... 像素不是均匀分布的,中间密度比两边大。。。
kun(小龙) 12:18:47
肯定和cube在屏幕边缘变形严重是一个问题
kun(小龙) 12:18:51
同样的矩阵
kun(小龙) 12:24:01
哦,fov ,应该用 aspect 计算。 呵呵,想起来以前查的BUG了
.牛顿顿- 12:39:34
变形严重,估计是 view matrix错了。
kun(小龙) 14:00:57
哭死了...扫描行颜色插值的时候,我增加了 y0 = y1 情况下的处理,把 按x 插值的代码拷贝了一份。。结果替换(x,y)的时候...只替换了一部分....实在是太多x,y了,眼睛瞎了..
kun(小龙) 14:03:11
关系就变成 y = 1/x 了, 所以 中间像素特集中...
kun(小龙) 14:04:14
数学怎么都是一致哦,连错误也是,如果早能意识到是倒数,直接查线性插值的地方就应该能法线
kun(小龙) 14:27:50
光8个顶点,没办法完美表达uv, 貌似需要更多的顶点,或者加入多层UV特性,才能让一个图片在6个面都显示的一样。
是不是 face 上有个属性, 决定顶点启用哪套uv坐标呢
kun(小龙) 14:34:10
和邱确认了,没有~ 加点吧
kun(小龙) 15:40:05
我的摄像机没记录旋转,结果搞乱了view空间的坐标轴,变成不是和xyz轴向平行的了
kun(小龙) 15:40:19
结果viewMatrix无情的错了
kun(小龙) 16:00:43
你看我理解的对不对:
记camera的旋转 : Rx, Ry,Rz 为绕x,绕y,绕z的旋转量。
每次旋转都只转一个分量(Rx+角度a, Rx')
然后按 Rx' Ry' Rz' 的顺序对 摄像机的 look,和right轴进行旋转,up由look.corssprodect(right)得出。
这样?
kun(小龙) 16:02:06
一次性构造矩阵,只能构造“按 Rx' Ry' Rz' 的顺序” 这3个旋转矩阵吧。位置什么貌似不需要啊,旋
投影到2D的三角形被裁剪后,最多会生成6个边,假设顶点编号为123456,怎么确定各个边的,比如 是 1-2 3-4 5-6 2-3 4-5 6-1 而不是 1-3 2-4 5-1 6-2呢?点的分布需要有规则吧,一般这个规则是什么?
想明白了,由法线。因为正面是 v0->v1 和 v0->v2确定出来的,所以切出来的新顶点也满足一定的排列顺序 . 和v0,v1,v2的值无关,只和顺序有关
我想的办法特别麻烦,需要根据N种情况作判断
kun(小龙) 14:00:34
新端点为123456,新线段则为 2-3,4-5,6-1。
以2-3线段举例,情况可能为
不包含角:线段为2-3
包含1个角:左上、右上,左下,右下,线段为2-角,角-3
包含2个角:左(上下),右(上下),上(左右),下(左右),线段为:
2-角1,角1-角2,角2-3.
这样就能得到新线段了。