I have written a lighting shader file that is used as the fragment shader part of a deferred lighting pipeline.
Unfortunately, each iteration seems to be adding 0.5ms to my frame time, so any more than a handful of dynamic lights results in unbearable slowdown.
So clearly I'm doing something stupid but I'm kinda new to optimising HLSL, so anything obvious you can spot would be greatly appreciated. Here is the shader code:
#include "DLLightingInclude.hlsli"
static const float MAX_DIFFUSE_ANGLE = 1.57079637;
Texture2D NormalGB : register(t0);
Texture2D DiffuseGB : register(t1);
Texture2D SpecularGB : register(t2);
Texture2D PositionGB : register(t3);
SamplerState NormalSampler : register(s0);
cbuffer CameraProperties : register(cb0) {
float3 CameraPosition;
}
cbuffer LightProperties : register(cb1) {
float3 LightPosition;
float LightRadius;
float3 LightColor;
};
void GetGBValues(
in int2 screenPosition,
in float2 texturePosition,
out float3 normal,
out float3 diffuseAlbedo,
out float3 specularAlbedo,
out float specularPower,
out float3 position)
{
int3 screenPos3 = int3(screenPosition, 0);
normal = normalize(NormalGB.Sample(NormalSampler, texturePosition).xyz);
diffuseAlbedo = DiffuseGB.Load(screenPos3).xyz;
float4 specularValues = SpecularGB.Load(screenPos3);
specularAlbedo = specularValues.xyz;
specularPower = specularValues.w * 50.0f;
position = PositionGB.Load(screenPos3).xyz;
}
FS_OUT_SPLIT main(FS_IN input) {
FS_OUT_SPLIT result;
float3 N;
float3 diffuseAlbedo;
float3 specularAlbedo;
float specularPower;
float3 position;
GetGBValues((int2) input.Position, input.TexCoord, N, diffuseAlbedo, specularAlbedo, specularPower, position);
float3 L = LightPosition - position;
float lightDistance = length(L);
float invAttenuation = max(0.0f, 1.0f - (lightDistance / LightRadius));
float NdotL = max(dot(N, L), 0.0f);
float angle = acos(NdotL / (lightDistance * length(N)));
float3 diffuseTerm = LightColor * diffuseAlbedo * (MAX_DIFFUSE_ANGLE - angle);
float3 V = CameraPosition - position;
float3 H = normalize(L + V);
float3 NdotH = dot(N, H);
float3 specularTerm = pow(saturate(NdotH), specularPower) * LightColor * specularAlbedo * min(NdotL, 1.0f);
result.BackBuffer = result.PreBloomBuffer = float4(diffuseTerm * invAttenuation + specularTerm * invAttenuation, 1.0f);
return result;
}
And the included file, DLLightingInclude.hlsli, looks like this:
struct VS_IN {
float3 Position : POSITION;
float2 TexCoord : TEXCOORD0;
};
struct VS_OUT {
float4 Position : SV_POSITION;
float2 TexCoord : TEXCOORD0;
};
typedef VS_OUT FS_IN;
struct FS_OUT {
float4 Color : SV_TARGET0;
};
struct FS_OUT_SPLIT {
float4 BackBuffer : SV_TARGET0;
float4 PreBloomBuffer : SV_TARGET1;
};
I can't really see anything particularly obvious in what I've written- but like I say, I'm kind of a noob at this.