Shader doesn't load

I installed
libglu1-mesa-dev freeglut3-dev mesa-common-dev, libglew-dev and flex on my device than making a very simple OPENGL-Program worked without any errors worked, but when I wanted to run it said:


Error compiling shader type 35633: '0:1(10): error: GLSL 3.30 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, and 3.00 ES

Now until now I was able to call it via the script:


#!/bin/bash
MESA_GL_VERSION_OVERRIDE=3.3COMPAT ./$1

but now it has a problem:
a shader is loaded and this fails somehow:

const char* LoadShader(const char* filename)
{
errno = 0;
#ifdef WIN32
    FILE* infile;
    fopen_s(&infile, filename, "rb");
#else
    FILE* infile = fopen(filename, "rb");
#endif // WIN32

    if (!infile) 
    {
        fprintf(stderr, "Could not open shader file %s
", filename);
	printf("Error %d 
", errno);
        exit(0);
    }

    fseek(infile, 0, SEEK_END);
    int len = ftell(infile);
    fseek(infile, 0, SEEK_SET);

    char* source = malloc(sizeof(char) * (len+1));

    fread(source, 1, len, infile);
    fclose(infile);

    source[len] = 0;

    return (const char*)(source);
}

I get the error:


Could not open shader file shaders/vertexshader.vs
Error 2 

I have confirmed that vertexshader.vs is in the shader folder and fully accessible (chmod 777).
Is there anything else I could do?
System Info:
OS: Ubuntu 18.04.2 LTS
Device: Travelmate 5760

This doesn’t really have anything to do with OpenGL.

You’re trying to load a file using a relative path (“shaders/vertexshader.vs”), and it’s failing to open the file with fopen() (ERRNO 2 is ENOENT by the way, which means the file or directory doesn’t exist).

The reason is most likely that the current working directory active when you call fopen() is not the one you think it is (the one one level up from the “vertexshader.vs” file). You just need to figure out why.

Right before your fopen(), try adding this:


   #include <unistd.h>  // Put this line at the top of the file outside of all functions, of course
   char dir[1024];
   getcwd( dir, sizeof( dir ) );
   printf( "CWD = %s
", dir );

That will tell you what directory is the current directory at that point.

Also, at the top of your bash script (just below the #!/bin/bash line), add a “pwd” command. That will tell you what the current working directory is as soon as your script is invoked.

When you are one directory level up from the shader file, instead of using your wrapper script, try running:


  env MESA_GL_VERSION_OVERRIDE=3.3COMPAT ./yourapp

Does that work?

In your shell, try cd’ing someplace (e.g. cd /usr/bin), now run “bash” with no options, and then run “pwd” and then “exit”. Did your pwd command reveal that you were in a different directory. If so, it is likely that you have a command which changes the current working directory in one of your bash startup profiles (check them for “cd” commands for example: ~/.profile, ~/.bashrc, /etc/profile, or /etc/bash.bashrc). Whenever you startup a new bash shell (which you’re doing with your bash script file), bash will run the commands in those startup scripts before it runs the commands in the script you’re invoking. Once you remove that (or those) “cd” commands from the bash startup profiles, then your wrapper script will likely work as you expect it to again.

Of course, another alternative which bypasses all of this is to, in your C++ code when you call fopen(), provide a full path from root to fopen() and not a relative path. Then it doesn’t make any difference what the current working directory is. Alternatively, build a full path to the file using some relative path in your code combined with a base path from root, specified by some command-line option, configuration file option, or environment variable.

[QUOTE=Dark Photon;398241]This doesn’t really have anything to do with OpenGL.

You’re trying to load a file using a relative path (“shaders/vertexshader.vs”), and it’s failing to open the file with fopen() (ERRNO 2 is ENOENT by the way, which means the file or directory doesn’t exist).

The reason is most likely that the current working directory active when you call fopen() is not the one you think it is (the one one level up from the “vertexshader.vs” file). You just need to figure out why.

Right before your fopen(), try adding this:


   #include <unistd.h>  // Put this line at the top of the file outside of all functions, of course
   char dir[1024];
   getcwd( dir, sizeof( dir ) );
   printf( "CWD = %s
", dir );

That will tell you what directory is the current directory at that point.

Also, at the top of your bash script (just below the #!/bin/bash line), add a “pwd” command. That will tell you what the current working directory is as soon as your script is invoked.

When you are one directory level up from the shader file, instead of using your wrapper script, try running:


  env MESA_GL_VERSION_OVERRIDE=3.3COMPAT ./yourapp

Does that work?

In your shell, try cd’ing someplace (e.g. cd /usr/bin), now run “bash” with no options, and then run “pwd” and then “exit”. Did your pwd command reveal that you were in a different directory. If so, it is likely that you have a command which changes the current working directory in one of your bash startup profiles (check them for “cd” commands for example: ~/.profile, ~/.bashrc, /etc/profile, or /etc/bash.bashrc). Whenever you startup a new bash shell (which you’re doing with your bash script file), bash will run the commands in those startup scripts before it runs the commands in the script you’re invoking. Once you remove that (or those) “cd” commands from the bash startup profiles, then your wrapper script will likely work as you expect it to again.

Of course, another alternative which bypasses all of this is to, in your C++ code when you call fopen(), provide a full path from root to fopen() and not a relative path. Then it doesn’t make any difference what the current working directory is. Alternatively, build a full path to the file using some relative path in your code combined with a base path from root, specified by some command-line option, configuration file option, or environment variable.[/QUOTE]

Yes moving the script to the same directory worked, also env from the same directory as the app worked. I will make an alias or try to go directly into the directory with in the script (split the input before the last / and than make a cd to the first half should work but how do I do this?).
Is there a possibility to write this Version Overwrite directly into the C-code if needed (for example via conditioned pre-compiler)? I would like this code in an extra file, as I will need for all my projects.

[QUOTE=rickpas;398248]I will make an alias or try to go directly into the directory with in the script
(split the input before the last / and than make a cd to the first half should work but how do I do this?).[/QUOTE]

You can do that by manually calling chdir() to change to the appropriate directory before you call fopen().

Alternatively, just build a full path to the shader file and then fopen() that. For example


  #include <stdio.h>
  ...
  static const char BASE_PATH[] = "/some/directory/on/my/system";
  char path[ 1024 ];
  snprintf( path, sizeof( path ), "%s/%s", BASE_PATH, "shaders/vertexshader.vs" );

  FILE* infile = fopen(path, "r");

(NOTE: You’re using Linux here, so you don’t have to worry about the buggy behavior of Microsoft’s snprintf() which didn’t null terminate on truncate for an insane number of years.)

Rather than hard-code BASE_PATH, a more general solution would be to pass this string in via a command-line parameter or read it from an environment variable.

Is there a possibility to write this Version Overwrite directly into the C-code if needed (for example via conditioned pre-compiler)?

Sure. You should be able to put that environment var in the environment before you initialize OpenGL (Mesa3D, in this case). See this link for instance. Adapted for your use case:


     #include <stdlib.h>
     ...
     static const char* EnvVar = "MESA_GL_VERSION_OVERRIDE=3.3COMPAT";

     putenv( (char *) EnvVar );

Just put this up at the top of your main() routine, before you initialize OpenGL. Just keep in mind that this is only going to do something useful on systems using OpenGL drivers based on Mesa3D.