# 游戏人生

### Blog Stats

• Posts - 147
• Stories - 1

2.linear depth

linear depth通常使用view space的z 再除以max view distance即far clip distance得到单位化的z,这个z值可以直接写入zbuffer, 用于depth test, 不过需要所有的shader都输出linear depth才能正常使用, 除了那些不需要深度写和深度测试的对象, 可以不用修改.

3.如果不用linear depth, 需要将NDC坐标unproject到world space, 即乘以 invViewProjection, 一次矩阵运算来得到world space.

viewPos = [view space origin +] view space ray * viewdepth
viewPos = ray * viewDistance (后面有备注)

world pos = eyePos + worldRay * viewdepth  viewDistance

worldRay = normalize(world pos - view pos);

float3 worldRay : TEXCOORD1
uniform float4 eye_position : EYE_POS    //eye pos in world space

...
//expand INTZ
float depth = dot(tex2D(depthBuffer, depthUV).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));
float3 worldPos = eye_position.xyz + worldRay * depth;

Directional light的优化

uniform int direcitonal_count;
uniform float4 light_drections[MAX_DIR_LIGHT_COUNT];
uniform float4 directional_diffuses[MAX_DIR_LIGHT_COUNT];
uniform float4 directional_speculars[MAX_DIR_LIGHT_COUNT];
for(int i = 0; i < directional_count; ++i)
{
color += shading(light_drections[i], diretional_diffuses[i], directioanl_speculars[i], normal, depth);
}

for(int i = 0; i < light_directional_count; ++i)
{
float3 light_dir = light_directions[i].xyz;
//direcitonal lights doesn't need world position, thus doesn't need depth sampling,
//the depthBuffer sampling will be optimized by compiler.
float3 half_vec = normalize(light_dir + (-worldRay));
... // calculate lighting
}

viewDepth = dot(pos, worldViewMatrixCol3) / faclipDist, 而且worldViewMatrixCol3可以在CPU端预乘1/farClipDist, 这样计算view space normalized depth只需要一条指令, 这样的话没有多余的计算, 就不需要考虑在view space计算光照了.

//////////////////////////////////////////////////////////////////////////
//vector to calculate view space normalized depth
//this is an optimization for shader, use dot(v, viewdepthvector) instead of mul(v,world_view_matrix).z / far_clip_distance
class ViewDepthVectorUpdater : public InstanceVariableUpdater
{
public:
ViewDepthVectorUpdater(WorldViewMatrixUpdater* worldViewUpdater)
:InstanceVariableUpdater(SCT_FLOAT4, 1)
,mWorldViewUpdater(worldViewUpdater)
,mWorldViewMatrixCol3(Vector4::ZERO)
{

}

/** @brief  */
virtual const void* updateData() const
{
if( camera == NULL )
return &Vector4::ZERO;

const Matrix44& worldViewMat = *(const Matrix44*)mWorldViewUpdater->getVariable()->getData();
mWorldViewMatrixCol3[0] = worldViewMat[0][2];
mWorldViewMatrixCol3[1] = worldViewMat[1][2];
mWorldViewMatrixCol3[2] = worldViewMat[2][2];
mWorldViewMatrixCol3[3] = worldViewMat[3][2];
//note: since we're using Right Hand axis, the view direction points at -Z,
//view space position's z values are negative.
//use this negative value to generate a positive z value into z buffer
mWorldViewMatrixCol3 *= -1.0f / camera->getFarClipDistance();
return &mWorldViewMatrixCol3;
}

protected:
WorldViewMatrixUpdater* mWorldViewUpdater;
mutable Vector4    mWorldViewMatrixCol3;
};

RAWZ v.s. INTZ

posted on 2015-12-25 17:16 crazii 阅读(...) 评论(...) 编辑 收藏