Long time not to update. H3D studio now is developing the whole new project .

    After seven months development, we can show it now (dev code:Project H)...I don't like this code very much...hm,mm....whatever.  Now. It include a game prototype(single mode and multiplayer mode), a new 3d engine, and a whole new editor.

    The Engine support per-pixel lighting and other next-gen graphic functions. not much to say...You got 3d gurus in your team, find those rendering technologies  from ShaderX ,Game Programming Gems, and GPU Gems series. Also u can get the papers from GDC conference and sigraph conf pdf...something like that...then put some rendering trick with artists' help.

    Here 's some screenshot from the Editor. I adjusted some post process parameters in my taste.. hehe. maybe it's too heavy ...

 

*One of our character without animation. I can turn on the realtime shadow in the editor. so I put the actor model under the shadow of leaves.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

*

We use different HDR parameters to make the different style in the same terrain.

the following pic it's blur....I just show our camera system here. there's a build-in depth of field modular in it.

 

    We use motion blur ,the tech is  same as NFS13 ,and the result is very ok .

    About the future, hmm..SSAO is very easy to implement. i doubt if it can improve the scene much.
    The next step is about multithread rendering (for speed)and some global illumination(....for my own interesting...and for more detailed in-door rendering), i will keep improving the nature rendering effect like water,all kinds of trees,better static shadow(maybe use distance field alpha test texture like ue3).and also, deferred rendering with massive lights is attractive..but in our game propotype, there's no need for complex in-door scene with multiple lights.
    We also developed a lightmap generator .it can generates the normal lightmap like half-life2 . but i doubt maybe the lispsm+csm with phong shading is very ok for outdoor rendering(like the lost planet). UE3 use the normal lightmap to render all static surface like floor and the walls.
    At last ,we all know now: the tool set is the key. the most important key...copying the rendering tech is easy ......,but developing a real product pipeline is long way to go...

 

     I will keep giving some dev infos here. hope it can make you got the desire to join us if you are a 3d tool/rendering/engine dev guru!

    My email is puzzy4d@yahoo.com.cn . You can contact me if you think you want to get a very exciting job in realtime 3d rendering and game dev field

 

posted @ 2009-12-01 15:13 puzzy3d 阅读(2205) | 评论 (7)编辑

对象生存周期管理是C++工程最重要一个环节。关于此类问题《游戏编程精粹》(GPG)系列一直有文章在提。比如第三册 1.5 《基于句柄的智能指针》,第四册1.7的《弱引用和空对象》。在GPG4 1.7给出的代码中发现了一些问题。原始代码如果放入实际工程结果会很不美妙。这里提一下

原文对指针的包装做如下处理:

template <class ResourceType> class ResPtr
{

public:

     //一些构造函数

    ResPtr(const ResPtr<ResourceType> & resPtr);
    explicit ResPtr(ResourceType * pRes);
    ResPtr(ResourcePtrHolder * pHolder = NULL);

public:

   //析构
    ~ResPtr();

private:

//用这个中间层封装指针
    ResourcePtrHolder * m_pResHolder;
}

class ResourcePtrHolder
{
public:
    ResourcePtrHolder (IResource * p) : pRes(p) {}
    ~ResourcePtrHolder();

//用户对象指针放这里
    IResource * pRes;
};

 

template <class ResourceType> ResPtr<ResourceType>::ResPtr(ResourceType * pRes)
{
    m_pResHolder = new ResourcePtrHolder(pRes); //封装原生指针时,在heap生成一个新ResourcePtrHolder对象
}

template <class ResourceType> ResPtr<ResourceType>::~ResPtr()
{//空析构
}

其他ResPtr代码略,但值得一提的是没有 delete   m_pResHolder  字样...

也就是说假如直接使用ResPtr ,用一次就有一个  ResourcePtrHolder 对象泄露

 

代码提供了另外一套引用计数的指针包装版本,ResourcePtrHolder内使用了delete this 销毁内存。但依然有个问题:

 

ResourcePtrHolder::~ResourcePtrHolder()
{
    delete pRes;
}

首先IResource 对外部要管理的指针类型做出了强制性的规定。必须是从IResource派生的类。其次是在holder析构时,不由分说把一个外部传入要管理的对象指针的内容删除。这样强硬的策略我想无论放到哪里都会导致异常巨大的问题。即便是采用引用计数版本,在holder计数到0再删除自己,顺带删除管理的对象,对于外部来讲也是个黑洞。

 

1.7代码的质量让人惊诧,还不知道整本书有多少类似的

posted @ 2008-07-31 10:34 puzzy3d 阅读(304) | 评论 (0)编辑

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吧.....

posted @ 2008-07-25 19:53 puzzy3d 阅读(595) | 评论 (2)编辑

多数初学者往往陷入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,都要从软件光栅机理开始。

posted @ 2008-07-22 10:35 puzzy3d 阅读(703) | 评论 (9)编辑

回到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效果还是不一样.....

 

后面给出技术细节

 

posted @ 2008-07-22 02:45 puzzy3d 阅读(674) | 评论 (2)编辑

透视投影,与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变化。
因为显卡硬件(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光栅化

posted @ 2008-07-05 04:32 puzzy3d 阅读(2770) | 评论 (6)编辑
     摘要: 网站http://www.horizon3d.com.cn公司核心技术studio有很多年历史。2005年成立公司。招聘通用C++程序和图形程序员。欢迎发送简历和DEMO SRC到hr@horizon3d.com.cn  阅读全文
posted @ 2008-06-28 11:21 puzzy3d 阅读(774) | 评论 (1)编辑
     摘要: 不挪动了位置: http://blog.csdn.net/puzzy3d  阅读全文
posted @ 2008-06-28 11:15 puzzy3d 阅读(306) | 评论 (3)编辑
posted @ 2008-06-28 10:16 puzzy3d 阅读(784) | 评论 (3)编辑
     摘要: hmm.....  阅读全文
posted @ 2008-06-16 17:17 puzzy3d| 编辑