[HLSL] How Does Simple Lighting Work?

Started by
5 comments, last by Xrystal 17 years ago
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.
Advertisement
I'd recommend taking a PIX capture and stepping through the shader to see how your computations and parameters are coming out.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

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:

// Lightingfloat3 LightDir;		// Light's direction in world spacefloat3 LightDiffuse;		// Light's diffuse color (was float4)float3 LightAmbient;		// Light's ambient color (was float4)// Materialsfloat4 MaterialAmbientColor;	// Material's ambient colorfloat4 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.
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.

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.
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.

*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 beengEffect[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.

This topic is closed to new replies.

Advertisement