Jump to content
  • Advertisement
Sign in to follow this  
irlanrobson

Problem with DirectX 11 Vertex Layout

This topic is 1331 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm having some trouble while seen the correct result of my computations. I'll post my current setup.

I'll ommit the others parts of the code like matrices, device creation because I've already checked and its 100% working.

I'm loading models from .fbx and I tried to convert the order of drawing to CCW and CW. Also, I tried to invert the Z coordinate of the normals, positions, and the UV's Y coordinate like 1.0f - UV.y.

For the vertex buffers I'm using one per attribute. In my case 5 vertex buffers one for each attribute.

I have the DirectX 11's Debug Layer activated (no warnings/errors) and I don't have PIX, Render Doc working and I don't have money to buy a version of Visual Studio with integrated  Graphics Debugger.

 

Vertex Shader:

cbuffer Model : register(b0) {
	float4x4 mWorldView;
	float4x4 mProjection;
	float4x4 mNormal;
};

struct VS_INPUT {
	float4 vPos : POSITION0;
	float2 vTexCoord : TEXCOORD0;
	float3 vNormal : NORMAL0;
	float3 vBinormal : NORMAL1;
	float3 vTangent : TANGENT0;
};

struct VS_OUTPUT {
	float4 vPos : SV_POSITION;
	float4 vViewSpacePos : POSITION0;
	float2 vTexCoord : TEXCOORD0;
	float3 vNormal : NORMAL0;
	float3 vToLight : NORMAL1;
	float3 vToViewer : NORMAL2;
};

void main( in VS_INPUT _viIn, out VS_OUTPUT _voOut ) {
	_voOut.vViewSpacePos = mul( mWorldView, _viIn.vPos );
	_voOut.vTexCoord = _viIn.vTexCoord;
	_voOut.vNormal = _viIn.vNormal;
	_voOut.vToLight = float3(0.0, 10.0, 0.0) - _voOut.vViewSpacePos.xyz;
	_voOut.vToViewer = -_voOut.vViewSpacePos.xyz;
	_voOut.vPos = mul( mProjection, _voOut.vViewSpacePos );
}

Vertex Layout:

D3D11_INPUT_ELEMENT_DESC CDirectX11Shader::m_pcDefaultVertexDesc[VA_MAX] = {
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 1, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 2, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "NORMAL", 1, DXGI_FORMAT_R32G32B32_FLOAT, 3, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 4, 56, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

Here's my .fbx simple loading (wich I'll convert to my own file format later).

std::vector<glm::vec4> vPos(iFaceVertexCount);
	std::vector<glm::vec2> vTexCoord(iFaceVertexCount);
	std::vector<glm::vec3> vNormal(iFaceVertexCount);
	std::vector<glm::vec3> vBinormal(iFaceVertexCount);
	std::vector<glm::vec3> vTangent(iFaceVertexCount);
	std::vector<unsigned int> vIndex(iFaceCount * 3);

	CMesh* pMesh = new CMesh();
	for (int iFace = 0; iFace < iFaceCount; ++iFace) {
		unsigned int ui32RenderPart = static_cast<unsigned int>( vMaterialIndex.GetAt(iFace) );
		if ( (ui32RenderPart + 1) > pMesh->m_vRenderPart.size() ) {
			pMesh->m_vRenderPart.resize(ui32RenderPart + 1);
			CMaterialManager::CreateMaterial(pfbxnMeshNode->GetMaterial(ui32RenderPart), pMesh->m_vRenderPart[ui32RenderPart].miMaterial);
		}
		++pMesh->m_vRenderPart[ui32RenderPart].ui32FaceCount;
	}

	unsigned int ui32LastFaceStart = 0;
	for (size_t ui32RenderPart = 0; ui32RenderPart < pMesh->m_vRenderPart.size(); ++ui32RenderPart) {
		pMesh->m_vRenderPart[ui32RenderPart].ui32FaceStart = ui32LastFaceStart;
		ui32LastFaceStart += pMesh->m_vRenderPart[ui32RenderPart].ui32FaceCount;
		pMesh->m_vRenderPart[ui32RenderPart].ui32FaceCount = 0;
	}
	
	int iVertex = 0;
	for (int iFace = 0; iFace < iFaceCount; ++iFace) {
		int iFaceSize = _pfbxmMesh->GetPolygonSize(iFace);
		int iRenderPart = vMaterialIndex.GetAt(iFace);

		unsigned int ui32IndexStart = pMesh->m_vRenderPart[iRenderPart].ui32FaceStart * iFaceSize; 
		unsigned int ui32IndexCount = pMesh->m_vRenderPart[iRenderPart].ui32FaceCount * iFaceSize;
		unsigned int ui32IndexOffset = ui32IndexStart + ui32IndexCount;

		for (int iFaceVertex = 0; iFaceVertex < iFaceSize; ++iFaceVertex) {
			int iControlPoint = _pfbxmMesh->GetPolygonVertex(iFace, iFaceVertex);

			FbxVector4 vFbxPos = _pfbxmMesh->GetControlPointAt(iControlPoint);
			vPos[iVertex].x = static_cast<float>(vFbxPos[0]);
			vPos[iVertex].y = static_cast<float>(vFbxPos[1]);
			vPos[iVertex].z = static_cast<float>(vFbxPos[2]);
			vPos[iVertex].w = 1.0f;

			if ( lUVNames.GetCount() ) {
				FbxVector2 vFbxUv;
				bool bUnmappedUv;
				_pfbxmMesh->GetPolygonVertexUV(iFace, iFaceVertex, lUVNames[0], vFbxUv, bUnmappedUv);
				vTexCoord[iVertex].x = static_cast<float>(vFbxUv[0]);
				vTexCoord[iVertex].y = static_cast<float>(1.0f - vFbxUv[1]);
			}

			FbxVector4 vFbxNormal;
			_pfbxmMesh->GetPolygonVertexNormal(iFace, iFaceVertex, vFbxNormal);
			vNormal[iVertex].x = static_cast<float>(vFbxNormal[0]);
			vNormal[iVertex].y = static_cast<float>(vFbxNormal[1]);
			vNormal[iVertex].z = static_cast<float>(vFbxNormal[2]);
			
			/*
			FbxVector4 vFbxBinormal;
			_pfbxmMesh->GetPolygonVertex(iFace, iFaceVertex, vFbxNormal);
			vNormal[iVertex].x = static_cast<float>(vFbxNormal[0]);
			vNormal[iVertex].y = static_cast<float>(vFbxNormal[1]);
			vNormal[iVertex].z = static_cast<float>(vFbxNormal[2]);
			*/
			
			/*
			FbxVector4 vFbxTangent;
			_pfbxmMesh->GetPolygonVertex(iFace, iFaceVertex, vFbxNormal);
			vNormal[iVertex].x = static_cast<float>(vFbxNormal[0]);
			vNormal[iVertex].y = static_cast<float>(vFbxNormal[1]);
			vNormal[iVertex].z = static_cast<float>(vFbxNormal[2]);
			*/

			vIndex[ui32IndexOffset + iFaceVertex] = iVertex;

			++iVertex;
		}
		
		//0 1 2 -> 2 1 0 In the case I want to convert to CW.
		//unsigned int ui32TmpIndex = vIndex[ui32IndexOffset + 0];
		//vIndex[ui32IndexOffset + 0] = vIndex[ui32IndexOffset + 2];
		//vIndex[ui32IndexOffset + 2] = ui32TmpIndex;

		++pMesh->m_vRenderPart[iRenderPart].ui32FaceCount;
	}

	pMesh->m_vvbVertexBuffer.resize(5);
	
	pMesh->m_vvbVertexBuffer[0].CreateApi( sizeof(glm::vec4) * vPos.size(), &vPos[0], BU_STATIC);
	pMesh->m_vvbVertexBuffer[0].m_uiStrides = sizeof(glm::vec4);
	pMesh->m_vvbVertexBuffer[0].m_uiStartSlot = 0;

	pMesh->m_vvbVertexBuffer[1].CreateApi(sizeof(glm::vec2) * vTexCoord.size(), &vTexCoord[0], BU_STATIC);
	pMesh->m_vvbVertexBuffer[1].m_uiStrides = sizeof(glm::vec2);
	pMesh->m_vvbVertexBuffer[1].m_uiStartSlot = 1;

	pMesh->m_vvbVertexBuffer[2].CreateApi( sizeof(glm::vec3) * vNormal.size(), &vNormal[0], BU_STATIC);
	pMesh->m_vvbVertexBuffer[2].m_uiStrides = sizeof(glm::vec3);
	pMesh->m_vvbVertexBuffer[2].m_uiStartSlot = 2;
	
	pMesh->m_vvbVertexBuffer[3].CreateApi(sizeof(glm::vec3) * vBinormal.size(), &vBinormal[0], BU_STATIC);
	pMesh->m_vvbVertexBuffer[3].m_uiStrides = sizeof(glm::vec3);
	pMesh->m_vvbVertexBuffer[3].m_uiStartSlot = 3;
	
	pMesh->m_vvbVertexBuffer[4].CreateApi(sizeof(glm::vec3) * vTangent.size(), &vTangent[0], BU_STATIC);
	pMesh->m_vvbVertexBuffer[4].m_uiStrides = sizeof(glm::vec3);
	pMesh->m_vvbVertexBuffer[4].m_uiStartSlot = 4;

	pMesh->m_ibIndexBuffer.CreateApi( sizeof(unsigned int) * vIndex.size(), reinterpret_cast<const void*>(&vIndex[0]), BU_STATIC);

Here's my drawing calls:

 

Ex:

	
//For each attribute...
CDirectX11::GetDeviceContext()->IASetVertexBuffers(m_uiStartSlot, 1, &m_pbBuffer, &m_uiStrides, &m_uiOffsets);

Later:


	CDirectX11::GetDeviceContext()->IASetIndexBuffer(m_pd3dBuffer, DXGI_FORMAT_R32_UINT, 0);
	CDirectX11::GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	CDirectX11::GetDeviceContext()->DrawIndexed(_ui32IndexCount, _ui32StartIndex, 0);

Results:

 

results.png

Edited by Irlan

Share this post


Link to post
Share on other sites
Advertisement

Since you are using one vertex buffer per component, the AlignedByteOffset value in D3D11_INPUT_ELEMENT_DESC should be 0 because the data in each vertex buffer starts at offset 0.

Edited by megadan

Share this post


Link to post
Share on other sites

Since you are using one vertex buffer per component, the AlignedByteOffset value in D3D11_INPUT_ELEMENT_DESC should be 0 because the data in each vertex buffer starts at offset 0.

"The problems of porting OpenGL to DirectX 11 starts here.". I forgot that. It solved my problem.

Thank you.

Share this post


Link to post
Share on other sites

{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 2, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 1, DXGI_FORMAT_R32G32B32_FLOAT, 3, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 }

 

I think that you have made a calculation error here : 24 + 3 x float = 36

 

You could/should use the automated location calculator (ie. D3D11_APPEND_ALIGNED_ELEMENT flag).

 

Cheers!

Edited by kauna

Share this post


Link to post
Share on other sites

{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 2, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 1, DXGI_FORMAT_R32G32B32_FLOAT, 3, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 }

 

I think that you have made a calculation error here : 24 + 3 x float = 36

 

You could/should use the automated location calculator (ie. D3D11_APPEND_ALIGNED_ELEMENT flag).

 

Cheers!

 

As megadan said, I'm using per component vertex buffers. I have my problem solved. Anyway, I think it was correct.
 
POSITION0 = 0
TEXCOORD0 = 16 (POSITION0) 
NORMAL0 = 16 (POSITION0) + 8 (TEXCOORD0) = 24
NORMAL1 = 16 (POSITION0) + 8 (TEXCOORD0) + 16 (NORMAL0) = 40 
etc.
Edited by Irlan

Share this post


Link to post
Share on other sites


NORMAL1 = 16 (POSITION0) + 8 (TEXCOORD0) + 16 (NORMAL0) = 40 

 

Since you don't need to specify these offsets at all to solve your problem this is pretty tangential to the solution, but I'm with kauna in asking why would NORMAL0 create an offset of 16 and not 12?

Share this post


Link to post
Share on other sites

 


NORMAL1 = 16 (POSITION0) + 8 (TEXCOORD0) + 16 (NORMAL0) = 40 

 

Since you don't need to specify these offsets at all to solve your problem this is pretty tangential to the solution, but I'm with kauna in asking why would NORMAL0 create an offset of 16 and not 12?

 

Yeah you're right. I need to take a sleep a little. he correct is:

 

POSITION0 = 0
TEXCOORD0 = 16 (POSITION0) 
NORMAL0 = 16 (POSITION0) + 8 (TEXCOORD0) = 24
NORMAL1 = 16 (POSITION0) + 8 (TEXCOORD0) + 12 (NORMAL0) = 36
etc.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!