Generic Draw Calls

Started by
7 comments, last by Shael 14 years, 1 month ago
Where can I find information on designing a renderer for use with in a 3d game engine? When using the approach of a draw call, something like : Struct DrawCall { Shader pShader; IndexBuffer pIndexBuffer; VertexBuffer pVertexBuffer; Material pMaterial; } Does the shader parameter include both the vertex and pixel shader to be used? Because I’m thinking that the vertex shader is going to be pretty fixed for most purposes. For example Non-Skinned and skinned meshes. Whilst the vertex shader for these is different, when it comes to rendering them in different ways, I figure it’s only going to be the pixel shader that will change. So the renderer would receive the draw call, figure out if its a skinned or non skinned mesh, and set the appropriate vertex shader automatically, which the user can’t change. But the renderer will use the pixel shader that the user has chosen. So for some in game editor, it seems to make more sense to just ask the user what pixel shader they want to use, rather than also offering them a list of vertex shaders, which I can’t really think of any. For Skinned and non skinned meshes the vertex shader is just responsible for transforming the vertices, and so Im thinking the vertex shader should be fixed. Where as the pixel shader can vary alot, such as :- -Basic Materials -Complex Materials -Pixel Shaders specifically designed for rendering things like metal of realistic eyes So in the end, the renderer would have knowledge of vertex shaders, and pick the correct one depending on the mesh data passed in, maybe it has a SKINNED flag or something like that. But the pixel shader is set by the draw call. Or do you think that the draw call should also contain which Vertex Shader to use? Basically, im trying to reduce the number of shader combinations, and I figure that the pixel shaders used for skinned and non skinned meshes are going to be the same, and only the vertex shaders will change. So why also include which vertex shader to use in the draw call when its always going to be the same. Either a skinnedMeshVertexShader or a NonSkinnedMeshVertexShader. Something which I think can be figured out from the mesh itself.
Advertisement
I would suggest having the shader set inside the material itself. The material will almost certainly need a specific shader to produce the desired result so it makes more sense then for a user to apply a material rather than a material AND shader. In regards to having a single vertex shader for each object, while the same shader might work for a lot of pixel shader effects it will likely either a) Have wasted calculations / interpolants b) Be missing some values you need for more advanced pixel shaders. So I'd consider the vertex/pixel shader to usually be a joint entity (Like the DirectX effect system considers them to be). Just my 2 cents.
Thumbs up for what knighty33, has written above.
It is worth linking the spiritual parent discussion.
Quote:Original post by hick18
Does the shader parameter include both the vertex and pixel shader to be used? Because I’m thinking that the vertex shader is going to be pretty fixed for most purposes. For example Non-Skinned and skinned meshes. Whilst the vertex shader for these is different, when it comes to rendering them in different ways, I figure it’s only going to be the pixel shader that will change.

So the renderer would receive the draw call, figure out if its a skinned or non skinned mesh, and set the appropriate vertex shader automatically, which the user can’t change. But the renderer will use the pixel shader that the user has chosen.
I see you're still carrying on the previous idea of a smart renderer which somehow figures out how to render stuff in a mostly-fixed way. I thought it received enough hate in the previous thread, but let's elaborate on it even more.

I suggest you to think more generically. Yes, I can somehow share your feelings about the VS changing more rarely than the PS and the PS to change more rarely than its parameter buffers, but hey, think larger. Other vertex shaders you may need:
Billboarded polygons. Vector-based graphics. The 'breating meat' organic shader every game uses sooner or later. Flag shader. Leaves. Scrolling texture shader. Blink shader (using vertex color). Animating texture shader (using 3D texture brick on 'p' coord).
Providing your renderer the brains to figure out this stuff is something beyond me. I admit this with no fear nor shame.

Quote:Original post by hick18
Or do you think that the draw call should also contain which Vertex Shader to use? Basically, im trying to reduce the number of shader combinations, and I figure that the pixel shaders used for skinned and non skinned meshes are going to be the same, and only the vertex shaders will change. So why also include which vertex shader to use in the draw call when its always going to be the same.
No, it's not going to be the same. It's going to rarely change. This implies two possibilities:
1- You should state-bucket sort OR
2- Just have a material-based system (and maybe short-circuit later).
Have fun mixing and matching all this stuff. In general, either you build the machinery to ensure the information stays constant - which I highly suggest - or provide a generic way to ensure every possible information can be managed, or both.

Previously "Krohm"

Ok, so you're saying that you recommend that all shaders should consist of both vertex and pixel parts and should not be shared. So if I had 3 general shaders, Simple Illumination, Metal and maybe cloth. I should write the vertex/pixel shader for each possible use. So if I had just skinned and non skinned meshes that would require these kind of shaders, i would have

Non-Skinned
------------
Vertex\pixel combo for simple illumination shader
Vertex\pixel combo for metal shader
Vertex\pixel combo for cloth shader

Skinned
--------
Vertex\pixel combo for simple illumination shader
Vertex\pixel combo for metal shader
Vertex\pixel combo for cloth shader

Where the shader type is specified in the material.
Personally for shaders that can be used on skinned/non skinned characters I just build the shader multiple times with #defines for whether it's skinned. The change is usually easily separable from the rest of the vertex shader.
Quote:Original post by hick18
Ok, so you're saying that you recommend that all shaders should consist of both vertex and pixel parts and should not be shared. So if I had 3 general shaders, Simple Illumination, Metal and maybe cloth. I should write the vertex/pixel shader for each possible use.
Yes, for the time being. This combinatorial shader count explosion is a well known problem. You are not going to solve this easily, trust us.

Previously "Krohm"

Personally I took a different approach with my renderer, instead of having the "DrawCall" structure containing information about Materials/Shaders etc, it simply contains the information needed to render a set of primitives.

That being:

Primitive Type
Vertex Data (Buffer, Declaration, Count, Start)
Index Data (Buffer, Count, Start)

Then at the slightly higher level I have a Renderable struct, which contains the Shaders/Materials/etc and a DrawCall.

My Scene Manager then orders the renderables by Shader/Material/etc, then goes through them and sets them only if different from the last Renderable it processed and fires off the DrawCall to the Renderer.
Thanks for the reples so far.

@adt7 : How do you pass shader paramters such as bone matrices of specific consts for some specific.

@Krohm : Yes I agree my approach of the renderer being able to figure what the vertex type is before finding a matching shader is a bad approach. But whilst the renderer may not need to know this, as it can be stored before hand, dont you think that other parts of code should? Take for example an editor, where the user has imported a mesh, and wants to apply a material, from the editors material library, which has materials such as metal or cloth that provide the effect through some specific shader code. The application will somehow need to figure out the type of mesh vertex, ie is it a skinned mesh? does it have tangent/bitangent data? etc, before it can find a matching shader that the user has requested, that can perform the requested look with the mesh vertex type.

For this I was thinking about having an enumerated list of possible vertex types. Something like :

VERTEX TYPES {
POSITION_UV_NORMAL,
POSITION_UV_NORMAL_BITANGENT_TANGENT,
POSITION_UV_NORMAL_BITANGENT_TANGENT_BONEDATA,
};

And then say compiling the shader, say metal for this example, 3 times to match each of the above vertex types, ( if possible ). Then, when the user chooses "Metal" from the material library, the editor will try to find a matching metal shader, depending on the vertex type of the mesh it will be applied to. Where the "Metal Shader" for POSITION_UV_NORMAL_BITANGENT_TANGENT_BONEDATA would be the same as POSITION_UV_NORMAL_BITANGENT_TANGENT but with skinning computation too etc. Is having all these combinations what you meant by combination explosion?

Using your approach, without having this test, wouldnt the user have to set a matching shader effect themselves. ie make sure that the mesh vertex type has all the data the shader needs.
The way I do it is I have a shader for skinned meshes and one for static meshes. Since I am using .x meshes I simply have effect parameters defined inside the mesh which specify which shader to use and what the material parameters are etc. It can also specify what technique to use if it wants to. To make things easier I put a few restrictions in here and there on how the shaders are written. For example any textures must use the naming convention of "Texture#" where # is a number from >= 0. As for specific stuff like bone matrices I simply check if the mesh is skinned and if it is I update the matrices in the shader. In terms of vertex declarations when loading any meshes I force all meshes to have the same basic format.

This topic is closed to new replies.

Advertisement