Posted on 2010-10-20 23:18
魔のkyo 阅读(1234)
评论(0) 编辑 收藏 引用
以前我的理解天空盒是一个盒子形状的模型(8个顶点,6个面),当然确实也可以这么做,不过今天自己实现了一个天空盒,发现只用4个顶点(1个面)也是可以的
///天空盒VS////////////////////////////////////////
struct VS_IN
{
float3 ObjPos : POSITION;
};
struct VS_OUT
{
float4 ProjPos : POSITION;
float3 texCoord : TEXCOORD0;
};
float4x4 matView : register(c64);
float4x4 matProj : register(c68);
VS_OUT main( VS_IN In )
{
// 如果视“天空盒”为一个模型,本应该对其进行matView*matProj变换
// 现在对texCoord(即用于采样的方向向量)进行matView的反向旋转,效果等同于对所谓“天空盒”模型进行matView变换
VS_OUT Out;
float4 vPosition = float4(In.ObjPos,1.0f); //不乘View矩阵,让4个顶点的位置总是保持和摄像机的相对位置不变
Out.ProjPos = mul( vPosition, matProj); //得到投影后的顶点位置
Out.texCoord = mul(matView, float4(In.ObjPos,0.0f)).xyz; //用matView的逆对In.ObjPos进行变换,起到旋转天空盒的效果
return Out;
}
///天空盒PS////////////////////////////////////////
struct PS_IN
{
float3 texCoord : TEXCOORD0;
};
samplerCUBE g_SkyBox : register(s0);
float4 main( PS_IN In ) : COLOR
{
return texCUBE(g_SkyBox, In.texCoord);
}
{ //创建顶点声明
D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
D3DDECL_END()
};
GetD3DDevice()->CreateVertexDeclaration( decl, &m_pVertexDeclaration );
}
{ //加载VertexBuffer
GetD3DDevice()->CreateVertexBuffer( sizeof(Vertex)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_pVertexBuffer, NULL);
float lx = 50.0f; // lx应>=lz*tg(FOVX/2)=lz*tg(FOVY/2)*Aspect
float ly = 50.0f; // ly应>=lz*tg(FOVY/2)
float lz = 50.0f; // lz应在Zn到Zf之间
Vertex vertex[4] = {
{{-lx, -ly, lz}},
{{-lx, ly, lz}},
{{ lx, -ly, lz}},
{{ lx, ly, lz}},
};
void* pData = NULL;
m_pVertexBuffer->Lock(0, sizeof(Vertex)*4, &pData, D3DLOCK_NOOVERWRITE);
if(pData)
{
for(int i=0;i<4;i++)
{
((Vertex*)pData)[i] = vertex[i];
}
m_pVertexBuffer->Unlock();
}
}
其实如果你愿意只用3个顶点也可以只要那个三角形能挡住摄像机(截穿视域体)就够了,至于顶点的数据也可以设置成投影空间的,这样就不用预先知道关于投影的参数,在VS中乘以matProj的逆反算得到vPosition,再乘以matView的逆得到texCoord