여러 점 광원을 지원하는 쉐이더가 간단합니다.
라이트는 라이트 구조체의 배열 (최대 크기까지)로 저장되며 변경 될 때 활성 라이트 수를 전달합니다.
PixelShader 함수에 문제가 있습니다 :
기본 요소입니다. 텍스처에서 기본 색상을 가져오고 numActiveLights에 0을위한 광원 배열을 반복하고 효과를 추가하면 효과는 있지만 성능은 끔찍합니다!
그러나 전역 var numActiveLights에 대한 참조를 동일한 값의 상수로 바꾸면 성능이 좋습니다.
왜 변수를 참조하면 30+ fps 차이가 나는지 알 수 없습니다.HLSL 픽셀 쉐이더 조명 성능 (XNA)
아무도 설명해 주시겠습니까?
전체 쉐이더 코드 :
#define MAX_POINT_LIGHTS 16
struct PointLight
{
float3 Position;
float4 Color;
float Radius;
};
float4x4 World;
float4x4 View;
float4x4 Projection;
float3 CameraPosition;
float4 SpecularColor;
float SpecularPower;
float SpecularIntensity;
float4 AmbientColor;
float AmbientIntensity;
float DiffuseIntensity;
int activeLights;
PointLight lights[MAX_POINT_LIGHTS];
bool IsLightingEnabled;
bool IsAmbientLightingEnabled;
bool IsDiffuseLightingEnabled;
bool IsSpecularLightingEnabled;
Texture Texture;
sampler TextureSampler = sampler_state
{
Texture = <Texture>;
Magfilter = POINT;
Minfilter = POINT;
Mipfilter = POINT;
AddressU = WRAP;
AddressV = WRAP;
};
struct VS_INPUT
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float3 Normal : NORMAL0;
};
struct VS_OUTPUT
{
float3 WorldPosition : TEXCOORD0;
float4 Position : POSITION0;
float3 Normal : TEXCOORD1;
float2 TexCoord : TEXCOORD2;
float3 ViewDir : TEXCOORD3;
};
VS_OUTPUT VS_PointLighting(VS_INPUT input)
{
VS_OUTPUT output;
float4 worldPosition = mul(input.Position, World);
output.WorldPosition = worldPosition;
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.Normal = normalize(mul(input.Normal, World));
output.TexCoord = input.TexCoord;
output.ViewDir = normalize(CameraPosition - worldPosition);
return output;
}
float4 PS_PointLighting(VS_OUTPUT IN) : COLOR
{
if(!IsLightingEnabled) return tex2D(TextureSampler,IN.TexCoord);
float4 color = float4(0.0f, 0.0f, 0.0f, 0.0f);
float3 n = normalize(IN.Normal);
float3 v = normalize(IN.ViewDir);
float3 l = float3(0.0f, 0.0f, 0.0f);
float3 h = float3(0.0f, 0.0f, 0.0f);
float atten = 0.0f;
float nDotL = 0.0f;
float power = 0.0f;
if(IsAmbientLightingEnabled) color += (AmbientColor*AmbientIntensity);
if(IsDiffuseLightingEnabled || IsSpecularLightingEnabled)
{
//for (int i = 0; i < activeLights; ++i)//works but perfoemnce is terrible
for (int i = 0; i < 7; ++i)//performance is fine but obviously isn't dynamic
{
l = (lights[i].Position - IN.WorldPosition)/lights[i].Radius;
atten = saturate(1.0f - dot(l, l));
l = normalize(l);
nDotL = saturate(dot(n, l));
if(IsDiffuseLightingEnabled) color += (lights[i].Color * nDotL * atten);
if(IsSpecularLightingEnabled) color += (SpecularColor * SpecularPower * atten);
}
}
return color * tex2D(TextureSampler, IN.TexCoord);
}
technique PerPixelPointLighting
{
pass
{
VertexShader = compile vs_3_0 VS_PointLighting();
PixelShader = compile ps_3_0 PS_PointLighting();
}
}
이렇게 보입니다. 나는 아직도 믿기 어렵다. 그러나 루프의 멋진 콤팩트를 다음과 같은로드로 대체했다 : if (activeLights> 0) color + = [light function]; if (activeLights> 1) color + = [조명 기능]; if (activeLights> 2) color + = [조명 기능]; ... 최대 조명 수와 성능이 처음으로 돌아갔습니다./ 좋은 성능과 코드의 중간 지점을 찾고 누군가를 보여주기가 부끄럽지 않기를 바랍니다. – DFreeman
한 가지 가능성에 대해 제 편집을 참조하십시오. –