Sign in to follow this  
Atrix256

Is this (simple) HLSL shader correct?

Recommended Posts

Hey Guys, I'm trying to make a shader that supports up to 8 lights with or without a texture on the model, and with or without a bump map. I had heard that if you use uniform bools like i am that the fx framework will automatically create a seperate shader for each permutation instead of doing branching at run time. Anyhow, does this look correct to you guys? I know the bump mapping isn't correct but am i doing anything retarded otherwise, anything that might be hurting preformance or that could be done in a better way etc? Thank you!
//////////////////////////////////////////////////////////////////////
//                         STRUCTURES
//////////////////////////////////////////////////////////////////////

struct VS_OUTPUT
{
  float4 hposition : POSITION;
  float2 texture0  : TEXCOORD0;
  float4 color     : COLOR0;
  float3 Norm      : TEXCOORD2;
};

//////////////////////////////////////////////////////////////////////
//                         GLOBALS
//////////////////////////////////////////////////////////////////////

float4x4 WorldViewProj : WorldViewProjection; // This matrix will be loaded by the application
float4x4 World;
float4 Diffuse;

texture Texture; // This texture will be loaded by the application

sampler Sampler = sampler_state
{
  Texture   = (Texture);
  MipFilter = NONE;
  MinFilter = NONE;
  MagFilter = NONE;
};

texture BumpMapTexture; // This texture will be loaded by the application

sampler BumpMapSampler = sampler_state
{
  Texture   = (BumpMapTexture);
  MipFilter = NONE;
  MinFilter = NONE;
  MagFilter = NONE;
};

//whether we should use textures or not
uniform bool UseTextures;

//whether we should use bump maps or not
uniform bool UseBumpMap;

//which lights are turned on
uniform bool UseLight1;
uniform bool UseLight2;
uniform bool UseLight3;
uniform bool UseLight4;
uniform bool UseLight5;
uniform bool UseLight6;
uniform bool UseLight7;
uniform bool UseLight8;

//light position or direction information
uniform float4 LightPosDir1;
uniform float4 LightPosDir2;
uniform float4 LightPosDir3;
uniform float4 LightPosDir4;
uniform float4 LightPosDir5;
uniform float4 LightPosDir6;
uniform float4 LightPosDir7;
uniform float4 LightPosDir8;

//light color
uniform float4 LightColor1;
uniform float4 LightColor2;
uniform float4 LightColor3;
uniform float4 LightColor4;
uniform float4 LightColor5;
uniform float4 LightColor6;
uniform float4 LightColor7;
uniform float4 LightColor8;

//ambient light
uniform float4 AmbientLight;

//////////////////////////////////////////////////////////////////////
//                         VERTEX
//////////////////////////////////////////////////////////////////////

VS_OUTPUT vs_main( float4 Position : POSITION, float2 Texture : TEXCOORD0, float3 Normal : NORMAL )
{
  VS_OUTPUT OUT;

  OUT.hposition = mul( Position , WorldViewProj);
  OUT.texture0 = Texture;
  OUT.color = Diffuse;

  OUT.Norm     = -normalize(mul(Normal,World));

  return OUT;
}

//////////////////////////////////////////////////////////////////////
//                         PIXEL
//////////////////////////////////////////////////////////////////////

float4 ps_main( VS_OUTPUT IN, uniform bool ShouldUseTextures, uniform bool ShouldUseBumpMap
                            , uniform bool ShouldUseLight1, uniform bool ShouldUseLight2
			    , uniform bool ShouldUseLight3, uniform bool ShouldUseLight4
                            , uniform bool ShouldUseLight5, uniform bool ShouldUseLight6
                            , uniform bool ShouldUseLight7, uniform bool ShouldUseLight8 ) : COLOR
{
  float4 Out;
  float4 SourceColor;
  float3 Bump;
  float3 Norm;

  //get the color of the object
  if(ShouldUseTextures)
  {
    SourceColor = tex2D( Sampler, IN.texture0 ) * IN.color;
  }
  else
  {
    SourceColor = IN.color;
  }

  //handle ambient lighting
  Out = SourceColor * AmbientLight;

  //handle bump mapping
  if(ShouldUseBumpMap)
  {
    IN.Norm += normalize(tex2D( BumpMapSampler, IN.texture0 ) * 2 - 1);
  }

  //handle light 1
  if(ShouldUseLight1)
  {
      Out += saturate(dot(LightPosDir1,IN.Norm)) * SourceColor * LightColor1;
  }

  //handle light 2
  if(ShouldUseLight2)
  {
      Out += saturate(dot(LightPosDir2,IN.Norm)) * SourceColor * LightColor2;
  }

  //handle light 3
  if(ShouldUseLight3)
  {
      Out += saturate(dot(LightPosDir3,IN.Norm)) * SourceColor * LightColor3;
  }

  //handle light 4
  if(ShouldUseLight4)
  {
      Out += saturate(dot(LightPosDir4,IN.Norm)) * SourceColor * LightColor4;
  }

  //handle light 5
  if(ShouldUseLight5)
  {
      Out += saturate(dot(LightPosDir5,IN.Norm)) * SourceColor * LightColor5;
  }

  //handle light 6
  if(ShouldUseLight6)
  {
      Out += saturate(dot(LightPosDir6,IN.Norm)) * SourceColor * LightColor6;
  }

  //handle light 7
  if(ShouldUseLight7)
  {
      Out += saturate(dot(LightPosDir7,IN.Norm)) * SourceColor * LightColor7;
  }

  //handle light 8
  if(ShouldUseLight8)
  {
      Out += saturate(dot(LightPosDir8,IN.Norm)) * SourceColor * LightColor8;
  }

  Out = saturate(Out);

  return Out;
}

//////////////////////////////////////////////////////////////////////
//                         TECHNIQUE
//////////////////////////////////////////////////////////////////////

technique Technique0
{
  pass Pass0
  {
    Sampler[0] = (Sampler); // Needed by pixel shader
    Sampler[1] = (BumpMapSampler);

    VertexShader = compile vs_2_0 vs_main();
    PixelShader  = compile ps_2_0 ps_main(UseTextures,UseBumpMap,UseLight1,UseLight2,UseLight3,UseLight4,UseLight5,UseLight6,UseLight7,UseLight8);
  }
}

Share this post


Link to post
Share on other sites
Would the looping be slower?

Right now (to my understanding at least!!), it will create a shader for each permutation needed so if i have an area that only needs 3 lights, it will make a shader that processes 3 lights without branching or looping.

Is that right?

(btw wow... gd.net forums were down for at least 6 hours what happened i wonder??)

Share this post


Link to post
Share on other sites
I have this working pretty well now but am trying to convert it to using arrays in the shader instead of having LightColor1, LightColor2, etc.

Problem is, how do i set the value of an array in a shader?

For setting a regular variable i do it like this:

anEffect->SetBool("UseLight1",true);

but if UseLight was a uniform bool array in the shader, how would i set UseLight[1] to true?

Share this post


Link to post
Share on other sites
Here is some code showing how I do it

in the shader

shared float4 lightpos[10];

then in c++ code, MAXLIGHTS defined as 10

D3DXHANDLE lightposarray;
shared_lightpos_fx = new D3DXHANDLE[MAXLIGHTS];

lightposarray = Shaderfx->GetParameterByName( NULL, "lightpos" );
for ( a = 0 ; a < MAXLIGHTS ; a++ ) {
shared_lightpos_fx[a] = Shaderfx->GetParameterElement(lightposarray,a);
}

Share this post


Link to post
Share on other sites
Thanks for that!

I got this working a little bit ago and with arrays it's much nicer, thanks for the input guys (:

In the example code above this post, it does this:


shared_lightpos_fx = new D3DXHANDLE[MAXLIGHTS];



Since MAXLIGHTS is a compile time constant, I'd say the better way would be to declare shared_lightpos_fx with a size of [MAXLIGHTS] instead of using new, since dynamic allocation is slow, can cause memory fragmentation, is easily leaked, etc!

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