Direct3D---三维天空的构建

本文介绍了一个基于Direct3D的三维天空盒系统实现方法,包括天空盒类的设计、顶点缓冲区的创建与填充、纹理加载及渲染流程。通过设置天空盒大小和纹理,能够渲染出具有动态效果的三维天空背景。
//=============================================================================
// Name: SkyBoxClass.h
//  Des: 一个封装了三维天空盒系统的类的头文件
// 2013年 3月24日  Create by 浅墨 
//=============================================================================
#pragma once
#include "D3DUtil.h"

//为天空盒类定义一个FVF灵活顶点格式
struct SKYBOXVERTEX
{
    float   x,y,z;
    float   u,v;
};
#define D3DFVF_SKYBOX D3DFVF_XYZ|D3DFVF_TEX1


class SkyBoxClass
{
private:
    LPDIRECT3DDEVICE9       m_pd3dDevice;           //D3D设备对象
    LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer;        //顶点缓存对象
    LPDIRECT3DTEXTURE9      m_pTexture[5];          //5个纹理接口对象
    float                   m_Length;               //天空盒边长

public:
    SkyBoxClass( LPDIRECT3DDEVICE9  pDevice );      //构造函数
    virtual ~SkyBoxClass(void);                        //析构函数

public:
    BOOL    InitSkyBox( float Length );   //初始化天空盒函数
    //从文件加载天空盒五个方向上的纹理
    BOOL    LoadSkyTextureFromFile(wchar_t *pFrontTextureFile, wchar_t *pBackTextureFile, wchar_t *pLeftTextureFile, 
                                   wchar_t *pRightTextureFile, wchar_t *pTopTextureFile); 
    //渲染天空盒,根据第一个参数设定天空盒世界矩阵,第二个参数选择是否渲染出线框
    VOID    RenderSkyBox( D3DXMATRIX *pMatWorld, BOOL bRenderFrame ); 
};

//=============================================================================
// Name: SkyBoxClass.cpp
//  Des: 一个封装了三维天空盒系统的类的源文件
// 2013年 3月24日  Create by 浅墨 
//=============================================================================
#include "d3dx9.h"
#include "SkyBoxClass.h"
#include "D3DUtil.h"


//-------------------------------------------------------------------------------------------------
// Desc: 构造函数
//-------------------------------------------------------------------------------------------------
SkyBoxClass::SkyBoxClass( LPDIRECT3DDEVICE9  pDevice )
{
    //给各个参数赋初值
    m_pVertexBuffer=NULL;
    m_pd3dDevice=pDevice;
    for(int i=0; i<5; i++)
        m_pTexture[i] = NULL; 
    m_Length = 0.0f;
}

//-------------------------------------------------------------------------------------------------
// Name:  SkyBoxClass::InitSkyBox( )
// Desc: 天空盒初始化函数,顶点缓冲区的赋值
//-------------------------------------------------------------------------------------------------
BOOL SkyBoxClass::InitSkyBox( float Length )
{
    m_Length=Length;

    //1.创建。创建顶点缓存
     m_pd3dDevice->CreateVertexBuffer( 20 * sizeof(SKYBOXVERTEX), 0, 
        D3DFVF_SKYBOX, D3DPOOL_MANAGED, &m_pVertexBuffer, 0 );

    //用一个结构体把顶点数据先准备好
    SKYBOXVERTEX vertices[] =
    {
        //前面的四个顶点
        { -m_Length/2, 0.0f,        m_Length/2, 0.0f, 1.0f, },
        { -m_Length/2, m_Length/2,  m_Length/2, 0.0f, 0.0f, },
        {  m_Length/2, 0.0f,        m_Length/2, 1.0f, 1.0f, },
        {  m_Length/2, m_Length/2,  m_Length/2, 1.0f, 0.0f, },

        //背面的四个顶点
        {  m_Length/2, 0.0f,        -m_Length/2, 0.0f, 1.0f, },
        {  m_Length/2, m_Length/2,  -m_Length/2, 0.0f, 0.0f, },
        { -m_Length/2, 0.0f,        -m_Length/2, 1.0f, 1.0f, },
        { -m_Length/2, m_Length/2,  -m_Length/2, 1.0f, 0.0f, },

        //左面的四个顶点
        { -m_Length/2, 0.0f,        -m_Length/2, 0.0f, 1.0f, },
        { -m_Length/2, m_Length/2,  -m_Length/2, 0.0f, 0.0f, },
        { -m_Length/2, 0.0f,        m_Length/2,  1.0f, 1.0f, },
        { -m_Length/2, m_Length/2,  m_Length/2,  1.0f, 0.0f, },

        //右面的四个顶点
        { m_Length/2, 0.0f,         m_Length/2,  0.0f, 1.0f, },
        { m_Length/2, m_Length/2,   m_Length/2,  0.0f, 0.0f, },
        { m_Length/2, 0.0f,         -m_Length/2, 1.0f, 1.0f, },
        { m_Length/2, m_Length/2,   -m_Length/2, 1.0f, 0.0f, },

        //上面的四个顶点
        {  m_Length/2, m_Length/2, -m_Length/2, 1.0f, 0.0f, },
        {  m_Length/2, m_Length/2,  m_Length/2, 1.0f, 1.0f, },
        { -m_Length/2, m_Length/2, -m_Length/2, 0.0f, 0.0f, },
        { -m_Length/2, m_Length/2,  m_Length/2, 0.0f, 1.0f, },

    };

    //准备填充顶点数据
    void* pVertices;
    //2.加锁
    m_pVertexBuffer->Lock( 0, 0, (void**)&pVertices, 0 );
    //3.访问。把结构体中的数据直接拷到顶点缓冲区中
    memcpy( pVertices, vertices, sizeof(vertices) );
    //4.解锁
    m_pVertexBuffer->Unlock();

     return TRUE;
}

//-------------------------------------------------------------------------------------------------
// Name:  SkyBoxClass::LoadSkyTextureFromFile( )
// Desc: 天空盒纹理加载函数
//-------------------------------------------------------------------------------------------------
BOOL SkyBoxClass::LoadSkyTextureFromFile(wchar_t *pFrontTextureFile, wchar_t *pBackTextureFile,wchar_t *pLeftTextureFile, wchar_t *pRightTextureFile,wchar_t *pTopTextureFile)
{
    //从文件加载五张纹理
    D3DXCreateTextureFromFile( m_pd3dDevice , pFrontTextureFile, &m_pTexture[0] );  //前面
    D3DXCreateTextureFromFile( m_pd3dDevice , pBackTextureFile,  &m_pTexture[1] );  //后面
    D3DXCreateTextureFromFile( m_pd3dDevice , pLeftTextureFile,  &m_pTexture[2] );  //左面
    D3DXCreateTextureFromFile( m_pd3dDevice , pRightTextureFile, &m_pTexture[3] );  //右面
    D3DXCreateTextureFromFile( m_pd3dDevice , pTopTextureFile,   &m_pTexture[4] );  //上面    
    return TRUE;
}

//--------------------------------------------------------------------------------------
// Name: SkyBoxClass::RenderSkyBox()
// Desc: 绘制出天空盒,可以通过第二个参数选择是否绘制出线框
//--------------------------------------------------------------------------------------
void SkyBoxClass::RenderSkyBox( D3DXMATRIX *pMatWorld, BOOL bRenderFrame )
{
    //D3DTSS_COLOROP: 纹理颜色的混合方法
    //D3DTOP_SELECTARG1: 将颜色混合阶段的第一个参数的颜色值输出
    //D3DTSS_COLORARG1: 对纹理颜色混合阶段的第一个参数进行操作
    //D3DTA_TEXTURE: 默认值,表示纹理阶段的参数就取纹理的颜色
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);//将纹理颜色混合的第一个参数的颜色值用于输出
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );   //纹理颜色混合的第一个参数的值就取纹理颜色值
    m_pd3dDevice->SetTransform( D3DTS_WORLD, pMatWorld );                       //设置世界矩阵
    m_pd3dDevice->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(SKYBOXVERTEX)); //把包含的几何体信息的顶点缓存和渲染流水线相关联  
    m_pd3dDevice->SetFVF(D3DFVF_SKYBOX);  //设置FVF灵活顶点格式

    //一个for循环,将5个面绘制出来
    for(int i =0; i<5; i++)
    {
        m_pd3dDevice->SetTexture(0, m_pTexture[i]);
        m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, i*4, 2);
    }

    //对是否渲染线框的处理代码
    if (bRenderFrame)  //如果要渲染出线框的话
    {
        m_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); //把填充模式设为线框填充
        //一个for循环,将5个面的线框绘制出来
        for(int i =0; i<5; i++)
        {
            m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, i*4, 2);   //绘制顶点 
        }

        m_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);    //把填充模式调回实体填充
    }
}


//-------------------------------------------------------------------------------------------------
// Desc: 析构函数
//-------------------------------------------------------------------------------------------------
SkyBoxClass::~SkyBoxClass(void)
{
    SAFE_RELEASE( m_pVertexBuffer );
    for(int i=0; i<5; i++)
    {
        SAFE_RELEASE( m_pTexture[i] );
    }
}

调用:

Objects_Init()
描述:渲染资源初始化函数,在此函数中进行要被渲染的物体的资源的初始化

//创建并初始化天空对象
    g_pSkyBox = new SkyBoxClass( g_pd3dDevice );
    g_pSkyBox->LoadSkyTextureFromFile(L"GameMedia\\frontsnow1.jpg",L"GameMedia\\backsnow1.jpg",L"GameMedia\\leftsnow1.jpg",
    L"GameMedia\\rightsnow1.jpg", L"GameMedia\\topsnow1.jpg");//从文件加载前、后、左、右、顶面5个面的纹理图
    g_pSkyBox->InitSkyBox(20000);  //设置天空盒的边长

Direct3D_Render()
描述:使用Direct3D进行渲染

//绘制天空
    D3DXMATRIX matSky, matTransSky, matRotSky;
    D3DXMatrixTranslation(&matTransSky, 0.0f, -3500.0f, 0.0f);
    D3DXMatrixRotationY(&matRotSky, -0.000005f*timeGetTime());  //旋转天空网格, 简单模拟云彩运动效果
    matSky = matTransSky * matRotSky;
    g_pSkyBox->RenderSkyBox(&matSky, false);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值