四面体简单光照渲染+漫游(使用多个ConstantBuffer减小带宽)

2016-12-13 19:31:27来源:CSDN作者:qq_34581491人点击

建立了三个ConstantBuffer,一个是每一帧都需要从cpu传过来的用来旋转的world矩阵,一个是摄影机操作后传过来的view矩阵,还有一个是只传过来一次的projection矩阵和两个方向光的向量

1.lighting.fx

// Constant Buffer Variablescbuffer CBChangesEveryFrame : register( b0 ){	matrix World;};cbuffer CBChangesWhenMoving : register( b1 ){	matrix View;}cbuffer CBNeverChange : register( b2 ){	matrix Projection;	float4 vLightDir[2];};struct VS_INPUT{    float4 Pos : POSITION;    float3 Norm : NORMAL;};struct PS_INPUT{    float4 Pos : SV_POSITION;    float3 Norm : TEXCOORD0;};// 以上都是声明// Vertex ShaderPS_INPUT VS( VS_INPUT input ){    PS_INPUT output = (PS_INPUT)0;    output.Pos = mul( input.Pos, World );    output.Pos = mul( output.Pos, View );    output.Pos = mul( output.Pos, Projection );	output.Norm = mul( float4(input.Norm, 1), World ).xyz;// .xyz指取前三位向量,等式左边的PS_INPUT中的Norm是float3型,而右边是float4型	// 也可写成output.Norm = mul( input.Norm, (float3x3)World );        return output;}// Pixel Shaderfloat4 PS( PS_INPUT input) : SV_Target{	static float4 vLightColor = {1.0f, 1.0f, 1.0f, 1.0f};    float4 finalColor = 0;	float k = 0.85f;// 反射率    for(int i = 0; i < 2; i++)    {        finalColor += k * saturate(dot((float3)vLightDir[i], -input.Norm) * vLightColor);// 反射率 * saturate(dot(两光线向量·顶点法线向量)·颜色值),saturate表示饱和处理——大于1变为1,小于0变成0    }    finalColor.a = 1;// 同finalColor.w = 1; rgba对应xyzw    return finalColor;}

2.winmain.cpp
#include <windows.h>#include <d3d11_1.h>#include <d3dcompiler.h>#include <directxmath.h>#include <directxcolors.h>#pragma comment(linker,"/manifestdependency:/"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'/"") // 找到项目的属性->链接器->输入->附加依赖项,在%(AdditionalDependencies)前追加上以下项:// d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;// 或者像下面这样添加代码:#pragma comment(lib, "d3d11.lib")#pragma comment(lib, "d3dcompiler.lib")#pragma comment(lib, "dxguid.lib")#pragma comment(lib, "winmm.lib")#pragma comment(lib, "comctl32.lib")using namespace DirectX;struct VertexNormal{	XMFLOAT3 Pos;	XMFLOAT3 Normal;};struct CBChangesEveryFrame{	XMMATRIX mWorld;};struct CBChangesWhenMoving{	XMMATRIX mView;};struct CBNeverChanges{	XMMATRIX mProjection;	XMFLOAT4 vLightDir[2];};struct Camera{	Camera()		: vAxisX(XMVectorSet(1.0f, 0.0f, 0.0f, 1.0f))		, vAxisAim(XMVectorSet(1.0f, 0.0f, 0.0f, 1.0f))		, vAxisY(XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f))		, vAxisZ(XMVectorSet(0.0f, 0.0f, 1.0f, 1.0f))		, vPosition(XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f)) 	{}	Camera(const XMVECTOR & xAxis, const XMVECTOR & yAxis, const XMVECTOR & zAxis, const XMVECTOR & pos)		: vAxisX(XMVector3Normalize(xAxis))		, vAxisAim(XMVector3Normalize(xAxis))		, vAxisY(XMVector3Normalize(yAxis))		, vAxisZ(XMVector3Normalize(zAxis))		, vPosition(pos)	{}	// 前后平移	void XMove(float dx)	{		XMMATRIX move = XMMatrixTranslationFromVector(dx * vAxisX);		vPosition = XMVector3TransformCoord(vPosition, move);	}	// 左右平移	void YMove(float dy)	{		XMMATRIX move = XMMatrixTranslationFromVector(dy * vAxisY);		vPosition = XMVector3TransformCoord(vPosition, move);	}	// 上下平移	void ZMove(float dz)	{		XMMATRIX move = XMMatrixTranslationFromVector(dz * vAxisZ);		vPosition = XMVector3TransformCoord(vPosition, move);	}	void ZSpin(float angle)	{		XMMATRIX mspin = XMMatrixRotationAxis(vAxisZ, angle);		vAxisX = XMVector3Transform(vAxisX, mspin);		vAxisAim = XMVector3Transform(vAxisAim, mspin);		vAxisY = XMVector3Transform(vAxisY, mspin);	}	void YSpin(float angle)	{		XMMATRIX mspin = XMMatrixRotationAxis(vAxisY, angle);		vAxisAim = XMVector3Transform(vAxisAim, mspin);	}	void ZoomIn(float in)	{		XMMATRIX move = XMMatrixTranslationFromVector(in * vAxisAim);		vPosition = XMVector4Transform(vPosition, move);	}	XMVECTOR vEye() const {return vPosition;}	XMVECTOR vUp() const {return XMVector4Transform(vAxisAim, XMMatrixRotationAxis(vAxisY, -XM_PIDIV2));}	XMVECTOR vFocus() const {return vPosition + vAxisAim;}	XMVECTOR vPosition;// 摄像机位矢	XMVECTOR vAxisAim;// 瞄准轴(可以在摄像机vAxisX-vAxisZ平面内上下转动)	XMVECTOR vAxisX;// 摄像机前后移动轴单位向量	XMVECTOR vAxisY;// 摄像机左右移动轴单位向量	XMVECTOR vAxisZ;// 摄像机上下移动轴单位向量};HINSTANCE				g_hInst = nullptr;HWND					g_hWnd = nullptr;D3D_DRIVER_TYPE				g_driverType = D3D_DRIVER_TYPE_NULL;D3D_FEATURE_LEVEL			g_featureLevel = D3D_FEATURE_LEVEL_11_0;ID3D11Device*				g_pd3dDevice = nullptr;ID3D11Device1*				g_pd3dDevice1 = nullptr;ID3D11DeviceContext*			g_pImmediateContext = nullptr;ID3D11DeviceContext1*			g_pImmediateContext1 = nullptr;IDXGISwapChain*				g_pSwapChain = nullptr;IDXGISwapChain1*			g_pSwapChain1 = nullptr;ID3D11RenderTargetView*			g_pRenderTargetView = nullptr;ID3D11Texture2D*			g_pDepthStencil = nullptr;ID3D11DepthStencilView*			g_pDepthStencilView = nullptr;ID3D11VertexShader*			g_pVertexShader = nullptr;ID3D11PixelShader*			g_pPixelShader = nullptr;ID3D11InputLayout*			g_pVertexLayout = nullptr;ID3D11Buffer*				g_pVertexBuffer = nullptr;ID3D11Buffer*				g_pCBChangesEveryFrame = nullptr;ID3D11Buffer*				g_pCBChangesWhenMoving = nullptr;ID3D11Buffer*				g_pCBNeverChange = nullptr;Camera					g_Camera;HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut );HRESULT InitDevice();void CleanupDevice();void KeyDownEvent(WPARAM wParam);void MouseEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);void CameraOperator(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );void Render();int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow ){	UNREFERENCED_PARAMETER( hPrevInstance );	UNREFERENCED_PARAMETER( lpCmdLine );	if( FAILED( InitWindow( hInstance, nCmdShow ) ) )		return 0;	if( FAILED( InitDevice() ) )	{		CleanupDevice();		return 0;	}	MSG msg = {};	while( WM_QUIT != msg.message )	{		if( PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) )		{			TranslateMessage( &msg );			DispatchMessage( &msg );		}		else		{			Render();		}	}	CleanupDevice();	UnregisterClass(L"class1", g_hInst);	return ( int )msg.wParam;}HRESULT InitDevice(){	HRESULT hr = S_OK;	// 1.Create device	RECT rc;	GetClientRect( g_hWnd, &rc );	UINT width = rc.right - rc.left;	UINT height = rc.bottom - rc.top;	UINT createDeviceFlags = 0;#ifdef _DEBUG	createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;#endif	D3D_DRIVER_TYPE driverTypes[] =	{		D3D_DRIVER_TYPE_HARDWARE,		D3D_DRIVER_TYPE_WARP,		D3D_DRIVER_TYPE_REFERENCE,	};	UINT numDriverTypes = ARRAYSIZE( driverTypes );	D3D_FEATURE_LEVEL featureLevels[] =	{		D3D_FEATURE_LEVEL_11_1,		D3D_FEATURE_LEVEL_11_0,		D3D_FEATURE_LEVEL_10_1,		D3D_FEATURE_LEVEL_10_0,	};	UINT numFeatureLevels = ARRAYSIZE( featureLevels );	for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )	{		g_driverType = driverTypes[driverTypeIndex];		hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,			D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );		if ( hr == E_INVALIDARG )		{			// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it			hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,				D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );		}		if( SUCCEEDED( hr ) )			break;	}	if( FAILED( hr ) )		return hr;	// Obtain DXGI factory from device (since we used nullptr for pAdapter above)	IDXGIFactory1* dxgiFactory = nullptr;	{		IDXGIDevice* dxgiDevice = nullptr;		hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) );		if (SUCCEEDED(hr))		{			IDXGIAdapter* adapter = nullptr;			hr = dxgiDevice->GetAdapter(&adapter);			if (SUCCEEDED(hr))			{				hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) );				adapter->Release();			}			dxgiDevice->Release();		}	}	if (FAILED(hr))		return hr;	// 2.Create swap chain	IDXGIFactory2* dxgiFactory2 = nullptr;	hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) );	if ( dxgiFactory2 )	{		// DirectX 11.1 or later		hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) );		if (SUCCEEDED(hr))		{			(void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) );		}		DXGI_SWAP_CHAIN_DESC1 sd;		ZeroMemory(&sd, sizeof(sd));		sd.Width = width;		sd.Height = height;		sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;		sd.SampleDesc.Count = 1;		sd.SampleDesc.Quality = 0;		sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;		sd.BufferCount = 1;		hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 );		if (SUCCEEDED(hr))		{			hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) );		}		dxgiFactory2->Release();	}	else	{		// DirectX 11.0 systems		DXGI_SWAP_CHAIN_DESC sd;		ZeroMemory(&sd, sizeof(sd));		sd.BufferCount = 1;		sd.BufferDesc.Width = width;		sd.BufferDesc.Height = height;		sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;		sd.BufferDesc.RefreshRate.Numerator = 60;		sd.BufferDesc.RefreshRate.Denominator = 1;		sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;		sd.OutputWindow = g_hWnd;		sd.SampleDesc.Count = 1;		sd.SampleDesc.Quality = 0;		sd.Windowed = TRUE;		hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain );	}	// Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut	dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER );	dxgiFactory->Release();	if (FAILED(hr))		return hr;	// 3.Create a render target view	ID3D11Texture2D* pBackBuffer = nullptr;	hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) );	if( FAILED( hr ) )		return hr;	hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView );	pBackBuffer->Release();	if( FAILED( hr ) )		return hr;	// 4.Create depth stencil texture	D3D11_TEXTURE2D_DESC descDepth;	ZeroMemory( &descDepth, sizeof(descDepth) );	descDepth.Width = width;	descDepth.Height = height;	descDepth.MipLevels = 1;	descDepth.ArraySize = 1;	descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;	descDepth.SampleDesc.Count = 1;	descDepth.SampleDesc.Quality = 0;	descDepth.Usage = D3D11_USAGE_DEFAULT;	descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;	descDepth.CPUAccessFlags = 0;	descDepth.MiscFlags = 0;	hr = g_pd3dDevice->CreateTexture2D( &descDepth, nullptr, &g_pDepthStencil );	if( FAILED( hr ) )		return hr;	// 5.Create the depth stencil view	D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;	ZeroMemory( &descDSV, sizeof(descDSV) );	descDSV.Format = descDepth.Format;	descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;	descDSV.Texture2D.MipSlice = 0;	hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView );	if( FAILED( hr ) )		return hr;	g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView );	// 6.Setup the viewport	D3D11_VIEWPORT vp;	vp.Width = (FLOAT)width;	vp.Height = (FLOAT)height;	vp.MinDepth = 0.0f;	vp.MaxDepth = 1.0f;	vp.TopLeftX = 0;	vp.TopLeftY = 0;	g_pImmediateContext->RSSetViewports( 1, &vp );	// 7.Compile and create the vertex shader. Define, create and set the input layout at the same time.	// 7.1.Compile the vertex shader	ID3DBlob* pVSBlob = nullptr;	hr = CompileShaderFromFile( L"lighting.fx", "VS", "vs_5_0", &pVSBlob );	if( FAILED( hr ) )	{		MessageBox( nullptr,			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );		return hr;	}	// 7.2.Create the vertex shader	hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader );	if( FAILED( hr ) )	{			pVSBlob->Release();		return hr;	}	// 7.3.Define the input layout	D3D11_INPUT_ELEMENT_DESC layout[] =	{		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },		{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },// 12是对齐字节位移,前一个元素是XMFLOAT3,大小3 * sizeof(XMFLOAT3) = 12,为了方便可用D3D11_APPEND_ALIGNED_ELEMENT可以代替12	};	UINT numElements = ARRAYSIZE( layout );	// 7.4.Create the input layout	hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),		pVSBlob->GetBufferSize(), &g_pVertexLayout );	pVSBlob->Release();	if( FAILED( hr ) )		return hr;	// 7.5.Set the input layout	g_pImmediateContext->IASetInputLayout( g_pVertexLayout );	// 8.Compile and create the pixel shader	// 8.1.Compile the pixel shader	ID3DBlob* pPSBlob = nullptr;	hr = CompileShaderFromFile( L"lighting.fx", "PS", "ps_5_0", &pPSBlob );	if( FAILED( hr ) )	{		MessageBox( nullptr,			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );		return hr;	}	// 8.2.Create the pixel shader	hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader );	pPSBlob->Release();	if( FAILED( hr ) )		return hr;	// 9.Create  and set vertex buffer	// 9.1.Create vertex buffer	VertexNormal source[12] = 	{		{XMFLOAT3(1, 0, 0), XMFLOAT3()},		{XMFLOAT3(0, 0, 1), XMFLOAT3()},		{XMFLOAT3(-1, -1, 0), XMFLOAT3()},		{XMFLOAT3(-1, 1, 0), XMFLOAT3()},		{XMFLOAT3(0, 0, 1), XMFLOAT3()},		{XMFLOAT3(1, 0, 0), XMFLOAT3()},		{XMFLOAT3(-1, -1, 0), XMFLOAT3()},		{XMFLOAT3(0, 0, 1), XMFLOAT3()},		{XMFLOAT3(-1, 1, 0), XMFLOAT3()},		{XMFLOAT3(-1, -1, 0), XMFLOAT3()},		{XMFLOAT3(-1, 1, 0), XMFLOAT3()},		{XMFLOAT3(1, 0, 0), XMFLOAT3()},	};	// 赋予各个面单位化外法向量	for (int i = 0; i < 4; i++)	{		XMVECTOR v01 = XMLoadFloat3(&source[3 * i + 1].Pos) - XMLoadFloat3(&source[3 * i].Pos);		XMVECTOR v02 = XMLoadFloat3(&source[3 * i + 2].Pos) - XMLoadFloat3(&source[3 * i].Pos);		XMVECTOR normal = XMVector3Normalize(XMVector3Cross(v01, v02));		for (int j = 0; j < 3; j++)		{			XMStoreFloat3(&source[3 * i + j].Normal, normal);		}	}	D3D11_BUFFER_DESC bd;	ZeroMemory( &bd, sizeof(bd) );	bd.Usage = D3D11_USAGE_DEFAULT;	bd.ByteWidth = sizeof( VertexNormal ) * 12;// 顶点数	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;	bd.CPUAccessFlags = 0;	D3D11_SUBRESOURCE_DATA InitData;	ZeroMemory( &InitData, sizeof(InitData) );	InitData.pSysMem = source;	hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );	//delete pVertices;	if( FAILED( hr ) )		return hr;	// 9.2.Set vertex buffer	UINT stride = sizeof( VertexNormal );	UINT offset = 0;	g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );	// 10.Create and set index buffer 	// We don't need this step in this example, because the vertices are sorted to be clockwise already.	// 10.1.Create index buffer	// 10.2.Set index buffer	// 11.Set primitive topology	g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );	// 12.Create the constant buffer	bd.Usage = D3D11_USAGE_DEFAULT;	bd.ByteWidth = sizeof(CBChangesEveryFrame);	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;	bd.CPUAccessFlags = 0;	hr = g_pd3dDevice->CreateBuffer( &bd, nullptr, &g_pCBChangesEveryFrame );	if( FAILED( hr ) )		return hr;	bd.ByteWidth = sizeof(CBChangesWhenMoving);	hr = g_pd3dDevice->CreateBuffer(&bd, nullptr, &g_pCBChangesWhenMoving);	if (FAILED(hr))		return hr;	bd.ByteWidth = sizeof(CBNeverChanges);	hr = g_pd3dDevice->CreateBuffer(&bd, nullptr, &g_pCBNeverChange);	if (FAILED(hr))		return hr;		// 13.Initialize the world matrix, view matrix, projection matrix	CBChangesEveryFrame cb_changes_every_frame = {};	cb_changes_every_frame.mWorld = XMMatrixTranspose(XMMatrixIdentity());	g_pImmediateContext->UpdateSubresource(g_pCBChangesEveryFrame, 0, nullptr, &cb_changes_every_frame, 0, 0);	g_Camera = Camera(XMVectorSet(1.0f, 0.0f, 0.0f, 1.0f), XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f), XMVectorSet(0.0f, 0.0f, 1.0f, 1.0f), XMVectorSet(-5.0f, 0.0f, 1.0f, 1.0f));	XMMATRIX view = XMMatrixLookAtLH(g_Camera.vEye(), g_Camera.vFocus(), g_Camera.vUp());	CBChangesWhenMoving cb_changes_when_moving = {};	cb_changes_when_moving.mView = XMMatrixTranspose(view);	g_pImmediateContext->UpdateSubresource(g_pCBChangesWhenMoving, 0, nullptr, &cb_changes_when_moving, 0, 0);	CBNeverChanges cb_never_changes = {};	float nearZ = 0.01f;	float farZ = 500.0f;	XMMATRIX projection = XMMatrixPerspectiveFovLH( XM_PIDIV4, width / (FLOAT)height, nearZ, farZ );	cb_never_changes.mProjection = XMMatrixTranspose(projection);	cb_never_changes.vLightDir[0] = XMFLOAT4(0.0f, 1.0f, -0.5f, 1.0f);	cb_never_changes.vLightDir[1] = XMFLOAT4(0.0f, -1.0f, -0.5f, 1.0f);	g_pImmediateContext->UpdateSubresource(g_pCBNeverChange, 0, nullptr, &cb_never_changes, 0, 0);	return S_OK;}void Render(){	static DWORD t0 = GetTickCount();	DWORD t1 = GetTickCount();	float t = (t1 - t0) / 1000.0f;	CBChangesEveryFrame cb = {};	cb.mWorld = XMMatrixTranspose(XMMatrixIdentity() * XMMatrixRotationZ(2.0f * XM_PI / 3.0f * t));// 周期3s	g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, Colors::Black);// 清屏	g_pImmediateContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);// 清depth stencil view	g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);	g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pCBChangesEveryFrame);// ID3D11DeviceContext::VSSetConstantBuffers()方法: Sets the constant buffers used by the vertex shader pipeline stage. 设置顶点着色管线阶段所使用的常量缓存	g_pImmediateContext->VSSetConstantBuffers(1, 1, &g_pCBChangesWhenMoving);// 如本例中,fx文件中的CBChangesWhenMoving常量缓存定义是register(b1),那么ID3D11DeviceContext::VSSetConstantBuffers()第一个参数就是1	g_pImmediateContext->VSSetConstantBuffers(2, 1, &g_pCBNeverChange);	g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);	g_pImmediateContext->PSSetConstantBuffers(0, 1, &g_pCBChangesEveryFrame);// ID3D11DeviceContext::PSSetConstantBuffers()方法: Sets the constant buffers used by the pixel shader pipeline stage.	g_pImmediateContext->PSSetConstantBuffers(1, 1, &g_pCBChangesWhenMoving);	g_pImmediateContext->PSSetConstantBuffers(2, 1, &g_pCBNeverChange);	g_pImmediateContext->UpdateSubresource(g_pCBChangesEveryFrame, 0, nullptr, &cb, 0, 0);// ID3DBuffer继承于ID3DResource,一个更新一个draw	g_pImmediateContext->Draw(12, 0);// 如果用了索引缓存,用DrawIndexed()	g_pSwapChain->Present(1, 0);// 第一个参数调节刷新率}// 键盘按键按下事件void KeyDownEvent(WPARAM wParam){	static float step = 1.0f;	switch (wParam)	{	case 'W':// 前进		{			g_Camera.XMove(step);		}		break;	case 'S':// 后退		{			g_Camera.XMove(-step);		}		break;	case 'A':// 左平移		{			g_Camera.YMove(-step);		}		break;	case 'D':// 右平移		{			g_Camera.YMove(step);		}		break;	case 'Q':// 上升		{			g_Camera.ZMove(step);		}		break;	case 'Z':// 下降		{			g_Camera.ZMove(-step);		}		break;	case VK_RIGHT:// 右转		{			g_Camera.ZSpin(5.0f / 180.0f * XM_PI);		}		break;	case VK_LEFT:// 左转		{			g_Camera.ZSpin(-5.0f / 180.0f * XM_PI);		}		break;	case VK_UP:// 仰		{			g_Camera.YSpin(-5.0f / 180.0f * XM_PI);		}		break;	case VK_DOWN:// 俯		{			g_Camera.YSpin(5.0f / 180.0f * XM_PI);		}		break;	default:		break;	}}// 鼠标事件void MouseEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){	static bool s_bRBtnDown = false;	static POINT s_Pos0;	switch (uMsg)	{	case WM_MOUSEWHEEL:		{			static float distance = 1.0f;			if ((INT)wParam > 0)// 前滚			{				g_Camera.ZoomIn(distance);			}			else// 后滚			{				g_Camera.ZoomIn(-distance);			}		}		break;	case WM_RBUTTONDOWN:		{			s_bRBtnDown = true;			GetCursorPos(&s_Pos0);		}		break;	case WM_RBUTTONUP:		{			s_bRBtnDown = false;		}		break;	case WM_MOUSEMOVE:		{			if (s_bRBtnDown)			{							POINT Pos1;				GetCursorPos(&Pos1);				int dx = Pos1.x - s_Pos0.x;				int dy = Pos1.y - s_Pos0.y;				float degree = 1.0f;				if (dx > 0)				{					g_Camera.ZSpin(degree / 180.0f * XM_PI);				}				else if (dx < 0)				{					g_Camera.ZSpin(-degree / 180.0f * XM_PI);				}				if (dy < 0)				{					g_Camera.YSpin(-degree / 180.0f * XM_PI);				}				else if (dy > 0)				{					g_Camera.YSpin(degree / 180.0f * XM_PI);				}				s_Pos0 = Pos1;			}		}		break;	default:		break;	}}void CameraOperator(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){	MouseEvent(hWnd, uMsg, wParam, lParam);	KeyDownEvent(wParam);	CBChangesWhenMoving cb_changes_when_moving = {};	XMMATRIX view = XMMatrixLookAtLH(g_Camera.vEye(), g_Camera.vFocus(), g_Camera.vUp());	cb_changes_when_moving.mView = XMMatrixTranspose(view);	g_pImmediateContext->UpdateSubresource(g_pCBChangesWhenMoving, 0, nullptr, &cb_changes_when_moving, 0, 0);}// 初始化窗口HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){	// Register class	WNDCLASSEX wcex;	wcex.cbSize = sizeof( WNDCLASSEX );	wcex.style = CS_HREDRAW | CS_VREDRAW;	wcex.lpfnWndProc = WndProc;	wcex.cbClsExtra = 0;	wcex.cbWndExtra = 0;	wcex.hInstance = hInstance;	wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_APPLICATION );	wcex.hCursor = LoadCursor( nullptr, IDC_ARROW );	wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );	wcex.lpszMenuName = nullptr;	wcex.lpszClassName = L"class1";	wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_APPLICATION );	if( !RegisterClassEx( &wcex ) )		return E_FAIL;	// Create window	g_hInst = hInstance;	RECT rc = { 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) };	AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );	g_hWnd = CreateWindow( L"class1", L"简单四面体方向光渲染",		WS_POPUP,		CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance,		nullptr );	if( !g_hWnd )		return E_FAIL;	ShowWindow( g_hWnd, nCmdShow );	return S_OK;}void CleanupDevice(){	if (g_pImmediateContext) g_pImmediateContext->ClearState();	if (g_pCBChangesEveryFrame) g_pCBChangesEveryFrame->Release();	if (g_pCBChangesWhenMoving) g_pCBChangesWhenMoving->Release();	if (g_pCBNeverChange) g_pCBNeverChange->Release();	if (g_pVertexBuffer) g_pVertexBuffer->Release();	if (g_pVertexLayout) g_pVertexLayout->Release();	if (g_pVertexShader) g_pVertexShader->Release();	if (g_pPixelShader) g_pPixelShader->Release();	if (g_pDepthStencil) g_pDepthStencil->Release();	if (g_pDepthStencilView) g_pDepthStencilView->Release();	if (g_pRenderTargetView) g_pRenderTargetView->Release();	if (g_pSwapChain1) g_pSwapChain1->Release();	if (g_pSwapChain) g_pSwapChain->Release();	if (g_pImmediateContext1) g_pImmediateContext1->Release();	if (g_pImmediateContext) g_pImmediateContext->Release();	if (g_pd3dDevice1) g_pd3dDevice1->Release();	if (g_pd3dDevice) g_pd3dDevice->Release();}// 回调函数LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){	switch (uMsg)	{	case WM_DESTROY:		{			PostQuitMessage(0);		}		break;	case WM_KEYDOWN:		{			if (wParam == VK_ESCAPE)			{				if (MessageBox(g_hWnd, L"确认退出?", L"提醒", MB_OKCANCEL) == IDOK)				{					SendMessage(g_hWnd, WM_DESTROY, 0, 0);				}			}			CameraOperator(hWnd, uMsg, wParam, lParam);		}								break;	case WM_MOUSEMOVE:		{			CameraOperator(hWnd, uMsg, wParam, lParam);		}		break;	case WM_RBUTTONDOWN:		{			CameraOperator(hWnd, uMsg, wParam, lParam);		}		break;	case WM_RBUTTONUP:		{			CameraOperator(hWnd, uMsg, wParam, lParam);		}		break;	case WM_MOUSEWHEEL:		{			CameraOperator(hWnd, uMsg, wParam, lParam);		}		break;	default:		return DefWindowProc(hWnd, uMsg, wParam, lParam);	}	return 0;}// 从文件编译着色器,由微软官网例子提供HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut ){	HRESULT hr = S_OK;	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;#ifdef _DEBUG	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.	// Setting this flag improves the shader debugging experience, but still allows 	// the shaders to be optimized and to run exactly the way they will run in 	// the release configuration of this program.	dwShaderFlags |= D3DCOMPILE_DEBUG;	// Disable optimizations to further improve shader debugging	dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;#endif	ID3DBlob* pErrorBlob = nullptr;	hr = D3DCompileFromFile( szFileName, nullptr, nullptr, szEntryPoint, szShaderModel, 		dwShaderFlags, 0, ppBlobOut, &pErrorBlob );	if( FAILED(hr) )	{		if( pErrorBlob )		{			OutputDebugStringA( reinterpret_cast<const char*>( pErrorBlob->GetBufferPointer() ) );			pErrorBlob->Release();		}		return hr;	}	if( pErrorBlob ) pErrorBlob->Release();	return S_OK;}

3. 效果图:


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台