Search code examples
c++openglfragment-shaderopengl-3

Why won't fragment shader compile?


I have used the below fragment shader on a number of Windows 7 & 8 PCs without problem.

#ifndef STRINGIFY
#define STRINGIFY(a) #a
#endif

char *fsFont  = STRINGIFY(

precision mediump float;
varying vec2 v_texCoord;
vec2 v_texCoord;
uniform sampler2D s_texture;
uniform vec4      vColor4;

varying lowp vec4 DestinationColor;

void main()
{
  gl_FragColor = vec4( 1, 1, 1, texture2D( s_texture, v_texCoord).a ) * vColor4;
}

);

Recently I tried running my app on a Windows 10 machine and I get the following errors when I try to compile the shader:

0x0059f3dc "0(1) : warning C7022: unrecognized profile specifier "mediump"
0(1) : warning C7022: unrecognized profile specifier "precision"
0(1) : error C1038: declaration of "v_texCoord" conflicts with previous declaration at 0(1)
0(1) : error C0000: syntax error, u"

And if I comment out the precision mediump float line..

0x0137f2c8 "0(1) : error C0000: syntax error, unexpected identifier, expecting "::" at token "lowp"
"

What's the problem? Is it because the PC I'm using supports a different version of OpenGL than I'm expecting?

UPDATE: This post suggests that precision mediump float line is only for OpenGL ES. That still doesn't explain why it works on most of my PCs. Moving on, what's wrong with the lowp declaration?

Here's my SDL initialisation code which chooses the OpenGL profile/version:

#ifndef _WIN32
  SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );
  SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
  SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 0 );
#else
  // Use OpenGL 3.1 core 
  SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
  SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 ); 
  SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
#endif

UPDATE: Here is the updated shader which is now working thanks to the comments from everybody:

char *fsFont  = 

"#version 330\n"
"precision mediump float;\n"
"varying vec2 v_texCoord;\n"

"uniform sampler2D s_texture;"
"uniform vec4      vColor4;"

"varying lowp vec4 DestinationColor;"

"void main()"
"{"
  "gl_FragColor = vec4( 1, 1, 1, texture2D( s_texture, v_texCoord).a ) * vColor4;"
"}"

;                 

UPDATE: I've removed STRINGIFY from all of my shaders, moved to OpenGL 3.3. All of my shaders compile with one exception:

    char *vs3DShader  = 

    "#version 330\n"
    "layout (location = 0) in vec3 Position;"
    "layout (location = 1) in vec4 color;"
    "layout (location = 2) in vec3 normal;"

    "out vec4 frag_color;"

    "uniform mat4 transform;"

    "void main()"
    "{"
    "  gl_Position = transform * vec4( Position.x, Position.y, Position.z, 1.0 );"

    "  // Pass vertex color to fragment shader.."
    "  frag_color = color;"
    "}"
;

Error:

0x0055f370 "(0) : error C0000: syntax error, unexpected $end at token "<EOF>"
"

Solution

  • The shader wouldn't compile because:

    • there was no #version line in the shader source (version was undefined and could have been any default on the different machines)
    • STRINGIFY() macro doesn't work with # characters so it would be better to load the shader as text from a file or specify it with double quotes around each line, remembering to use \n after lines starting with '#' or comments - preferably each line to be on the safe side
    • when attempting to remove STRINGIFY(), new line characters must be added after any comments, otherwise everything that is appended after the comment will be commented out
    • a duplicate variable had been introduced while trying to figure out why warnings/errors were being generated for mediump and varying keywords
    • Correct GLSL #version must be used that corresponds to the version of OpenGL being used as indicated by genpfault in this table (ie. OpenGL3.1 must use #version 140)