D3D10与Geometry Shader用于细分曲面几点学习笔记(1)
华南理工大学,张嘉华 newzjh@126.com QQ:188318005,欢迎和我多多交流,共同学习进步
1. Direct3D 10的流水线
在细分曲面里面,最有新用途的就是Geometry Shader和Stream Out,前者可以输入一些数据,然后产生一些三角形,后者可以断绝Pixel Shader,做完Geometry Shader就直接输出回Input Assembler,这就意味着可以做GPU递归和迭代。
2、Direct3D 10环境配置
首先当然就是Vista 和NV8800+啦,接着就是基本环境的搭建.有能力的话可以考虑一下搭建一个自己的引擎.
有一个朋友问到我如何实现内嵌消息循环实现设备窗口大小改变.通常情况下我们都需要在窗口初始化的时候定义消息循环,然后把创建好的窗口的Hwnd传递给引擎图形设备的创建函数,然后订阅这个消息循环的WM_SIZE消息,在窗口改变的时候由应用程序调用引擎改变设备大小.那么能否像Dotnet那样通过添加一个订阅句柄到消息循环中呢.其实是可以的.首先通过GetWindowLongPtr第二个参数设置GWL_WNDPROC获得我们应用程序的消息循环函数指针,因为对于引擎来说,通常是dll,它不可能知道外部应用程序那个函数实现了消息循环,而我们创建引擎的时候也只传递进hwnd,因此需要用GetWindowLongPtr获得外部的消息循环函数,然后用引擎内部的消息循环函数替代,代码2.1实现了这个目的.那么另外一个问题是如何只添加我们需要的消息订阅绑定而不覆盖掉,我们需要对引擎的消息循环函数在默认情况下,即不触发我们引擎消息的情况下调用回外部应用程序的消息循环函数.
----------------------------------------------------------------------------------------------------------------------------------------
g_applicationwindproc= (WNDPROC)(::GetWindowLongPtr(hwnd, GWL_WNDPROC));
SetWindowLongPtr(hwnd,GWL_WNDPROC,(LONG_PTR)&GComponentModel::ComponentModelMsgProc);
----------------------------------------------------------------------------------------------------------------------------------------
代码2.1:用引擎的消息循环函数代替外部的消息循环函数
代码2.2在默认的情况下最后调用了外部的消息循环函数applicationwindproc.
----------------------------------------------------------------------------------------------------------------------------------------
LRESULT GComponentModel::ComponentModelMsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_CLOSE:
GComponentModel::Closing();
return 0;
case WM_SIZE:
RECT rect1;
RECT rect2;
if (GGraphicsDevice::GetHandle())
{
GetWindowRect(GGraphicsDevice::GetHandle(),&rect1);
GetClientRect(GGraphicsDevice::GetHandle(),&rect2);
if (rect1.right-rect1.left==0 || rect1.bottom-rect1.top==0||
rect2.right-rect2.left==0 || rect2.bottom-rect2.top==0)
{
GComponentModel::SetFocus(false);
}
else
{
GComponentModel::SetFocus(true);
GGraphicsController::SwitchAccordingWindow();
}
}
return 0;
default:
return g_applicationwindproc(hWnd, msg, wParam, lParam );
}
}
----------------------------------------------------------------------------------------------------------------------------------------
代码2.2:引擎内部的消息循环函数
有了这些之后,DirectX10完全放弃了固定流水线,全部用可编程流水线,所以也就是必须进行GPU Coding,写HLSL等,并且对于输入更研究,创建IA的时候需要HLSL的输入与定义一致。
下面是Direct3D 10 C ++的一个IA定义与设置:
----------------------------------------------------------------------------------------------------------------------------------------
ID3D10InputLayout* pVertexLayout ;
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ "TEXTURE0", 0, DXGI_FORMAT_R 32G 32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = sizeof(layout)/sizeof(layout[0]);
// Create the input layout
D3D10_PASS_DESC PassDesc;
m_hTechs[m_PostEffectType]->GetPassByIndex( 0 )->GetDesc( &PassDesc );
hr = pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &pVertexLayout );
if( FAILED( hr ) )
return hr;
// Set the input layout
pd3dDevice->IASetInputLayout( pVertexLayout );
----------------------------------------------------------------------------------------------------------------------------------------
代码2.1:Direct3D 10 C ++