Sign in to follow this  
pcwlai

Vertex color or material for lighting calculation?

Recommended Posts

I am curioucas about, what most people do for lighting lculation. The default behavior in DirectX 9 is using vertex color to track the lighting calculation. This will require every vertex to have a diffuse and/or ambient color. The other way is using material which requires a lot of API calls in order to set up the material properly. The benefits is there is no need for every vertex to have vertex color which minimizes the data transmition. So, which one is more common in the industry? Another problem which makes me feel confused is: if I enabled material and still have vertex color in each vertex, what is the result? e.g. having lighting calculation on material then blend with the vertex color and finally, blend with texture. Or vertex color is just skipped? I tried in real codes and notice no difference between vertex color only, material and vertex color with material. Am I right? Or just I did something wrong? Thanks.

Share this post


Link to post
Share on other sites
You can select where each color comes from:

D3DRS_COLORVERTEX - enables vertex coloring for lighting.
D3DRS_DIFFUSEMATERIALSOURCE - choose where to find diffuse color
D3DRS_AMBIENTMATERIALSOURCE - choose where to find ambient color
D3DRS_SPECULARMATERIALSOURCE - choose where to find specular color
D3DRS_EMISSIVEMATERIALSOURCE - choose where to find emissive color

the options for each are D3DMCS_MATERIAL, which will look in the appropriate section of the material structur. D3DMCS_COLOR1, which looks at the vertex diffuse, and D3DMCS_COLOR2, which looks at vertex specular. You will need a material when using specular as there is no other way to set the specular power.

Also, none of this matters when using a vertex shader, as you handle lighting yourself.

Share this post


Link to post
Share on other sites
Thanks for your information, Namethatnobodyelsetook.

My main problem is, when using the fixed pipeline (which is enough for most of my engine), using vertex color is a bit wasting as each vertex needs a color component in the vertex buffer which using material requires more API calls.

The default behaviour of DirectX is vertex color for lighting calculation. So, which method is a more common way in doing the lighting calculation? And why?

Share this post


Link to post
Share on other sites
Material color means you can render the same object with various colors easily, and easily change the alpha level too. If you don't need to modify the colors very often, this can be a good fit. When you aren't using a texture, such as for simple toon shading, each part of a model can have it's own material settings to choose between shirt color, pants color, skin color, etc. Since these are easily changed without locking a buffer, you can customize the colors without much effort. When using a texture, you can use this to tint a texture, for team colors, or whatever.

Vertex color allows you to change colors frequently. This may allow you to reuse a texture between multiple objects, and tint it by vertex colors. It could be used for coarse ambient occlusion information rather than adding a texture to hold that data. Varying the color per instance may require multiple vertex streams, or using dynamic vertex buffers. It allows changing of color or alpha levels within a single draw call. The toon shading example I used above could be done with vertex color, allowing you to render the object in a single draw call, instead of requiring one per material change. Customizing the colors would require locking the vertex buffer.

Which method you use depends on your needs. If you don't need to change the colors for a model, and can't leverage the vertex color to reduce the number of draw calls, then you might as well use the material color. The method used can vary by model. A table may use material colors, while a person uses vertex colors. The extra space used by vertex colors is fairly minimal. There is a slight performance loss using vertex colors because of both extra data to fetch and because the light and vertex colors must be mixed per vertex. Material and light colors can be mixed once at the start of a draw call. It's a very minor difference, but it does exist. On the other hand, GPUs prefer data in 32-byte chunks. If diffuse color aligns the data, it may render faster. If diffuse data causes a mis-alignment, it may render slower.

For example: Position = 12 bytes. Normal = 12 bytes. UV = 8 bytes. We're at 32 bytes. Adding in diffuse may cause a (very slight) loss in performance if your indices jump around the vertex buffer quite a bit, as most data fetches become two fetches.

Your selection should be based on what you need first. If the colors must change, you must use vertex colors. If you want easily changing colors or alpha per instance, then favor material colors. If either method works for your needs, it doesn't really matter which method you use. If one method will potential give a slight speed or memory boost, you might as well use that technique in that case.

Share this post


Link to post
Share on other sites
Really thanks for your thorough explanations, Namethatnobodyelsetook!

I used to use OpenGL and so, get confused with how DirectX handles vertex color and materials. Now, I know how to choose the appropriate method. Really thanks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this