DX 11 中的光照

为实现更逼真的3D效果,我们需要光照和阴影

为了理解光照,下面从数学方面来讲(Phong光照模型,参考书籍3d programming game with dx 11)

Normal Vector

为了计算光照,必须取得当前的法线向量

在 Δ p0 p1 p2中,定义 u = p1 – p0  v = p2 – p0

那么表面法线为 

 

可如下计算

void ComputeNormal(const D3DXVECTOR3& p0,
const D3DXVECTOR3& p1,
const D3DXVECTOR3& p2,
D3DXVECTOR3& out)
{
    D3DXVECTOR3 u = p1 - p0;
    D3DXVECTOR3 v = p2 - p0;
    D3DXVec3Cross(&out, &u, &v);
    D3DXVec3Normalize(&out, &out);
}

然而对于不规则物体或者是多面体来说,每个点的法线都是不一样的

 

那么法线的平均值N_avg计算取均值即可

在代码中可以一个面的法向量可以求一个三角形的法向量,然后再单位化即可

Transforming Normal Vectors

既然可以求出每个面的法向量,那么如果这个物体经过某种变换即:

原来向量 u·n = 0

变化矩阵 A,变化后

uA

如何求出变化后的法向量?

以上三幅图说明了如何求变换后的法向量

即:B = (A–1)T

那么代码可以这样写

static XMMATRIX InverseTranspose(CXMMATRIX M)
{
    XMMATRIX A = M;
    A.r[3] = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
    XMVECTOR det = XMMatrixDeterminant(A);
    return XMMatrixTranspose(XMMatrixInverse(&det, A));
}

LAMBERT’S COSINE LAW

wikipedia 

余弦辐射体,也称为朗伯辐射体(Lambert radiator),指的是发光强度的空间分布符合余弦定律的发光体(不论是自发光或是反射光)

简单来说辐射值和consine值相关

L 和 n 是单位向量

DIFFUSE LIGHTING

漫反射光,假设一个点的材质将光线反射情况如下:

50% red light  100% green light 75% blue light

可表示为

假设光线为白光,强度为80%,可表示为

那么漫反射可这样计算

这时缺少辐射因子,由上面可得

那么乘上辐射因子可得漫反射计算公式

AMBIENT LIGHTING

由于在Phong模型中认为环境光是常量,那么

那么漫反射加上环境光现在为

SPECULAR LIGHTING

镜面反射

已知 n,I和ϕmax,求v即可

V的单位向量为

那么又可得

cos (ϕ) = v ∙ r.(r也是单位化的)

那么r可以这样求

r = I - 2 (n · I)n;(n 是单位化的)

为了使反射效果强烈,我们需要在辐射因子的次方值

 

L·n是检查入射光不能从背面射入并反射

 总的光照计算公式

漫反射+环境+镜面

 

几种灯光类型

PARALLEL LIGHTS

平行光,不赘述,这里需要知道方向即可

POINT LIGHTS

光源Q点,到位置P

方向:

需要记住光源点Q

Attenuation

 插入一点,光的衰减与距离的二次方成反比

I0 初始光强,d为距离

我们一般将分母化为如下形式,

那么,加上颜色计算

Range

对于点光源来说,我们加上一个range参数

1)为了对某一特定区域使用

2)为了提高shader效率

SPOTLIGHTS

一个聚光灯模型如下

已知 Q maxϕ,d P

那么光线方向可得

那么cosϕ = -L · d

光强因子

加上颜色计算

HLSL实现(待续)

posted @ 2015-07-03 23:43  W.Heisenberg  阅读(358)  评论(0编辑  收藏  举报