初学Direct X (2)


这一次要学习如何现实位图,尽管看过对双缓冲机制还有很多疑问,但是这并不阻碍我对他的入门了解

Direct3D提供了一个双重/后台缓冲区,在调用CreateDevice之时就有了。其运行机制就是,我们需要在其中一个缓冲区上绘制完所需要显示的一切,之后将这个缓冲区快速的复制到另一个缓冲区,因为后者的缓冲区被称为Front Buffer,显示器在刷新之时会直接从中取出数据以显示,而前者就称之为backbuffer

但是,还有一种buffer,是可供我们在内存中进行操作的,被称之为surface,也有离屏表面的称呼,后面的表面都指的是离屏表面

1. 使用表面的实例

初始化变量:

LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL;
// 指向内存中的表面
LPDIRECT3DSURFACE9 surface = NULL;

1.1 Game_Init()

bool Game_Init(HWND hwnd)
{
//initialize Direct3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (d3d == NULL)
{
MessageBox(hwnd, "Error initializing Direct3D", "Error", MB_OK);
return false;
} //set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp; d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&dm); ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = dm.Width;
d3dpp.BackBufferHeight = dm.Height;
d3dpp.hDeviceWindow = hwnd; //create Direct3D device
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &d3ddev); if (!d3ddev)
{
MessageBox(hwnd, "Error creating Direct3D device", "Error", MB_OK);
return false;
} //set random number seed
// 用于Game_Run()
srand((unsigned int)time(NULL)); //clear the backbuffer to black
//注意这里并没有获取到backbuffer指针,就可以直接Clear backbuffer
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); //create pointer to the back buffer
//通常这是指向真实后台缓冲区的指针
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); //create surface
HRESULT result = d3ddev->CreateOffscreenPlainSurface(
100, //width of the surface
100, //height of the surface
D3DFMT_X8R8G8B8, //surface format
D3DPOOL_DEFAULT, //memory pool to use
&surface, //pointer to the surface
NULL); //reserved (always NULL) if (result != D3D_OK) return false; return true;
}

这样一来,就获取了backbuffer的位置,并且创造了一个离屏表面,可供我们进行绘图操作

1.2 Game_Run()

void Game_Run(HWND hwnd)
{
//make sure the Direct3D device is valid
if (!d3ddev) return; //start rendering
if (d3ddev->BeginScene())
{
//将离屏表面填色
int r = rand() % 255;
int g = rand() % 255;
int b = rand() % 255;
d3ddev->ColorFill(surface, NULL, D3DCOLOR_XRGB(r, g, b)); //把离屏表面复制到backbuffer
RECT rect;
rect.left = rand() % dm.Width;
rect.right = rect.left + rand() % (dm.Width - rect.left);
rect.top = rand() % dm.Height;
rect.bottom = rect.top + rand() % (dm.Height - rect.top);
d3ddev->StretchRect(surface, NULL, backbuffer, &rect, D3DTEXF_NONE); //stop rendering
d3ddev->EndScene(); //将backbuffer的数据显示到屏幕上
d3ddev->Present(NULL, NULL, NULL, NULL);
} //check for escape key (to exit program)
if (KEY_DOWN(VK_ESCAPE))
PostMessage(hwnd, WM_DESTROY, 0, 0);
}

1.3写到这里的时候我发现几个问题

1) 似乎无法操作front buffer?

这正是双缓冲的机制,因为直接操作front buffer会导致一些问题,想象一下,若屏幕的刷新频率很快,而此时你正在生成一个计算量巨大的数据,正在你计算之时,显示器已经来尝试取n次数据了,而这n次取出的图像都是一部分且不连贯的。故而出现了双缓冲技术,在backbuffer绘制好之后再将其显示在屏幕上

2)backbuffer和frontbuffer的是怎么运转的,好像只要调用Present就可以将backbuffer的显示在屏幕上了

2. 加载位图

需要使用d3dx,它是Direct3D Extensions 即Direct3D的扩展,需要进行如下的引用:

#include <d3dx9.h>
#pragma comment(lib,"d3dx9.lib")

有趣的就是D3DXLoadSurfaceFromFile函数了,他可以装载.bmp , .jpng, .png等一系列的位图,调用示例如下:

result = D3DXLoadSurfaceFromFile(
surface,
NULL,
NULL,
"show.png",
NULL,
D3DX_DEFAULT,
0,
NULL
);

3. 绘制表面

StretchRect函数可以将某个表面的一部分或全部位块传输到另一个表面

HRESULT StretchRect(
IDirect3DSurface9* pSourceSurface,
CONST RECT* pSourceRect,
IDirect3DSurface9* pDestSurface,
CONST RECT* pDestRect,
D3DTEXTUREFILTERTYPE Filter)

这里值得一提的是,若rect超出了pDestSurface的显示范围,函数还是可以正常运行的,下面是调用示例:

	d3ddev->StretchRect(surface, NULL, backbuffer, &rect, D3DTEXF_NONE);

最新文章

  1. JavaScript DOM学习总结(一)
  2. 21045308刘昊阳 《Java程序设计》第九周学习总结
  3. javascript变量名提升
  4. java中判断字符串是否为数字的三种方法
  5. nginx php-cgi php
  6. PE文件结构学习
  7. Android之按钮
  8. java的socket 编程
  9. 问题-安装XP时,提示不识别SATA硬盘
  10. Web Service学习笔记(webservice、soap、wsdl、jws详细分析) (转)
  11. 获取电脑cpu的使用情况
  12. acFileStorage equivalent
  13. hdu2203 KMP水的问题
  14. 用Quick Cocos2dx做一个连连看(二)
  15. Linux 下操作Mysql指令的总结 远程连接的设置
  16. Building gRPC Client iOS Swift Note Taking App
  17. 3. SpringBoot ——自动配置原理浅析
  18. Java——IO类,字节流写数据
  19. PHP SNOOPY采集类 总结
  20. 解决myeclipse启动慢的问题

热门文章

  1. Redis启动问题解决方案
  2. Coursera机器学习基石 第1讲:The Learning Problem
  3. iOS 加载pdf格式的文件
  4. 用DecimalFormat格式化十进制数字的实际应用
  5. ffmpeg教程
  6. Oracle 创建触发器实现自增长
  7. STM32之关闭JTAG
  8. ObjC之RunTime(上)
  9. python打印99乘法表
  10. Wireshark工具抓包的数据包分析