Strange behaviour when I'm drawing my reflection texture

Hi! For refraction effect I draw the scene 6 times into a cubemap attached to an FBO. (X positive, X negative, Y positive, Y negative, Z positive and Z negative), and then I draw the cubemap onto a 2D texture attached to another FBO.

The problem is that at some execution, the refraction texture is flickering, and the pixels are not good so it looks strange; in this video we can see at the first execution the refraction texture is displaying well but not at the next executions.

https://www.youtube.com/watch?v=x2Fw6Q7so7k&feature=youtu.be

The source code can be found here you just need to install cwc to build and run it.

It seems it draws on the refraction texture before the cubemap is drawn so it takes a random colour of the cubemap.

I called glMemoryBarrier and glFinish but it doesn’t solve the problem.

I tried to add this after drawing the linked list :

glCheck(glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT));

But it doesn’t work, when I draw the cubemap faces on the screen they are drawing well, but when I want to use my cubemap into a shader, there is the synchronisation problem.

I’ve run the program with RenderDoc and there is a fatal error, when allocating memory.

I’ve 6 GB of VRAM so it shoudn’t be a problem.

Ok I reduced the depth of the linked list buffer from 20 to 10 and now the allocation memory problem disappeared, but I can’t capture frames to see what’s wrong when I want to capture a frame the application close.

Ok I let this down I think it’s a driver bug because it’s really strange that sometimes the refraction texture is displayed well, sommetimes not and even with a glMemoryBarrier invocation, the shader doesn’t pick the right cube map colour it’s like the cubemap has not finished to be drawn with the per pixel linked list, when it enter’s to the next shader. I don’t know how to report bugs here…

The bug is that the driver doesn’t bind my cubemap texture to the shader :

I think the problem is that opengl returns me a GL_OUT_OF_MEMORY error, so the colour in the framebuffer is undetermined.
I tried to put a glFinish or a glFlush but it doesn’t solve the problem.
Isn’t there a way to increase command buffer size ?

it’s written on wikipedia : The simplest to understand is glFinish. It will not return, stopping the current CPU thread, until all rendering commands that have been sent have completed .

But it doesn’t seems to work.

I’ve found the problem for the GL_OUT_OF_MEMORY error but it doesn’t solve the initial bug with the refraction texture which doesn’t display well at each execution.

There is something strange, in this shader :

R"(#version 460
                                                                in vec4 frontColor;
                                                                in vec3 normal;
                                                                in vec3 pos;
                                                                uniform vec3 cameraPos;
                                                                uniform samplerCube sceneBox;
                                                                uniform sampler2D depthBuffer;
                                                                uniform vec3 resolution;
                                                                layout (location = 0) out vec4 fColor;
                                                                void main () {
                                                                    vec2 position = (gl_FragCoord.xy / resolution.xy);
                                                                    vec4 depth = texture2D(depthBuffer, position);
                                                                    float ratio = 1.00 / 1.33;
                                                                    vec3 i = normalize(pos - cameraPos);
                                                                    vec3 r = refract (i, normalize(normal), ratio);
                                                                    vec3 n = normalize(normal);
                                                                    r = normalize(r);
                                                                    if (depth.z > 0) {
                                                                        fColor = vec4(abs(r.r), abs(r.g), abs(r.b), 1);/*texture(sceneBox, r) * (1 - depth.a);*/
                                                                    } else {
                                                                        fColor = vec4(abs(r.r), abs(r.g), abs(r.b), 1);/*texture(sceneBox, r);*/
                                                                    }
                                                                }
                                                              )";

The vectors i and n seems to be good but the vector r is always null. (black texture)

Ok it’s a problem in the shader I coded the reflect function by myself, and sometimes the r vector is null, sometimes not :

R"(#version 460
                                                                in vec4 frontColor;
                                                                in vec3 normal;
                                                                in vec3 pos;
                                                                uniform vec3 cameraPos;
                                                                uniform samplerCube sceneBox;
                                                                uniform sampler2D depthBuffer;
                                                                uniform vec3 resolution;
                                                                layout (location = 0) out vec4 fColor;
                                                                vec3 refl(vec3 i, vec3 n) {
                                                                    return i - 2.0 * dot (n, i) * n;
                                                                }
                                                                vec3 refr(vec3 i, vec3 n, float eta) {
                                                                   float k = 1.0 - eta * eta * (1.0 - dot(n, i) * dot(n, i));
                                                                   if (k < 0.0) {
                                                                       return vec3(0, 0, 0);
                                                                   } else {
                                                                       return eta * i - (eta * dot(n, i) + sqrt(k)) * n;
                                                                   }
                                                                }
                                                                void main () {
                                                                    vec2 position = (gl_FragCoord.xy / resolution.xy);
                                                                    vec4 depth = texture2D(depthBuffer, position);
                                                                    float ratio = 1.00 / 1.33;
                                                                    vec3 i = (pos - cameraPos);
                                                                    vec3 r = refl (i, normalize(normal));
                                                                    vec3 n = normalize(normal);
                                                                    r = normalize(r);
                                                                    if (depth.z > 0) {
                                                                        fColor = vec4(abs(r.r), abs(r.g), abs(r.b), 1);/*texture(sceneBox, r) * (1 - depth.a);*/
                                                                    } else {
                                                                        fColor = vec4(abs(r.r), abs(r.g), abs(r.b), 1);/*texture(sceneBox, r);*/
                                                                    }
                                                                }
                                                              )";

This is not normal that the values of the r vector are not the same at each frame.
Here is a video which show the values of the r vector varying by themselve :
nvidia driver bug

Here is a more simple source code with reproduce the bug :

#include "application.h"
#include <SFML/OpenGL.hpp>
#include <SFML/Window/WindowStyle.hpp>
#include <stdio.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stddef.h>
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace odfaeg::core;
using namespace odfaeg::math;
using namespace odfaeg::physic;
using namespace odfaeg::graphic;
using namespace odfaeg::window;
using namespace odfaeg::audio;
using namespace sorrok;
using namespace std;
// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods
enum Camera_Movement {
    FORWARD,
    BACKWARD,
    LEFT,
    RIGHT,
    UP,
    DOWN
};

// Default camera values
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;


// An abstract camera class that processes input and calculates the corresponding Euler Angles, Vectors and Matrices for use in OpenGL
class Camera
{
public:
    // camera Attributes
    glm::vec3 Position;
    glm::vec3 Front;
    glm::vec3 Up;
    glm::vec3 Right;
    glm::vec3 WorldUp;
    // euler Angles
    float Yaw;
    float Pitch;
    // camera options
    float MovementSpeed;
    float MouseSensitivity;
    float Zoom;

    // constructor with vectors
    Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = position;
        WorldUp = up;
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }
    // constructor with scalar values
    Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = glm::vec3(posX, posY, posZ);
        WorldUp = glm::vec3(upX, upY, upZ);
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }

    // returns the view matrix calculated using Euler Angles and the LookAt Matrix
    glm::mat4 GetViewMatrix()
    {
        return glm::lookAt(Position, Position + Front, Up);
    }
    glm::mat4 lookAt (Camera_Movement direction) {
        if (direction == FORWARD) {
            return glm::lookAt(Position, Position + Front, Up);
        }
        if (direction == BACKWARD) {
            return glm::lookAt(Position, Position - Front, Up);
        }
        if (direction == LEFT) {
            return glm::lookAt(Position, Position - Right, Up);
        }
        if (direction == RIGHT) {
            return glm::lookAt(Position, Position + Right, Up);
        }
        if (direction == UP) {
            return glm::lookAt(Position, Position + Up, Up);
        }
        if (direction == DOWN) {
            return glm::lookAt(Position, Position - Up, Up);
        }
    }
    // processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime)
    {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
    }

    // processes input received from a mouse input system. Expects the offset value in both the x and y direction.
    void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true)
    {
        xoffset *= MouseSensitivity;
        yoffset *= MouseSensitivity;

        Yaw   += xoffset;
        Pitch += yoffset;

        // make sure that when pitch is out of bounds, screen doesn't get flipped
        if (constrainPitch)
        {
            if (Pitch > 89.0f)
                Pitch = 89.0f;
            if (Pitch < -89.0f)
                Pitch = -89.0f;
        }

        // update Front, Right and Up Vectors using the updated Euler angles
        updateCameraVectors();
    }

    // processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
    void ProcessMouseScroll(float yoffset)
    {
        Zoom -= (float)yoffset;
        if (Zoom < 1.0f)
            Zoom = 1.0f;
        if (Zoom > 45.0f)
            Zoom = 45.0f;
    }

private:
    // calculates the front vector from the Camera's (updated) Euler Angles
    void updateCameraVectors()
    {
        // calculate the new Front vector
        glm::vec3 front;
        front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
        front.y = sin(glm::radians(Pitch));
        front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
        Front = glm::normalize(front);
        // also re-calculate the Right and Up vector
        Right = glm::normalize(glm::cross(Front, WorldUp));  // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
        Up    = glm::normalize(glm::cross(Right, Front));
    }
};
unsigned int loadCubemap(vector<std::string> faces);
Matrix4f glmToODFAEGMatrix(glm::mat4 mat);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
Camera camera2;
float lastX = (float)SCR_WIDTH / 2.0;
float lastY = (float)SCR_HEIGHT / 2.0;
bool firstMouse = true;

// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
float speed = 10.f;
float sensivity = 0.1f;
float oldX = (float)SCR_WIDTH / 2.0;
float oldY = (float)SCR_HEIGHT / 2.0;

int main(int argc, char* argv[])
{
    /*EXPORT_CLASS_GUID(BoundingVolumeBoundingBox, BoundingVolume, BoundingBox)
    EXPORT_CLASS_GUID(EntityTile, Entity, Tile)
    EXPORT_CLASS_GUID(EntityTile, Entity, BigTile)
    EXPORT_CLASS_GUID(EntityWall, Entity, g2d::Wall)
    EXPORT_CLASS_GUID(EntityDecor, Entity, g2d::Decor)
    EXPORT_CLASS_GUID(EntityAnimation, Entity, Anim)
    EXPORT_CLASS_GUID(EntityHero, Entity, Hero)
    EXPORT_CLASS_GUID(EntityMesh, Entity, Mesh)
    MyAppli app(sf::VideoMode(800, 600), "Test odfaeg");
    return app.exec();*/
// create the window
    sf::Window window(sf::VideoMode(800, 600), "OpenGL", sf::Style::Default, sf::ContextSettings(24, 0, 4, 4, 6));
    glewInit();
    window.setVerticalSyncEnabled(true);

    // activate the window
    window.setActive(true);
    // load resources, initialize the OpenGL states, ...
    glEnable(GL_DEPTH_TEST);
    // build and compile shaders
    // -------------------------
    const std::string refractCubeVS = R"(#version 460
                                         layout (location = 0) in vec3 aPos;
                                         layout (location = 1) in vec2 aTexCoords;
                                         uniform mat4 model;
                                         uniform mat4 view;
                                         uniform mat4 projection;
                                         out vec2 texCoords;
                                         void main() {
                                             gl_Position = projection * view * model * vec4(aPos, 1.0);
                                             texCoords = aTexCoords;
                                         }
                                         )";
    const std::string refractCubeFS = R"(#version 460
                                         uniform sampler2D texture;
                                         in vec2 texCoords;
                                         out vec4 FragColor;
                                         void main() {
                                            FragColor = texture2D (texture, texCoords);
                                         })";
    const std::string cubeMapsVS = R"(#version 460
                                    layout (location = 0) in vec3 aPos;
                                    layout (location = 1) in vec3 aNormal;
                                    out vec3 Normal;
                                    out vec3 Position;
                                    uniform mat4 model;
                                    uniform mat4 view;
                                    uniform mat4 projection;
                                    void main()
                                    {
                                        Normal = mat3(transpose(inverse(model))) * aNormal;
                                        Position = vec3(model * vec4(aPos, 1.0));
                                        gl_Position = projection * view * model * vec4(aPos, 1.0);
                                    }
                                )";
    const std::string cubeMapsFS = R"(#version 460
                                        out vec4 FragColor;
                                        in vec3 Normal;
                                        in vec3 Position;
                                        uniform vec3 cameraPos;
                                        uniform samplerCube skybox;
                                        void main()
                                        {
                                            vec3 I = normalize(Position - cameraPos);
                                            vec3 R = reflect(I, normalize(Normal));
                                            R = normalize(R);
                                            FragColor = vec4(abs(R.r), abs(R.g), abs(R.b), 1); /*vec4(texture(skybox, R).rgb, 1.0);*/
                                        }
                                   )";
    const std::string skyboxVS = R"(#version 460
                                    layout (location = 0) in vec3 aPos;
                                    out vec3 TexCoords;
                                    uniform mat4 projection;
                                    uniform mat4 view;
                                    void main()
                                    {
                                        TexCoords = aPos;
                                        vec4 pos = projection * view * vec4(aPos, 1.0);
                                        gl_Position = pos.xyww;
                                    }
                                )";
    const std::string skyboxFS = R"(#version 460
                                    out vec4 FragColor;
                                    in vec3 TexCoords;
                                    uniform samplerCube skybox;
                                    void main()
                                    {
                                        FragColor = texture(skybox, TexCoords);
                                    }
                                    )";
    odfaeg::graphic::Shader shader, skyboxShader, refractCubeShader;
    shader.loadFromMemory(cubeMapsVS, cubeMapsFS);
    skyboxShader.loadFromMemory(skyboxVS, skyboxFS);
    refractCubeShader.loadFromMemory(refractCubeVS, refractCubeFS);
    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float cubeVertices[] = {
        // positions          // normals
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
         0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,

        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

         0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
         0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
         0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
         0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
         0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
         0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
         0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
         0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
         0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
    };
    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float skyboxVertices[] = {
        // positions
        -1.0f,  1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,
         1.0f, -1.0f, -1.0f,
         1.0f, -1.0f, -1.0f,
         1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,

        -1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,

         1.0f, -1.0f, -1.0f,
         1.0f, -1.0f,  1.0f,
         1.0f,  1.0f,  1.0f,
         1.0f,  1.0f,  1.0f,
         1.0f,  1.0f, -1.0f,
         1.0f, -1.0f, -1.0f,

        -1.0f, -1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
         1.0f,  1.0f,  1.0f,
         1.0f,  1.0f,  1.0f,
         1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,

        -1.0f,  1.0f, -1.0f,
         1.0f,  1.0f, -1.0f,
         1.0f,  1.0f,  1.0f,
         1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f, -1.0f,

        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
         1.0f, -1.0f, -1.0f,
         1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
         1.0f, -1.0f,  1.0f
    };
    float fullScreenQuadVertices2[] = {
        // positions        //TexCoords
        -1.0f,  1.0f, 0.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
         1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
         1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
         1.0f,  1.0f, 0.0f, 1.0f, 1.0f,
        -1.0f,  1.0f, 0.0f, 0.0f, 1.0f,
    };
    // cube VAO
    unsigned int cubeVAO, cubeVBO;
    glGenVertexArrays(1, &cubeVAO);
    glGenBuffers(1, &cubeVBO);
    glBindVertexArray(cubeVAO);
    glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    // skybox VAO
    unsigned int skyboxVAO, skyboxVBO;
    glGenVertexArrays(1, &skyboxVAO);
    glGenBuffers(1, &skyboxVBO);
    glBindVertexArray(skyboxVAO);
    glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

    // load textures
    // -------------
    vector<std::string> faces
    {
        "tilesets/skybox/right.jpg",
        "tilesets/skybox/left.jpg",
        "tilesets/skybox/top.jpg",
        "tilesets/skybox/bottom.jpg",
        "tilesets/skybox/front.jpg",
        "tilesets/skybox/back.jpg"
    };
    std::vector<sf::Image> images;
    for (unsigned int i = 0; i < 6; i++) {
        sf::Image image;
        image.loadFromFile(faces[i]);
        images.push_back(image);
    }
    int width = images[0].getSize().x;
    int height = images[0].getSize().y;
    odfaeg::graphic::Texture cubeMapTex, cubeMapFBOTex, refractTex;
    cubeMapTex.createCubeMap(width, height, images);
    cubeMapFBOTex.createCubeMap(SCR_WIDTH, SCR_WIDTH);
    refractTex.create(SCR_WIDTH, SCR_HEIGHT);
    glEnable(GL_TEXTURE_CUBE_MAP);
    sf::Context context(sf::ContextSettings(0, 0, 4, 4, 6), SCR_WIDTH, SCR_WIDTH);
    context.setActive(true);
    unsigned int skyboxVAOFBO;
    glGenVertexArrays(1, &skyboxVAOFBO);
    glBindVertexArray(skyboxVAOFBO);
    glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);


    GLuint frameBufferID;
    glGenFramebuffers(1, &frameBufferID);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
    glDrawBuffer(GL_COLOR_ATTACHMENT0);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeMapFBOTex.getNativeHandle(), 0);
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        std::cerr << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
        return false;
    }
    sf::Context context2(sf::ContextSettings(0, 0, 4, 4, 6), SCR_WIDTH, SCR_WIDTH);
    context2.setActive(true);
    unsigned int fsQuadVAOFBO, fsQuadVBOFBO;
    glGenVertexArrays(1, &fsQuadVAOFBO);
    glBindVertexArray(fsQuadVAOFBO);
    glGenBuffers(1, &fsQuadVBOFBO);
    glBindBuffer(GL_ARRAY_BUFFER, fsQuadVBOFBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(fullScreenQuadVertices2), &fullScreenQuadVertices2, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    GLuint frameBufferID2;
    glGenFramebuffers(1, &frameBufferID2);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID2);
    glDrawBuffer(GL_COLOR_ATTACHMENT0);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, refractTex.getNativeHandle(), 0);
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        std::cerr << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
        return false;
    }
   // shader configuration
    // --------------------
    shader.setParameter("skybox", cubeMapFBOTex);
    skyboxShader.setParameter("skybox", cubeMapTex);
    refractCubeShader.setParameter("texture", refractTex);
    int oldX = sf::Mouse::getPosition(window).x;
    int oldY = sf::Mouse::getPosition(window).y;
    sf::Clock time;
    // run the main loop
    bool running = true;
    glEnable(GL_TEXTURE_CUBE_MAP);
    while (running)
    {
         // per-frame time logic
        // --------------------
        // per-frame time logic
        // --------------------
        float currentFrame = time.getElapsedTime().asSeconds();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
        // handle events
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                // end the program
                running = false;
            }
            else if (event.type == sf::Event::Resized)
            {
                // adjust the viewport when the window is resized
                glViewport(0, 0, event.size.width, event.size.height);
            }
            else if (event.type == sf::Event::MouseMoved) {
                if (firstMouse)
                {
                    lastX = event.mouseMove.x;
                    lastY = event.mouseMove.y;
                    firstMouse = false;
                }

                float xoffset = event.mouseMove.x - lastX;
                float yoffset = lastY - event.mouseMove.y; // reversed since y-coordinates go from bottom to top

                lastX = event.mouseMove.x;
                lastY = event.mouseMove.y;

                camera.ProcessMouseMovement(xoffset, yoffset);
            } else if (event.type == sf::Event::MouseWheelScrolled) {
                camera.ProcessMouseScroll(event.mouseWheelScroll.delta);
            }
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
            camera.ProcessKeyboard(FORWARD, deltaTime);
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
            camera.ProcessKeyboard(BACKWARD, deltaTime);
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
            camera.ProcessKeyboard(RIGHT, deltaTime);
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
            camera.ProcessKeyboard(LEFT, deltaTime);
        }
        // clear the buffers
        // render
        // ------
        window.setActive(true);
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        context2.setActive(true);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        context.setActive(true);
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        for (unsigned int i = 0; i < 6; i++) {
            glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubeMapFBOTex.getNativeHandle(), 0);
            glViewport(0, 0, SCR_WIDTH, SCR_WIDTH);
            glm::mat4 view;
            if (i == 0) {
                view = camera2.lookAt(FORWARD);
            }
            if (i == 1) {
                view = camera2.lookAt(BACKWARD);
            }
            if (i == 2) {
                view = camera2.lookAt(UP);
            }
            if (i == 3) {
                view = camera2.lookAt(DOWN);
            }
            if (i == 4) {
                view = camera2.lookAt(RIGHT);
            }
            if (i == 5) {
                view = camera2.lookAt(LEFT);
            }
            glm::mat4 projection = glm::perspective(glm::radians(camera2.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
            odfaeg::graphic::Shader::bind(&skyboxShader);
            Matrix4f viewMatrix = glmToODFAEGMatrix(view);
            Matrix4f projectionMatrix = glmToODFAEGMatrix(projection);
            skyboxShader.setParameter("view", viewMatrix);
            skyboxShader.setParameter("projection", projectionMatrix);
            // skybox cube
            glBindVertexArray(skyboxVAOFBO);
            glActiveTexture(GL_TEXTURE0);
            odfaeg::graphic::Texture::bind(&cubeMapTex, odfaeg::graphic::Texture::Normalized);
            glDrawArrays(GL_TRIANGLES, 0, 36);
            glBindVertexArray(0);
        }
        glMemoryBarrier(GL_ALL_BARRIER_BITS);
        glFlush();
        //window.setActive(true);
        context2.setActive(true);
        glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
        // draw...
        odfaeg::graphic::Shader::bind(&shader);
        glm::mat4 model = glm::mat4(1.0f);
        glm::mat4 view = camera.GetViewMatrix();
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        Matrix4f modelMatrix = glmToODFAEGMatrix(model);
        Matrix4f viewMatrix = glmToODFAEGMatrix(view);
        Matrix4f projectionMatrix = glmToODFAEGMatrix(projection);
        shader.setParameter("model", modelMatrix);
        shader.setParameter("view", viewMatrix);
        shader.setParameter("projection", projectionMatrix);
        shader.setParameter("cameraPos", camera.Position.x,camera.Position.y,camera.Position.z);
        // cubes
        glBindVertexArray(cubeVAO);
        glActiveTexture(GL_TEXTURE0);
        odfaeg::graphic::Texture::bind(&cubeMapFBOTex, odfaeg::graphic::Texture::Normalized);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glBindVertexArray(0);
        window.setActive(true);
        //Draw skybox.
        glDepthFunc(GL_LEQUAL);  // change depth function so depth test passes when values are equal to depth buffer's content
        odfaeg::graphic::Shader::bind(&skyboxShader);
        view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix
        projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        viewMatrix = glmToODFAEGMatrix(view);
        skyboxShader.setParameter("view", viewMatrix);
        skyboxShader.setParameter("projection", projectionMatrix);
        // skybox cube
        glBindVertexArray(skyboxVAO);
        glActiveTexture(GL_TEXTURE0);
        odfaeg::graphic::Texture::bind(&cubeMapTex, odfaeg::graphic::Texture::Normalized);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glBindVertexArray(0);
        // refract cube.
        glDepthFunc(GL_LESS);
        model = glm::mat4(1.0f);
        view = camera2.GetViewMatrix();
        projection = glm::ortho(-1, 1, -1, 1);
        modelMatrix = glmToODFAEGMatrix(model);
        viewMatrix = glmToODFAEGMatrix(view);
        projectionMatrix = glmToODFAEGMatrix(projection);
        refractCubeShader.setParameter("model", modelMatrix);
        refractCubeShader.setParameter("view", viewMatrix);
        refractCubeShader.setParameter("projection", projectionMatrix);
        odfaeg::graphic::Shader::bind(&refractCubeShader);
        glBindVertexArray(fsQuadVAOFBO);
        glActiveTexture(GL_TEXTURE0);
        odfaeg::graphic::Texture::bind(&refractTex, odfaeg::graphic::Texture::Normalized);
        glDrawArrays(GL_TRIANGLES, 0, 6);
        glBindVertexArray(0);

        window.display();
        oldX = sf::Mouse::getPosition(window).x;
        oldY = sf::Mouse::getPosition(window).y;
    }
    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &cubeVAO);
    glDeleteVertexArrays(1, &skyboxVAO);
    glDeleteVertexArrays(1, &skyboxVAOFBO);
    glDeleteBuffers(1, &cubeVBO);
    glDeleteBuffers(1, &skyboxVAO);
    // release resources...

    return 0;
}
Matrix4f glmToODFAEGMatrix(glm::mat4 mat) {
    Matrix4f odfaegMatrix(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
                         mat[1][0], mat[1][1], mat[1][2], mat[1][3],
                         mat[2][0], mat[2][1], mat[2][2], mat[2][3],
                         mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
    return odfaegMatrix;
}

It’s when I want to draw the cube with the refraction in a FBO that the problem occurs.

It seems when I use a single context for all my FBO and not one context per FBO it works better so the bug is when we use several opengl contexts. SFML have a shared context so all my shaders and textures should be shared between every contexts.

Where can I report this bug please I paid for this new PC with a new nvidia graphic card, I would like to have a driver which works.

Ok it’s not the refraction function wich bug, but the normal which is sometimes null when I do instanced rendering (Whe n I doesn’t do instanced rendering it works)

So I put the four first vertices on a VBO and the four first normals on another VBO.

And then I defines pointers :

void RenderTarget::drawInstanced(VertexBuffer& vertexBuffer, enum sf::PrimitiveType type, unsigned int start, unsigned int nb, unsigned int nbInstances, RenderStates states, unsigned int vboMatrix1, unsigned int vboMatrix2) {
            if (vertexBuffer.getVertexCount() == 0) {
                return;
            }

            if (activate(true))
            {
                if (!m_cache.glStatesSet)
                    resetGLStates();
                // Apply the view
                if (m_cache.viewChanged)
                    applyCurrentView();

                if (states.blendMode != m_cache.lastBlendMode)
                    applyBlendMode(states.blendMode);

                // Apply the texture
                sf::Uint64 textureId = states.texture ? states.texture->getNativeHandle() : 0;
                if (textureId != m_cache.lastTextureId)
                    applyTexture(states.texture);
                // Apply the shader
                if (states.shader)
                    applyShader(states.shader);
                if (m_versionMajor > 3 || m_versionMajor == 3 && m_versionMinor >= 3)
                    glCheck(glBindVertexArray(m_vao));
                if (m_cache.lastVboBuffer != &vertexBuffer) {
                    if (m_versionMajor > 3 || m_versionMajor == 3 && m_versionMinor >= 3) {
                        glCheck(glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.vboVertexBuffer));
                        glCheck(glEnableVertexAttribArray(0));
                        glCheck(glEnableVertexAttribArray(1));
                        glCheck(glEnableVertexAttribArray(2));
                        glCheck(glEnableVertexAttribArray(3));
                        glCheck(glVertexAttribPointer(0, 3,GL_FLOAT,GL_FALSE,sizeof(Vertex), (GLvoid*) 0));
                        glCheck(glVertexAttribPointer(1, 4,GL_UNSIGNED_BYTE,GL_TRUE,sizeof(Vertex),(GLvoid*) 12));
                        glCheck(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) 16));
                        glCheck(glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.vboNormalBuffer));
                        glCheck(glVertexAttribPointer(3, 3, GL_FLOAT,GL_FALSE,sizeof(sf::Vector3f), (GLvoid*) 0));
                        glCheck(glDisableVertexAttribArray(0));
                        glCheck(glDisableVertexAttribArray(1));
                        glCheck(glDisableVertexAttribArray(2));
                        glCheck(glDisableVertexAttribArray(3));
                        glCheck(glBindBuffer(GL_ARRAY_BUFFER, 0));

                        /*va_list args;
                        va_start(args, n);
                        for (unsigned int i = 0; i < n; i++) {
                            unsigned int vboMatrices = va_arg(args, unsigned int);
                            for (unsigned int j = 0; j < 4; j++) {
                                glCheck(glEnableVertexAttribArray(i * 4 + j + 3));
                                glCheck(glBindBuffer(GL_ARRAY_BUFFER, vboMatrices));
                                glCheck(glVertexAttribPointer(i * 4 + j + 3, 4, GL_FLOAT, GL_FALSE, sizeof(math::Matrix4f),
                                                        (const GLvoid*)(sizeof(GLfloat) * i * 4)));
                                glCheck(glBindBuffer(GL_ARRAY_BUFFER, 0));
                                glCheck(glVertexAttribDivisor(i * 4 + j + 3, 1));
                                glCheck(glDisableVertexAttribArray(i * 4 + j + 3));
                            }
                        }
                        va_end(args);*/
                        if (vboMatrix1 != 0) {
                            for (unsigned int i = 0; i < 4; i++) {
                                glCheck(glEnableVertexAttribArray(i + 4));
                                glCheck(glBindBuffer(GL_ARRAY_BUFFER, vboMatrix1));
                                glCheck(glVertexAttribPointer(i + 4, 4, GL_FLOAT, GL_FALSE, sizeof(math::Matrix4f),
                                                        (const GLvoid*)(sizeof(GLfloat) * i * 4)));
                                glCheck(glBindBuffer(GL_ARRAY_BUFFER, 0));
                                glCheck(glVertexAttribDivisor(i + 4, 1));
                                glCheck(glDisableVertexAttribArray(i + 4));
                            }
                        }
                        if (vboMatrix2 != 0) {
                            for (unsigned int i = 0; i < 4; i++) {
                                glCheck(glEnableVertexAttribArray(i + 8));
                                glCheck(glBindBuffer(GL_ARRAY_BUFFER, vboMatrix2));
                                glCheck(glVertexAttribPointer(i + 8, 4, GL_FLOAT, GL_FALSE, sizeof(math::Matrix4f),
                                                        (const GLvoid*)(sizeof(GLfloat) * i * 4)));
                                glCheck(glBindBuffer(GL_ARRAY_BUFFER, 0));
                                glCheck(glVertexAttribDivisor(i + 8, 1));
                                glCheck(glDisableVertexAttribArray(i + 8));
                            }
                        }
                    }
                    m_cache.lastVboBuffer = &vertexBuffer;

                }
                if (m_versionMajor > 3 || m_versionMajor == 3 && m_versionMinor >= 3) {
                    glCheck(glEnableVertexAttribArray(0));
                    glCheck(glEnableVertexAttribArray(1));
                    glCheck(glEnableVertexAttribArray(2));
                    glCheck(glEnableVertexAttribArray(3));
                    if (vboMatrix1 != 0) {
                        for (unsigned int i = 0; i < 4 ; i++) {
                            glCheck(glEnableVertexAttribArray(4 + i));
                        }
                    }
                    if (vboMatrix2 != 0) {
                        for (unsigned int i = 0; i < 4 ; i++) {
                            glCheck(glEnableVertexAttribArray(8 + i));
                        }
                    }
                    static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
                                                       GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
                    GLenum mode = modes[type];
                    glCheck(glBindFramebuffer(GL_FRAMEBUFFER, m_framebufferId));
                    glCheck(glDrawArraysInstanced(mode,start,nb,nbInstances));
                    glCheck(glDisableVertexAttribArray(0));
                    glCheck(glDisableVertexAttribArray(1));
                    glCheck(glDisableVertexAttribArray(2));
                    glCheck(glDisableVertexAttribArray(3));
                    if (vboMatrix1 != 0) {
                        for (unsigned int i = 0; i < 4 ; i++) {
                            glCheck(glDisableVertexAttribArray(4 + i));
                        }
                    }
                    if (vboMatrix2 != 0) {
                        for (unsigned int i = 0; i < 4 ; i++) {
                            glCheck(glDisableVertexAttribArray(8 + i));
                        }
                    }
                    glCheck(glBindVertexArray(0));

                }
            }
        }

But it seems the normals are not always correctly instanced like the other vertices attributes in this shader sometimes the normal is null :

const std::string buildFramebufferShader = R"(#version 460
                                                                in vec4 frontColor;
                                                                in vec3 normal;
                                                                in vec3 pos;
                                                                uniform vec3 cameraPos;
                                                                uniform samplerCube sceneBox;
                                                                uniform sampler2D depthBuffer;
                                                                uniform vec3 resolution;
                                                                layout (location = 0) out vec4 fColor;
                                                                void main () {
                                                                    vec2 position = (gl_FragCoord.xy / resolution.xy);
                                                                    vec4 depth = texture2D(depthBuffer, position);
                                                                    float ratio = 1.00 / 1.33;
                                                                    vec3 i = (pos - cameraPos);
                                                                    vec3 r = refract (i, normalize(normal), ratio);
                                                                    vec3 n = normalize(normal);
                                                                    r = normalize(r);
                                                                    if (depth.z > 0) {
                                                                        fColor = texture(sceneBox, r) * (1 - depth.a);
                                                                    } else {
                                                                        fColor = texture(sceneBox, r);
                                                                    }
                                                                }
                                                              )";

That’s the bug.

Ok! I’ve found the problem it was here : if (n-1 <= 0) in the function which compute normals.
n is an unsigned int so it if n = 0, n-1 is invalid. I corrected it by if (n==0)
So It was not a driver bug sorry.