每天30分钟搞Software Rendering--(0)搜集资料,阅读,了解
不学这个实在不行啊!不能这么糊里糊涂地过日子!知其然不知其所以然!有木有!写blog的目的也就是让自己能坚持下去!就从这炎热的夏夜开始吧!
http://en.wikipedia.org/wiki/Software_rendering
Software rendering
In the context of rendering (computer graphics), software rendering refers to a rendering process that is unaided by any specialized graphics hardware, such as a graphics card. The rendering takes place entirely in the CPU. Rendering everything with the (general-purpose) CPU has the main advantage that it is not restricted to the (limited) capabilities of graphics hardware.
Software rendering can be split into two main categories: real-time rendering, and offline rendering. Real-time rendering is used to interactively render a scene, like in 3D computer games, and generally each frame must be rendered in a few miliseconds. Offline rendering is used to create realistic images and movies, where each frame can take hours or days to complete.
下面是puzzy3d的文章,大牛啊!受益匪浅!敬礼!
http://blog.csdn.net/puzzy3d/article/details/2709612
softcore -- CPU rasterization
回到20世纪90年代,PC上进入3D图形硬件光栅化时代。VOODOO取代了CPU 光栅化渲染。随后出现NVIDIA TNT。直到GEFORCE将3DFX吞并。现在GPU的演变已经8年,基于屏幕上每个象素的复杂计算已经可以让老shader程序员忽略C和HLSL的区别。
在下一代mmo 3d引擎工具平台开发之前,有必要重新回到GPU内部,关注几何与光栅管道。越来越复杂的shader效果一切均基于光栅器的运作机理。把工作从GPU搬回CPU目的为使图形开发人员打捞图形学基础,在次世代开发中更好的运用GPU功能。
softcore 是一个软件光栅器。用于从场景物体的geometry transform, clipping,lighting, texture mapping, gouraud shading,到最后光栅化显示的整个图形处理管道技术演示。此项目为了保持代码清晰,省略了所有优化。只在可以使用SIMD和MULTITHREAD的步骤做出了标记。为了便于学习,project整合了id software doom3 sdk中SIMD和数学库代码。
由于是两个星期业余时间制作,时间有限,主要目的在于演示3D加速核心算法,光栅化部分的tc,color数值计算和sampler部分仍然需要进一步tunning。需要去除溢出和浮点转整数规则调整。这些可由感兴趣人员自行修改。
softcore project
done:
* CPU soft rasterization
* Z-buffer
* Gouraud Shading
* Perspective Correct Texturemapping
* Near plane Clipping
* Back face culling(geometry)
* Directional lighting
not do:
x Phong shading/bump mapping
x Bilinear filter
x Mipmap
x Dynamic lightmap
x Vertex color export/import
x Optimization
以下是3DSMAX中场景原图。有了硬件BILINEAR效果还是不一样.....
多数初学者往往陷入3D API细节。认为绘制带有各种效果的三角形就是在做引擎。或者疲于把各种NV SDK或者D3D SDK的sample code加入自己的工程。当然,用orge3d这样的开源渲染器也可以做出《天龙八部》,《巨人》等商业产品,不过,想快速开发符合要求的次世代渲染器,需要大量实际工程方面的工作。针对范围很狭窄的渲染器而言,对渲染效果质量的调整,以及自行开发美术需要的效果,不是照抄fx composer或者render monkey那么简单。由于对GPU工作原理认识不深,对某些效果优化实现背后的理论基础认识不深,都会直接带来在实际工程中开发的障碍。或者导致质量下降。
按说做为图形程序员应该对3D光栅渲染的整条流水线做到倒背如流。不过3D硬件厂商加速了应用的进程。使得在屏幕上绘制三角形这件工作变得容易。也许会忽略人们对实时三维渲染的系统知识体系建立。在高级图形渲染逐渐进入更复杂光照,全局光,基于物理或模拟基于物理的技术层面之后,不对GPU工作机理做到透彻了解,在工作中会举步为艰。因为所有渲染工作逐渐移到GPU寄存器中用可编程代码进行。整条管道,从Geometry transform,clipping,vertex lighting,到pixel的shading都由程序员控制。但GPU仍然自动进行了screen space的一些工作。包括clipping,扫描线线性插值,texture sampler等。这是光栅器能够数百倍快于raytracing渲染的本质。但如果图形程序员不了解被GPU自动进行的工作,也会象C++程序员不了解缺省构造函数一样盲目。
举例,众所周知普通的shadowmap 完全不具备工程实用性。最重要的是因为出于内存限制,shadowmap texture尺寸不可能满足实际渲染精度需要。并且收到三角形在camera space中斜率影响巨大。Depth Bias问题的本质是什么。与何参数相关。目前采用的各种调节depthmap渲染精度的方法背后理论依据是什么。Perspective shadowmap,light space shadowmap等各自优化方法会遇到什么问题,各自优缺点,以及工程中如何tunning,尤其用于self-shadow的问题。基于PCF(percentage closer filter)的各种软阴影算法的应用。
在对bumpmap技术改进过程中,在tangent space使用ray-tracing的reliefmap以及relaxed cone stepping relief map,以及带有凹凸轮廓的releif map技术。以及parallax map,和其变种dynamic parallax occlusion map。如何在pixel级别用bilinear gouraud 和这些象素级别lighting进行LOD,如何改进parallax map随视角变化而产生纹理浮动的问题,如何调整线性迭代和2分查找对效率和效果的影响。甚至从本质上了解tangent space,phong shading,都要从软件光栅机理开始。
softcore -- CPU rasterization Demo&Src from H3D
http://www.horizon3d.com.cn/news.asp
vc7.1的 MFC project
像素的buffer使用了D3D9的frame buffer surface。主要是为了以后CPU/GPU共同光栅化/raytracing 混合渲染实验的方便
目前只支持透视校正纹理映射的三角形光栅器
只简单的支持3DS文件
图片支持使用ALT的 CImage
没有做任何优化...
代码花了两个星期的晚上。技术细节有空再写
集成了ID SOFTWARE 公司DOOM3 SDK中 idlib 代码
如果有人有兴趣把SIMD优化加上,我再弄个SVN吧.....
【熊猫注:要理解这些东西,买书找补是必不可缺的,大学里没好好学习,现在该补上了!!!那时感觉用不上,实在学不下去,没人指点,迷茫啊!总是要跟具体的需要结合起来才有兴趣和动力去学习!】
几本3D编程相关的书
《3D游戏编程大师技巧》是一本好书,宏篇巨著。所有的核心原理都掰得很碎。从理论证明到代码实现全部细致周详。而且有中文版。英文是《trick of 3d game programming gurus - advanced 3d graphics and resterization》。内容涵盖广泛。在900多页想把游戏编程,高级计算机图形学,光栅化原理和实现,线性代数与解析几何都讲清楚,野心非凡。当时邮电出版社要我翻译时,由于精力有限,这本书的厚度和广度让人望而却步。所以选了GPU GEMS来翻译。当时GPU的发展正在如火如荼,3D硬件从简单的光栅化处理器发展为可编程的专用处理器。但这本书则专门介绍3D的软件实现。和当时的趋势有些背道而驰。不过现在翻了下。感到在使用D3D GL API做硬件3D绘图之前,把光栅化所有原理和背后理论体系都搞清楚,将会使学习和开发进度成倍。涉及高级shader的技术也会进展迅速。 大学本科的计算机图形学是门初级入门课程。只能概要的建立一个知识框架。在应用技术方面,想在图形技术领域有所收获,要往里填补的理论知识很多。读过这本书,比较强的感受是如果从一开始建立比较牢固的理论体系,之后的技术研发速度会很快。实时三维图形学只是一个旁支。图形学理论知识体系对它非常重要。 想要更好的利用不断发展的GPU,对GPU工作原理,光栅化过程,背后的数学知识,都有深入了解的必要。这几年工作中,体会加深。 最近偶然翻到《数值分析》对常微分方程的数值解法,这是物理引擎的积分求解理论基础。大学都教授的这门课程忘差不多了。看siggraph创立physics based modeling的paper时感到吃力。用GPU在shader里使用欧拉积分做布料也是一种很简化的数值计算方法。在书店找到几本计算几何学。是物理引擎碰撞部分的理论基础。另外物理引擎涉及到的一块是理论力学的刚体动力学部分。具体计算还要使用LCP(线性互补问题)的解法。涉及到软体的物理模拟情况就更复杂一些。感觉短时间是不太容易都找补全。用一用商业的AGEIA物理引擎可能只需要高中的数学勉强就够了。不过真要做一套,没有一些数学底子还是很困难的一件事。传闻盛大的疯狂赛车根本没用物理。当然,当初的玛利奥赛车也不用。所以说游戏制作是个很玄妙的事。。。和技术似有关似无关。。。。。。 《3D游戏编程大师技巧》的作者是个非常专业的技术人员。并且在介绍技术时,对重要的原理和公式都有推导和论证的过程。这样的作法在技术应用书籍里其实很少。多数初等技术书籍都在讲述一个API有几个参数每个参数什么意思。这本书实际在用CPU实现一个简化GPU。作者一看就是对3D RENDERING和游戏编程每个细节都有大量实践。所以从理论知识到技术实现细节,包括优化,讲解很通透。做为大学游戏专业的教材是最适合不过。
在查阅书中用到的数学公式时,发现另外一个堪比《REALTIME RENDERING》的经典书籍:《Mathematics.for.3D.Game.Programming.and.Computer.Graphics》。这本书比《3D ENGINE DESIGN》要平易近人得多。本着实用的角度,用浅显易懂的描述语言对游戏和计算机图形学用到的数学知识一一进行讲解和证明。比起另外一本经典著作《3D ENGINE DESIGN》,其作者是个博士,全书都用教科书般精确简练的数学语言描述3D引擎理论体系,对没有受过专门数学训练的人读起来都是颇为吃力。《MATH FOR 3D GAME AND CG》则是从实际工程技术角度出发,用高中数学课本形式的语言详细介绍了3D图形编程中所用到的数学知识,同时还保持了广度和深度。同样类型的书籍还有《PHYSICS BASED RENDERING》和《PHYSICS BASED ANIMATION》。当然知识体系更深入。
看全局光照时,PRT着实让数学不好的人头大。手头必须常备微积分,微分方程,概率学,傅里叶变换等一些书籍。残缺不全的知识体系很挠头。这是任凭多少技术实践也无法倒推补全的。中间发现一套非常好的微积分教程。俄国菲赫金哥尔茨的《微积分学教程》全3卷。我感觉大学要是用这个当教材我现在的日子还能过得稍微舒服一点点。
【熊猫注:说到书,索性再粘贴一篇,方便经常温习!貌似对《Head First Design Patterns》推崇备至啊,好好读读!】
书
最近买了不少游戏编程相关的书,十分应景儿。只要愿意等,甚至省却了海外用美元购买的麻烦。祖国劳动人民群众玩游戏的设备走在世界风潮脚后跟,技术该前该后,有待商榷。况且游戏好坏,技术的侧重点并不在新。最重要的是,中文阅读技术书籍,感官体验甚好。
对并行程序,《并行设计模式》,《WIN32多线程编程》,《并行程序设计》,《WINDOS系统编程》(Johnson M.Hart) 介绍的比较好。尤其《并行设计模式》,犹如《设计模式》于OO。INTEL的《多核程序设计技术》也还可以,不过做为面向工程的一本书,略显松散,不少地方潜尝而止。也许和翻译也有关系。翻译有时走偏。
虽说网络盗版为常态,但电脑阅读质量比较低。面试时问到哪本书是“网上找来看了一下”,基本可认为没读。不过有本《C++ 面向对象多线程编程》没的买,里面包罗万象讲了从多态,组件,死锁,到封装并行编程所需的对象和框架。甚是奇怪。总之给人一种云山雾罩的错觉。搞不清是讲C++还是组件还是并行编程还是什么。网上有评是垃圾。外来书也有垃圾,外国人也有江湖道士。中国早期跑江湖的都被希望出版社搜罗去了。这作者不会和希望出版社有什么瓜葛吧。
《GPU GEMS2》以闪电速度翻译完,被清华出版社压了好一阵才出来。翻译质量不错。令人欣喜的邮电出版社出了《GAME PROGRAMMING 5》和6 。发现其非常务实的把GRAPHIC篇章让给了SHADERXn(1<=n<=6) 和GPU GEMSn(1<=n<=3)系列(当然投稿质量也下降了),不再有大篇幅的图形技术。在游戏编程各个部分都有涉及。 GEMS6 开篇就讲了一下无锁编程。然后是OPENMP 使用。GPG系列总能让人闻到当前GAME TECH的味道。
清华出版社的东西良莠不齐。远远不在机械出版社,电子工业出版社一个层次。所谓《3D游戏开发大全(高级篇)》,其实就是TORQUE SCRIPT使用手册,充满了江湖术士混吃混喝的味道。做为实现自己引擎的脚本系统接口参考可能有用。。。
INTEL《多核技术》的另外一本《软件优化技术》非常过瘾。从软到硬的各个层面介绍软件性能解决手段的问题。由创造技术的人讲解技术意义非凡。
最有趣的和值得推荐的书要数这个: <HEAD FIRST 设计模式 >
从来没有一本DESIGN PATTERN的书这么牛逼的深入浅出的讲解了“封装变化”这一精要。而不是永远腻歪在教科书的“多态”“继承”那些傻乎乎词汇上解释。用C++写游戏的程序员真该多读几遍《DESIGN PATTERNS》。很多熟练使用C++技法的游戏程序也许不是应对变化的基础上编程,制造灾难。书店里这本书被摆在角落,用塑料膜封上。很可惜。这样的优秀大作,当培训教材都能给游戏公司创造无尽财富。
要是一开始就有人拿几本书砸我(C++ PROGRAMMING LAUNGUAGE, C++ PRIMER, EFFECTIVE C++, DESIGN PATTERNS。。。),我相信能比现在早好几年写出不那么糟糕的代码。
其实光从C++无数暗礁爬出来混口饭就不容易。看看 EFECTIVE C++,MORE EFFECTIVE, EXCPETIONAL C++ MORE EXCEPTIONAL ,高质量C++ 那些成百上千的条目。我觉着那些写诸如《21日精通C++》的都该在封面上加一条“除非你丫智商250”。那些自己没有写过五万行C++代码的所谓“老师”,我觉着每天都在恶行不断。。。
计算机书可分两种,时髦的,和不时髦的。由时髦的技术评论家撰写的一般都是前者。他们能从长期观察中得到当前国情中,要糊口要发家,可是性格内向举止局促、内心桀骜可心态混乱的软件人员最缺什么。于是成为知名撰稿人。 国外发PAPER多的,做成功项目知名的, 发明技术研究科学的,是常发言的。国内因为自己没发展太多计算机相关的科学,也没什么技术,所以发言的以专注传道授业者多。当然和经济发达程度相关。月球都能去, 我国科和技发达也是早晚的事。这个不急,还是猪肉要紧。所以《软件架构设计》由《程序员》撰稿人来写,很符合国情。标题很好很强大。 我买了。期望对下一代引擎设计有帮助。起码,我要尝试让同事该知道这封面的标题是个很时髦很有猪肉购买力的词汇。
以上黑体字书籍通读且牢记,理解且实践后,做为C++游戏程序工程师,本公司一定以国内高薪期权而聘用之。 当然,话说回来了,国外国内上市游戏公司也应该不会拒之门外。。。
http://blog.csdn.net/puzzy3d/article/details/2613128
透视投影,与Z BUFFER求值
透视投影,与Z BUFFER求值 为什么有透视。因为眼球是个透镜。假如地球生物进化的都靠超声波探测空间,那也许眼睛就不会有变成球,而是其他形状... 为什么有人玩3D头晕?其中一个重要的作用是,眼球不完全是个透镜。所以当视野大于60度,屏幕四周投影的变形就比眼球投影视网膜利害多。而且人脑习惯了矫正眼球投影的信息。突然有个屏幕上粗糙的模拟眼球成像,大脑还真一时适应不了。
Z BUFFER数值计算,以及PERSPECTIVE PROJECTION MATRIX设置,使用D3D或者OPENGL,可以直接让显卡完成这些工作。但是弄清Z BUFFER如何计算,以及PROJECT MATRIX的原理。对于进行各种高级图像处理,非常有用。例如shadowmap的应用。目前为了得到好的shadowmap,很多人在如何加大shadowmap精度做了很多努力(改变生成shadowmap时的perspective project matrix来生成精度更合理的shadowmap) 。比如透视空间的perspective shadow map,light空间的Light-space perspective shadow,perspective shadowmap变种Trapezoidal shadow maps,改正交投影为对数参数投影的 Logarithmic Shadow Maps。另外,Doom3中shadow volume采用的无限远平面透视矩阵绘制stencil shadow volume。都需要对perspective projection有透彻了解。
以下描述z buffer计算以及perspective projection matrix原理。
假设坐标在 world space 是 Pw = {Xw,Yw,Zw}
经过camera space transform 得到 Pe = {Xe,Ye,Ze}
然后经过project transform 转为 device space,这里假设转为 Zp 范围 [-1,1](OPENG的Z BUFFER)
Pe在near平面的投影为: Xep = n* Xe/(-Ze) (n为近平面到eye距离). 注意这里OPENGL 右手系camera space是Z轴负方向为眼睛看的方向。当计算投影时,x,y都应该除以一个正的数值。所以Ze取负。
这么做的目的是为了让在view space中所有在视锥平截体内的点,X数值投影到近平面上,都在near平面上的left到right。接下来是求最后在device space里x,y,z的数值,device space是坐标为-1到1的立方体。其中x/2+0.5,y/2+0.5 分别再乘以窗口长宽就是屏幕上像素的位置。那么屏幕这个像素的Z数值就可以按以下方法求出:需要把view space中(left,right,top,bottom,near,far)的frustum转换到长宽为(-1,1)的正方体内,就是说,把Xe,Ye,Ze都映射到[-1,1]的范围内。前面已经求出了Xe在camera space near平面上的投影Xep。这个投影的数值就是在frustum平截体near平面上的位置。把平截体near平面映射到-1,1的正方形很简单,X方向按如下映射: Xp = (Xep - left)*2/(right-left) -1 。
当Xep在left到right变化时,Xp在-1到1变化。Xp就是Z BUFFER数值。因为显卡硬件(GPU)的扫描线差值都是透视矫正的,考虑投影后,顶点Xp和Yp都是 1/(-Ze) 的线性关系。那么在device单位立方体内,Zp 的范围在[-1,1]之间,Zp也就是Z BUFFER的数值。根据前面推导,要保证透视校正,Zp也是以1/(-Ze)的线性关系。即,总能找到一个公式,使得 Zp = A* 1/(-Ze) + B。
也就是说,不管A和B是什么,在Z BUFFER中的数值,总是和物体顶点在camera space中的 -1/Ze 成线性的关系。 我们要做的就是求A 和B。求A和B,我们利用以下条件:当Ze = far 时, Zp = 1 当Ze = near时,Zp = -1(在OPENGL下是这样。在D3D下是Zp =0) 这实际是个2元一次方程。有了两个已知解,可以求出A和B。OPENGL下, A = 2nf/(f-n), B = (f+n)/(f-n)
这样一来,我们就知道Z BUFFER的数值如何求得。先把物体顶点世界坐标Pw变换到camera space中得到Pe。然后再经过透视投影变换,求得Ze->Zp的数值。把这个数值填入Z buffer,就是显卡用来比较哪个像素在前,哪个像素在后的依据了。这也就是为什么near和far设置不合适的时候,很容易发生z fighting。一般情况下,离屏幕很近的一段距离,已经用掉了90%的z 浮点精度。在用于渲染视角里中远距离的场景时,深度的判别只靠剩下的10%精度来进行。具体推导可以看看http://www.cs.kuleuven.ac.be/cwis/research/graphics/INFOTEC/viewing-in-3d/node8.html
逐渐被D3D抛弃的W BUFFER,场景远近与W数值是线性的。即,100米的距离,在near=1 far=101时,每一米在D3D W BUFFER的表示中,就是差不多 1/100 那么大。但是在Z BUFFER中就完全不是均匀分配。
下面考虑perspective projection matrix。根据线性代数原理,我们知道无法用一个3x3的matrix对顶点(x,y,z)进行透视映射。无法通过一个3X3的矩阵得到 x/z 的形式。进而引进齐次坐标矩阵---4x4 matrix。顶点坐标(x,y,z,w)。 齐次坐标中,顶点(x, y, z, w)相当于(x/w, y/w, z/w, 1)。 看到这个顶点坐标,我们会联想到前面我们最终求出的z buffer数值Zp和单位device space中的Xp坐标。利用矩阵乘法,可以得到一个矩阵Mp,使得(Xe,Ye,Ze,1)的顶点坐标转换为齐次坐标规一化后的 (Xp,Yp,Zp,1) 。 即: Vp = Mp * Ve . Vp是单位设备坐标系的顶点坐标(Xp,Yp,Zp,1)。Ve是camera space顶点坐标(Xe,Ye,Ze,1)。
考虑 Xp = (Xep - left)*2/(right-left) -1 (Xep = -n* Xe/Ze) Yp = (Yep - left)*2/(right-left) -1 (Yep = -n* Ye/Ze) Zp = A* 1/Ze + B
为了得到4X4 MATRIX,我们需要把(Xp,Yp,Zp,1)转为齐次坐标 (-Xp*Ze, -Yp*Ye, -Zp*Ze, -Ze) 。然后由矩阵乘法公式和上面已知坐标,就可以得到PROJECTION MATRIX。
Xp*(-Ze) = M0 M1 M2 M3 Xe Yp*(-Ze) = M4 M5 M6 M7 x Ye Zp*(-Ze) = M8 M9 M10 M11 Ze -Ze = M12 M13 M14 M15 1
这里拿 M0, M1, M2, M3 的求解来举例: M0* Xe + M1* Ye + M2* Ze + M3= (-Ze)*(-n*Xe/Ze-left )*2/(right-left) +Ze M1 = 2n/(right-left) M2 = 0 M3 = (right+left)/(right-left) M4 = 0
最后得到Opengl 的 Perspective Projection Matrix:
[ 2n/(right-left) 0 (right+left)/(right-left) 0 ] [ 0 2*near/(top-bottom) (top+bottom)/(top-bottom) 0 ] [ 0 0 -(far+near)/(far-near) -2far*near/(far-near) ] [ 0 0 -1 0 ]
D3D 的左手系透视投影矩阵和OPENGL有以下区别。 1, D3D device space 不是个立方体,是个扁盒子。z的区间只有[0,1] 。x,y区间还是[-1,1] 2,D3D的camera space Z轴朝向正方向,计算camera space中投影时不用 Xep = n*Xe/(-Ze), 而是 Xep = n*Xe/Ze 3,D3D中,从camera space的视椎平截体到device space的单位体(扁盒子)摄影,采用了很奇怪的作法。把frustum右上角映射为device单位体的(0,0,0)位置
请RE D3D PERSPECTIVE PROJECTION MATRIX推导过程~
后面若有时间继续 透视校正texture mapping,phong shading以及bump mapping等per-pixel processing光栅化