Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: GLSL Shaders and CMake

  1. #1
    Junior Member Newbie
    Join Date
    Aug 2013
    Posts
    5

    Question GLSL Shaders and CMake

    Hello World,

    I'm currently trying to get OpenGL to work using c++, CMake and QT-creator, and I am now trying to create a shader program using external vertex and fragment shaders saved seperately from the main script. I have already managed to create a simple 2d triangle using glBegin() and glEnd(), but I didn't use any custom shader program. I have configured to add the shaders to the executable in the following line:

    add_executable(4d main.cpp Vertexshader.vs Fragmentshader.fs)

    Where Vertexshader.vs and Fragmentshader.fs have been saved in the source directory. I am puzzeled how I should now acces the information I stored in these files to compile them in runtime. I have found several scripts that somehow use CMake and GLSL shaders, but they are either a massive avelanche of code, or they don't seem to work in the first place. What I am looking for is the most simple piece of code implementing both CMake and GLSL shaders possible and/or available. Is there any basic tutorial/source code material available?

    Just for clarity, here is the entire CMakeLists.txt code:
    Code :
    cmake_minimum_required(VERSION 2.8)
    PROJECT(4D)
     
    find_package(GLUT REQUIRED)
    include_directories(${GLUT_INCLUDE_DIRS})
    link_directories(${GLUT_LIBRARY_DIRS})
    add_definitions(${GLUT_DEFINITIONS})
     
    find_package(OpenGL REQUIRED)
    include_directories(${OpenGL_INCLUDE_DIRS})
    link_directories(${OpenGL_LIBRARY_DIRS})
    add_definitions(${OpenGL_DEFINITIONS})
     
    add_executable(4d main.cpp Vertexshader.vs Fragmentshader.fs)
     
    target_link_libraries(4d ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} )

    And the main.cpp code:

    Code :
    #include <iostream>
     
    // ensure apple compatibility
    #ifdef __apple__
    #   include <GLUT/glut.h>
    #   include <OpenGL/OpenGL.h>
    #else
    #   include <GL/glew.h>
    #   include <GL/freeglut.h>
    #endif
    #
     
    using namespace std;
     
    void render(void) {
        glBegin(GL_TRIANGLES);
        glVertex2f(-0.5, -0.5);
        glVertex2f(0.5, -0.5);
        glVertex2f(0.0, 0.5);
        glEnd();
        glutSwapBuffers();
    }
     
    int main (int argc, char* argv[]) {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
        glutInitWindowSize(1280, 720);
        glutCreateWindow("Test");
     
        glutDisplayFunc(render);
     
        glutMainLoop();
    }

    Best Regards,
    Jan Heemstra

    Ps: English is not my native language. I apologise for any language errors.

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,128
    You can simply include in the source files where you need the GLSL source strings like this (assuming shader sources are in the same directory as the C++ source files that wants to access them):

    Code :
    #include "Vertexshader.vs"
    #include "Fragmentshader.fs"

    Also, what you with the add_executable function is add source files to the list compiled by g++. However, you'll see no effect with file endings like *.vs or
    *.fs because CMake simply ignores them. CMake will only add files with specific endings, like *.cpp or *.c

  3. #3
    Junior Member Newbie
    Join Date
    Aug 2013
    Posts
    5
    Quote Originally Posted by thokra View Post
    You can simply include in the source files where you need the GLSL source strings like this (assuming shader sources are in the same directory as the C++ source files that wants to access them):

    Code :
    #include "Vertexshader.vs"
    #include "Fragmentshader.fs"
    Also, what you with the add_executable function is add source files to the list compiled by g++. However, you'll see no effect with file endings like *.vs or
    *.fs because CMake simply ignores them. CMake will only add files with specific endings, like *.cpp or *.c
    If I understand what's happening correctly, c++ now treats the Vertexshader.vs as a DLL, which means I still have to write the shader code inside a c++ string. This is also not going to work (at least not efficiently) when I'm trying to acces other non-script data structures, like textures. Is there any way I can tell CMake to include the shaders into the executable without having the compiler trying to compile it? And, is there any way to access it on run-time, and to convert it into a string?

  4. #4
    Junior Member Newbie
    Join Date
    May 2013
    Location
    Germany
    Posts
    8
    Quote Originally Posted by 8baanknexer View Post
    If I understand what's happening correctly, c++ now treats the Vertexshader.vs as a DLL,
    The compiler will, as far as I know, "copy-and-paste" the code from the Shaderfiles into that specific file you used the include statement at that exaxt location. Then it will compile the whole File.
    Using a shader in opengl requires to load the shader source code at runtime, pass it to opengl and compile it at runtime.
    So you need the shader sourcecode as a string (a char array to be more precise) and pass it via glShaderSource to opengl.
    Then you need to compile the code using glCompileShader. To use the vertex and fragment shader you'll need to link them into a shader program using glAttachShader and glLinkProgram. Last but not least to make that program active you will need to use glUseProgram.

    I Hope that helped a little

    Best regards
    Lighttec

    EDIT: To access the information in the external files, you'll need to write a simple ascii/utf-8 reader.
    Last edited by Lighttec; 08-31-2013 at 10:20 AM.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    add_executable(4d main.cpp Vertexshader.vs Fragmentshader.fs)
    You shouldn't do this. GLSL is not something that is (generally speaking) compiled by an off-line compiler.

    The way GLSL works is that your C++ code, at runtime, will load those files and compile them into programs. This is not a process that CMake will be useful at handling. Think of shader loading the way you would texture loading or handling of any other file-based asset.

    CMake might be of use to you by generating C++ files that contain these shader files. But that would require some kind of build script to handle this. And that would mean a lot of CMake configuration stuff.

    The compiler will, as far as I know, "copy-and-paste" the code from the Shaderfiles into that specific file you used the include statement at that exaxt location. Then it will compile the whole File.
    Yes, that's what happens. I just don't see how that helps.

    GLSL is *not* C++. GLSL is not something that a C++ compiler can process. Now, a string literal that just so happens to contain GLSL is something that a C++ compiler can process. But that's just because it's a string literal.

    #including a text file does not turn it into a string literal. If you #include a text file, the compiler will do exactly what you said: copy the data from the shader into your C++ source code.

    So unless your GLSL shader files are already written C++ string literals (and if they are, you're probably the only person who does that), #including them is not going to work.

  6. #6
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    755
    GUI toolkits often have "resource compilers" that allow embedding of various data (often icons or string tables for localization) into executables. It may be possible to (ab-)use on of those to get the shader source into string literals.

  7. #7
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    491
    On Windows, you can store strings as resources in the executable then access them with LoadString().

    On Unix, you can use "ld -b binary ..." to convert an arbitrary file to an object file containing the data as an array.

    Or you can look for the "bin2c" utility which will convert arbitrary files to C source code containing the data as an array initialisation.

  8. #8
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,128
    Another way in C++11 is to wrap the shader code as raw string literal. As Alfonse already mentioned, you can have CMake do that for you.

  9. #9
    Junior Member Newbie
    Join Date
    Aug 2013
    Posts
    5
    Just for clarity, the end result I'd like to have is preferably to have the GLSL code somehow embedded into the executable to make for an executable that is not dependant on external recourses. Also, I'd like to be able to write the code into the text file without having to worry about the character array declaration (thus, directly writing in GLSL and afterwards having the c++ code convert it into a const char on runtime). Then my worries are on how to acces the code on running the program.

    Quote Originally Posted by GClements View Post
    On Windows, you can store strings as resources in the executable then access them with LoadString().

    On Unix, you can use "ld -b binary ..." to convert an arbitrary file to an object file containing the data as an array.

    Or you can look for the "bin2c" utility which will convert arbitrary files to C source code containing the data as an array initialisation.
    Is "ld -b binary ..." supposed to be make code? Or should this be passed onto the compiler? Where should it be written? I'm really confused.

    Quote Originally Posted by thokra View Post
    Another way in C++11 is to wrap the shader code as raw string literal. As Alfonse already mentioned, you can have CMake do that for you.
    Does that mean the text file is already converted into a string when the build environment is made? Because I really want to do that upon running the executable.

  10. #10
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    Is "ld -b binary ..." supposed to be make code?
    `ld` is a program. The above is a command line. Where you put it is up to you. It could go into a makefile, or it could go elsewhere.

    Does that mean the text file is already converted into a string when the build environment is made? Because I really want to do that upon running the executable.
    Upon running what executable? The one you're trying to build?

    CMake can be used to generate source code at one of two times. It could do it when CMake builds the build system. Or it could be done as part of the build system; that is, when you're building the executable. It can't be done *after* the executable you're trying to compile has been compiled.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •