zoukankan      html  css  js  c++  java
  • Direct3D轮回:基于ID3DXSprite的2D元素绘制

    D3D中的2D元素绘制主要是通过ID3DXSprite来完成的。

    我们通过调用D3DXCreateSprite来完成ID3DXSprite接口对象的创建,同时使用介于Begin与End之间的Draw方法来完成D3D中2D元素的绘制。

    下面,我们对IDirect3DTexture9和ID3DXSprite进行二次封装,使其接口趋于人性化,使用起来更加便捷:

    /*-------------------------------------

    代码清单:Texture2D.h
    来自:
    http://www.cnblogs.com/kenkao

    -------------------------------------
    */

    #include 
    "D3DInit.h"

    #pragma once

    class CTexture2D
    {
    public:
        CTexture2D(
    void);
        
    ~CTexture2D(void);
    public:
        
    void LoadTexture(                                             //纹理加载
            char* szFxFileName,                                       //文件路径
            UINT SizeX = D3DX_DEFAULT_NONPOW2,                        //X默认非2次幂尺寸
            UINT SizeY = D3DX_DEFAULT_NONPOW2                         //Y默认非2次幂尺寸
            );
        
    void Release()  {ReleaseCOM(m_pTexture);}                     //释放纹理
    public:
        UINT               GetWidth()       {
    return m_Width;}         //获得纹理宽
        UINT               GetHight()       {return m_Height;}        //获得纹理高
        RECT               GetRect()        {return m_SurRect;}       //获得纹理尺寸
        IDirect3DTexture9* GetTexture()     {return m_pTexture;}      //获得纹理指针
        D3DXIMAGE_INFO     GetTextureInfo() {return m_TextureInfo;}   //获得纹理信息
    private:
        IDirect3DTexture9
    * m_pTexture;                                //纹理指针
        D3DXIMAGE_INFO     m_TextureInfo;                             //纹理信息
        RECT               m_SurRect;                                 //纹理尺寸
        UINT               m_Width;                                   //纹理宽
        UINT               m_Height;                                  //纹理高
    };
    /*-------------------------------------

    代码清单:Texture2D.cpp
    来自:
    http://www.cnblogs.com/kenkao

    -------------------------------------
    */

    #include 
    "StdAfx.h"
    #include 
    "Texture2D.h"
    #include 
    "D3DGame.h"

    extern IDirect3DDevice9* g_pD3DDevice;

    CTexture2D::CTexture2D(
    void):m_pTexture(NULL)
    {
    }

    CTexture2D::
    ~CTexture2D(void)
    {
    }

    void CTexture2D::LoadTexture(char* szFxFileName, UINT SizeX, UINT SizeY)
    {
        D3DXCreateTextureFromFileEx(
            g_pD3DDevice,
            szFxFileName,
            SizeX, 
            SizeY,
            D3DX_FROM_FILE,
            D3DPOOL_DEFAULT,
            D3DFMT_FROM_FILE,
            D3DPOOL_MANAGED,
            D3DX_DEFAULT,
            D3DX_DEFAULT,
            D3DCOLOR_COLORVALUE(
    0.0f,0.0f,0.0f,1.0f),
            
    &m_TextureInfo,
            NULL,
            
    &m_pTexture);
        
    if(SizeX==(UINT)-2)
            m_Width 
    = m_TextureInfo.Width;
        
    else
            m_Width 
    = SizeX;
        
    if(SizeY==(UINT)-2)
            m_Height 
    = m_TextureInfo.Height;
        
    else
            m_Height 
    = SizeY;
        m_SurRect.top    
    = 0;
        m_SurRect.left   
    = 0;
        m_SurRect.right  
    = m_Width;
        m_SurRect.bottom 
    = m_Height;
    }

    我们依然通过调用D3DXCreateTextureFromFileEx函数从特定的Img文件产生纹理,只不过这次通过传入特定的参数使其产生专门用于2D绘制的纹理。

    大家可以看到LoadTexture中的SizeX,SizeY我给定了默认值D3DX_DEFAULT_NONPOW2,意在使所获得的纹理默认支持非二次幂尺寸;而两个值如果默认为0的话,纹理尺寸会被自动拉伸到最相近的二次幂值,这不是我们所期待的结果。

    加载完毕的纹理必要信息,会被存放到一个D3DXIMAGE_INFO类型的结构体中,其定义可以参看SDK,很好理解~

    /*-------------------------------------

    代码清单:D3DSprite.h
    来自:
    http://www.cnblogs.com/kenkao

    -------------------------------------
    */

    #include 
    "Texture2D.h"

    #pragma once

    class CD3DSprite
    {
    public:
        CD3DSprite(IDirect3DDevice9
    * pDevice);
        
    ~CD3DSprite(void);
    public:
        
    void Begin(DWORD Flags);                 // 开启Sprite绘制
        void End();                              // 结束Sprite绘制
        void Draw(                               // 绘制Sprite
            CTexture2D* pTexture,                // 2D纹理
            const POINT& Position,               // 位置
            D3DCOLOR Color                       // 色相
            );
        
    void Draw(
            CTexture2D
    * pTexture, 
            
    const POINT& Position, 
            
    const RECT& SurRect,                 // 指定绘制纹理区域
            D3DCOLOR Color
            );
        
    void Draw(
            CTexture2D
    * pTexture, 
            
    const POINT& Pos, 
            
    const D3DXMATRIX& TransMatrix,       // 变换矩阵
            const RECT& SurRect, 
            D3DCOLOR Color
            );
        
    void Draw(
            CTexture2D
    * pTexture, 
            
    const POINT& Pos, 
            
    const POINT& Size,                   // 绘制尺寸
            const RECT& SurRect, 
            D3DCOLOR Color
            );
        
    void Draw(
            CTexture2D
    * pTexture, 
            
    const RECT& DesRect,                 // 指定绘制目标区域
            const RECT& SurRect, 
            D3DCOLOR Color
            );
        
    void Draw(
            CTexture2D
    * pTexture, 
            
    const RECT& DesRect, 
            D3DCOLOR Color
            );
        
    void Release(){ReleaseCOM(m_pSprite)};   // 释放Sprite
    public:
        ID3DXSprite
    * GetSprite(){return m_pSprite;}   // 获得Sprite指针
    private:
        ID3DXSprite
    * m_pSprite;                  // Sprite指针
        D3DXMATRIX   m_orgMatrix;                // 原始矩阵
    };
    /*-------------------------------------

    代码清单:D3DSprite.cpp
    来自:
    http://www.cnblogs.com/kenkao

    -------------------------------------
    */

    #include 
    "StdAfx.h"
    #include 
    "D3DSprite.h"

    CD3DSprite::CD3DSprite(IDirect3DDevice9
    * pDevice)
    {
        D3DXCreateSprite(pDevice, 
    &m_pSprite);
        D3DXMatrixTranslation(
    &m_orgMatrix,1.0f,1.0f,0.0f);
    }

    CD3DSprite::
    ~CD3DSprite(void)
    {
    }

    void CD3DSprite::Begin(DWORD Flags)
    {
        m_pSprite
    ->Begin(Flags);
    }

    void CD3DSprite::End()
    {
        m_pSprite
    ->End();
    }

    void CD3DSprite::Draw(CTexture2D* pTexture, const POINT& Pos, D3DCOLOR Color)
    {
        Draw(pTexture,Pos,pTexture
    ->GetRect(),Color);
    }

    void CD3DSprite::Draw(CTexture2D* pTexture, const POINT& Pos, const RECT& SurRect, D3DCOLOR Color)
    {
        m_pSprite
    ->Draw(pTexture->GetTexture(),&SurRect,&D3DXVECTOR3(0.0f,0.0f,0.0f),&D3DXVECTOR3(Pos.x,Pos.y,0.0f),Color);
    }

    void CD3DSprite::Draw(CTexture2D* pTexture, const POINT& Pos, const D3DXMATRIX& TransMatrix, const RECT& SurRect, D3DCOLOR Color)
    {
        
    // 设置缩放矩阵
        m_pSprite->SetTransform(&TransMatrix);
        Draw(pTexture,Pos,SurRect,Color);
        
    // 还原缩放矩阵
        m_pSprite->SetTransform(&m_orgMatrix);
    }

    void CD3DSprite::Draw(CTexture2D* pTexture, const POINT& Pos, const POINT& Size, const RECT& SurRect, D3DCOLOR Color)
    {
        D3DXMATRIX TransMatrix;
        FLOAT ScalX, ScalY;
        ScalX 
    = (FLOAT)Size.x/(FLOAT)(SurRect.right-SurRect.left);
        ScalY 
    = (FLOAT)Size.y/(FLOAT)(SurRect.bottom-SurRect.top);
        D3DXMatrixScaling(
    &TransMatrix,ScalX,ScalY,0.0f);
        Draw(pTexture,Pos,TransMatrix,SurRect,Color);
    }

    void CD3DSprite::Draw(CTexture2D* pTexture, const RECT& DesRect, const RECT& SurRect, D3DCOLOR Color)
    {
        POINT Pos;
        Pos.x 
    = DesRect.left;
        Pos.y 
    = DesRect.top;
        POINT Size;
        Size.x 
    = DesRect.right - DesRect.left;
        Size.y 
    = DesRect.bottom - DesRect.top;
        Draw(pTexture, Pos, Size, SurRect, Color);
    }

    void CD3DSprite::Draw(CTexture2D* pTexture, const RECT& DesRect, D3DCOLOR Color)
    {
        Draw(pTexture,DesRect,pTexture
    ->GetRect(),Color);
    }

    我们的CD3DSprite在原有ID3DXSprite基础上所做的主要工作是提供了大量的重载Draw函数,以更加人性化的参数设计提供更加便捷的函数调用。

    这里值得一提的是

    m_pSprite->SetTransform(&TransMatrix);

    方法的调用。所传入参数就目前测试来看,只可以是缩放矩阵,平移与旋转矩阵被认定是非法的。ID3DXSprite接口对象就是通过这种方式来完成2D图像的缩放工作的。(感谢CSDN游戏开发论坛一位大侠的提点 ^ ^)

    D3DGame.cpp
    /*-------------------------------------

    代码清单:D3DGame.cpp
    来自:
    http://www.cnblogs.com/kenkao

    -------------------------------------
    */

    #include 
    "StdAfx.h"
    #include 
    "D3DGame.h"
    #include 
    "D3DCamera.h"
    #include 
    "D3DEffect.h"
    #include 
    "CoordCross.h"
    #include 
    "SimpleXMesh.h"
    #include 
    "Texture2D.h"
    #include 
    "D3DSprite.h"
    #include 
    <stdio.h>

    //---通用全局变量

    HINSTANCE  g_hInst;
    HWND       g_hWnd;
    D3DXMATRIX g_matProjection;

    //---D3D全局变量

    IDirect3D9       
    *g_pD3D           = NULL;
    IDirect3DDevice9 
    *g_pD3DDevice     = NULL;
    CMouseInput      
    *g_pMouseInput    = NULL;
    CKeyboardInput   
    *g_pKeyboardInput = NULL;
    CD3DCamera       
    *g_pD3DCamera     = NULL;
    CCoordCross      
    *g_pCoordCross    = NULL;
    CSimpleXMesh     
    *g_pSimpleXMesh   = NULL;
    CD3DEffect       
    *g_pD3DEffect     = NULL;
    CD3DSprite       
    *g_pD3DSprite     = NULL;
    CTexture2D       
    *g_pTexture2D     = NULL;

    //---HLSL全局变量句柄

    D3DXHANDLE   g_CurrentTechHandle 
    = NULL;
    D3DXHANDLE   g_matWorldViewProj  
    = NULL;  
    D3DXHANDLE   g_matWorld          
    = NULL;
    D3DXHANDLE   g_vecEye            
    = NULL;
    D3DXHANDLE   g_vecLightDir       
    = NULL;
    D3DXHANDLE   g_vDiffuseColor     
    = NULL;
    D3DXHANDLE   g_vSpecularColor    
    = NULL;
    D3DXHANDLE   g_vAmbient          
    = NULL;

    // HLSL特效参数设置
    void GetParameters();
    void SetParameters();

    void Initialize(HINSTANCE hInst, HWND hWnd)
    {
        g_hInst 
    = hInst;
        g_hWnd  
    = hWnd;
        InitD3D(
    &g_pD3D, &g_pD3DDevice, g_matProjection, hWnd);
        g_pMouseInput 
    = new CMouseInput;
        g_pMouseInput
    ->Initialize(hInst,hWnd);
        g_pKeyboardInput 
    = new CKeyboardInput;
        g_pKeyboardInput
    ->Initialize(hInst,hWnd);
        g_pD3DCamera 
    = new CD3DCamera;
    }

    void LoadContent()
    {
        g_pCoordCross 
    = new CCoordCross;
        
    // 设置摄影机位置
        g_pD3DCamera->SetCameraPos(D3DXVECTOR3(0.5f,0.5f,-5.0f));
        g_pSimpleXMesh 
    = new CSimpleXMesh;
        
    // 加载X网格
        g_pSimpleXMesh->LoadXMesh("teapot.X");
        g_pD3DEffect 
    = new CD3DEffect;
        
    char ErrMsg[60];
        
    // 加载fx特效
        if(!g_pD3DEffect->LoadEffect("Light.fx",ErrMsg))
            ::MessageBox(g_hWnd,ErrMsg,
    0,0);
        
    // 获得句柄
        GetParameters();
        g_pD3DSprite 
    = new CD3DSprite(g_pD3DDevice);
        g_pTexture2D 
    = new CTexture2D;
        
    // 加载纹理
        g_pTexture2D->LoadTexture("img.jpg");
    }

    void Update()
    {
        g_pMouseInput
    ->GetState();
        g_pKeyboardInput
    ->GetState();
        g_pD3DCamera
    ->Update();
    }

    void Draw()
    {
        
    // 参数设定
        SetParameters();
        g_pD3DDevice
    ->SetTransform(D3DTS_VIEW,&g_pD3DCamera->GetViewMatrix());
        POINT pos;
        pos.x
    =0;
        pos.y
    =0;
        g_pD3DDevice
    ->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f0);
        
    if(SUCCEEDED(g_pD3DDevice->BeginScene())) 
        {
            g_pCoordCross
    ->Draw();

            
    // Sprite绘制开始
            g_pD3DSprite->Begin(D3DXSPRITE_ALPHABLEND);
            
    // Sprite绘制
            g_pD3DSprite->Draw(g_pTexture2D,pos,g_pTexture2D->GetRect(),D3DXCOLOR_WHITE);
            
    // Sprite绘制结束
            g_pD3DSprite->End();

            UINT numPasses;
            
    // 开启特效
            g_pD3DEffect->BeginEffect(numPasses);
            
    for(UINT i=0;i<numPasses;i++)
            {
                
    // 开启路径
                g_pD3DEffect->GetEffect()->BeginPass(i);
                
    for(DWORD j=0;j<g_pSimpleXMesh->GetMaterialNum();j++)
                {
                    g_pSimpleXMesh
    ->DrawXMeshSubset(j);
                }
                
    // 路径结束
                g_pD3DEffect->GetEffect()->EndPass();
            }
            
    // 特效结束
            g_pD3DEffect->EndEffect();
        
            g_pD3DDevice
    ->EndScene();
        }
        g_pD3DDevice
    ->Present(NULL, NULL, NULL, NULL);
    }

    void UnloadContent()
    {
        ReleaseCOM(g_pTexture2D);
        ReleaseCOM(g_pD3DSprite);
        ReleaseCOM(g_pD3DEffect);
        ReleaseCOM(g_pSimpleXMesh);
        ReleaseCOM(g_pCoordCross);
    }

    void Dispose()
    {
        ReleaseCOM(g_pD3DCamera);
        ReleaseCOM(g_pKeyboardInput);
        ReleaseCOM(g_pMouseInput);
        ReleaseCOM(g_pD3DDevice);
        ReleaseCOM(g_pD3D);
    }

    void GetParameters()
    {
        
    // 获得HLSL中各个全局变量句柄
        g_CurrentTechHandle = g_pD3DEffect -> GetEffect() -> GetTechniqueByName("SpecularLight");
        g_matWorldViewProj  
    = g_pD3DEffect -> GetEffect() -> GetParameterByName(0"matWorldViewProj");
        g_matWorld          
    = g_pD3DEffect -> GetEffect() -> GetParameterByName(0"matWorld");
        g_vecEye            
    = g_pD3DEffect -> GetEffect() -> GetParameterByName(0"vecEye");
        g_vecLightDir       
    = g_pD3DEffect -> GetEffect() -> GetParameterByName(0"vecLightDir");
        g_vDiffuseColor     
    = g_pD3DEffect -> GetEffect() -> GetParameterByName(0"vDiffuseColor");
        g_vSpecularColor    
    = g_pD3DEffect -> GetEffect() -> GetParameterByName(0"vSpecularColor");
        g_vAmbient          
    = g_pD3DEffect -> GetEffect() -> GetParameterByName(0"vAmbient");
    }

    void SetParameters()
    {
        
    // 设定当前技术
        g_pD3DEffect -> GetEffect() -> SetTechnique(g_CurrentTechHandle);
        
    // 设定HLSL中的各个参数
        D3DXMATRIX worldMatrix;
        D3DXMatrixTranslation(
    &worldMatrix,0.0f,0.0f,0.0f);
        g_pD3DEffect 
    -> GetEffect() -> SetMatrix(g_matWorldViewProj,&(worldMatrix*g_pD3DCamera->GetViewMatrix()*g_matProjection));
        g_pD3DEffect 
    -> GetEffect() -> SetMatrix(g_matWorld,&worldMatrix);
        D3DXVECTOR3 cameraPos 
    = g_pD3DCamera->GetCameraPos();
        D3DXVECTOR4 vecEye 
    = D3DXVECTOR4(cameraPos.x,cameraPos.y,cameraPos.z,0.0f);
        g_pD3DEffect 
    -> GetEffect() -> SetVector(g_vecEye,&vecEye);
        D3DXVECTOR4 vLightDirection 
    = D3DXVECTOR4(0.0f0.0f-1.0f1.0f);
        g_pD3DEffect 
    -> GetEffect() -> SetVector(g_vecLightDir,&vLightDirection);
        D3DXVECTOR4 vColorDiffuse 
    = D3DXVECTOR4(0.8f0.0f0.0f1.0f);
        D3DXVECTOR4 vColorSpecular 
    = D3DXVECTOR4(1.0f1.0f1.0f1.0f);
        D3DXVECTOR4 vColorAmbient 
    = D3DXVECTOR4(0.1f0.1f0.1f1.0f);
        g_pD3DEffect 
    -> GetEffect() -> SetVector(g_vDiffuseColor,&vColorDiffuse);
        g_pD3DEffect 
    -> GetEffect() -> SetVector(g_vSpecularColor,&vColorSpecular);
        g_pD3DEffect 
    -> GetEffect() -> SetVector(g_vAmbient,&vColorAmbient);
    }

    效果图:

  • 相关阅读:
    POJ1486 Sorting Slides 二分图or贪心
    POJ2060 Taxi Cab Scheme 最小路径覆盖
    POJ3083 Children of the Candy Corn 解题报告
    以前的文章
    POJ2449 Remmarguts' Date K短路经典题
    这一年的acm路
    POJ3014 Asteroids 最小点覆盖
    POJ2594 Treasure Exploration 最小路径覆盖
    POJ3009 Curling 2.0 解题报告
    POJ2226 Muddy Fields 最小点集覆盖
  • 原文地址:https://www.cnblogs.com/kenkao/p/2096657.html
Copyright © 2011-2022 走看看