Jump to content
  • Advertisement
Sign in to follow this  
Atrix256

Is this (simple) HLSL shader correct?

This topic is 3024 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Advertisement
Why not pass the number of lights to the shader, put the relative data in an array, then use a loop to deal with the lights in turn?

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 think it should create permutations for you...you can just use fxc and check the resulting assembly if you'd like to be sure.

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
Couldn't you set the array just before you send the data into the array?

for all lights
light = true/false

anEffect->SetBoolArray(handle, boolArray, 8)


I think that should work.

Share this post


Link to post
Share on other sites
Use an array instead. :-)
Have you eventually heard of Deferred Rendering?
It may be a bit simpler for many light sources.

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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!