请问一下DX9关于surface的问题
1.如何显示一块surface
2.如何对surface像素进行操作
[解决办法]
我给你一个完整的例子(除了加载和渲染IDirect3DSurface9外,没有其他多余代码),另外有一个读取tga问的函数,这函数是为了演示如何手动加载像素到IDirect3DSurface9的,另外D3D的相关定义未给出,这个也就没必要写了:
// 保存对齐状态#pragma pack(push)#pragma pack(1)// TGA 文件头struct TGA_FILE_HEADER { // TGA像素数据的排列顺序:B G R A BYTE IdLength; // 图像信息字段(默认:0) BYTE ColorMapType; // 颜色标的类型(默认0) BYTE ImageType; // 图像类型码(支持2或10) WORD ColorMapFirstIndex; // 颜色表的索引(默认:0) WORD ColorMapLength; // 颜色表的长度(默认:0) BYTE ColorMapEntrySize; // 颜色表表项的为数(默认:0,支持16/24/32) WORD XOrigin; // 图像X坐标的起始位置(默认:0) WORD YOrigin; // 图像Y坐标的起始位置(默认:0) WORD ImageWidth; // 图像的宽度 WORD ImageHeight; // 图像的高度 BYTE PixelDepth; // 图像每像素存储占用位数 BYTE ImageDescruptor; // 图像描述字符字节(默认:0,不支持16bit 565格式)};// 像素struct PIXEL32{ BYTE B; // 蓝色 BYTE G; // 绿色 BYTE R; // 红色 BYTE A; // 通道};#pragma pack(pop)//恢复对齐状态// 获取tga文件的bmp数据(无压缩的tga文件)void GetBmpFromTga(const char* srcFile, UINT** ppDstBmpBuffer, int* pOutWidth, int* pOutHeight, int* pOutSize){ TGA_FILE_HEADER TgaHeader; memset(&TgaHeader, 0, sizeof(TGA_FILE_HEADER)); FILE* pFile = fopen(srcFile, "rb"); if (pFile == NULL) { char strErrorInfo[256]; sprintf(strErrorInfo, "%s打开失败!", srcFile); MessageBox(0, strErrorInfo, 0, MB_OK); return; } UINT* pBmpData = NULL; int pixelCount = 0; // 读TGA图像文件头 fread((char*)(&TgaHeader), sizeof(TGA_FILE_HEADER), 1, pFile); pixelCount = TgaHeader.ImageWidth * TgaHeader.ImageHeight; pBmpData = new UINT[pixelCount]; // 读图像数据 fread(pBmpData, sizeof(PIXEL32)*pixelCount, 1, pFile); fclose(pFile); if (ppDstBmpBuffer != NULL) *ppDstBmpBuffer = pBmpData; if (pOutWidth != NULL) *pOutWidth = TgaHeader.ImageWidth; if (pOutHeight != NULL) *pOutHeight = TgaHeader.ImageHeight; if (pOutSize != NULL) *pOutSize = sizeof(PIXEL32) * pixelCount;}// 初始化void CRender::InitData(){ m_pSurface = NULL; D3DXIMAGE_INFO imageInfo; D3DXGetImageInfoFromFile("test.tga", &imageInfo); HRESULT hr; hr = m_pD3DDevice->CreateOffscreenPlainSurface(imageInfo.Width, imageInfo.Height, imageInfo.Format, D3DPOOL_DEFAULT, &m_pSurface, NULL); if (FAILED(hr)) { MessageBox(0, "CreateOffscreenPlainSurface()创建失败!", 0, MB_OK); } m_Width = imageInfo.Width; m_Height = imageInfo.Height; // 用D3DXLoadSurfaceFromFile()加载像素 if (true) { D3DXLoadSurfaceFromFile(m_pSurface, NULL, NULL, "test.tga", NULL, D3DX_FILTER_NONE, 0, &imageInfo); } // 手动加载像素 if (false) { UINT* pBmp32 = NULL; // 加载tga文件 { GetBmpFromTga("test.tga", &pBmp32, &m_Width, &m_Height, NULL); } D3DLOCKED_RECT lrect; hr = m_pSurface->LockRect(&lrect, NULL, 0); if (FAILED(hr)) { delete pBmp32; pBmp32 = NULL; m_pSurface->UnlockRect(); return; } UINT* pSrc = (UINT*)pBmp32; UINT* pDst = static_cast<UINT*>(lrect.pBits); int pitch = lrect.Pitch/sizeof(UINT); pSrc += (m_Height-1)*m_Width; for (int h=0, w=0, index=0; h<m_Height; h++) { memcpy(pDst, pSrc, sizeof(UINT)*m_Width); pSrc-=m_Width, pDst+=pitch; } m_pSurface->UnlockRect(); delete pBmp32; pBmp32 = NULL; }}// 加载表面数据void CRender::InitData(){ m_pSurface = NULL; D3DXIMAGE_INFO imageInfo; D3DXGetImageInfoFromFile("test.tga", &imageInfo); HRESULT hr; hr = m_pD3DDevice->CreateOffscreenPlainSurface(imageInfo.Width, imageInfo.Height, imageInfo.Format, D3DPOOL_DEFAULT, &m_pSurface, NULL); if (FAILED(hr)) { MessageBox(0, "CreateOffscreenPlainSurface()创建失败!", 0, MB_OK); } m_Width = imageInfo.Width; m_Height = imageInfo.Height; // 用D3DXLoadSurfaceFromFile()加载像素 if (true) { D3DXLoadSurfaceFromFile(m_pSurface, NULL, NULL, "test.tga", NULL, D3DX_FILTER_NONE, 0, &imageInfo); } // 手动加载像素 if (false) { UINT* pBmp32 = NULL; // 加载tga文件 { GetBmpFromTga("test.tga", &pBmp32, &m_Width, &m_Height, NULL); } D3DLOCKED_RECT lrect; hr = m_pSurface->LockRect(&lrect, NULL, 0); if (FAILED(hr)) { delete pBmp32; pBmp32 = NULL; m_pSurface->UnlockRect(); return; } UINT* pSrc = (UINT*)pBmp32; UINT* pDst = static_cast<UINT*>(lrect.pBits); int pitch = lrect.Pitch/sizeof(UINT); pSrc += (m_Height-1)*m_Width; for (int h=0, w=0, index=0; h<m_Height; h++) { memcpy(pDst, pSrc, sizeof(UINT)*m_Width); pSrc-=m_Width, pDst+=pitch; } m_pSurface->UnlockRect(); delete pBmp32; pBmp32 = NULL; }}// 渲染表面数据void CRender::RenderExample(){// ... IDirect3DSurface9* backbuffer = NULL; RECT rcSrc = { 0, 0, m_Width, m_Height }; // 纹理坐标 RECT rcDst = { 200, 200, 0, 0 }; // 目标矩形区域 rcDst.right = rcDst.left + (rcSrc.right-rcSrc.left); rcDst.bottom = rcDst.top + (rcSrc.bottom-rcSrc.top); m_pD3DDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); m_pD3DDevice->StretchRect(m_pSurface, &rcSrc, backbuffer, &rcDst, D3DTEXF_NONE); m_pD3DDevice->UpdateSurface(m_pSurface, NULL, backbuffer, NULL);//...}