一个DrectX程序的基本流程(DXD10以下)

本文章通过一个简单的示例来说明一下一个D3D程序的基本流程

[注]:本程序使用DirectX 9.0实现并使用了Qt,参照的时候不要链接库链接错了哦.

示例<使用D3D渲染一个jpg图像到窗口>

步骤:
1、创建一个Windows窗口程序
2、初始化D3D
3、渲染

1、使用VS2010(或其他版本)创建一个标准的WIN32程序.  (这个步骤不多做解释)


2、以下步骤的操作封装在D3DRender中

步骤2、3:

封装一个类(D3DRender)

test.h


#include "d3dx9.h"
#include "Windows.h"
#include <QImage>

class D3DRender
{
private:
    static int                     g_DeviceWidth     ;
    static int                     g_DeviceHeight    ;
    static LPDIRECT3D9             g_pD3D            ; //* 用来创建D3D设备
    static LPDIRECT3DDEVICE9       g_pd3dDevice      ; //* D3D设备
    static LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer   ; //* 顶点缓存
    static LPDIRECT3DTEXTURE9      g_pTexture        ; //* 纹理
    static HWND                    g_hTargetWin      ; //* 目标窗口(也就是该D3D程序的主窗口)
    static QImage                  g_TargetImage     ; //* 被渲染的图片

    //响应操作
    void onKeyDown(WPARAM wParam, LPARAM lParam);
    void onPaint(HDC hdc);
    void getWndClassEx(WNDCLASSEX& wc);

public:
    D3DRender();
    ~D3DRender();

    HRESULT initD3D(HWND hWnd);
    void render();

    void cleanup();
    void renderTest();
};

test.cpp

#include "test.h"

#include "atldef.h"

// .lib files.
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

int                     D3DRender::g_DeviceWidth     = 0;
int                     D3DRender::g_DeviceHeight    = 0;
LPDIRECT3D9             D3DRender::g_pD3D            = 0; //* 用来创建D3D设备
LPDIRECT3DDEVICE9       D3DRender::g_pd3dDevice      = 0; //* D3D设备
LPDIRECT3DVERTEXBUFFER9 D3DRender::g_pVertexBuffer   = 0; //* 顶点缓存
LPDIRECT3DTEXTURE9      D3DRender::g_pTexture        = 0; //* 纹理
HWND                    D3DRender::g_hTargetWin      = 0; //* 目标窗口(也就是该D3D程序的主窗口)
QImage                  D3DRender::g_TargetImage        ; //* 被渲染的图片

//* 带RHW 和 Color格式的顶点
struct CustomVertex_RHW_COLOR
{
    float x,y,z,rhw;
    unsigned long color;
};

#define D3DFVF_CUSTOMERTEX_RHW_COLOR (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

//* 带TEX1格式的顶点
struct CustomVertex_XYZ_TEX1
{
	float x,y,z;
	float tu,tv;
};

#define D3DFVF_CUSTOMERTEX_XYZ_TEX1 (D3DFVF_XYZ|D3DFVF_TEX1)

void D3DRender::cleanup()
{
    if( g_pVertexBuffer != NULL)
        g_pVertexBuffer->Release();
    if( g_pd3dDevice != NULL)
        g_pd3dDevice->Release();
    if( g_pD3D != NULL)
        g_pD3D->Release();
}

void D3DRender::renderTest()
{
    if( NULL == g_pd3dDevice )
            return;

	float fBlue = 0.01024;

	//* 初始化背景颜色
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
		D3DCOLOR_COLORVALUE(0.0f, 0.0f, fBlue, 1.0f), 1.0f, 0); 

	//* 开始渲染场景
	g_pd3dDevice->BeginScene();

	//* 获取需要渲染的缓冲区
	LPDIRECT3DSURFACE9 pBackBuffer;
	g_pd3dDevice->GetRenderTarget(0, &pBackBuffer);

	//* 如果纹理被创建则将纹理渲染
	if(g_pTexture)
	{
		//* 渲染到纹理
		LPDIRECT3DSURFACE9 pRenderSurface;
		g_pTexture->GetSurfaceLevel(0, &pRenderSurface);

		RECT wrt = {0};
		GetWindowRect(g_hTargetWin, &wrt);
		
		float currentWindowWidth = wrt.right - wrt.left;
		float currentWindowHeight = wrt.bottom - wrt.top;
		float currentImageWidth = g_TargetImage.width();
		float currentImaeHeight = g_TargetImage.height();

		float showImageWidth  =  currentImageWidth ;
		float showImageHeight =  currentImaeHeight;


		//D3DVIEWPORT9 viewPort = {0,0, showImageWidth / aspX, showImageHeight / aspY, 0.0f, 1.0f};
		//g_pd3dDevice->SetViewport(&viewPort);


		//* 将图片数据拷贝到纹理
		D3DLOCKED_RECT lockRect;
		if(SUCCEEDED(pRenderSurface->LockRect(&lockRect, 0, 0)))
		{
			unsigned char* pdata = g_TargetImage.bits();
			unsigned char* pDstBits = (unsigned char*)lockRect.pBits;
			int byteCount = g_TargetImage.byteCount();

			memcpy(pDstBits, pdata, byteCount);
			pRenderSurface->UnlockRect();
		}

		// Make sure that the z-buffer and lighting are disabled
		g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
		g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

		// Use the alpha channel
		g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

		// Draw our quad
		g_pd3dDevice->SetTexture( 0, g_pTexture );
		g_pd3dDevice->SetStreamSource(0, g_pVertexBuffer, 0 ,sizeof(CustomVertex_XYZ_TEX1));
		g_pd3dDevice->SetFVF(D3DFVF_CUSTOMERTEX_XYZ_TEX1);

		// Render target
		g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); 
	}

	//* 结束场景渲染
	g_pd3dDevice->EndScene();
	
	//* 刷新
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}

HRESULT D3DRender::initD3D(HWND hWnd)
{
	g_DeviceWidth  	   = 0;
	g_DeviceHeight 	   = 0;
	g_pD3D         	   = 0;
	g_pd3dDevice   	   = 0;
	g_pVertexBuffer	   = 0;
	g_pTexture     	   = 0;

	g_hTargetWin       = hWnd;


	//* 加载需要渲染的图片 
	if(!g_TargetImage.load("D:/SVN/code/output/W3L/res/Image/Common/Test/GameZoneAD.png"))
	{
		return E_FAIL;
	}

	//* 根据需要转换格式
	//g_TargetImage = g_TargetImage.convertToFormat(QImage::Format_RGBA8888_Premultiplied);

    BOOL isWindowMode = TRUE;
	HRESULT hr = E_FAIL;

    // 创建D3D对象
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;
		
    // 获取当前的显示模式
    D3DDISPLAYMODE d3ddm;

	hr = g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
    if(FAILED(hr))
        return E_FAIL;

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.Windowed = isWindowMode; // 是否全屏模式
	//if(isWindowMode)
	//{
	//	RECT rt;
	//	GetWindowRect(hWnd,&rt);
	//    d3dpp.BackBufferWidth  = rt.right - rt.left ;
	//    d3dpp.BackBufferHeight = rt.bottom - rt.top ;
	//}
	//else
	//{
	//	d3dpp.BackBufferWidth  = d3ddm.Width ;
	//	d3dpp.BackBufferHeight = d3ddm.Height;
	//}
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;   // 设置交换模式
    d3dpp.BackBufferFormat = d3ddm.Format;      // 设置背景缓冲区格式为当前左面格式
    d3dpp.BackBufferCount = 1;


    // 创建D3D设备
    // 第一个参数:使用默认的显卡
    // 第二个参数:请求使用硬件抽象层(HAL)
    // 第三个参数:窗口句柄
    // 第四个参数:使用软件处理顶点
    // 第五个参数:创建的参数
    // 第六个参数:创建的D3D设备指针
	hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp,
		&g_pd3dDevice );

    if(FAILED(hr))
    {
        return E_FAIL;
    }

    //初始化顶点缓冲区
    int w = isWindowMode ? d3ddm.Width  : d3dpp.BackBufferWidth;
    int h = isWindowMode ? d3ddm.Height : d3dpp.BackBufferHeight;
	g_DeviceWidth  = w;
	g_DeviceHeight = h;


	//* 注意0~1 是宽度1是实际宽度,0是0,大于1就是放大了
	CustomVertex_XYZ_TEX1 vertexs[] =
	{
		{-1.0f,  1.0f, 0.0f, 0.0f, 0.0f},
		{ 1.0f,  1.0f, 0.0f, 1.0f, 0.0f},
		{-1.0f, -1.0f, 0.0f, 0.0f, 1.0f},
		{ 1.0f, -1.0f, 0.0f, 1.0f, 1.0f},
	};
    
    int vertexsSize = sizeof(vertexs);

	//* 创建定点缓存
    LPDIRECT3DVERTEXBUFFER9 pVertexBuffer;
	hr = g_pd3dDevice->CreateVertexBuffer(vertexsSize,
		                                 D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMERTEX_XYZ_TEX1,
		                                 D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
    if(FAILED(hr))
    {
        return E_FAIL;
    }
    g_pVertexBuffer = pVertexBuffer;

    void* pVertex = 0;
    pVertexBuffer->Lock(0, vertexsSize, (void**)&pVertex, 0);
    memcpy(pVertex, vertexs, vertexsSize);
    pVertexBuffer->Unlock();


	//* 初始化纹理
	hr = g_pd3dDevice->CreateTexture(g_TargetImage.width(),
								     g_TargetImage.height(),
									 1,
									 0,
									 d3ddm.Format,
									 D3DPOOL_MANAGED,
									 &g_pTexture,
									 NULL);
	if(FAILED(hr))
	{
		return E_FAIL;
	}
	

    return S_OK;
}

D3DRender::D3DRender()
{
	
}

D3DRender::~D3DRender()
{
	cleanup();
}

void D3DRender::render()
{
    if( NULL == g_pd3dDevice )
            return;


	renderTest();
	return ;
}

 

这个D3DRender最好是最为全局的单例使用。

在WM_CREATE的处理函数中:

D3DRender::Instance()->initD3D(hWnd);

在WM_PAINT的处理函数中

D3DRender::Instance()->render();

 

运行程序,得到结果:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值