Book - Intro to 3D Game Programming with DX10

Started by
3 comments, last by _damN_ 14 years, 1 month ago
Hi! Ive purchased a book by frank D. Luna and im stuck on tutorial 6. Basically the book shows you how to create and render lights seperately in the scene, but for the life of me i cant get 2 lights to render at the same time. Here are the shader codes:

//=============================================================================
// lighthelper.fx by Frank Luna (C) 2008 All Rights Reserved.
//
// Structures and functions for lighting calculations.
//=============================================================================


struct Light
{
	float3 pos;
	float3 dir;
	float4 ambient;
	float4 diffuse;
	float4 spec;
	float3 att;
	float  spotPower;
	float  range;
};

struct SurfaceInfo
{
	float3 pos;
    float3 normal;
    float4 diffuse;
    float4 spec;
};

float3 ParallelLight(SurfaceInfo v, Light L, float3 eyePos)
{
	float3 litColor = float3(0.0f, 0.0f, 0.0f);
 
	// The light vector aims opposite the direction the light rays travel.
	float3 lightVec = -L.dir;
	
	// Add the ambient term.
	litColor += v.diffuse * L.ambient;	
	
	// Add diffuse and specular term, provided the surface is in 
	// the line of site of the light.
	
	float diffuseFactor = dot(lightVec, v.normal);
	[branch]
	if( diffuseFactor > 0.0f )
	{
		float specPower  = max(v.spec.a, 1.0f);
		float3 toEye     = normalize(eyePos - v.pos);
		float3 R         = reflect(-lightVec, v.normal);
		float specFactor = pow(max(dot(R, toEye), 0.0f), specPower);
					
		// diffuse and specular terms
		litColor += diffuseFactor * v.diffuse * L.diffuse;
		litColor += specFactor * v.spec * L.spec;
	}
	
	return litColor;
}

float3 PointLight(SurfaceInfo v, Light L, float3 eyePos)
{
	float3 litColor = float3(0.0f, 0.0f, 0.0f);
	
	// The vector from the surface to the light.
	float3 lightVec = L.pos - v.pos;
		
	// The distance from surface to light.
	float d = length(lightVec);
	
	if( d > L.range )
		return float3(0.0f, 0.0f, 0.0f);
		
	// Normalize the light vector.
	lightVec /= d; 
	
	// Add the ambient light term.
	litColor += v.diffuse * L.ambient;	
	
	// Add diffuse and specular term, provided the surface is in 
	// the line of site of the light.
	
	float diffuseFactor = dot(lightVec, v.normal);
	[branch]
	if( diffuseFactor > 0.0f )
	{
		float specPower  = max(v.spec.a, 1.0f);
		float3 toEye     = normalize(eyePos - v.pos);
		float3 R         = reflect(-lightVec, v.normal);
		float specFactor = pow(max(dot(R, toEye), 0.0f), specPower);
	
		// diffuse and specular terms
		litColor += diffuseFactor * v.diffuse * L.diffuse;
		litColor += specFactor * v.spec * L.spec;
	}
	
	// attenuate
	return litColor / dot(L.att, float3(1.0f, d, d*d));
}

float3 Spotlight(SurfaceInfo v, Light L, float3 eyePos)
{
	float3 litColor = PointLight(v, L, eyePos);
	
	// The vector from the surface to the light.
	float3 lightVec = normalize(L.pos - v.pos);
	
	float s = pow(max(dot(-lightVec, L.dir), 0.0f), L.spotPower);
	
	// Scale color by spotlight factor.
	return litColor*s;
}

 
 
And the other effect file is...

//=============================================================================
// lighting.fx by Frank Luna (C) 2008 All Rights Reserved.
//
// Transforms and lights geometry.
//=============================================================================

#include "lighthelper.fx"
 
cbuffer cbPerFrame
{
	Light gLight;
	int gLightType; 
	float3 gEyePosW;
	
};

cbuffer cbPerObject
{
	float4x4 gWorld;
	float4x4 gWVP;
};

struct VS_IN
{
	float3 posL    : POSITION;
	float3 normalL : NORMAL;
	float4 diffuse : DIFFUSE;
	float4 spec    : SPECULAR;
};

struct VS_OUT
{
	float4 posH    : SV_POSITION;
    float3 posW    : POSITION;
    float3 normalW : NORMAL;
    float4 diffuse : DIFFUSE;
    float4 spec    : SPECULAR;
};

VS_OUT VS(VS_IN vIn)
{
	VS_OUT vOut;
	
	// Transform to world space space.
	vOut.posW    = mul(float4(vIn.posL, 1.0f), gWorld);
	vOut.normalW = mul(float4(vIn.normalL, 0.0f), gWorld);
		
	// Transform to homogeneous clip space.
	vOut.posH = mul(float4(vIn.posL, 1.0f), gWVP);
	
	// Output vertex attributes for interpolation across triangle.
	vOut.diffuse = vIn.diffuse;
	vOut.spec    = vIn.spec;
	
	return vOut;
}
 
float4 PS(VS_OUT pIn) : SV_Target
{
	// Interpolating normal can make it not be of unit length so normalize it.
    pIn.normalW = normalize(pIn.normalW);
   
   
    SurfaceInfo v = {pIn.posW, pIn.normalW, pIn.diffuse, pIn.spec};
    
    float3 litColor;
      float3 litColor2;
  
    

    
    if( gLightType == 0 ) // Parallel
    {
		litColor = ParallelLight(v, gLight, gEyePosW);
    }
    else if( gLightType == 1 ) // Point
    {
		litColor = PointLight(v, gLight, gEyePosW);

	}
	else // Spot
	{
		litColor = Spotlight(v, gLight, gEyePosW);
	}
	
    return float4(litColor, pIn.diffuse.a);
}

technique10 LightTech
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}


Is it a case of adding 2 colors together? Do i have to use a special function to do this? Ive been stuck on this problem for a really long time! PLEASE HELP ME!
Advertisement
Adding the colours should do the trick.
You mean like so...

PointLight(SurfaceInfo v, Light L, float3 eyePos) + PointLight(SurfaceInfo v, Light L, float3 eyePos) // Both functions return the litColor.

or...

litColor + litColor2?

When i do that i just get black?
Hey, I'm currenty reading the same book... just starting chapter 8. Anywho, here is my shader code for that exercise... combined with some code for the other exercises I believe. Anyways, if this doesn't work the problem isn't your shader... Also, I passed in two seperate lights into my shader code
//=============================================================================// lighting.fx by Frank Luna (C) 2008 All Rights Reserved.//// Transforms and lights geometry.//=============================================================================#include "lighthelper.fx" cbuffer cbPerFrame{	Light gLight; ***********	Light gLight2; ********** Two seperate light attributes	int gLightType; 	float3 gEyePosW;	};cbuffer cbPerObject{	float4x4 gWorld;	float4x4 gWVP;};struct VS_IN{	float3 posL    : POSITION;	float3 normalL : NORMAL;	float4 diffuse : DIFFUSE;	float4 spec    : SPECULAR;};struct VS_OUT{    float4 posH    : SV_POSITION;    float3 posW    : POSITION;    float3 normalW : NORMAL;    float4 diffuse : DIFFUSE;    float4 spec    : SPECULAR;};VS_OUT VS(VS_IN vIn){	VS_OUT vOut;		// Transform to world space space.	vOut.posW    = mul(float4(vIn.posL, 1.0f), gWorld);	vOut.normalW = mul(float4(vIn.normalL, 0.0f), gWorld);			// Transform to homogeneous clip space.	vOut.posH = mul(float4(vIn.posL, 1.0f), gWVP);		// Output vertex attributes for interpolation across triangle.	vOut.diffuse = vIn.diffuse;	vOut.spec    = vIn.spec;		return vOut;} float4 PS(VS_OUT pIn) : SV_Target{	// Interpolating normal can make it not be of unit length so normalize it.    pIn.normalW = normalize(pIn.normalW);          SurfaceInfo v = {pIn.posW, pIn.normalW, pIn.diffuse, pIn.spec};        float3 litColor;    if( gLightType == 0 ) // Parallel    {		litColor = ParallelLight(v, gLight, gEyePosW);    }    else if( gLightType == 1 ) // Point    {		litColor = PointLight(v, gLight, gEyePosW);	}	else if ( gLightType == 2) // Spot	{		litColor = Spotlight(v, gLight, gEyePosW);	}	else if ( gLightType == 3)// spot + point	{		litColor = PointLight(v,gLight,gEyePosW) + Spotlight(v,gLight2,gEyePosW);	}	       return float4(litColor, pIn.diffuse.a);}technique10 LightTech{    pass P0    {        SetVertexShader( CompileShader( vs_4_0, VS() ) );        SetGeometryShader( NULL );        SetPixelShader( CompileShader( ps_4_0, PS() ) );    }}


Also, I passed in two seperate lights into my shader code
void LightingApp::drawScene(){	D3DApp::drawScene();			// Restore default states, input layout and primitive topology 	// because mFont->DrawText changes them.  Note that we can 	// restore the default states by passing null.	md3dDevice->OMSetDepthStencilState(0, 0);	float blendFactors[] = {0.0f, 0.0f, 0.0f, 0.0f};	md3dDevice->OMSetBlendState(0, blendFactors, 0xffffffff);    md3dDevice->IASetInputLayout(mVertexLayout);    md3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);	// Set per frame constants.	mfxEyePosVar->SetRawValue(&mEyePos, 0, sizeof(D3DXVECTOR3));	mfxLightVar->SetRawValue(&mLights[mLightType], 0, sizeof(Light));	mfxLightType->SetInt(mLightType);	if(mLightType==3)	{		mfxLightVar->SetRawValue(&mLights[1],0,sizeof(Light));		mfxLightVar2->SetRawValue(&mLights[2],0,sizeof(Light));	}    D3D10_TECHNIQUE_DESC techDesc;    mTech->GetDesc( &techDesc );    for(UINT i = 0; i < techDesc.Passes; ++i)    {        ID3D10EffectPass* pass = mTech->GetPassByIndex(i);		mWVP = mLandWorld*mView*mProj;		mfxWVPVar->SetMatrix((float*)&mWVP);		mfxWorldVar->SetMatrix((float*)&mLandWorld);		pass->Apply(0);		mLand.draw();			mWVP = mWavesWorld*mView*mProj;		mfxWVPVar->SetMatrix((float*)&mWVP);		mfxWorldVar->SetMatrix((float*)&mWavesWorld);		pass->Apply(0);		mWaves.draw();    }
Thank you!!! It helps alot!

What kind of framerate do you get with that? Ive managed to add 2 directional lights with the example using an array, but the framerate drops considerably when i add a few lights.

My shader looks like this when adding 2 directional lights.

Quote:
//=============================================================================
// lighting.fx by Frank Luna (C) 2008 All Rights Reserved.
//
// Transforms and lights geometry.
//=============================================================================

#include "lighthelper.fx"

#define MAX_LIGHTS 10

cbuffer cbPerFrame
{
Light gLight[MAX_LIGHTS];
float3 gEyePosW;

};

cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWVP;
};

struct VS_IN
{
float3 posL : POSITION;
float3 normalL : NORMAL;
float4 diffuse : DIFFUSE;
float4 spec : SPECULAR;
};

struct VS_OUT
{
float4 posH : SV_POSITION;
float3 posW : POSITION;
float3 normalW : NORMAL;
float4 diffuse : DIFFUSE;
float4 spec : SPECULAR;
};

VS_OUT VS(VS_IN vIn)
{
VS_OUT vOut;

// Transform to world space space.
vOut.posW = mul(float4(vIn.posL, 1.0f), gWorld);
vOut.normalW = mul(float4(vIn.normalL, 0.0f), gWorld);

// Transform to homogeneous clip space.
vOut.posH = mul(float4(vIn.posL, 1.0f), gWVP);

// Output vertex attributes for interpolation across triangle.
vOut.diffuse = vIn.diffuse;
vOut.spec = vIn.spec;

return vOut;
}

float4 PS(VS_OUT pIn) : SV_Target
{
// Interpolating normal can make it not be of unit length so normalize it.
pIn.normalW = normalize(pIn.normalW);


SurfaceInfo v = {pIn.posW, pIn.normalW, pIn.diffuse, pIn.spec};

float3 litColor;


for(int i = 0; i <MAX_LIGHTS;i++)
{
litColor += ParallelLight(v, gLight, gEyePosW);
}


return float4(litColor, pIn.diffuse.a);
}

technique10 LightTech
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}





I get a framerate of about 11. Any idea why it might be doing that? Or is it a bad idea to have loops in shader code?

This topic is closed to new replies.

Advertisement