最近尝试采用D3D9的UVAtlas+TextureGutterHelper+effect(v_2_0)进行模型的lightmap烘焙,在写effect文件的vertexshader时遇到一个奇怪的问题,使用UVAtlas展开UV后,计划按照纹理的UV坐标输出贴图的position,.fx文件中完整代码如下:
//Vertexshader输入
struct VS_INPUT
{
float4 Pos : POSITION;
float3 Normal : NORMAL;
float2 Tex0 : TEXCOORD0;
};
//Vertexshader输出与PixelShader输入
struct PSUVIn
{
float4 Pos : POSITION;
float2 Tex0 : TEXCOORD0;
float4 Clr0 : COLOR0;
};
PSUVIn VSRenderToUV(VS_INPUT input, uniform bool bPtLight, uniform bool bSpecular)
{
PSUVIn output = (PSUVIn)0;
float2 screenTex = input.Tex0*float2(2, 2) - float2(1, 1);
output.Pos = float4(screenTex, 0.5, 1);
// 转换顶点到世界坐标
float4 vPosWorld = mul(input.Pos, g_mWorld);
// 将法线转换到世界坐标系
float3 vNormalWorld = mul(input.Normal, (float3x3)g_mWorld);
//将纹理坐标直接输出,传递给pixelshader
output.Tex0 = input.Tex0;
// 计算光线方向向量
float3 vLight;
if (bPtLight) //是点光源
vLight = normalize(g_vLightPosition - vPosWorld.xyz);
else //方向光
vLight = normalize(g_vLightDirection);
// 计算光照度
output.Clr0.rgb = g_vLightColor * g_vMaterialAmbient;
output.Clr0.rgb += g_vLightColor * g_vMaterialDiffuse * saturate(dot(vLight, vNormalWorld));
// 计算镜面光
if (bSpecular)
{
float3 vCamera = normalize(vPosWorld.xyz - g_vCameraPosition);
float3 vReflection = reflect(vLight, vNormalWorld);
float fPhongValue = saturate(dot(vReflection, vCamera));
output.Clr0.rgb += g_vMaterialSpecular * pow(fPhongValue, g_nMaterialShininess);
}
output.Clr0.a = g_fMaterialAlpha;
return output;
}
float4 PSRenderToUV(PSUVIn input, uniform bool bTexture) : COLOR0
{
//将vertexshader计算的光照直接输出渲染为纹理
float4 colorOut = input.Clr0;
return colorOut;
}
在vertexshader函数VSRenderToUV中,以下代码部分负责将贴图的UV坐标换算为输出纹理的xy坐标
float2 screenTex = input.Tex0*float2(2, 2) - float2(1, 1);
output.Pos = float4(screenTex, 0.5, 1);
测试过程使用了d3d的示例模型,模型样式和纹理如下两图
采用上述effect代码,输出纹理样式为
可以看出烘焙后的纹理图与原始贴图坐标不一致,在Y方向上发生了翻转,为此改变UV换算代码为
float2 screenTex = input.Tex0*float2(2, -2) - float2(1, -1);
output.Pos = float4(screenTex, 0.5, 1);
希望将输出纹理的y坐标翻转过来,然而测试后发现,只能输出如下图像
可以发现翻转y以后模型面部、腿部等部分纹理没有输出,求教各位大神问题出在哪里,如何解决?谢谢~