现在的位置: 首页 > 综合 > 正文

D3D中的重要注意事项

2013年06月17日 ⁄ 综合 ⁄ 共 1998字 ⁄ 字号 评论关闭
  1. stencilbuffer的比较是用参考值与目标值比较,参考值在前面,所以如果比较函数是小于,那么是参考值小于目标值。

  2.  COLORWITEENABLE渲染状态有点特殊,禁用可以是FALSE,但启用一遍要用0x7.因为COLORWRITEENABLE可以控制4个颜色通道。分别用低4为控制,0x7可启用的蓝绿红3个通道。

  3.  DirectX所有的Draw函数要根据三角形的朝向,不要以为只有DrawIndexedPrimitive.

  4.  使用CD3DMesh的时候要注意,一般加载的模型以具有所需的顶点格式,记住调用SetFVF

  5.  当采用固定管线启用关照不成功是,如果灯管材质都设置了,模型还是黑的,可能是光照的Diffuse值为0,影响Diffuse可能是物体没有法线,所以用CD3DMesh要特别注意,一定要SetFVF一下,保证有需要的格式。当然其他的可能也有,只是特别提示这个,以便能在需要的时候想起来。

  6.  在给网格创建或者转换顶点格式的时候,尽量使用常规的顶点格式,如坐标是float3,法线也用float3. 否则在某些情况下会出现问题。如下面的代码:

 

HRESULT CMyD3DApplication::LoadXFile(TCHAR* name)
{
	HRESULT		hr;
	LPD3DXMESH	pMeshSysMem = NULL, pMeshSysMem2 = NULL;

	if (FAILED (D3DXLoadMeshFromX(name, D3DXMESH_SYSTEMMEM, 
				m_pd3dDevice, NULL, NULL, NULL, NULL, &pMeshSysMem)))
		return E_FAIL;

	D3DVERTEXELEMENT9 decl[]=
	{
		// stream, offset, type, method, semantic type (for example normal), ?
		{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
		{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
		D3DDECL_END()
	};

	hr = pMeshSysMem->CloneMesh(D3DXMESH_MANAGED, decl, m_pd3dDevice, &m_pD3DXMesh);

	// compute the normals
	hr = D3DXComputeNormals(m_pD3DXMesh,NULL);
	if(FAILED(hr))
	{
		SAFE_RELEASE(pMeshSysMem);
		return E_FAIL;
	}
	// cleanup
	SAFE_RELEASE(pMeshSysMem);


	return S_OK;
}

如果将decl中的NORMAL,POSITION任意一个改成D3DDECLTYPE_FLOAT4,并且将offset进行相应修改, 则下面的计算法线的函数将会报错。具体原因暂时未能在Doc明确查明,只是找到一张FVF映射到Vertex Element 的图,因为FVF是D3D中比较规范并支持的,所以按FVF格式应该没问题。

 

      7.    以前总认为由于float在计算后存在误差,以至于认为两次相同的 A  * B 相乘结果会不同。这样的想法是错误,硬件是极其固件化的,即使结果可能存在误差,但是两次相同的浮点数相乘总能得到完全相同的结果。在ShadowVolume给我一个教训,要想让原物体网格和阴影网格完完全全重叠,必须让阴影网格和原物体网格使用相同的变换矩阵。例如:A是用于原物体网格的变换矩阵。W是用于阴影网格的矩阵。A = B * ( C * D );  W
= ( B * C ) * D; 这样的A,W就是问题,他们的结果是存在极细微误差的,而这点误差就会导致z fighting。 如果想让两者完全相同的则两次的计算顺序也必须相同。 紧记。

     8.    在使用DXUT框架时,一般情况下,如窗口大小改变,将会引起OnLostDevice()和OnCreateDevice()被调用。 但是如果在OnLostDevice()中未能将所有存在于POOL_DEFAULT的资源释放,则DXUT框架会调用OnDestroyDevice(),并重新调用OnCreateDevice(). 特别注意。

     9.     并不是所有网格的纹理坐标都在(0,1),所以不要盲目的设定纹理U,V的访问模式为Clamp,有的物体网格是需要Wrap的,如Media\tiger\tiger.x。让我找了1个小时的bug才找出来是UV访问模式的问题。

     10.   在pick操作中,我们应该知道投影平面是位于z=1的上的,另外点在投影平面的位置可能被缩放过,所以需要从投影矩阵的读出缩放量,在转换成正确的值。

抱歉!评论已关闭.