Direct3D 10 Renderstates for light rendering

Started by
4 comments, last by HermanssoN 14 years, 11 months ago
Hello. I'm currently implementing some dynamic lights. For now I can only have one ligh per scene, wich won't do. I don't know how to set the correct render state when I draw the scene for all my lights, eg:


       ID3D10EffectTechnique* pTech = pShader->GetTechnique();
       D3D10_TECHNIQUE_DESC techDesc;
	
	
	//Draw the one and only ambient
	pShader->SetTechnique("ambientTech");
	pTech->GetDesc( &techDesc );
   
	pShader->SetLight( pLightManager->GetAmbientLight()->GetLight());
	for(UInt32 p = 0; p < techDesc.Passes; ++p)
        {
                pTech->GetPassByIndex( p )->Apply(0);
        	pEntity->Draw();
         }
         
        /* SET SOME RENDERSTATES HERE SO WE CAN BLEND THE SCENE LIGTNING?*/
        
	//Draw the scene with a point light
	pShader->SetTechnique("pointTech");
	pTech->GetDesc( &techDesc );
        E3DPointLight* pPointLight=  pLightManager->GetPointLight(0);
        pShader->SetLight( pPointLight->GetLight());
	for(UInt32 p = 0; p < techDesc.Passes; ++p)
	{
	     pTech->GetPassByIndex( p )->Apply(0);
	     pEntity->Draw();
			
	 }         


I've rendered the scene with just the point light so I know it works as it should. I'm also not quite sure if I should set the renderstate in the .cpp or inside the shader. //}{ermanssoN
Advertisement
For blending with multipass lighting, you want to enable additive blending. You could do this by adding a second Technique to your Effect, and have it call the same vertex/pixel shaders but with the appropriate render states set. To enable additive blending you need to set BLENDENABLE to true, SRCBLEND to ONE, DESTBLEND to ONE, and BLENDOP to ADD.

Also keep in mind that it's possible to calculate and sum the contribution from multiple lights in a single pixel shader pass. In many cases this will be more efficient than multipass lighting, since you don't have draw the geometry a second time, change renderstates, or blend with the framebuffer.
You mean, if I know I wan't two point lights and one directional I should make a shader designed for taking two poinlights and one directional.
What I'm trying do now is a "default" shader for my hobby engine. I've only used shaders in a D3D9 engine at my school before, that engine rendered each mesh once per light, having different techniques depending on what sort of light.

I'm generally interested in different approches. I have the
"Introduction to 3D Game Programming wi DirectX 10" by Frak D Luna as guideline for my design choise, but the book don't cover rendering several lights in the same scene.
I might add that I'm currently not using several passes inside the shader.

I got two techniques, as you saw above, I set the ambient technique, draw the scene, then set the point light technique and draw the scene again.

eg:
BlendState AdditiveBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = ONE;
DestBlend = ONE;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
technique10 pointTech
{

pass P0
{

SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS_Point() ) );
SetBlendState( AdditiveBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
}
technique10 ambientTech
{
pass P0
{

SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS_Ambient() ) );
}
}
Only the part of my object (a cube) that are inside the poinligts radius is visible.

If I undertstod things correctly using addative blending should prevent this?

I've checked out some SDK samples from the SDK. All states seems to be set inside the shader.

The correct way of rendering the scene with sevral light should be:

Draw Scene with ambient light using following states:

//blend states
BlendState NoBlending
{
BlendEnable[0] = FALSE;
};
BlendState AdditiveBlending
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = ONE;
DestBlend = ONE;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
RenderTargetWriteMask[0] = 0x0F;
};
//depthstates
DepthStencilState EnableDepth
{
DepthEnable = TRUE;
DepthWriteMask = ALL;
};
//cullign
RasterizerState DisableCulling
{
CullMode = NONE;
};

RasterizerState EnableCulling
{
CullMode = BACK;
};

//Ambient
SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
SetDepthStencilState( EnableDepth, 0 );
SetRasterizerState( EnableCulling );

And Draw the scene again with a point light:

//Point
SetBlendState( AdditiveBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
SetDepthStencilState( EnableDepth, 0 );
SetRasterizerState( EnableCulling );

I would really apprichiate any sample ora link to some tutorial showing the correct way do this.

//HermanssoN

This topic is closed to new replies.

Advertisement