Member 14131869 Ответов: 1

Не удается привязать индексный буфер directx 11.


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: я использую эти странные индексы только для тестирования, так как предполагал, что они вызывают проблему.

Что я уже пробовал:

Вот этот код:
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);
}

Функция рендеринга вызывается в разделе перед заменой буферов

Shao Voon Wong

Ваш вершинный и пиксельный шейдер-это один и тот же файл! Для меня они обычно находятся в отдельном файле.

Shao Voon Wong

Ваши показатели просто смешные. Обычно индексов больше, чем вершин. Вершина не должна повторяться, иначе она разрушает цель использования индексов. Индексы должны быть в этом паттерне.

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

Поскольку ваши вершины-это вся модель, вы должны отказаться от индексов и вызвать Draw(), а не DrawIndexed(). В этом случае не отправляйте свои индексы в контекст DX.

Member 14131869

я знаю, это было просто для проверки. и как ни странно, даже Draw() не работает.

Shao Voon Wong

Попробуйте сначала нарисовать треугольник без нормали.

1 Ответов

Рейтинг:
0

Shao Voon Wong

Я замечаю, что вы не установили свои нормали, они все нули.

Вы можете попробовать установить топологию как trianglelist перед установкой макета ввода.

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


Вы можете попробовать установить режим выбраковки. Для ваших треугольников это должен быть режим передней отбраковки.

Это способ инициализации переднего отбора, который должен быть CCW в DX 11.

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.");


Приведенный выше код должен быть правильным. Не меняйте D3D11_CULL_BACK на D3D11_CULL_FRONT.

Вызовите функцию RSSetState (), чтобы установить отбраковку перед DrawIndexed().

direct3DDeviceContext->RSSetState(RasterizerStates::FrontCulling.Get());
direct3DDeviceContext->DrawIndexed(mPhotoIndexCount, 0, 0);


Member 14131869

Не могли бы вы взглянуть, если бы я поделился с вами проектом?