Jump to content
  • Advertisement
Sign in to follow this  
Deathlike

DX11 Use different shaders

This topic is 905 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 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.

Edited by Deathlike

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites


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?

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Edited by LHLaurini

Share this post


Link to post
Share on other sites

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

Edited by Eduards Brown

Share this post


Link to post
Share on other sites

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 VSIt 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.

Edited by kubera

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!