shader Sky

struct VS_INPUT
{
 // We only need 2d screen position, that's all.
 float2 pos : POSITION;
};

 

struct VS_OUTPUT
{
 float4 pos : POSITION;
 float3 texCoord : TEXCOORD0;
};

 

VS_OUTPUT VS_Sky(VS_INPUT In)
{
 VS_OUTPUT Out;
 Out.pos = float4(In.pos.xy, 0, 1);
 // Also negate xy because the cube map is for MDX (left handed)
 // and is upside down
 Out.texCoord = mul(float4(-In.pos, scale, 0), viewInverse).xyz;
 // And fix rotation too (we use better x, y ground plane system)
 Out.texCoord = float3( -Out.texCoord.x*1.0f, -Out.texCoord.z*0.815f, -Out.texCoord.y*1.0f);
 return Out;

}

 

// VS_TSky(..)
float4 PS_Sky(VS_OUTPUT In) : COLOR
{
 float4 texCol = ambientColor * texCUBE(diffuseTextureSampler, In.texCoord);
 return texCol;
}

 

 // PS_SkyCubeMap(.)
technique TSky
{
 pass P0
 {
   ZEnable = false;
   VertexShader = compile vs_1_1 VS_Sky();
   PixelShader  = compile ps_1_1 PS_Sky();
 }
 // pass P0
} // technique

 

以前我的理解天空盒是一個盒子形狀的模型(8個頂點,6個面),當然確實也可以這麼做,不過今天自己實現了一個天空盒,發現只用4個頂點(1個面)也是可以的
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->///天空盒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);
}

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->//創建頂點聲明
    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(0sizeof(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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章