There is my shader fragment program
#version 330 core
precision highp float;
struct frec {
vec4 WorldPosition;
vec3 LightEmissive;
vec3 LightDiffuse;
vec3 LightSpecular;
vec3 Emissive;
vec3 Diffuse;
float DiffusePower;
vec3 Specular;
float SpecularPower;
float Opacity;
float OpacityMask;
vec3 Normal;
vec3 CameraVector;
};
struct lrec {
vec4 WorldPosition;
vec3 Ambient;
vec3 Diffuse;
vec3 Specular;
vec3 SpotDirection;
float SpotCutoff;
float SpotExponent;
float ConstantAtten;
float LinearAtten;
float QuadAtten;
};
in vec4 fWorldPosition;
in vec3 fCameraVector;
out vec4 FragColor;
layout(std140) uniform LightsBlock {
uniform lrec Lights[16];
};
uniform ivec4 LightIndices[16];
uniform int LightNumber;
void GetFragment(inout frec A);
void Illuminate(inout frec A);
void PassFragmentColor(inout frec A);
void main()
{
frec Local0;
Local0.Opacity = 1.0;
GetFragment(Local0);
Illuminate(Local0);
PassFragmentColor(Local0);
}
void GetFragment(inout frec A)
{
A.WorldPosition = fWorldPosition;
A.CameraVector = fCameraVector;
}
void pointLight(inout frec A, lrec B)
{
float nDotVP; // normal . light direction
float nDotHV; // normal . light half vector
float attenuation; // computed attenuation factor
float d; // distance from surface to light source
vec3 VP; // direction from surface to light position
vec3 halfVector; // direction of maximum highlights
// Compute vector from surface to light position
VP = B.WorldPosition.xyz - A.WorldPosition.xyz;
// Compute distance between surface and light position
d = length(VP);
// Normalize the vector from surface to light position
VP = normalize(VP);
// Compute attenuation
attenuation = 1.0 / (B.ConstantAtten + B.LinearAtten * d + B.QuadAtten * d * d);
halfVector = normalize(VP + A.CameraVector);
nDotVP = pow(max(0.0, dot(A.Normal, VP)), A.DiffusePower);
nDotHV = pow(max(0.0, dot(A.Normal, halfVector)), A.SpecularPower);
A.LightEmissive += B.Ambient * attenuation;
A.LightDiffuse += B.Diffuse * nDotVP * attenuation;
A.LightSpecular += B.Specular * nDotHV * attenuation;
}
void spotLight(inout frec A, lrec B)
{
float nDotVP; // normal . light direction
float nDotHV; // normal . light half vector
float spotDot; // cosine of angle between spotlight
float spotAttenuation; // spotlight attenuation factor
float attenuation; // computed attenuation factor
float d; // distance from surface to light source
vec3 VP; // direction from surface to light position
vec3 halfVector; // direction of maximum highlights
// Compute vector from surface to light position
VP = B.WorldPosition.xyz - A.WorldPosition.xyz;
// Compute distance between surface and light position
d = length(VP);
// Normalize the vector from surface to light position
VP = normalize(VP);
// Compute attenuation
attenuation = 1.0 / (B.ConstantAtten + B.LinearAtten * d + B.QuadAtten * d * d);
// See if point on surface is inside cone of illumination
spotDot = dot(-VP, normalize(B.SpotDirection));
if (spotDot < cos(0.01745329251994*B.SpotCutoff))
{
spotAttenuation = 0.0; // light adds no contribution
}
else
{
spotAttenuation = pow(spotDot, B.SpotExponent);
}
// Combine the spotlight and distance attenuation.
attenuation *= spotAttenuation;
halfVector = normalize(VP + A.CameraVector);
nDotVP = pow(max(0.0, dot(A.Normal, VP)), A.DiffusePower);
nDotHV = pow(max(0.0, dot(A.Normal, halfVector)), A.SpecularPower);
A.LightEmissive += B.Ambient * attenuation;
A.LightDiffuse += B.Diffuse * nDotVP * attenuation;
A.LightSpecular += B.Specular * nDotHV * attenuation;
}
void directionalLight(inout frec A, lrec B)
{
float nDotVP; // normal . light direction
float nDotHV; // normal . light half vector
vec3 VP; // direction from surface to light position
vec3 halfVector; // direction of maximum highlights
// Compute vector from surface to light position
VP = normalize(B.WorldPosition.xyz - A.WorldPosition.xyz);
halfVector = normalize(B.SpotDirection + A.CameraVector);
nDotVP = pow(max(0.0, dot(A.Normal, VP)), A.DiffusePower);
nDotHV = pow(max(0.0, dot(A.Normal, halfVector)), A.SpecularPower);
A.LightEmissive += B.Ambient;
A.LightDiffuse += B.Diffuse * nDotVP;
A.LightSpecular += B.Specular * nDotHV;
}
void infiniteSpotLight(inout frec A, lrec B)
{
float nDotVP; // normal . light direction
float nDotHV; // normal . light half vector
vec3 VP; // direction from surface to light position
vec3 halfVector; // direction of maximum highlights
float spotAttenuation;
vec3 Ppli;
vec3 Sdli;
// Compute vector from surface to light position
VP = normalize(B.WorldPosition.xyz - A.WorldPosition.xyz);
halfVector = normalize(B.SpotDirection + A.CameraVector);
nDotVP = pow(max(0.0, dot(A.Normal, VP)), A.DiffusePower);
nDotHV = pow(max(0.0, dot(A.Normal, halfVector)), A.SpecularPower);
Ppli = -VP;
Sdli = B.SpotDirection;
spotAttenuation = pow(dot(Ppli, Sdli), B.SpotExponent);
A.LightEmissive += B.Ambient * spotAttenuation;
A.LightDiffuse += B.Diffuse * nDotVP * spotAttenuation;
A.LightSpecular += B.Specular * nDotHV * spotAttenuation;
}
void Illuminate(inout frec A)
{
A.LightEmissive = vec3(0.0,0.0,0.0);
A.LightDiffuse = vec3(0.0,0.0,0.0);
A.LightSpecular = vec3(0.0,0.0,0.0);
for (int I = 0; I<LightNumber && I<16; I++)
{
int J = LightIndices[i].x;
lrec LightSource = Lights[J];
if (LightSource.WorldPosition.w == 1.0)
{
if (LightSource.SpotCutoff == 180.0)
{
pointLight(A,LightSource);
}
else
{
spotLight(A,LightSource);
}
}
else
{
if (LightSource.SpotCutoff == 180.0)
{
directionalLight(A,LightSource);
}
else
{
infiniteSpotLight(A,LightSource);
}
}
}
vec3 finalColor;
finalColor = A.Emissive*clamp(A.LightEmissive,vec3(0.0),vec3(1.0));
finalColor += A.Diffuse*clamp(A.LightDiffuse,vec3(0.0),vec3(1.0));
finalColor += A.Specular*clamp(A.LightSpecular,vec3(0.0),vec3(1.0));
A.Emissive = finalColor;
}
void PassFragmentColor(inout frec A)
{
FragColor = vec4(A.Emissive, A.Opacity);
}
The fragment object compile successfully, but program linking fail with error
Fragment shader(s) failed to link, vertex shader(s) failed to link.
unexpected error.
unexpected error.
I trying to test it by GPU Shader Analyze
in version 1.53 all fine,
but in version 1.55 fail with error
Internal compilation failure. Possibly caused by GSA not supporting a GLSL feature used in shader.
ERROR: 0:7: error(#132) Syntax error: ‘;’ parse error
ERROR: error(#273) 1 compilation errors. No code generated
Also I trying to simplify the shader, to leave only a one pointLight for first light source, to replace the uniform block to one structured uniform - does not help.
My system
Catalist 10.10 or 10.9
Radeon HD5450
WinXP SP2