Reputation: 282845
If I had a syntax error in my GLSL, it would fail at link time, shouldn't it?
Anyway, I tried running my program in glslDevil (never used this program before) and it just keeps repeating wglGetCurrentContext()
. I'm not sure if it's supposed to do that, or it's getting confused because it's a CLR app.
Is there an easier way to check for syntax errors in my GLSL code?
It appears to be the fragment shader that's causing the problem....here's the code if needed:
#version 330
const int MAX_POINT_LIGHTS = 2;
in vec2 TexCoord0;
in vec3 Normal0;
in vec3 WorldPos0;
out vec4 FragColor;
struct BaseLight
{
vec3 Color;
float AmbientIntensity;
float DiffuseIntensity;
};
struct DirectionalLight
{
struct BaseLight Base;
vec3 Direction;
};
struct Attenuation
{
float Constant;
float Linear;
float Exp;
};
struct PointLight
{
struct BaseLight Base;
vec3 Position;
Attenuation Atten;
};
uniform int gNumPointLights;
uniform DirectionalLight gDirectionalLight;
uniform PointLight gPointLights[MAX_POINT_LIGHTS];
uniform sampler2D gSampler;
uniform vec3 gEyeWorldPos;
uniform float gMatSpecularIntensity;
uniform float gSpecularPower;
vec4 CalcLightInternal(struct BaseLight Light, vec3 LightDirection, vec3 Normal)
{
vec4 AmbientColor = vec4(Light.Color, 1.0f) * Light.AmbientIntensity;
float DiffuseFactor = dot(Normal, -LightDirection);
vec4 DiffuseColor = vec4(0, 0, 0, 0);
vec4 SpecularColor = vec4(0, 0, 0, 0);
if (DiffuseFactor > 0) {
DiffuseColor = vec4(Light.Color, 1.0f) * Light.DiffuseIntensity * DiffuseFactor;
vec3 VertexToEye = normalize(gEyeWorldPos - WorldPos0);
vec3 LightReflect = normalize(reflect(LightDirection, Normal));
float SpecularFactor = dot(VertexToEye, LightReflect);
SpecularFactor = pow(SpecularFactor, gSpecularPower);
if (SpecularFactor > 0) {
SpecularColor = vec4(Light.Color, 1.0f) *
gMatSpecularIntensity * SpecularFactor;
}
}
return (AmbientColor + DiffuseColor + SpecularColor);
}
vec4 CalcDirectionalLight(vec3 Normal)
{
return CalcLightInternal(gDirectionalLight.Base, gDirectionalLight.Direction, Normal);
}
vec4 CalcPointLight(int Index, vec3 Normal)
{
vec3 LightDirection = WorldPos0 - gPointLights[Index].Position;
float Distance = length(LightDirection);
LightDirection = normalize(LightDirection);
vec4 Color = CalcLightInternal(gPointLights[Index].Base, LightDirection, Normal);
float Attenuation = gPointLights[Index].Atten.Constant +
gPointLights[Index].Atten.Linear * Distance +
gPointLights[Index].Atten.Exp * Distance * Distance;
return Color / Attenuation;
}
void main()
{
vec3 Normal = normalize(Normal0);
vec4 TotalLight = CalcDirectionalLight(Normal);
for (int i = 0 ; i < gNumPointLights ; i++) {
TotalLight += CalcPointLight(i, Normal);
}
FragColor = texture2D(gSampler, TexCoord0.xy) * TotalLight;
}
Edit: Specifically, I get GL_INVALID_OPERATION
when I call glUseProgram
. The docs say:
GL_INVALID_OPERATION is generated if program is not a program object.
GL_INVALID_OPERATION is generated if program could not be made part of current state.
GL_INVALID_OPERATION is generated if glUseProgram is executed between the execution of glBegin and the corresponding execution of glEnd.
But I don't think it can be the first or last case, because the program ran fine until I tweaked the shader. "could not be made part of the current state" doesn't give me much to go on.
Upvotes: 0
Views: 2820
Reputation: 13
In my case, I had an extra tick mark at the end of a line. Fat thumb typing.
gl_FragColor = vec4(0.6, 0.6, 0.6, 1.0);`
Removing the tick mark fixed the problem.
Weird that it gets all the way through compile, linking and throws the error when trying to use the program.
Upvotes: 1
Reputation: 11
When a program object has been successfully linked, the program object can be made part of current state by calling glUseProgram.So you should call program link before use program
Upvotes: 1
Reputation: 282845
The problem was this:
struct PointLight
{
struct BaseLight Base;
vec3 Position;
Attenuation Atten;
};
Should be just BaseLight Base
, no struct
And this:
vec4 CalcLightInternal(struct BaseLight Light, vec3 LightDirection, vec3 Normal)
Same problem.
Thought it looked funny, so I changed it, and it started working.
Upvotes: 1
Reputation: 3577
I think one possible explanation could be the for loop inside your code.
The for statement, in my humble experience, should be always avoided.
Consider that OpenGL ES supports only fixed number of iterations and, in your case, since you are basing it on a uniform, I would investigate on it.
Moreover, consider that many drivers unroll the for statement in order to optimize the generated code.
In other words, I would focus on a simpler version of your shader, something like the following:
if (gNumPointLights == 1) {
TotalLight += CalcPointLight(1, Normal);
} else if (gNumPointLights == 2) {
TotalLight += CalcPointLight(1, Normal);
TotalLight += CalcPointLight(2, Normal);
} else if (gNumPointLights == 3) {
TotalLight += CalcPointLight(1, Normal);
TotalLight += CalcPointLight(2, Normal);
TotalLight += CalcPointLight(3, Normal);
}
Obviously the code can be optmized in its style and efficiency but it is a quick starting point.
Anyway, realistically, you won't have thousands lights at the same time :)
Cheers
Upvotes: 1