Use different shaders

Started by
5 comments, last by kubera 8 years, 2 months ago

I'm still learning D3D11 and the logic behind it aswell. Currently, I have only one shader that I am using for pretty much everything. But, at this point, I need multiple shaders. (For shadows for example)

Now, I am loading my shader by using D3D11CompileFromFile in the code that follows:


void Renderer::InitPipeline()
{
	// compile the shaders
	ID3D10Blob *VS, *PS;
	D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, 0, 0);
	D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "PShader", "ps_4_0", 0, 0, 0, &PS, 0, 0);

	// create the shader objects
	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

	// set the shader objects
	devcon->VSSetShader(pVS, 0, 0);
	devcon->PSSetShader(pPS, 0, 0);

	// create the input element object
	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 },
	};

	dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
	devcon->IASetInputLayout(pLayout);

	// create the constant buffer
	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));

	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = 176;
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;

	dev->CreateBuffer(&bd, NULL, &pCBuffer);

	devcon->VSSetConstantBuffers(0, 1, &pCBuffer);
}

The problems are:

1. How can I load a different shader depending on what I need to draw?

2. Design-wise, which solution is the best?

Thanks in advance.

Advertisement

You can create a shader management class and then use a function inside the shader management class to load any shader you want and have a pointer stored for each loaded shader so you don't have to load it again.

The function will return that pointer if the shader was loaded before or load the shader if the shader was not loaded yet.


How can I load a different shader depending on what I need to draw?
How do you currently load a different texture depending on what you need to draw?

You can create a shader management class and then use a function inside the shader management class to load any shader you want and have a pointer stored for each loaded shader so you don't have to load it again.

The function will return that pointer if the shader was loaded before or load the shader if the shader was not loaded yet.

Could work!

@ Hodgman: my GameObject class has got a SetTexture method which is executed during the initialization of my Application class.

Also, I think you should know what Microsoft thinks about D3DX11CompileFromFile:

Note The D3DX (D3DX 9, D3DX 10, and D3DX 11) utility library is deprecated for Windows 8 and is not supported for Windows Store apps.
Note Instead of using this function, we recommend that you compile offline by using the Fxc.exe command-line compiler or use one of the HLSL compile APIs, like the D3DCompileFromFile API.

I use Fxc.exe to precompile my shaders, so I just need to call ID3D11Device::CreateWhateverShader with the compiled .cso file, which is simpler and faster. It also reports eventual errors at compile time instead of runtime which is very handy.

If you are using Visual Studio, just name your shader files <ShaderName>.hlsl and add to your project and they will be automatically compiled. If you're not, then you need to compile them manually using Fxc.exe (or write a .bat file to do that for you).

I'd say separate your model code from shader...

In your model you would setup Vertex/Index Buffers.

Have separate files for shaders, which compile shaders and set them...

(NOTE: The polygon layout you set inside Vertex Buffer can be different from the one shader requires as long as memory layout is the same).

So if your model and shader are separate you can do this:

Set Model ( Sending Vertex and Index buffers to shader)

Set Vertex Shader

Set Pixel Shader and Sampler

Set Model ( Sending Vertex and Index buffers to shader)

Set Another Vertex Shader

Set Another Pixel Shader and Sampler

Hi!

I have a containter class, which has a few std::unorderde_maps.

It has PSes, VSes and Input Layouts. These three classes may be merged into one combine.

One thing is important about Input Layouts. You need them: one per D3D11_INPUT_ELEMENT_DESC, not per VS. It makes code a bit complex.

I have also XML parser (very simple based on MS XML Light), which is a database describing how to join them.

The last thing, I have only precompiled shaders. They are loading faster.

Everything is called by the std::wstring - name.

This topic is closed to new replies.

Advertisement