博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

3D视觉与颜色组成

Posted on 2013-01-30 14:02  RUI2021  阅读(429)  评论(0编辑  收藏  举报

1.3D视觉效果

首先,从感性来说,一个平面图形怎么让人眼产生立体感,最简单的其实就是"近大远小"。

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

如上图,两条平行的线,由进及远距离原来越小,知道称为同一点(vanishing point),就形成了立体的效果。

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

上图描绘了另外一种情况(其实就是之前depth buffer的例子),四种图形相互掩盖,也能让人形成前后的视觉。

那单个物体,怎么现实立体感呢,看下图:

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

左边是个圆,正常人都会这么认为。。。不会把它想成球,右边则相反,怎么看都是个球体。两边差了啥呢?光照(lighting)和着色(shading,注意这个词不是阴影的意思)。

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

再看上图,一个飞机,嗯,为什么我们觉得它在空中,因为地上有影子(shadow),从影子我们可以知道两件事情,1.飞机的高度;2. 光照的方向。

OK,到这里,还没讨论啥高深的东西,你可能觉得这些东西你小学就知道,但后面我们要把这些简单的东西通过计算机图形学表现出来。

2. 建模

一个3D模型,或者说一个3D对象,在计算机图形学中,事实上(通常情况下)是一个三角形网格组成的近似模拟。

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

当然了,用代码写出这个么模型,基本是死路一条,一般我们都用建模工具来完成这些工作,如3ds Max (http://www.autodesk.com/3dsmax), LightWave 3D (http://www.newtek.com/lightwave/), Maya (http://www.autodesk.com/maya), and Softimage | XSI (www.softimage.com)。

3. 计算机颜色

计算机一般通过RGB三原色以及每种颜色的灰度来存储一种具体的颜色,随便打开个windows下的选色器就看出。

一般来说,我们用一个有三个数的结构来表现一个颜色,如(0.25, 0.67, 1.0),表示25%的红,67%的绿以及100%的蓝。由于这个结构很像向量,我们在D3D中还是用向量也表示它,称为颜色向量。

显然,向量的加减对颜色向量来说是有意义的:

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

加法相当于两种颜色重叠产生新颜色。

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

减法类似加法,代表我从一种颜色转换为另一种颜色(通过减掉某些颜色的比重)。

常数乘以一个颜色也同样有意义:

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

相当于整个颜色的浓度产生一定程度的变化。

接下来是点乘和×乘,后者是没有实际意义的,前者的意义是:

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

RGB三种颜色分别做了一定程度的变化,事实上,这是很有用的,主要用于模拟光照现象。比如我们有一束光,从远处照过一个平面,这个平面能吸收50%的红光,75%的绿光以及25%的蓝光,那通过一下算式,能得到光通过那个平面的颜色:

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

下面说下在D3D中具体的颜色的使用,D3D中,颜色被封装在结构D3DXCOLOR中(博客园的代码插入功能呢。。。):

typedef struct D3DXCOLOR

{

#ifdef __cplusplus

public:

D3DXCOLOR() {};

D3DXCOLOR(UINT argb);

D3DXCOLOR(CONST FLOAT *);

D3DXCOLOR(CONST D3DXFLOAT16 *);

D3DXCOLOR(FLOAT r, FLOAT g, FLOAT b, FLOAT a);

 

// casting

operator UINT () const;

operator FLOAT* ();

operator CONST FLOAT* () const;

 

// assignment operators

D3DXCOLOR& operator += (CONST D3DXCOLOR&);

D3DXCOLOR& operator -= (CONST D3DXCOLOR&);

D3DXCOLOR& operator *= (FLOAT);

D3DXCOLOR& operator /= (FLOAT);

 

// unary operators

D3DXCOLOR operator + () const;

D3DXCOLOR operator - () const;

 

// binary operators

D3DXCOLOR operator + (CONST D3DXCOLOR&) const;

D3DXCOLOR operator - (CONST D3DXCOLOR&) const;

D3DXCOLOR operator * (FLOAT) const;

D3DXCOLOR operator / (FLOAT) const;

 

friend D3DXCOLOR operator * (FLOAT, CONST D3DXCOLOR&);

BOOL operator == (CONST D3DXCOLOR&) const;

BOOL operator != (CONST D3DXCOLOR&) const;

#endif //__cplusplus

FLOAT r, g, b, a;

} D3DXCOLOR, *LPD3DXCOLOR;

 

可以看到上面的结构没有提供点乘的方法,因此,补充下面这个函数来完成此类操作。

D3DXCOLOR* D3DXColorModulate(

D3DXCOLOR* pOut, // Returns (cr, cg, cb, ca) D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客 (kr, kg, kb, ka)

CONST D3DXCOLOR* pC1, // (cr, cg, cb, ca)

CONST D3DXCOLOR* pC2 // (kr, kg, kb, ka)

);

从构造函数中,可以发现,有4个float,怎么多了一个呢?不是三原色么?多的那个就是传说中的alpha通道,用于阿尔法混合(blending),这里暂时不展开。

如果我们通过 D3DXCOLOR(FLOAT r, FLOAT g, FLOAT b, FLOAT a)这个构造函数构造的颜色向量是128bit的一个数据结构,事实上,咋某些情况下,我们认为太大了,有些浪费,但由于颜色总是需要经过复杂的运算,float的高精度可以保证错误不会一直积累导致最后偏差过大,所以,在计算过程中,我们使用浮点数表示颜色(每个颜色元素是0到1)。

当我们使用 D3DXCOLOR(UINT argb)来构造颜色向量的时候(传入一个32位的无符号整形),我们得到一个32位的颜色,它是这样对应4个子元素的:

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

由于32位色基本能满足视觉的要求(windows的桌面设置最高就是32位色),因此,将计算完的结构用32位色表示是最合适的,这里涉及到一个转化的问题,32位色和128位色怎么转化呢,看下面两个例子:

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客

如上,32位色转化成了128位色。

D3D学习总结渲染篇(一)--基础理论 - 老马 - 老马的博客