Skip to main content
GameDev.net gamedev.net
🔒 Locked

Shaders

Started by jpbb Dec 26, 2006 at 3:24 PM 2 replies 600+ views
Original Post
jpbb
jpbb
Hi, I have been learning about assembly shaders in DirectX, but I'm a little confused about some of the ways they are used. The books and other resources I have learnt from all have example applications and shaders, for example for a spot light, point light, water, bump mapping, even morphing animation, etc... But, for example, what if you want to have two point lights - I don't think you would render the scene twice, each time inputting the data for a different light. Or maybe you could just write the shader to handle two lights at once, but then how do engines handle more lights, say 5 (for example)... The same goes for shadow (shadow volumes, say) - how do you cast a shadow from a mesh using multiple lights? Also, say you want to animate a mesh using a morphing shader, and also have it coloured using a cartoon shader - do you render the mesh once for each shader, or write a seperate shader which incorporates both techniques? Basically, I guess I'm trying to ask how to pull what I have learnt about shaders together to actually be able to use them properly. Any explanations or links would be much appreciated, thanks.
jpbb
jpbb
I think I may have managed to answer this myself. Would you use something like the following:
for( each light in game ){    EnableAdditiveBlending          // so each light is blended correctly    for( each object in game )    {        SetVertexShader        SetPixelShader        RenderCurrentObject    }    RenderShadowVolumes}


Using something similar to this, I guess I'd have to combine the shaders, so if an object needed diffuse, texturing, bump mapping and specular lighting then I'd have to write a single vertex/pixel shader pair to perform all of it.

Is this in any way right?
Thanks.
mikeman
mikeman
Quote:

But, for example, what if you want to have two point lights - I don't think you would render the scene twice, each time inputting the data for a different light.


Actually, that's exactly what most games do; they use 1(or even more) rendering passes per light and accumulate the color buffer(through additive blending) in order to compose the final scene.

Because the shaders are expensive, most of the applications use a trick that take advantage of early z-testing. Regularly, the shader is executed before the depth test, so you could have situation where a shader for a specific (hidden) fragment is executed only to be discarded later. Early z-testing is a feature most cards have: The put an additional depth test before the shader execution, so the shader is not executed for fragments that fail the z-test. What most apps do is, they perform a quick first pass(no color,no lighting,no textures,just depth values). In subsequent passes(for the textures/lighting), the shader is executed only for visible fragments, resulting in zero overdraw and boosting performance.

There is another fundamentally different technique called deferred shading. Google for it. Basically, you render the geometry only once, but instead of texture/lighting info, you output geometry info for each fragment(like position,normal,texcoords) into a float buffer. That float buffer allows you to calculate the amount of lighting each fragment receives without having to actually render the geometry again.
HellRaiZer
HellRaiZer
As mikeman said, yes you got it right. Additively blending one light at a time would do the trick. I just want to point out a little problem with the code you posted. I think you should render the shadow volumes to the stencil buffer before the actual lighting pass. This way, the stencil test will let only fragments that are affected by the light to be drawn.

Something like this :

for( each light in game ){    RenderShadowVolumes    // Setup stencil test to pass only for fragment visible from the light    EnableAdditiveBlending          // so each light is blended correctly    for( each object in game )    {        SetVertexShader        SetPixelShader        RenderCurrentObject    }}


HellRaiZer
HellRaiZer

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.