前段时间在看wow的模型的时候, render flag中有一个很奇怪的渲染状态切换, 而且这个状态在WoWDev上也没有被提及.
pass.useEnvMap = (texunitlookup[tex[j].texunit] == -1) && ((rf.flags & 0x10) !=0) && rf.blend>2; //&& rf.blend<5; // Use environmental reflection effects?
当时跟踪了一下, 发现几个模型只有在使用某一类纹理时才会切换到这个"SphereMap", 文件名通常是:ARMORREFLECT4.BLP这样的
当时只是知道是用来做高光, 至于实现没有细看.
后来在项目中偶然发现也用了这项技术, 才知道除了Cubic Environment Mapping之外, 还有个Spherical Environment Mapping.
按DX SDK中的说法, UV坐标是这样计算的:, 其中Nx和Ny是摄像机空间顶点法线的xy分量. 原来画wow模型时没有实验成功, 就把这张纹理给当普通纹理处理了, 怪不得画出来的龙的牙跟爪子看起来没有wowmodelviewer的锐利@_@. 现在看来是我没有把法线变换到摄像机空间.
在RenderMonkey里拿个茶壶实验了一下, 这次效果对了:
float4x4 matViewProjection;
float4x4 matView;
struct VS_INPUT
{
float4 Position : POSITION0;
float3 Normal : NORMAL;
float2 Texcoord : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 Position : POSITION0;
float2 Texcoord : TEXCOORD0;
float2 SphereUV : TEXCOORD1;
};
VS_OUTPUT vs_main( VS_INPUT Input )
{
VS_OUTPUT Output;
Output.Position = mul( Input.Position, matViewProjection );
Output.Texcoord = Input.Texcoord;
float3 viewNormal = mul(Input.Normal, matView);
Output.SphereUV = viewNormal.xy * 0.5 + 0.5;
return( Output );
}
sampler2D baseMap;
sampler2D sphereMap;
struct PS_INPUT
{
float2 Texcoord : TEXCOORD0;
float2 ShpereUV : TEXCOORD1;
};
float4 ps_main( PS_INPUT Input ) : COLOR0
{
float4 diffuse = tex2D( baseMap, Input.Texcoord );
float4 envmap = tex2D(sphereMap, Input.ShpereUV);
return diffuse + envmap;
}
效果图: