Beginner's question on gl_FragColor issue in glsl 410

#1

Hi everyone,
A question from a beginner trying to upgrade his Blinn-Phong shaders to the glsl 410 core profile.
The error message is

'variable' : is removed in Forward Compatible context gl_FragColor

I would really appreciate some hint/direction on where to start looking.
The fragment fragment shader is the following.

#version 410

in vec3 Position_viewSpace;
in vec3 Normal_viewSpace;
in vec3 EyeDirection_viewSpace;
in vec3 LightDirection_viewSpace;
in vec3 vPosition;
in vec4 vertexcolor;

uniform int TwoSided;
uniform int lightOn;
uniform vec3 LightPosition_viewSpace;
uniform vec4 LightColor;
uniform float LightAmbient, LightDiffuse, LightSpecular;
uniform float Kc, Kl, Kq;
uniform float MaterialShininess;
uniform vec4 clipPlane0; // defined in view-space



out vec4 fragColor;

void main()
{
    // Material properties
    vec4 MaterialAmbientColor, MaterialDiffuseColor, MaterialSpecularColor;
    
    if (vPosition.z > clipPlane0.w)
    {
        discard;
        return;
    }
    
    if(lightOn==1)
    {
        MaterialAmbientColor  = vec4(vertexcolor.rgb * LightAmbient, vertexcolor.a);
        MaterialDiffuseColor  = vec4(vertexcolor.rgb * LightDiffuse, vertexcolor.a);
        MaterialSpecularColor = vec4(1.0, 1.0, 1.0, 1.0);
        
        // Distance to the light
        float distance = length(LightPosition_viewSpace - Position_viewSpace);
        
        // Normal of the computed fragment, in viewSpace
        vec3 N = normalize(Normal_viewSpace);
        
        // Direction from the fragment to the light
        vec3 L = normalize(LightDirection_viewSpace);
        
        // Cosine of the angle between the normal and the light direction, clamped above 0
        float cosTheta = 1.0;
        if(TwoSided==0) cosTheta = clamp(dot(N,L), 0.0, 1.0);
        else            cosTheta = abs(dot(N,L)); // reflection on both sides of the surface
        
        // Direction from the vertex to the eye, in view space.
        vec3 E = normalize(EyeDirection_viewSpace);
        
        // Direction in which the triangle reflects the light
        vec3 R = reflect(-L,N);
        
        // Cosine of the angle between the Eye vector and the Reflect vector,
        float cosAlpha = clamp(dot(E,R), 0.0, 1.0);
        
        float attenuation_factor = clamp(1.0/(Kc + Kl*distance + Kq*distance*distance), 0.00001, 1.0);
        
        gl_FragColor =
                MaterialAmbientColor  * LightColor +
                (MaterialDiffuseColor  * LightDiffuse  * cosTheta)                         * LightColor * attenuation_factor
                +(MaterialSpecularColor * LightSpecular * pow(cosAlpha, MaterialShininess)) * LightColor * attenuation_factor;
    }
    else
    {
        gl_FragColor  = vertexcolor;
    }
}


Thanks in advance.

#2

In the earliest versions of GLSL, fragment shaders operated by writing to the predefined outputs gl_FragColor or gl_FragData (the latter is an array, allowing for framebuffers with multiple colour attachments). These variables were deprecated in GLSL 1.3. Instead, you’re supposed to declare fragment shader output variables. Prior to GLSL 3.3, you need to associate output variables with colour attachments using glBindFragDataLocation(). In 3.3 and later, you can use layout qualifiers to specify the location.

With the code you have, you just need to replace both uses of [var]gl_FragColor[/var] with the user-defined variable [var]fragColor[/var] and either call


glBindFragDataLocation(program,0,"fragColor");

in the application or change the declaration of [var]fragColor[/var] to


layout(location=0) out vec4 fragColor;

#3

(for completeness…)

Or:
3) Use a compatibility context, or
4) Explicitly declare “#version 410 compatibility” to compile for the compatibility profile.

However, this won’t be forward-compatible, which you are clearly targeting.

#4

Thanks, that fixed the error.
Got nothing on the screen now, but I’ll try to figure it out.

#5

It turns out that the screen was blank because there wasn’t any VAO support. Apparently this isn’t a problem in Windows, but it seems to be required by MESA in Linux.

A new difficulty: this time, it’s the fragment shader for texture display which apparently needs some upgrade. The error message is


ERROR: 3:36: 'function' : is removed in Forward Compatible context texture2D
ERROR: 3:36: 'texture2D' : no matching overloaded function found (using implicit conversion) 
ERROR: 3:36: 'texture2D' : function is not known 
ERROR: 3:36: 'rgb' : field selection requires structure, vector, or matrix on left hand side 
ERROR: 3:36: 'constructor' : not enough data provided for construction 
ERROR: 3:37: 'function' : is removed in Forward Compatible context texture2D
ERROR: 3:37: 'texture2D' : no matching overloaded function found (using implicit conversion) 
ERROR: 3:37: 'texture2D' : function is not known 
ERROR: 3:37: 'rgb' : field selection requires structure, vector, or matrix on left hand side 
ERROR: 3:38: 'constructor' : not enough data provided for construction 
ERROR: 3:71: 'function' : is removed in Forward Compatible context texture2D
ERROR: 3:71: 'texture2D' : no matching overloaded function found (using implicit conversion) 
ERROR: 3:71: 'texture2D' : function is not known 
ERROR: 3:71: 'rgb' : field selection requires structure, vector, or matrix on left hand side 
ERROR: 3:72: 'constructor' : not enough data provided for construction 

And the shader code is

#version 330

// the texture fragment shader

uniform int lightOn;
uniform vec3 LightPosition_viewSpace;
uniform vec4 LightColor;
uniform float LightAmbient, LightDiffuse, LightSpecular;
uniform float Kc, Kl, Kq;
uniform int MaterialShininess;
uniform sampler2D textureSampler;
uniform vec4 clipPlane0; // defined in view-space

in vec3 Position_worldSpace;
in vec3 Normal_viewSpace;
in vec3 EyeDirection_viewSpace;
in vec3 LightDirection_viewSpace;
in vec2 UV;
in vec3 vPosition;

layout(location=0) out vec4 fragColor;


void main()
{
	// Material properties
	vec4 MaterialAmbientColor, MaterialDiffuseColor, MaterialSpecularColor;

	if (vPosition.z > clipPlane0.w)
	{
		discard;
		return;
	}

	if(lightOn==1)
	{
		MaterialAmbientColor  = vec4(texture2D(textureSampler, UV).rgb*LightAmbient, 1.0) ;
		MaterialDiffuseColor  = vec4(texture2D(textureSampler, UV).rgb*LightDiffuse, 1.0);


		MaterialSpecularColor = vec4(1.0, 1.0, 1.0, 1.0);

		// Distance to the light
		float distance = length(LightPosition_viewSpace - Position_worldSpace);

		// Normal of the computed fragment, in camera space
		vec3 N = normalize(Normal_viewSpace);

		// Direction of the light (from the fragment to the light)
		vec3 L = normalize(LightDirection_viewSpace);

		// Cosine of the angle between the normal and the light direction,
		float cosTheta = clamp(dot(N,L), 0.0, 1.0);

		// Eye vector (towards the camera)
		vec3 E = normalize(EyeDirection_viewSpace);

		// Direction in which the triangle reflects the light
		vec3 R = reflect(-L,N);

		// Cosine of the angle between the Eye vector and the Reflect vector,
		float cosAlpha = clamp(dot(E,R), 0.0, 1.0);

		float attenuation_factor = clamp(1.0/(Kc + Kl*distance + Kq*distance*distance), 0.00001, 1.0);

        fragColor =
			  MaterialAmbientColor  * LightColor +
			 (MaterialDiffuseColor  * LightDiffuse  * cosTheta)                         * LightColor * attenuation_factor
			+(MaterialSpecularColor * LightSpecular * pow(cosAlpha, MaterialShininess)) * LightColor * attenuation_factor;
	}
	else
        fragColor  = vec4(texture2D(textureSampler, UV).rgb, 1.0);

}

I could probably figure it out myself with a lot of time and effort, but you guys seem to understand this stuff way better than I do and you are really helpful.
So many thanks in advance for your help.

BTW, I’m using the Qt wrapper around OGL functions, although I believe this is unrelated to the issue.

#6

Probably different versions or profiles. Prior to 3.0, attribute array state was part of the context; in 3.0 and later, it’s stored in VAOs. In the compatibility profile, a VAO name (handle) of zero refers to the default VAO, which is bound initially. The core profile doesn’t have a default VAO; initially no VAO is bound, and glBindVertexArray(0) results in no VAO being bound. It is an error to modify vertex array state or issue draw calls without a VAO bound.

Use texture() instead. Early versions of GLSL had different functions for different texture targets (2D, 3D, cube map, etc). Later versions just overload the texture() function.