Sign in to follow this  
Xrystal

[HLSL] How Does Simple Lighting Work?

Recommended Posts

I was going to add this as a reply to another post but they seem to have a different problem. I am having problems getting my head around how the lighting works in HLSL fullstop. When using lights in the program it is simple. Set position, direction and colors and use it .. but in the HLSL fx file it seems there is a lot more involved. I took a look at both the BasicHLSL and DHPOWARE light demos but neither really helped to clear up the whys and hows of the excess of commands. Before I post up the code I am currently using the main question I am asking is .. Is there a SIMPLE HLSL book out there that I haven't stumbled across yet that someone can point out? edit: Just found this book 2 Books At Amazon that might be what I need. Anyone have them and can confirm they are at least partially useful ? Thanks. I've tried google but nothing as simple appears and my Shader books are currently too advanced for me and also doesn't show anything simple in HLSL language for me to try out. Okay, onto my source code for those that want to see it. Here's the fx file I have set up using the BasicHLSL as a guide.
// Matrices
float4x4 world;						// world matrix
float4x4 worldviewprojection;		// everything

// Lighting
float3 LightDir;					// Light's direction in world space
float4 LightDiffuse;				// Light's diffuse color
float4 LightAmbient;				// Light's ambient color

// Materials
float4 MaterialAmbientColor;		// Material's ambient color
float4 MaterialDiffuseColor;		// Material's diffuse color

// Textures
texture t0;
sampler t0Sampler = 
sampler_state { Texture = <t0>; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; };

// Structs
struct VS_OUTPUT
{
    float4 Position   : POSITION;   // vertex position 
    float4 Diffuse    : COLOR0;     // vertex diffuse color
    float2 TextureUV  : TEXCOORD0;  // vertex texture coords 
};
struct PS_OUTPUT
{
    float4 RGBColor : COLOR0;  // Pixel color    
};

// Shaders
VS_OUTPUT VSMesh( float4 vPos : POSITION, float3 vNormal : NORMAL, float2 vTexCoord0 : TEXCOORD0)
{
    VS_OUTPUT Output;
    float3 vNormalWorldSpace;
    
    // Transform the position from object space to homogeneous projection space
    Output.Position = mul(vPos, worldviewprojection); 
    // Transform the normal from object space to world space    
    vNormalWorldSpace = normalize(mul(vNormal, (float3x3)world)); // normal (world space)  
    // Compute simple directional lighting equation
    float3 vTotalLightDiffuse = float3(0,0,0);
    vTotalLightDiffuse += LightDiffuse * max(0,dot(vNormalWorldSpace, LightDir));       
    Output.Diffuse.rgb = MaterialDiffuseColor * vTotalLightDiffuse + 
                         MaterialAmbientColor * LightAmbient;   
    Output.Diffuse.a = 1.0f; 
    Output.TextureUV = vTexCoord0; 
    return Output;    
}
PS_OUTPUT PSMesh( VS_OUTPUT In) 
{ 
    PS_OUTPUT Output;
    Output.RGBColor = tex2D(t0Sampler, In.TextureUV) * In.Diffuse;
    return Output;
}

// Techniques
technique MeshShader
{
	pass p0
	{
        VertexShader = compile vs_2_0 VSMesh();
        PixelShader  = compile ps_2_0 PSMesh();
	}
}


And this is my Mesh Drawing Routine:
	bool bUseEffect = true;
	int effectID = 1;
	if (bUseEffect)
	{
		gEffect[effectID]->SetTechnique("MeshShader");
		gEffect[effectID]->SetTextureValue("t0",gTexture[0]->Retrieve());
		gEffect[effectID]->Retrieve()->SetValue("LightDir",&(gDirectX->Light().Direction),sizeof(D3DVECTOR));
		gEffect[effectID]->Retrieve()->SetValue("LightDiffuse",&(gDirectX->Light().Diffuse),sizeof(D3DCOLORVALUE));
		gEffect[effectID]->Retrieve()->SetValue("LightAmbient",&(gDirectX->Light().Ambient),sizeof(D3DCOLORVALUE));
		gEffect[effectID]->Retrieve()->SetValue("MaterialDiffuse",&(gDirectX->Material().Diffuse),sizeof(D3DCOLORVALUE));
		gEffect[effectID]->Retrieve()->SetValue("MaterialAmbient",&(gDirectX->Material().Ambient),sizeof(D3DCOLORVALUE));
	}
	else
	{
		gTexture[0]->Use(0,TRUE);
		gDirectX->EnableLight(0,TRUE);
		gDirectX->UseMaterial(TRUE);
	}
	gDirectX->PositionObject(D3DXVECTOR3(2.0f,-2.0f,5.0f));
	if (bUseEffect)
	{
		gEffect[effectID]->SetMatrixValue("world",&(gDirectX->World()));
		gEffect[effectID]->SetMatrixValue("worldviewprojection",&(gDirectX->WorldViewProjection()));
		passes = gEffect[effectID]->Begin();
		for (int i = 0; i < passes; i++)
		{
			gEffect[effectID]->BeginPass(i);
			gTeapot->DrawSubset(0);
			gEffect[effectID]->EndPass();
		}
		gEffect[effectID]->End();
	}
	else
	{
		gTeapot->DrawSubset(0);
	}
	gDirectX->PositionObject(D3DXVECTOR3(-2.0f,-2.0f,5.0f));
	if (bUseEffect)
	{
		gEffect[effectID]->SetMatrixValue("world",&(gDirectX->World()));
		gEffect[effectID]->SetMatrixValue("worldviewprojection",&(gDirectX->WorldViewProjection()));
		passes = gEffect[effectID]->Begin();
		for (int i = 0; i < passes; i++)
		{
			gEffect[effectID]->BeginPass(i);
			gCube->DrawSubset(0);
			gEffect[effectID]->EndPass();
		}
		gEffect[effectID]->End();
	}
	else
	{
		gCube->DrawSubset(0);
	}
	gDirectX->PositionObject(D3DXVECTOR3(2.0f,2.0f,5.0f));
	if (bUseEffect)
	{
		gEffect[effectID]->SetMatrixValue("world",&(gDirectX->World()));
		gEffect[effectID]->SetMatrixValue("worldviewprojection",&(gDirectX->WorldViewProjection()));
		passes = gEffect[effectID]->Begin();
		for (int i = 0; i < passes; i++)
		{
			gEffect[effectID]->BeginPass(i);
			gSphere->DrawSubset(0);
			gEffect[effectID]->EndPass();
		}
		gEffect[effectID]->End();
	}
	else
	{
		gSphere->DrawSubset(0);
	}
	gDirectX->PositionObject(D3DXVECTOR3(-2.0f,2.0f,5.0f));
	if (bUseEffect)
	{
		gEffect[effectID]->SetMatrixValue("world",&(gDirectX->World()));
		gEffect[effectID]->SetMatrixValue("worldviewprojection",&(gDirectX->WorldViewProjection()));
		passes = gEffect[effectID]->Begin();
		for (int i = 0; i < passes; i++)
		{
			gEffect[effectID]->BeginPass(i);
			gTorus->DrawSubset(0);
			gEffect[effectID]->EndPass();
		}
		gEffect[effectID]->End();
	}
	else
	{
		gTorus->DrawSubset(0);
	}


The positioning of the objects while using the effect file is perfect but they are being drawn black which seems to signify a sign of the lighting not working properly. All the global effect file values are being set to values the program uses to draw when not using the effect file so I can't see what is wrong unless the fx file itself is wrong or that I need to set more lighting values but no other lighting values are actually being used in the fx file. I'll have to investigate further but this is about the simplest lighting fx file I could find and if I can't get this working then I'll never get anything more complex working let alone understood. Thanks for any replies and for reading this loooong post.

Share this post


Link to post
Share on other sites
Hmm, well just tried PIX and not sure why its not working but it seems the following lines are at fault:

Heres the source code being used

gEffect[effectID]->Retrieve()->SetValue("LightDir",&(gDirectX->Light().Direction),sizeof(D3DVECTOR));
gEffect[effectID]->Retrieve()->SetValue("LightDiffuse",&(gDirectX->Light().Diffuse),sizeof(D3DVECTOR));
gEffect[effectID]->Retrieve()->SetValue("LightAmbient",&(gDirectX->Light().Ambient),sizeof(D3DCOLORVALUE));
gEffect[effectID]->Retrieve()->SetValue("MaterialDiffuse",&(gDirectX->Material().Diffuse),sizeof(D3DCOLORVALUE));
gEffect[effectID]->Retrieve()->SetValue("MaterialAmbient",&(gDirectX->Material().Ambient),sizeof(D3DCOLORVALUE));



And Heres the PIX output in question

1208 ID3DXEffect::SetValue(0x0047A834, 0x0012F640, 12) -- result: S_OK 2141702400
1209 ID3DXEffect::SetValue(0x0047A824, 0x0012F674, 12) -- result: D3DERR_INVALIDCALL 2141746560
1210 ID3DXEffect::SetValue(0x0047A814, 0x0012F704, 16) -- result: S_OK 2141790976
1211 ID3DXEffect::SetValue(0x0047A800, 0x0012F750, 16) -- result: D3DERR_INVALIDCALL 2141833088
1212 ID3DXEffect::SetValue(0x0047A7EC, 0x0012F7AC, 16) -- result: D3DERR_INVALIDCALL 2141877248




After some tweaking of the effect file as follows:


// Lighting
float3 LightDir; // Light's direction in world space
float3 LightDiffuse; // Light's diffuse color (was float4)
float3 LightAmbient; // Light's ambient color (was float4)

// Materials
float4 MaterialAmbientColor; // Material's ambient color
float4 MaterialDiffuseColor; // Material's diffuse color




The PIX output is as follows:

1208 ID3DXEffect::SetValue(0x0047A834, 0x0012F640, 12) -- result: S_OK 1820396672
1209 ID3DXEffect::SetValue(0x0047A824, 0x0012F674, 12) -- result: S_OK 1820440832
1210 ID3DXEffect::SetValue(0x0047A814, 0x0012F704, 16) -- result: S_OK 1820491392
1211 ID3DXEffect::SetValue(0x0047A800, 0x0012F750, 16) -- result: D3DERR_INVALIDCALL 1820534144
1212 ID3DXEffect::SetValue(0x0047A7EC, 0x0012F7AC, 16) -- result: D3DERR_INVALIDCALL 1820578816



Looks like its just the material at fault now so will have to check that out.

Share this post


Link to post
Share on other sites
Quote:
Original post by superpig
I'd recommend taking a PIX capture and stepping through the shader to see how your computations and parameters are coming out.


Thanks for that suggestion. I could never figure out how to get anything useful out of it before. Very useful tool.

Share this post


Link to post
Share on other sites
Quote:
Original post by glaeken
I have Introduction to 3D Game Programming with DirectX 9.0c: A Shader Approach and can definitely recommend it. It's a pretty good book.


Thanks, my book collection is getting pretty large so didn't want to buy another book if it wasn't really worth it. Anyway, book ordered so will have to read through it and see if I can make sense of my problem.

Share this post


Link to post
Share on other sites
*Slaps head a few times at the simplicity of the bug*


//The following code:
gEffect[effectID]->Retrieve()->SetValue("MaterialDiffuse",&(gDirectX->Material().Diffuse),sizeof(D3DCOLORVALUE));
gEffect[effectID]->Retrieve()->SetValue("MaterialAmbient",&(gDirectX->Material().Ambient),sizeof(D3DCOLORVALUE));

//should have been
gEffect[effectID]->Retrieve()->SetValue("MaterialDiffuseColor",&(gDirectX->Material().Diffuse),sizeof(D3DCOLORVALUE));
gEffect[effectID]->Retrieve()->SetValue("MaterialAmbientColor",&(gDirectX->Material().Ambient),sizeof(D3DCOLORVALUE));




I only noticed this after I received the book I mentioned in the earlier post and found I was doing the same way of setting as they were but with unexpected results. Added an extra line in to grab a Handle and saw that the result in PIX was NULL which then drew me to the cause of the problem. Source and Effect files had different values. I must have changed the Effect file after copying the value to my source file. *shakes head*

It's not perfectly working due to other code not being set in place in the effect file but I can see a slight light glow off of the material instead of pure black. Something to do with not setting the Inverse value which the book says has to be set to make lighting work.

Anyway, thanks for the suggestions and ideas that were posted and must confirm that at first browse through the book it seems pretty useful to have around.

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