Click here to Skip to main content
15,867,704 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have rendered 3d objects numerous times before in DirectX but this time encountered a strange problem, on which I wasted a day figuring out and still have nothing. I have a DX11 Context in which I load 3d models from obj files. I had to make a skybox and figured out that a good starting point would be to try to render a cube and then proceed further. My graphics pipeline draws many things, so unless I purposefully unbind the index shader, it will remain bound. If I try to render the cube with my cube’s index buffer bound, it doesn’t work. But if I don’t bind the index buffer it uses the previously bound buffer (as far as I can make out) and renders the vertices weirdly as expected. I must be missing something major here. I have spent hours and hours and still couldn’t solve the problem. I would be grateful if someone could help…

PS: I am using these weird indices just for testing, as I had assumed that they were causing the problem.

What I have tried:

Here's the code:
C++
void SkyBox::CreateShader(Vertex * verts, size_t size_of_verts, WORD* indices, size_t size_of_indices)
{
	// Shader Compilation 
	ID3D10Blob* VS = nullptr;
	ID3D10Blob* PS = nullptr;
	ID3D10Blob* ErrMSG = nullptr;

	D3DX11CompileFromFile("SkyShader.shader", 0, 0, "SKYMAP_VS", "vs_4_0", 0, 0, 0, &VS, &ErrMSG, 0);
	D3DX11CompileFromFile("SkyShader.shader", 0, 0, "SKYMAP_PS", "ps_4_0", 0, 0, 0, &PS, &ErrMSG, 0);
	char* p = new char[100];

	// encapsulate both shaders into shader objects
	if (!ErrMSG && VS && PS)
	{
		pRenderer->GetDevice()->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), nullptr, &pVertexShader);
		pRenderer->GetDevice()->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), nullptr, &pPixelShader);
	}
	else
	{
		ELOG("The Shader file cannot be compiled. Please run this executable from the directory that contains the Shader file.");
		exit(1);
	}
	D3D11_INPUT_ELEMENT_DESC IED[] =
	{
		{"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 },
	};
	UINT numElements = ARRAYSIZE(IED);
	pRenderer->GetDevice()->CreateInputLayout(IED, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);

	// Vertex Buffer 	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DYNAMIC;
	bd.ByteWidth = size_of_verts;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

	D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = verts;

	pRenderer->GetDevice()->CreateBuffer(&bd, &InitData, OUT &pVBuffer);	// creating the buffer

	// Index Buffer 
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = size_of_indices;
	bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	bd.CPUAccessFlags = 0;

	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = indices;

	pRenderer->GetDevice()->CreateBuffer(&bd, &InitData, OUT &pIBuffer);
}

SkyBox::SkyBox()
{
}

SkyBox::SkyBox(CRenderer * pRenderer)	:
	pRenderer(pRenderer)
{
}

void SkyBox::CreateTri()
{
	Vertex verts[]
	{
		{-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},

		{-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},

		{-0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},

		{ 0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},

		{-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f, -0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f, -0.5f, -0.5f,  0.0f, 0.0f, 0.0f},

		{-0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{ 0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f,  0.5f,  0.5f,  0.0f, 0.0f, 0.0f},
		{-0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 0.0f}
	};

	WORD indices[] {
		0, 1, 2,
		3, 4, 5,
		6, 7, 8,
		9, 10, 11,
		12, 13, 14,
		15, 16, 17,
		18, 19, 20,
		21, 22, 23,
		24, 25, 26,
		27, 28, 29,
		30, 31, 32,
		33, 34, 35,
	};

	CubeMesh Cube;
	Cube.CreateMesh();

	CreateShader(verts, sizeof(Vertex) * 36, indices, sizeof(WORD) * 36);
}

void SkyBox::Render()
{
	const UINT  vStride = sizeof(Vertex);
	const UINT vOffset = 0; 
	pRenderer->GetDeviceContext()->VSSetShader(pVertexShader, 0, 0);
	pRenderer->GetDeviceContext()->PSSetShader(pPixelShader, 0, 0);
	pRenderer->GetDeviceContext()->IASetInputLayout(pLayout);
	pRenderer->GetDeviceContext()->IASetVertexBuffers(0, 1, &pVBuffer, &vStride, &vOffset);
	pRenderer->GetDeviceContext()->IASetIndexBuffer(pIBuffer, DXGI_FORMAT_R16_UINT, 0);
	pRenderer->GetDeviceContext()->DrawIndexed(36, 0, 0);
}

The render function is called in the before swapping the buffers
Posted
Updated 23-Jun-19 20:59pm
v3
Comments
Shao Voon Wong 23-Jun-19 5:33am    
Your vertex and pixel shader are the same file! For me, they are usually in separate file.
Shao Voon Wong 23-Jun-19 5:44am    
Your indices are funny. There are usually more indices than vertices. Vertex should not be repeated else it defeats the purpose of using indices. Indices should be in this pattern.

0, 1, 2,
0, 2, 3,
1, 4, 5,
1, 5, 2, ...

Since your vertices is the whole model, you should ditch indices and call Draw(), not DrawIndexed(). Do not send your indices to DX context in this case.
Member 14131869 23-Jun-19 7:20am    
i know, that was just to test. and weirdly enough even Draw() doesn't work.
Shao Voon Wong 23-Jun-19 7:23am    
Try drawing a triangle without normal first.

1 solution

I notice that you did not set your normals, they are all zeroes.

You can try setting the topology as trianglelist before setting input layout.

C++
direct3DDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
direct3DDeviceContext->IASetInputLayout(mInputLayout.Get());


You can try setting the culling mode. For your triangles, it should be front culling mode.

This is the way to initialize front culling which should be CCW in DX 11.

C++
Microsoft::WRL::ComPtr<ID3D11RasterizerState> RasterizerStates::FrontCulling;

D3D11_RASTERIZER_DESC rasterizerStateDesc;
ZeroMemory(&rasterizerStateDesc, sizeof(rasterizerStateDesc));
		rasterizerStateDesc.FillMode = D3D11_FILL_SOLID;
		rasterizerStateDesc.CullMode = D3D11_CULL_BACK; //<- do not change this
		rasterizerStateDesc.FrontCounterClockwise = true;
		rasterizerStateDesc.DepthClipEnable = true;

ThrowIfFailed(direct3DDevice->CreateRasterizerState(&rasterizerStateDesc, FrontCulling.GetAddressOf()), "ID3D11Device::CreateRasterizerState() failed.");


The above code should be correct. Do not change D3D11_CULL_BACK to D3D11_CULL_FRONT.

Call RSSetState() to set the culling before DrawIndexed().

C++
direct3DDeviceContext->RSSetState(RasterizerStates::FrontCulling.Get());
direct3DDeviceContext->DrawIndexed(mPhotoIndexCount, 0, 0);
 
Share this answer
 
v2
Comments
Member 14131869 24-Jun-19 10:44am    
Could you have a look if i were to share the project with you?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900