d3d9 抓取windows屏幕

抓取桌面的几种方式里面,有GDI,direct3d, win10 的DXGI ,等等

以下代码已经在gitee上,使用direct3d方式抓屏,保存png方式图片,可自行下载,代码里面还有一些抓取音频的,这些还没有整理,空了就整理这些代码

https://gitee.com/guanzhi0319/capture

抓取的png图片

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

类声明

class ScreenCapture9
{
private:
	//HWND _hwnd = NULL;
	int _initbitmap = 0;
	BITMAPINFO _bitmapinfo;
	HDC _hMemDC = NULL;
	HDC _hDC = NULL;
	HBITMAP _hMemDCBitmap = NULL;
	BYTE * _pPixel = NULL;
	HCURSOR _hcur;
	//vars
	IDirect3D9*			g_pD3D = NULL;
	IDirect3DDevice9*	g_pd3dDevice = NULL;
	IDirect3DSurface9*	g_pSurface = NULL;
	HWND				ghWnd = NULL;
	RECT				gScreenRect = { 0,0,0,0 };
	UINT				gPitch = 0;
	void AddMouse(HDC hMemDC);
	HRESULT GrabImage(void* bitmap);
	//显示器个数
	UINT _DisplayCount = 1;
public:
	ScreenCapture9();
	~ScreenCapture9();
	//第几个显示器
	HRESULT	InitD3D(HWND hWnd,int nDisplay);
	UINT GetPitch();
	UINT GetHeight();
	UINT GetWidth();

	BYTE* Grab2Hwnd();

	void Cleanup();
	int InitDisplayCount();
	//void test();
};

实现,注意抓取鼠标的方式有一点小问题,可自行修改

#include "ScreenCapture9.h"

#include "DGIWPlus.h"
//#include <d3dx9.h>

ScreenCapture9::ScreenCapture9()
{
	CURSORINFO globalCursor;
	globalCursor.cbSize = sizeof(CURSORINFO); // could cache I guess...
	::GetCursorInfo(&globalCursor);
	_hcur = globalCursor.hCursor;
	//GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
}


ScreenCapture9::~ScreenCapture9()
{
	//GdiplusShutdown(m_gdiplusToken);
}

int ScreenCapture9::InitDisplayCount()
{
	if (g_pD3D == NULL)
	{
		if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
		{
			printf_s("Unable to Create Direct3D\n");
			return E_FAIL;
		}
	}
	_DisplayCount = g_pD3D->GetAdapterCount();
	return _DisplayCount;
}


HRESULT	ScreenCapture9::InitD3D(HWND hWnd,int nDisplay)
{

	D3DDISPLAYMODE	ddm;
	D3DPRESENT_PARAMETERS	d3dpp;
	if (g_pD3D == NULL)
	{
		if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
		{
			printf_s("Unable to Create Direct3D\n");
			return E_FAIL;
		}
		_DisplayCount = g_pD3D->GetAdapterCount();
	}

	if (nDisplay > _DisplayCount - 1)
	{
		nDisplay = D3DADAPTER_DEFAULT;
	}

	if (FAILED(g_pD3D->GetAdapterDisplayMode(nDisplay, &ddm)))
	{
		printf_s("Unable to Get Adapter Display Mode\n");
		return E_FAIL;
	}

	//g_pD3D->setA
	ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

	d3dpp.Windowed = true;
	d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
	d3dpp.BackBufferFormat =  ddm.Format;

	int width = ddm.Width; // rect.right - rect.left;
	int height = ddm.Height; // rect.bottom - rect.top;
#if 1
	d3dpp.BackBufferHeight = gScreenRect.bottom = ddm.Height;
	d3dpp.BackBufferWidth = gScreenRect.right = ddm.Width;
#endif
#if 0

	//gScreenRect = rect;
	d3dpp.BackBufferHeight = ddm.Height;// rect.bottom - rect.top;
	d3dpp.BackBufferWidth = ddm.Width;  // rect.right - rect.left;
#endif

	d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow = hWnd;
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

	
	if (FAILED(g_pD3D->CreateDevice(nDisplay, 
		D3DDEVTYPE_HAL, 
		hWnd, 
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		//D3DCREATE_HARDWARE_VERTEXPROCESSING , 
		&d3dpp, &g_pd3dDevice)))
	{
		printf_s("Unable to Create Device\n");
		return E_FAIL;
	}

	ghWnd = hWnd;

	if (FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8,
		D3DPOOL_SCRATCH, &g_pSurface, NULL)))
	{
		printf_s("Unable to Create Surface\n");
		return E_FAIL;
	}

	D3DLOCKED_RECT	lockedRect;

	if (FAILED(g_pSurface->LockRect(&lockedRect, NULL, 0)))					// compute the required buffer size
	{
		printf_s("Unable to Lock Surface\n");
		return E_FAIL;
	}
	gPitch = lockedRect.Pitch;
	if (FAILED(g_pSurface->UnlockRect()))
	{
		printf_s("Unable to Unlock Surface\n");
		return E_FAIL;
	}

	return S_OK;
}

UINT ScreenCapture9::GetPitch()
{
	return gPitch;
}

UINT ScreenCapture9::GetHeight()
{
	return gScreenRect.bottom - gScreenRect.top;
}

UINT ScreenCapture9::GetWidth()
{
	return gScreenRect.right -gScreenRect.left;
}


void ScreenCapture9::AddMouse(HDC hMemDC) {
	//	__int64 start = StartCounter();
	POINT p;

	GetCursorPos(&p);
	ICONINFO iconinfo;
	BOOL ret = ::GetIconInfo(_hcur, &iconinfo); // 0.09ms

	if (ret) {
		p.x -= iconinfo.xHotspot; // align mouse, I guess...
		p.y -= iconinfo.yHotspot;

		// avoid some memory leak or other...
		if (iconinfo.hbmMask) {
			::DeleteObject(iconinfo.hbmMask);
		}
		if (iconinfo.hbmColor) {
			::DeleteObject(iconinfo.hbmColor);
		}
	}

	DrawIcon(hMemDC, p.x, p.y, _hcur); // 0.042ms
									   //if (show_performance)
									   //	LocalOutput("add mouse took %.02f ms", GetCounterSinceStartMillis(start)); // sum takes around 0.125 ms
}

HRESULT ScreenCapture9::GrabImage(void* pBits)
{
	if (FAILED(g_pd3dDevice->GetFrontBufferData(0, g_pSurface)))
	{
		printf_s("Unable to get Buffer Surface Data\n");
		return E_FAIL;
	}
	/*static int i = 0;
	TCHAR buffer[256];
	wsprintf(buffer, L"CaptureScreenByDirectDraw%d.bmp",i);*/
	//D3DXSaveSurfaceToFile(buffer, D3DXIFF_BMP, g_pSurface, NULL, NULL);
	//HDC hdc;
	//HRESULT hok = g_pSurface->GetDC(&hdc);
	//if (hok == S_OK)
	//{
		//AddMouse(hdc);
	//}
	D3DLOCKED_RECT	lockedRect;
	if (FAILED(g_pSurface->LockRect(&lockedRect, NULL, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
	{
		printf_s("Unable to Lock Front Buffer Surface\n");
		return E_FAIL;
	}

	errno_t err;
	int height = gScreenRect.bottom - gScreenRect.top ;
	err = memcpy_s((BYTE*)pBits, lockedRect.Pitch*height, (BYTE*)lockedRect.pBits, lockedRect.Pitch*height);
	if (err)
	{
		printf_s("Error executing memcpy_s.\n");
	}
	
	if (FAILED(g_pSurface->UnlockRect()))
	{
		printf_s("Unable to Unlock Front Buffer Surface\n");
		return E_FAIL;
	}
	//g_pSurface->ReleaseDC(hdc);
	return S_OK;
}
#if 0
HRESULT ScreenCapture9::Reset()
{
	D3DDISPLAYMODE	ddm;
	D3DPRESENT_PARAMETERS	d3dpp;

	if (g_pSurface)															//Release the Surface - we need to get the latest surface
	{
		g_pSurface->Release();
		g_pSurface = NULL;
	}

	if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &ddm)))	//User might have changed the mode - Get it afresh
	{
		printf_s("Unable to Get Adapter Display Mode");
		return E_FAIL;
	}
	//if (FAILED(g_pD3D->GetAdapterDisplayMode(1, &ddm)))	//User might have changed the mode - Get it afresh
	//{
	//	printf_s("Unable to Get Adapter Display Mode");
	//	return E_FAIL;
	//}

	ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));

	d3dpp.Windowed = true;
	d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
	d3dpp.BackBufferFormat = ddm.Format;
	d3dpp.BackBufferHeight = gScreenRect.bottom = ddm.Height;
	d3dpp.BackBufferWidth = gScreenRect.right = ddm.Width;
	d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow = ghWnd;
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

	if (FAILED(g_pd3dDevice->Reset(&d3dpp)))
	{
		printf_s("Unable to Reset Device");
		return E_FAIL;
	}

	if (FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, /*D3DFMT_R8G8B8*/ D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &g_pSurface, NULL)))
	{
		printf_s("Unable to Create Surface");
		return E_FAIL;
	}

	return S_OK;
}
#endif
void ScreenCapture9::Cleanup()
{
	if (g_pSurface)
	{
		g_pSurface->Release();
		g_pSurface = NULL;
	}
	if (g_pd3dDevice)
	{
		g_pd3dDevice->Release();
		g_pd3dDevice = NULL;
	}
	if (g_pD3D)
	{
		g_pD3D->Release();
		g_pD3D = NULL;
	}
	//if (_pPixel != NULL)
	//	delete[]_pPixel;
	if(_hMemDC!=NULL)
		DeleteDC(_hMemDC);
	if(_hMemDCBitmap!=NULL)
		DeleteObject(_hMemDCBitmap);
}



BYTE* ScreenCapture9::Grab2Hwnd()
{
	
	int width = GetWidth();
	int height = GetHeight();
	int biBitCountchar = 32;
	if (_initbitmap == 0)
	{
		HDC hDC = GetDC(ghWnd);
		_initbitmap = 1;
		ZeroMemory(&_bitmapinfo, sizeof(BITMAPINFO));
		BITMAPINFOHEADER &bmiHeader = _bitmapinfo.bmiHeader;
		bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
		bmiHeader.biWidth = width;
		bmiHeader.biHeight = 0 - height;
		bmiHeader.biPlanes = 1;
		bmiHeader.biBitCount = biBitCountchar; // 32  24; 
		bmiHeader.biXPelsPerMeter = 0;
		bmiHeader.biYPelsPerMeter = 0;
		bmiHeader.biSizeImage = width*height;
		bmiHeader.biClrUsed = 0;
		bmiHeader.biClrImportant = 0;

		_hMemDC = CreateCompatibleDC(hDC);
		_hMemDCBitmap = CreateDIBSection(_hMemDC, &_bitmapinfo, DIB_RGB_COLORS
			, (void**)&_pPixel, NULL, 0);

		SelectObject(_hMemDC, _hMemDCBitmap);
		DeleteDC(hDC);
	}



	GrabImage(_pPixel);
	AddMouse(_hMemDC);
	//memcpy(_pPixel, pData, width*height*biBitCountchar / 8);
	//if (hWnd != NULL)
	//{
		//BitBlt(hDC, 0, 0, width, height, _hMemDC, 0, 0, SRCCOPY);
	//}

	return _pPixel;
	//pDestBuffer->Release();
}

main函数开始抓屏幕

int main()
{
 	ScreenCapture9* screenCapture9 = new ScreenCapture9();
	RECT rect = { 0,0,1920,1080 };
	screenCapture9->InitD3D(NULL,0);
	int w = screenCapture9->GetPitch();
	int h = screenCapture9->GetHeight();
	//void* bitmap = malloc(w*h);
	//WCHAR file[100];
	char file[100]; 
	GUID GUID_ContainerFormat = GUID_ContainerFormatPng;		//Change the container format according to the file format we use eg:Bmp
	BYTE *bitmap;
	for (int i = 0; i < 100; i++)
	{
		DWORD t1 = GetTickCount();
		bitmap = screenCapture9->Grab2Hwnd();
		DWORD t2 = GetTickCount();

		int len = screenCapture9->GetWidth() * 4 * screenCapture9->GetHeight();
#if 0
		printf("the time is %d\n", t2 - t1);
		char * pbuffer = NULL;
		int retlen = BMP2JPEG((char*)bitmap, len, &pbuffer);
		if (pbuffer != NULL)
		{
			FILE * fp;

			sprintf(file, "content\\GrabbedImage%d.jpg", i + 1);
			fp = fopen(file, "wb");
			if (fp != NULL)
			{
				fwrite(pbuffer, retlen, 1, fp);
				fclose(fp);
			}
		}
#endif
		//wsprintf(file, L"content\\GrabbedImage%d.png", i + 1);
		//sprintf(file, "content\\GrabbedImage%d.bmp", i + 1);
		//DGIPicStorage::SaveRgb2Bmp((char*)bitmap, screenCapture9->GetWidth(), screenCapture9->GetHeight(),32, file);
		
		//SavePixelsToFile32bppPBGRA(screenCapture9->GetWidth(), screenCapture9->GetHeight(), screenCapture9->GetPitch(), (BYTE*)bitmap, file, GUID_ContainerFormatBmp);
		SavePixelsToFile32bppPBGRA(screenCapture9->GetWidth(), screenCapture9->GetHeight(), screenCapture9->GetPitch(), (BYTE*)bitmap, file, GUID_ContainerFormatPng);
	}
	//free(bitmap);
	screenCapture9->Cleanup();
    return 0;
}

https://gitee.com/guanzhi0319/capture

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
directx 3d 实例#include #include "d3d9.h" #include "d3dx9.h" #include "Direct3D.h" // Direct3D objects IDirect3D9 *g_pD3D = NULL; IDirect3DDevice9 *g_pD3DDevice = NULL; // Sky vertex structure, fvf, vertex buffer, and texture typedef struct { float x, y, z, rhw; float u, v; } sSkyVertex; #define SKYFVF (D3DFVF_XYZRHW | D3DFVF_TEX1) IDirect3DVertexBuffer9 *g_SkyVB = NULL; IDirect3DTexture9 *g_SkyTexture = NULL; // Land and water meshes D3DXMESHCONTAINER_EX *g_WaterMesh = NULL; D3DXMESHCONTAINER_EX *g_LandMesh = NULL; // Window class and caption text char g_szClass[] = "TextureTransformationClass"; char g_szCaption[] = "Texture Transformation Demo by Jim Adams"; // Function prototypes int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow); long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void Matrix4x4To3x3(D3DXMATRIX *matOut, D3DXMATRIX *matIn); BOOL DoInit(HWND hWnd, BOOL Windowed = TRUE); void DoShutdown(); void DoFrame(); int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow) { WNDCLASSEX wcex; MSG Msg; HWND hWnd; // Initialize the COM system CoInitialize(NULL); // Create the window class here and register it wcex.cbSize = sizeof(wcex); wcex.style = CS_CLASSDC; wcex.lpfnWndProc = WindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInst; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = NULL; wcex.lpszMenuName = NULL; wcex.lpszClassName = g_szClass; wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wcex)) return FALSE; // Create the main window hWnd = CreateWindow(g_szClass, g_szCaption, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 0, 0, 640, 480, NULL, NULL, hInst, NULL); if(!hWnd) return FALSE; ShowWindow(hWnd, SW_NORMAL); UpdateWindow(hWnd); // Call init function and enter message pump if(DoInit(hWnd) == TRUE) { // Start message pump, waiting for user to exit ZeroMemory(&Msg, sizeof(MSG)); while(Msg.message != WM_QUIT) { if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } // Render a single frame DoFrame(); } } // Call shutdown DoShutdown(); // Unregister the window class UnregisterClass(g_szClass, hInst); // Shut down the COM system CoUninitialize(); return 0; } long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, \ WPARAM wParam, LPARAM lParam) { // Only handle window destruction messages switch(uMsg) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; } BOOL DoInit(HWND hWnd, BOOL Windowed) { // Initialize Direct3D InitD3D(&g_pD3D, &g_pD3DDevice, hWnd); // Load the land and water meshes LoadMesh(&g_WaterMesh, g_pD3DDevice, "..\\Data\\Water.x", "..\\Data\\"); LoadMesh(&g_LandMesh, g_pD3DDevice, "..\\Data\\Land.x", "..\\Data\\"); // Create the sky backdrop sSkyVertex SkyVerts[4] = { { 0.0f, 0.0, 1.0, 1.0f, 0.0f, 0.0f }, { 640.0f, 0.0, 1.0, 1.0f, 1.0f, 0.0f }, { 0.0f, 480.0, 1.0, 1.0f, 0.0f, 1.0f }, { 640.0f, 480.0, 1.0, 1.0f, 1.0f, 1.0f } }; g_pD3DDevice->CreateVertexBuffer(sizeof(SkyVerts), D3DUSAGE_WRITEONLY, SKYFVF, D3DPOOL_DEFAULT, &g_SkyVB, NULL); char *Ptr; g_SkyVB->Lock(0,0, (void**)&Ptr, 0); memcpy(Ptr, SkyVerts, sizeof(SkyVerts)); g_SkyVB->Unlock(); D3DXCreateTextureFromFile(g_pD3DDevice, "..\\Data\\Sky.bmp", &g_SkyTexture); // Setup a light D3DLIGHT9 Light; ZeroMemory(&Light, sizeof(Light)); Light.Diffuse.r = Light.Diffuse.g = Light.Diffuse.b = Light.Diffuse.a = 1.0f; Light.Type = D3DLIGHT_DIRECTIONAL; D3DXVECTOR3 vecLight = D3DXVECTOR3(-1.0f, -1.0f, 0.5f); D3DXVec3Normalize(&vecLight, &vecLight); Light.Direction = vecLight; g_pD3DDevice->SetLight(0, &Light); g_pD3DDevice->LightEnable(0, TRUE); // Start playing a waterfall sound PlaySound("..\\Data\\Waterfall.wav", NULL, SND_ASYNC | SND_LOOP); return TRUE; } void DoShutdown() { // Stop playing an ocean sound PlaySound(NULL, NULL, 0); // Free meshes delete g_WaterMesh; g_WaterMesh = NULL; delete g_LandMesh; g_LandMesh = NULL; // Release sky data ReleaseCOM(g_SkyVB); ReleaseCOM(g_SkyTexture); // Release D3D objects ReleaseCOM(g_pD3DDevice); ReleaseCOM(g_pD3D); } void DoFrame() { // Create and set the view transformation D3DXMATRIX matView; D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(360.0f, -170.0f, -430.0f), &D3DXVECTOR3(65.0f, 70.0f, -15.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView); // Clear the device and start drawing the scene g_pD3DDevice->Clear(NULL, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0,0,64,255), 1.0, 0); if(SUCCEEDED(g_pD3DDevice->BeginScene())) { // Set identity matrix for world transformation D3DXMATRIX matWorld; D3DXMatrixIdentity(&matWorld); g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld); // Draw the sky g_pD3DDevice->SetFVF(SKYFVF); g_pD3DDevice->SetStreamSource(0, g_SkyVB, 0, sizeof(sSkyVertex)); g_pD3DDevice->SetTexture(0, g_SkyTexture); g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // Enable lighting g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE); // Draw the land meshes DrawMeshes(g_LandMesh); // Setup the texture transformation float TimeFactor = (float)(timeGetTime() / 500.0f); D3DXMATRIX matTexture; D3DXMatrixTranslation(&matTexture, 0.0f, -TimeFactor, 0.0f); Matrix4x4To3x3(&matTexture, &matTexture); g_pD3DDevice->SetTransform(D3DTS_TEXTURE0, &matTexture); g_pD3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); // Draw the water (using alpha blending) DrawMeshes(g_WaterMesh); g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); // Disable lighting g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); // Turn off texture transformations g_pD3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); // End the scene g_pD3DDevice->EndScene(); } // Present the scene to the user g_pD3DDevice->Present(NULL, NULL, NULL, NULL); } void Matrix4x4To3x3(D3DXMATRIX *matOut, D3DXMATRIX *matIn) { matOut->_11 = matIn->_11; // Copy over 1st row matOut->_12 = matIn->_12; matOut->_13 = matIn->_13; matOut->_14 = 0.0f; matOut->_21 = matIn->_21; // Copy over 2nd row matOut->_22 = matIn->_22; matOut->_23 = matIn->_23; matOut->_24 = 0.0f; matOut->_31 = matIn->_41; // Copy bottom row matOut->_32 = matIn->_42; // used for translation matOut->_33 = matIn->_43; matOut->_34 = 0.0f; matOut->_41 = 0.0f; // Clear the bottom row matOut->_42 = 0.0f; matOut->_43 = 0.0f; matOut->_44 = 1.0f; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qianbo_insist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值