1、 引言(Introduction)
本文作者
Tomas Arce
2、什么是逐象素光照(What Is Per-Pixel Lighting)
烦恼的命名。
Bad name
纹素光照处理会更加真实。
Texel-lighting is more accurate.
纹理分辨率的问题 ― 有助于处理贴图。
Texture resolution matters -- tiling helps.
逐象素基本要做的复杂操作。
Complex operation done per-pixel basis.
纹理查找,三维点光照值生成及象素着色。
DP3Texture lookups, dp3, and pixel shaders.
利用颜色作为数据。
Use colors as data.
对纹理的象素法向量进行编码,填充RGB值:
Encode pixel-normals in texture, fill RGB as:
R=Normal.X, G=Normal.Y, B=Normal.Z
也要对光照引索进行编码,填充顶点颜色:
Light dir is also encoded, fill vertex color as:
R=LightDir.X, G = LightDir.Y, B = LightDir.Z
现在我们可以做:
Now we can do:
( Texture.Texel ) dot ( Vertex.Color )
3、逐象素为什么更好(Why Is Per-Pixel Better)
每顶点光照更快且其更加灵活,但是缺乏分辨率。
Per-vertex light is faster and more flexible but lacks resolution.
光照贴图有缺陷:
Light-maps have pit-falls:
不真实的镜面处理。
No real specular.
低分辨率。
Low resolution.
不适于工作在动态对象上。
Doesn't work for dynamic objects.
投射纹理不能获取更多的表面细节。
Projected textures don't give much detail for the surface.
细节?细节?细节。
Detail. Detail. Detail.
逐象素光照处理需要很少的网格多边形。
ppLighting needs few polygons per-mesh.
简化碰撞、模板阴影、存储。
Simplifies collision, stencil shadows, and memory.
凹凸贴图是逐象素光照的一个子集。
Bump mapping is a subset of the ppLighting
“法向量贴图”
“Normal maps”
法向量贴图可以很好的处理不同类型的光照及表面类型。
Normal maps handle different types of lights and surfaces well.
图1
4、如何存储纹素法向量(How to Store Normals in Texels)
空间是什么?
What space?
本地空间对纹理空间。
Local-Space vs Texture Space.
本地空间法向量。
Local Space Normals (LS)
使用对象的坐标的原点提取法向量。
Use the origin of the object to extract normals
纹理空间法向量。
Texture Space Normals (TS).
存储非普通空间的法向量,例如,正切空间。
Store normals in generic space, e.g., Tangent Space.
每个顶点储存一个矩阵,表示光线从本地空间到纹理空间的转换。
Store a matrix per vertex that takes the light from local-space to texture space.
Local Space
Texture Space
LS原理简单且处理速度极快。
LS is simple to work with and can be very fast.
但不允许压缩。
But cannot be compressed.
益用于处理象汽车般的人物与对象。
Good for characters and objects such as cars.
TS原理复杂但其有两个优点。
TS is more complex to work with but has 2 advantages.
允许图素贴图。
Tileable maps.
堆砌纹理。
Palletized textures.
适用于带细节纹理的地形。
Good for big things like terrain with detail textures.
5、光照的不同类型(Different Types of Lights)
三个典型的光照类型:
3 typical light types:
方向光
Directional
点光源
Point
聚光灯
Spot
点光源、聚光灯通常具有衰减系数。
Point and spot lighting usually have attenuation coefficients.
将聚光灯的衰减函数存在到纹理内。
Store spot lighting attenuation function in a texture.
X是距离的函数。
X is a function of the distance
Y是角度的函数。
Y is a function of the angle
点乘每个点光的方向向量。
The dot-product direction of the light with the vertex
直接在顶点着色内实现衰减函数:(1/(k1+d*k2 +d*d*k3))。
Implementing attenuation function (1/(k1+d*k2 +d*d*k3) ) directly in the vertex shader.
使用少量指令,就可使问题接近零。
Takes few instructions, but has issues going towards zero.
光照矢量通常不需要归一化,但是…
Light vector normalization is usually not needed but…
使用立方体贴图查找。
Use cube-map lookup (32x32 or so)
或在象素着色中使用Newton-Raphson方法。
Or use Newton-Raphson approximation in pixel-shader:
mul r0, LightDir, 0.5
dp3 r1, LightDir, LightDir
mad r0, 1-r1, r0, LightDir
图3
6、LS对TS的标准压缩(LS vs TS Standard Comparison)
; LS Directional Light
; Transform position to clip space and output it
dp4 oPos.x, V_POSITION, c[CV_WORLDVIEWPROJ_0]
dp4 oPos.y, V_POSITION, c[CV_WORLDVIEWPROJ_1]
dp4 oPos.z, V_POSITION, c[CV_WORLDVIEWPROJ_2]
dp4 oPos.w, V_POSITION, c[CV_WORLDVIEWPROJ_3]
; Output tex coords
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE
; TS Directional Light
; Transform position to clip space and output it
dp4 oPos.x, V_POSITION, c[CV_WORLDVIEWPROJ_0]
dp4 oPos.y, V_POSITION, c[CV_WORLDVIEWPROJ_1]
dp4 oPos.z, V_POSITION, c[CV_WORLDVIEWPROJ_2]
dp4 oPos.w, V_POSITION, c[CV_WORLDVIEWPROJ_3]
; Transform local space light by basis vectors to put it
; into texture space
dp3 LIGHT_T.x, V_S, c[L_DIR_LOCAL]
dp3 LIGHT_T.y, V_T, c[L_DIR_LOCAL]
dp3 LIGHT_T.z, V_Q, c[L_DIR_LOCAL]
; Scale to 0-1
add LIGHT_T, LIGHT_T, c[CV_ONE]
mul oD0, LIGHT_T, c[CV_HALF]
; Output tex coords
mov oT0, V_TEXTURE
mov oT1, V_TEXTURE
这个例子主要对僵硬的几何学而言。
This example is mostly for rigid geometry.
最优化TS:11条指令。
Optimized TS: 11 instructions
最优化LS:6条指令。
Optimizes LS: 6 instructions
注意LS能做到5个灯源的数目。
Note that the LS could do up to 5 lights
在本地空间里所有光源的方向都应作为象素着色的常量。
All light directions in local space are loaded into the pixel-shader constants
TS使用本地空间里光源的方向。
The TS uses light direction in local space.
其比基础矢量多边形转换要得多。
Faster than transforming the basis vectors
7、LS对TS的细腻蒙皮(LS vs TS Soft-Skin)
图4
// Transform pos with Weight 1
mov a0.x, V_INDICES.x
dp4 r1.x, V_POSITION, c[a0.x + CV_BONESTART + 0]
dp4 r1.y, V_POSITION, c[a0.x + CV_BONESTART + 1]
dp4 r1.z, V_POSITION, c[a0.x + CV_BONESTART + 2]
// Weight the light part 1
mul r7, c[a0.x + CV_LDIR_LOCALSPACE], V_WEIGHT0.x
// Transform pos with Weight 2
mov a0.x, V_INDICES.y
dp4 r2.x, V_POSITION, c[a0.x + CV_BONESTART + 0]
dp4 r2.y, V_POSITION, c[a0.x + CV_BONESTART + 1]
dp4 r2.z, V_POSITION, c[a0.x + CV_BONESTART + 2]
// Weight the 2 part of the light
mad r8, c[a0.x + CV_LDIR_LOCALSPACE], V_WEIGHT1.x, r7
// Blend