Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


Klopo

Member Since 16 May 2013
Offline Last Active Jun 17 2013 03:42 PM

Topics I've Started

Optimizing HLSL code

16 May 2013 - 04:31 PM

Hi Gamedev! I've coded little shader code for my small game to handle lights on my moving rectangles. It work and I'm quite happy with the visual result. Unfortunately it's badly implemented and the number of lights I can have on screen at same time is not enough. Changing pixelshader to use ps_3_0 instead of ps_2_0 made it possible to use 18 lights instead of 3. I know this is a bad solution and what I've to do is lower the number of instructions that is made on the pixel shader.

 

I would love any help I could get to optimize my code, by moving some parts to the vertex shader or change instructions on pixel shader.

 

//-----------------------------------------------------------------------------
// Texture sampler
//-----------------------------------------------------------------------------
uniform const texture BasicTexture;

uniform const sampler TextureSampler : register(s0) = sampler_state
{
	Texture = (BasicTexture);
	MipFilter = Linear;
	MinFilter = Linear;
	MagFilter = Linear;
};

//-----------------------------------------------------------------------------
// Material settings
//-----------------------------------------------------------------------------

uniform const float3	DiffuseColor	: register(c0) = 1;
uniform const float	Alpha		: register(c1) = 1;

//-----------------------------------------------------------------------------
// Matrices
//-----------------------------------------------------------------------------

uniform const float4x4	World		: register(vs, c2);		
uniform const float4x4	View		: register(vs, c6);		
uniform const float4x4	Projection	: register(vs, c10);

//-----------------------------------------------------------------------------
// Structure definitions
//-----------------------------------------------------------------------------

struct CommonVSOutput
{
	float4	Pos_ws;
	float4	Pos_ps;
	float4	Diffuse;
};

//-----------------------------------------------------------------------------
// Vertex shader inputs
//-----------------------------------------------------------------------------
struct VSInputTx
{
	float4	Position	: POSITION;
	float2	TexCoord	: TEXCOORD0;
};

//-----------------------------------------------------------------------------
// Vertex shader outputs
//-----------------------------------------------------------------------------
struct VertexLightingVSOutputTx
{
	float4	PositionPS	: POSITION;		// Position in projection space
	float4	Diffuse		: COLOR0;
	float2	TexCoord	: TEXCOORD0;
};

//-----------------------------------------------------------------------------
// Pixel shader inputs
//-----------------------------------------------------------------------------

struct VertexLightingPSInputTx
{
	float4	Diffuse		: COLOR0;
	float2	TexCoord	: TEXCOORD0;
};

CommonVSOutput ComputeCommonVSOutput(float4 position)
{
	CommonVSOutput vout;
	
	float4 pos_ws = mul(position, World);
	float4 pos_vs = mul(pos_ws, View);
	float4 pos_ps = mul(pos_vs, Projection);
	vout.Pos_ws = pos_ws;
	vout.Pos_ps = pos_ps;
	
	vout.Diffuse	= float4(DiffuseColor, Alpha);
	
	return vout;
}

VertexLightingVSOutputTx VSBasicTx(VSInputTx vin)
{
	VertexLightingVSOutputTx vout;
	
	CommonVSOutput cout = ComputeCommonVSOutput(vin.Position);

	vout.PositionPS	= cout.Pos_ps;
	vout.Diffuse	= cout.Diffuse;
	vout.TexCoord	= vin.TexCoord;

	return vout;
}

//-----------------------------------------------------------------------------
// Pixel shaders
//-----------------------------------------------------------------------------

#define MAX_LIGHTS 18

float2 lightPos[MAX_LIGHTS];
float  lightRadius[MAX_LIGHTS];
float  lightIntensity[MAX_LIGHTS];
float4 lightColor[MAX_LIGHTS];

float objectWidth;
float objectHeight;
float2 objectPosition;
float grayScaleIntensity = 1.0f;

float4 PSBasicTx(VertexLightingPSInputTx pin) : COLOR
{
	float4 texCol = tex2D(TextureSampler, pin.TexCoord);
	float4 color = texCol * pin.Diffuse;
	//color.a = texCol.a;

	//Pixel position
        float2 pixelPos = pin.TexCoord.xy * float2(objectWidth, objectHeight) + objectPosition.xy;

	//Grayscale
	float4 grayScale = texCol;
	grayScale.rgb = dot(texCol.rgb, float3(0.3, 0.59, 0.11));

	for(int i = 0; i < MAX_LIGHTS; i++){
		float dist = distance(lightPos[i], pixelPos);
		float distanceFactor = saturate((lightRadius[i]-dist) / lightRadius[i]);

		grayScale.rgb = lerp(grayScale, texCol, distanceFactor * grayScaleIntensity);

		color += saturate(distanceFactor * lightIntensity[i]) * (grayScale * lightColor[i]);
	}

	//fix overlaping lights
	color.r = min(color.r, texCol.r);
	color.b = min(color.b, texCol.b);
	color.g = min(color.g, texCol.g);

	return color;
}

float4 PSBasicTxNoLight(VertexLightingPSInputTx pin) : COLOR
{
	float4 texCol = tex2D(TextureSampler, pin.TexCoord);
	float4 color  = texCol * pin.Diffuse;
	return color;
}

//-----------------------------------------------------------------------------
// Shader and technique definitions
//-----------------------------------------------------------------------------

int ShaderIndex = 0;


VertexShader VSArray[2] =
{
	compile vs_3_0 VSBasicTx(),
	compile vs_3_0 VSBasicTx(),
};


PixelShader PSArray[2] =
{
	compile ps_3_0 PSBasicTx(),
	compile ps_3_0 PSBasicTxNoLight(),
};


Technique BasicEffect
{
	Pass
	{
		VertexShader = (VSArray[ShaderIndex]);
		PixelShader  = (PSArray[ShaderIndex]);
	}
}

PARTNERS