DirectX11 学习笔记9 - 动态顶点缓冲区 和 静态顶点缓冲区

首先说什么是缓冲区:

缓冲区就是在.fx效果文件(.ps .vs也是) 里面定义的一个数据结构。用于.fx和cpp文件的数据通信。

比如:

//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
cbuffer ConstantBuffer 
{
	matrix World;
	matrix View;
	matrix Projection;
};
cbuffer LightBuffer
{
    float3 cameraPosition;
    float padding;
};
cbuffer是关键字。  类似于struct 

这里就定义了2个缓冲区。

在程序运行的时候。效果文件.fx需要获得世界矩阵观察矩阵投影矩阵等等。 因此就需要为这个缓冲区赋值。一方面可以直接写在.fx文件里面。但是

直接写在效果文件 编译后就不能动态改变了,没有灵活性。

下面说说2种缓冲区

1:静态常量缓冲区

所谓静态就是在渲染器初始化的时候,就为缓冲区赋值好了。不会再变了。

// Create the constant buffer
	D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(ConstantBuffer);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = 0;
	hr = device->CreateBuffer( &bd, NULL, &m_matrixBuffer );
	if( FAILED( hr ) )
		return hr;
上面就是创建一个静态缓冲区的列子

其中bd.Usage属性  

D3D11_USAGE_DEFAULT
意思是 cpu在运行过程中不能够再读写数据了

bd.COUAccessFlags=0 也得设置为0才行。

定义好缓冲区结构之后就是初始化了

//
	// Update variables
	//
	ConstantBuffer cb;
	cb.mWorld = XMMatrixTranspose( worldMatrix);
	cb.mView = XMMatrixTranspose( viewMatrix );
	cb.mProjection = XMMatrixTranspose( projectionMatrix );
	deviceContext->UpdateSubresource( m_matrixBuffer, 0, NULL, &cb, 0, 0 );
	deviceContext->VSSetConstantBuffers( 0, 1, &m_matrixBuffer );

初始化很简单 这里拿世界矩阵 视图矩阵 投影矩阵为例子

2:动态顶点缓冲区

和静态缓冲区不同。动态缓冲区用于每一帧都需要动态改变渲染数据的情况。

比如水波,每一秒他的顶点结构都在变,因此需要用动态缓冲区动态赋值,而不是在初始化赋值

//create the light buffer
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DYNAMIC;
	bd.ByteWidth = sizeof(LightBuffer);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	hr = device->CreateBuffer( &bd, NULL, &m_lightmaterialBuffer );
	if( FAILED( hr ) )
		return hr;
	return S_OK;

定义基本一样。,只是在Usage 里面要设置为D3D11_USAGE_DYNAMIC  还有CPUAccessFlags也要设置为D3D11_CPU_ACCESS_WRITE

而且在更新数据的时候不一样

必须先用map锁定,防止还没更新好的时候设备就渲染了造成错误数据不一致

D3D11_MAPPED_SUBRESOURCE mappedResource;
	ConstantBuffer *data0;
	LightBuffer *data1;
	//
	// Update variables
	//
	//ConstantBuffer cb;
	//cb.mWorld = XMMatrixTranspose( worldMatrix);
	//cb.mView = XMMatrixTranspose( viewMatrix );
	//cb.mProjection = XMMatrixTranspose( projectionMatrix );
	//锁定常量缓冲区
	HR(deviceContext->Map(m_matrixBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&mappedResource));
	//deviceContext->UpdateSubresource( m_matrixBuffer, 0, NULL, &cb, 0, 0 );
	data0=(ConstantBuffer*)mappedResource.pData;
	data0->mWorld=XMMatrixTranspose( worldMatrix);
	data0->mView=XMMatrixTranspose( viewMatrix );
	data0->mProjection=XMMatrixTranspose( projectionMatrix );
	deviceContext->Unmap(m_matrixBuffer,0);
	deviceContext->VSSetConstantBuffers( 0, 1, &m_matrixBuffer );
	//LightBuffer lb;
	//lb.cameraPosition=cameraPos;
	//锁定光照缓冲区
	HR(deviceContext->Map(m_lightmaterialBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&mappedResource));
	data1=(LightBuffer*)mappedResource.pData;
	data1->cameraPosition=cameraPos;
	deviceContext->Unmap(m_lightmaterialBuffer,0);
	//deviceContext->UpdateSubresource( m_lightmaterialBuffer, 0, NULL, &lb, 0, 0 );
	deviceContext->VSSetConstantBuffers( 1, 1, &m_lightmaterialBuffer );


这里举了2个例子,同时渲染了2个缓冲区。要注意的是,渲染两个缓冲区的时候,不是简单的先写第一个再写第二个。 

有一点小区别。就是在deviceContext->VSSetConstantBuffers()的时候第一个参数要增加1. 表示是第二个缓冲区啦。其他都一样。

你可能感兴趣的:(C++,DirectX,directx11)