OpenGL Context is not active


#1

I’m trying to do my first OpenGL Programm with JUCE. The openGLContext is not active, for this reason it exits when I come into the render() method. I don’t exactly how I have to activate the OpenGL context, my shaders are right, they are very easy. I’m working with core profile 3.3. The Code is the following:

class CursorGL : public  OpenGLAppComponent {
public:
    CursorGL(std::shared_ptr<coord>  _coords, glm::mat4& _projection, glm::mat4& _model) {              
        coords = _coords->shared_from_this();
        setSize (600, 300);
        setVisible(true);
        position.x = coords->x1;
        position.y = coords->y1;
        target.x = coords->x2;
        target.y = coords->y2;
        thickness = 75.f;
        projection = _projection;
        model = _model;
        coordTemp = coords->x1;        
        openGLContext.makeActive();
        openGLContext.setMultisamplingEnabled(true);
        if(!openGLContext.isActive())
            std::cout<<"Could not activate OpenGl Context:"<<openGLContext.isActive()<<std::endl;
    }
    ~CursorGL() {        
        shutdownOpenGL();
    }
    void initialise() override {        
        GLfloat colors[] = {0.5f, 0.5f, 0.5f, 0.5f};
        //openGLContext.setOpenGLVersionRequired(openGLContext.openGL3_2);
        createShader();        
        openGLContext.extensions.glUseProgram(shaderProgram);
        glViewport(0,0, 300, 600);
         openGLContext.extensions.glUniformMatrix4fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
        openGLContext.extensions.glUniformMatrix4fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
        openGLContext.extensions.glUniform1fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "position"), 1, glm::value_ptr(position));        openGLContext.extensions.glUniform1fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "target"), 1, glm::value_ptr(target));        

   openGLContext.extensions.glUniform1f(openGLContext.extensions.glGetUniformLocation(shaderProgram, "thickness"), thickness);        
        openGLContext.extensions.glGenBuffers(1, &VBO);
        openGLContext.extensions.glGenVertexArrays(1, &VAO);
        openGLContext.extensions.glBindVertexArray(VAO);
        openGLContext.extensions.glBindBuffer(GL_ARRAY_BUFFER, VBO);
        openGLContext.extensions.glBufferData(GL_ARRAY_BUFFER, sizeof(colors), &colors, GL_STATIC_DRAW);
        openGLContext.extensions.glEnableVertexAttribArray(0);
        openGLContext.extensions.glVertexAttribPointer(0,4, GL_FLOAT, GL_FALSE, 4* sizeof(GL_FLOAT), 0);
        openGLContext.extensions.glBindVertexArray(0);
        openGLContext.extensions.glDeleteBuffers(1, &VBO);
    }
    void shutdown() override {        
        openGLContext.extensions.glUseProgram(0);              
        openGLContext.extensions.glDeleteShader(fragmentShader);
        openGLContext.extensions.glDeleteShader(geomShader);
        openGLContext.extensions.glDeleteShader(vertexShader);
        openGLContext.extensions.glDeleteProgram(shaderProgram);
        openGLContext.extensions.glDeleteVertexArrays(1, &VAO);
        
    }
    void render() override {
        //openGLContext.makeActive();
        jassert (OpenGLHelpers::isContextActive());
        //OpenGLHelpers::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        OpenGLHelpers::clear (juce::Colours::white);
        glEnable (GL_BLEND);
        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        if(coords->isPlaying && coordTemp != coords->x1) {            
            openGLContext.extensions.glUseProgram(shaderProgram);
            coordTemp = coords->x1;
            position.x = coords->x1;
            position.y = coords->y1;
            target.x = coords->x2;
            target.y = coords->y2;
            openGLContext.extensions.glUniform1fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "position"), 1, glm::value_ptr(position));
            openGLContext.extensions.glUniform1fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "target"), 1, glm::value_ptr(target));
        }
        openGLContext.extensions.glBindVertexArray(VAO);
        glDrawArrays(GL_POINTS, 0, 1);
        openGLContext.extensions.glBindVertexArray(0);
    }
    
    void paint(Graphics& g) override {        
    }
    
    void resized() override {       
    }
    void createShader() {
         
        vertexShaderSource = "#version 330 core\n"
        "layout (location = 0) in vec4 color\n"
        "uniform vec2 position\n"
        "out VS_OUT {\n"
        "   vec2 pos;\n"
        "   vec4 color;\n"
        "} vs_out;\n"
        "void main() {\n"
        "   vs_out.pos = position;\n"
        "   vs_out.color = color;\n"
        "}\n";
        fragmentShaderSource = "#version 330 core\n"
        "in vec4 fColor;\n"
        "out vec4 outColor;\n"
        "void main() {\n"
        "     outColor = fColor;\n"
        "}\n";
        geomShaderSource = "#version 330 core\n"
        "uniform float thickness;\n"
        "uniform vec2 win_scale;\n"
        "in VS_OUT {\n"
        "     vec2 pos;\n"
        "     vec4 color;\n"
        "} gs_in[]\n"
        "uniform mat4 projection;\n"
        "uniform mat4 model;\n"
        "out vec4 fColor\n"
        "vec2 screen_space(vec4 vertex) {\n"
        "   return vec2(vertex.xy/vertex.w) * win_scale;\n"
        "}\n"
        "void main() {\n"
        "   fColor = gs_in[0].color;\n"
        "   vec2 p0 = gs_in[0].pos;\n"
        "   vec2 p1 = target;\n"
        "   vec2 v0 = normalize(p1-p0);\n"
        "   vec2 n0 = vec2(-v0.y, v0.x);\n"
        "   gl_Position = projection * model *  vec4(p0 - thickness * n0, 0.0, 1.0);\n"
        "   EmitVertex();\n"
        "   gl_Position = projection * model *  vec4(p0 + thickness * n0, 0.0, 1.0);\n"
        "   EmitVertex();\n"
        "   gl_Position = projection  * model * vec4(p1 - thickness * n0, 0.0, 1.0);\n"
        "   EmitVertex();\n"
        "   gl_Position = projection  * model * vec4(p1 + thickness * n0, 0.0, 1.0);\n"
        "   EmitVertex();\n"
        "   EndPrimitive();\n"
        "}\n";      
        vertexShader = openGLContext.extensions.glCreateShader(GL_VERTEX_SHADER);
        openGLContext.extensions.glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
        openGLContext.extensions.glCompileShader(vertexShader);
        if (!checkShaderCompileStatus(vertexShader)) {
            std::cout<< "Vertex shader did not compile"<<std::endl;
            //exit(EXIT_FAILURE);
        }
        fragmentShader = openGLContext.extensions.glCreateShader(GL_FRAGMENT_SHADER);
        openGLContext.extensions.glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
        openGLContext.extensions.glCompileShader(fragmentShader);
        if (!checkShaderCompileStatus(fragmentShader)) {
            std::cout<< "Fragment shader did not compile"<<std::endl;            
        }
        
        geomShader = openGLContext.extensions.glCreateShader(GL_GEOMETRY_SHADER);
        openGLContext.extensions.glShaderSource(geomShader, 1, &geomShaderSource, NULL);
        openGLContext.extensions.glCompileShader(geomShader);
        if (!checkShaderCompileStatus(geomShader)) {
            std::cout<< "Geometry shader did not compile"<<std::endl;
            //exit(EXIT_FAILURE);
        }
        shaderProgram = openGLContext.extensions.glCreateProgram();
        openGLContext.extensions.glAttachShader(shaderProgram, vertexShader);
        openGLContext.extensions.glAttachShader(shaderProgram, fragmentShader);
        openGLContext.extensions.glAttachShader(shaderProgram, geomShader);
        openGLContext.extensions.glLinkProgram(shaderProgram);
        if (!checkShaderProgramLinkStatus(shaderProgram)) {
            std::cout<< "Shader did not link"<<std::endl;
            //exit(EXIT_FAILURE);
        }
        openGLContext.extensions.glUseProgram(shaderProgram);       
    }
    bool checkShaderCompileStatus(GLuint shaderID) {
        GLint status;
        openGLContext.extensions.glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
        if(status == GL_FALSE) {
            GLint length;
            openGLContext.extensions.glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length);
            GLchar* log = new char[length + 1];
            openGLContext.extensions.glGetShaderInfoLog(shaderID, length, &length, &log[0]);
            std::cout<<"Error by shader compilation:"<<log;
            return false;
        }
        return true;
    }
    bool checkShaderProgramLinkStatus(GLuint programID){
        GLint status;
        openGLContext.extensions.glGetProgramiv(programID, GL_LINK_STATUS, &status);
        if(status == GL_FALSE) {
            GLint length;
            openGLContext.extensions.glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &length);
            GLchar* log = new char[length + 1];
            openGLContext.extensions.glGetProgramInfoLog(programID, length, &length, &log[0]);
            std::cout<<"Error by shader linking:"<<log;
            return false;
        }
        return true;
    }
    
private:
    const char* vertexShaderSource;
    const char* fragmentShaderSource;
    const char* geomShaderSource;    
    std::shared_ptr<coord> coords;
    juce::String statusText;
    glm::mat4 projection, model;
    glm::vec2 position, target;
    float coordTemp;
    GLfloat thickness;
    GLuint VBO, VAO;
    GLuint shaderProgram;
    GLuint vertexShader, fragmentShader, geomShader;
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CursorGL)
};

I could see Juce don’t have the extension

glUniform2fv

available, only glUniform1fv.
I’m instantiating and stoping the class inside another, in the following way:

void JuceDevice::startCursorGL() {
    cursorGL = std::make_unique<CursorGL>(coords,projection, model);    
    cursorGL->initialise();
    cursorGL->render();
}

void JuceDevice::stopCursorGL() {
    cursorGL->shutdown();
    cursorGL.reset();
}

The Programm exits when I call the method render(), at the assertion jassert (OpenGLHelpers::isContextActive()); , how should I activate the OpenGL Context?
Regards


#2

You must never call initialise, shutdown or render yourself. These methods will be called by JUCE on an active OpenGL context.

As you are using an OpenGLAppComponent, initialise, shutdown and render will be called automatically. You can also force a render call with OpenGLContext::triggerRepaint. If you want to continuously call repaint then you can call OpenGLContext:: setContinuousRepainting (true) and adjust the swap interval with OpenGLContext::setSwapInterval.


#3

Thanks for your answer. I added setContinuousRepainting(true) openGLContext.setSwapInterval(1) and to the Class Constructor:

CursorGL(std::shared_ptr<coord>  _coords, glm::mat4& _projection, glm::mat4& _model) {
        coords = _coords->shared_from_this();
        setSize (600, 300);
        setVisible(true);
        openGLContext.setContinuousRepainting(true);
        openGLContext.setSwapInterval(1);
        position.x = coords->x1;
        position.y = coords->y1;
        target.x = coords->x2;
        target.y = coords->y2;
        thickness = 75.f;
        projection = _projection;
        model = _model;
        coordTemp = coords->x1;
        openGLContext.setMultisamplingEnabled(true);
        if(!openGLContext.isActive())
            std::cout<<"OpenGl Contextes is not active:"<<openGLContext.isActive()<<std::endl;
    }

But the OpenGL context is still not active, initialize, render and shutdown are not called. I can see it over the if branch at the end of Constructor.
If I call OpenGLContext:: setContinuousRepainting (true) in Constructor or in another place, I become always an error.
These class, CursorGL is not the “MainContentComponent” class, CursorGL is instantiated (created) inside another class called “JuceDevice”. Again, this is not the MainContentComponent, JuceDevice is instantiated inside the MainContentComponent class, called “GuidoComponent”, this class is not an OpenGLAppComponent. I think this could be the problem, I’m painting the others elements with Juce:Graphics, I want to add some animations with OpenGL to it. There is another way to create an OpenGL context and activate it for my self, other should I Instantiate the class GLCursor inside the MainComponent class, or should this class (GLCursor) be inherited from the MainComponent class in order to activate the OpenGL context?


#4

The OpenGLContext will only ever be active within the initialise, shutdown or render calls. This means that if you call your CursorGL constructor outside one of these calls then the context will not be active.


#5

@fabian I don’t understand what are you meaning. The class CursorGL is inherited from OpenGLAppComponent, as you can see before: class CursorGL : public OpenGLAppComponent therefore initialize(), render() and shutdown are methods from the class CursorGL. Did you men I should call the CursorGL constructor inside their own methods ?:

void CursorGL::initialise() {
          CursorGL(...) //class constructor

That looks very strange. The compiler don’t allows this kind of declarations.
That would be a recursive call, if I do it in this way that could lead to an infinite recursion.
Regards


#6

You are expecting the context to be active in your CursorGL constructor but, as I said, the context is only active in the initialize, render and shutdown callbacks.


#7

@fabian thanks again for your reply. I made the class CursorGL a child from the class GuidoComponent: class CursorGL : public OpenGLAppComponent, GuidoComponent { ...more and I instantiated it inside GuidoComponent in the following way:

//Creation
void GuidoComponent::initializeCursor() {
    computeCoordinates(LineCoordinates, pn);
    manager = std::make_unique<PdManager>(coords, LineCoordinates);
    coordTemp = coords->x1;
    manager->startMetronome();
    glm::mat4 projection = gDevice.getProjectionMatrix();
    glm::mat4 model = gDevice.getModelMatrix();
    cursorGL = std::make_shared<CursorGL>(coords, projection, model);    
    this->addAndMakeVisible((juce::OpenGLAppComponent*)cursorGL.get(), -1);    
    startTimer(5);
    //repaint();
}
//destruction
bool GuidoComponent::deleteCursor() {
    if(manager) {
        stopTimer();
        manager->stopMetronome();        
        this->removeChildComponent((juce::OpenGLAppComponent*)cursorGL.get());        
        cursorGL.reset();        
        manager.reset();        
    }
    repaint();
    return true;
}

Now is the OpenGL context created and activated. There is still a problem, apparently Juce doesn’t support the #version 330 core because i become the following message from the method checkShaderCompileStatus(GLuint shaderID):

Error by shader compilation:ERROR: 0:1: '' :  version '330' is not supported 
ERROR: 0:1: '' : syntax error: #version ...more
Vertex shader did not compile

The same by the fragment shader and geometry shader, There is a way to use the core profile 3.3 or higher in Juce? Are geometry shaders supported?
Regards.


#8

OpenGL 3.2 is the newest supported by JUCE currently. And we don’t support geometry shaders.


#9

@fabian That’s a bit old (2009). Actually OpenGL 3.2 (version 150) supports Geometry Shaders. Are you planing to adding support for modern OpenGL (Geometry Shaders, Tessellation) or Vulkan Support in the near Future? Vulkan supports now OSX and iOS (from iOS 9) too. Vulkan’s performance is better as OpenGL. Geometry Shaders and Tessellation are very useful specially working in 3D.
Regards


#10

@fabian I changed the shaders in order to work with OpenGL 3.2. The modified code is placed under. First I want to do only a very easy thing, to draw a rectangle on the screen. The code compiles, but when I instantiate (create) the OpenGL class I become the following error: Main Thread Checker: UI API called on a background thread: ...more
***** GL_INVALID_OPERATION at juce_OpenGLContext.cpp : 242 JUCE Assertion failure in juce_opengl.cpp:216
or:
**** GL_INVALID_ENUM at juce_OpenGLContext.cpp : 242 JUCE Assertion failure in juce_opengl.cpp:216
I looked at the file jute_openGLContext.cpp at the line 242 and 216, but I don’t know exactly what that’s means.
Another Problem is that Juce initialize a 2.1 Context, I placed this line openGLContext.setOpenGLVersionRequired(juce::OpenGLContext::openGL3_2); but apparently doesn’t have any effect, I put after in the Code the following line: std::cout<<"OpenGl Context is active:"<<openGLContext.isActive()<<" Version:"<<glGetString(GL_VERSION)<<", Vendor:"<<glGetString(GL_VENDOR)<<", Renderer:"<<glGetString(GL_RENDERER) <<std::endl;and I become Version:2.1 , my graphic cards supports OpenGL 4.1, I have already made Programs working with OpenGL 4.1. How can I enforce the context creation, other why Juce doesn’t creates the right context?
The actual Code is the following:

CursorGL::CursorGL(std::shared_ptr<coord>  _coords, glm::mat4& _projection, glm::mat4& _model) {
    coords = _coords->shared_from_this();
    setSize (500, 600);    
    //setVisible(true);    
    projection = _projection;
    model = _model;
    coordTemp = coords->x1;
    openGLContext.setMultisamplingEnabled(true);    
}

CursorGL::~CursorGL() {
     shutdownOpenGL();
}

void CursorGL::initialise() {
    openGLContext.makeActive();
    openGLContext.setContinuousRepainting(true);
    openGLContext.setSwapInterval(1);    openGLContext.setOpenGLVersionRequired(juce::OpenGLContext::openGL3_2);
    
    if(!openGLContext.isActive())
        std::cout<<"OpenGl Context is not active:"<<openGLContext.isActive()<<std::endl;
    else {
        openGLContext.setOpenGLVersionRequired(juce::OpenGLContext::openGL3_2);
        std::cout<<"OpenGl Context is active:"<<openGLContext.isActive()<<" Version:"<<glGetString(GL_VERSION)<<", Vendor:"<<glGetString(GL_VENDOR)<<", Renderer:"<<glGetString(GL_RENDERER) <<std::endl;
    }
    GLfloat vertices[] = {
        // positions    //colors           //alpha
        340.0f, 340.0f, 0.15f, 0.75f, 0.55f, 0.5f,   // top right
        340.0f, 220.0f, 0.15f, 0.75f, 0.55f, 0.5f, // bottom right
        220.0f, 220.0f, 0.15f, 0.75f, 0.55f, 0.5f, // bottom left
        220.0f, 340.0f, 0.15f, 0.75f, 0.55f, 0.5f // top left
    };
    GLuint elements[] = {
        0, 1, 3,
        1, 2, 3
    };
    //openGLContext.setOpenGLVersionRequired(openGLContext.openGL3_2);
    createShader();
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_MULTISAMPLE);    
    openGLContext.extensions.glUseProgram(shaderProgram);
    glViewport(0,0, 500, 600);
    openGLContext.extensions.glUniformMatrix4fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
    openGLContext.extensions.glUniformMatrix4fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
    openGLContext.extensions.glUniform1fv(openGLContext.extensions.glGetUniformLocation(shaderProgram, "position"), 1, glm::value_ptr(position));     
    openGLContext.extensions.glGenBuffers(1, &VBO);
    openGLContext.extensions.glGenBuffers(1, &EBO);
    openGLContext.extensions.glGenVertexArrays(1, &VAO);
    openGLContext.extensions.glBindVertexArray(VAO);
    openGLContext.extensions.glBindBuffer(GL_ARRAY_BUFFER, VBO);
    openGLContext.extensions.glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
    openGLContext.extensions.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    openGLContext.extensions.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
    GLint posAttrib = openGLContext.extensions.glGetAttribLocation(shaderProgram, "aPos");
    openGLContext.extensions.glEnableVertexAttribArray(posAttrib);
    openGLContext.extensions.glVertexAttribPointer(posAttrib,2, GL_FLOAT, GL_FALSE, 6* sizeof(GL_FLOAT), (void*)0);
    GLint colAttrib = glGetAttribLocation(shaderProgram, "aColor");
    openGLContext.extensions.glEnableVertexAttribArray(colAttrib);
    openGLContext.extensions.glVertexAttribPointer(colAttrib,4, GL_FLOAT, GL_FALSE, 6* sizeof(GL_FLOAT), (void*)(2 * sizeof(float)));
    
    openGLContext.extensions.glBindBuffer(GL_ARRAY_BUFFER, 0);
    openGLContext.extensions.glBindVertexArray(0);
    
}

void CursorGL::render() {
    std::cout<<"CursorGl render"<<std::endl;
    //openGLContext.makeActive();
    jassert (OpenGLHelpers::isContextActive());
    //OpenGLHelpers::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    OpenGLHelpers::clear (juce::Colours::white);
    glEnable (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    if(coords->isPlaying && coordTemp != coords->x1) {       
        openGLContext.extensions.glUseProgram(shaderProgram);
        coordTemp = coords->x1;
        
    }
    openGLContext.extensions.glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);    
    //openGLContext.extensions.glBindVertexArray(0);
    
}

void CursorGL::shutdown() {
    openGLContext.extensions.glUseProgram(0);
    openGLContext.extensions.glDeleteShader(fragmentShader);
    openGLContext.extensions.glDeleteShader(geomShader);
    openGLContext.extensions.glDeleteShader(vertexShader);
    openGLContext.extensions.glDeleteProgram(shaderProgram);
    openGLContext.extensions.glDeleteVertexArrays(1, &VAO);
    openGLContext.extensions.glDeleteBuffers(1, &VBO);
    openGLContext.extensions.glDeleteBuffers(1, &EBO);
}

void CursorGL::createShader() {   
    vertexShaderSource = "attribute vec2 aPos;\n"
    "attribute vec4 aColor;\n"
    "uniform mat4 projection;\n"
    "uniform mat4 model;\n"
    "varying vec4 ourColor;\n"
    "void main() {\n"
    "   gl_Position =  projection *  model * vec4(aPos, 0.0, 1.0);\n"
    "   ourColor = aColor;\n"
    "}\n";
    fragmentShaderSource = "varying vec4 ourColor;\n"
    "//varying vec4 FragColor;\n"
    "void main() {\n"
    "     gl_FragColor = ourColor;\n"
    "}\n";    
    openGLContext.setOpenGLVersionRequired(juce::OpenGLContext::openGL3_2);
    vertexShader = openGLContext.extensions.glCreateShader(GL_VERTEX_SHADER);
    openGLContext.extensions.glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    openGLContext.extensions.glCompileShader(vertexShader);
    if (!checkShaderCompileStatus(vertexShader)) {
        std::cout<< "Vertex shader did not compile"<<std::endl;
        //exit(EXIT_FAILURE);
    }
    fragmentShader = openGLContext.extensions.glCreateShader(GL_FRAGMENT_SHADER);
    openGLContext.extensions.glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    openGLContext.extensions.glCompileShader(fragmentShader);
    if (!checkShaderCompileStatus(fragmentShader)) {
        std::cout<< "Fragment shader did not compile"<<std::endl;
        //exit(EXIT_FAILURE);
    }
    shaderProgram = openGLContext.extensions.glCreateProgram();
    openGLContext.extensions.glAttachShader(shaderProgram, vertexShader);
    openGLContext.extensions.glAttachShader(shaderProgram, fragmentShader);
    //openGLContext.extensions.glAttachShader(shaderProgram, geomShader);
    //openGLContext.extensions.glBindFragDataLocation(shaderProgram, 0, "outColor");
    openGLContext.extensions.glLinkProgram(shaderProgram);
    if (!checkShaderProgramLinkStatus(shaderProgram)) {
        std::cout<< "Shader did not link"<<std::endl;
        //exit(EXIT_FAILURE);
    }
    openGLContext.extensions.glUseProgram(shaderProgram);
    
    std::cout<<"CursorGL, createShader isContextActive:"<<openGLContext.isActive()<<", GLSL Version:"<<glGetString ( GL_SHADING_LANGUAGE_VERSION )<<std::endl;
}

bool CursorGL::checkShaderCompileStatus(GLuint shaderID) {
    GLint status;
    openGLContext.extensions.glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
    if(status == GL_FALSE) {
        GLint length;
        openGLContext.extensions.glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length);
        GLchar* log = new char[length + 1];
        openGLContext.extensions.glGetShaderInfoLog(shaderID, length, &length, &log[0]);
        std::cout<<"Error by shader compilation:"<<log;
        return false;
    }
    return true;
}

bool CursorGL::checkShaderProgramLinkStatus(GLuint programID){
    GLint status;
    openGLContext.extensions.glGetProgramiv(programID, GL_LINK_STATUS, &status);
    if(status == GL_FALSE) {
        GLint length;
        openGLContext.extensions.glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &length);
        GLchar* log = new char[length + 1];
        openGLContext.extensions.glGetProgramInfoLog(programID, length, &length, &log[0]);
        std::cout<<"Error by shader linking:"<<log;
        return false;
    }
    return true;
}

#11

Again, as I’ve stated above, you can only use opengl calls on the open gl thread. This means you can only call them on the following OpenGLAppComponent callbacks:

initialise, shutdown and render.

Who is invoking your CursorGL::initialize?


#12

@fabian CursorGL::initialize is not invoked at all. I thought I don’t have to invoke it. I declared the class inside another called GuidoComponent in the following way:

void GuidoComponent::initializeCursor() {
    //...some code ...
    glm::mat4 projection = gDevice.getProjectionMatrix();
    glm::mat4 model = gDevice.getModelMatrix();
    cursorGL = std::make_shared<CursorGL>(coords, projection, model);    
    this->addAndMakeVisible(cursorGL.get(), -1);
    //more code ...
    startTimer(5);
    repaint();
}

The class GuidoComponent is a child of Component and Timer.
That’s no the actual problem. I placed a glGetError() call inside the method initialize() and I become error messages at the following places:

openGLContext.extensions.glGenVertexArrays(1, &VAO);
    if((err = glGetError()) != GL_NO_ERROR) {
        std::cerr << "OpenGL error after genVAO: " << err << std::endl;
    }
    openGLContext.extensions.glBindVertexArray(VAO);
    if((err = glGetError()) != GL_NO_ERROR) {
        std::cerr << "OpenGL error after bindVAO: " << err << std::endl;
    }

The error 1282 GL_INVALID_OPERATION appears there, because glGenVertexArrays and glBindVertexArray are available since OpenGL 3, and Juce is creating an OpenGL 2.1 context. Could you please tell me how I can create or enforce at least a OpenGL 3 context? Or why is not possible to do that in Juce? As I say, I have already used OpenGL 3.3, 4.0 and 4.1 on my Computer. OpenGL 2.1 is really very old.
The call openGLContext.setOpenGLVersionRequired(juce::OpenGLContext::openGL3_2); apparently doesn’t have any effect. Where should be placed it, inside render()?