<p>While porting <a href="https://github.com/progschj/OpenGL-Examples/blob/master/12shader_image_load_store.cpp" rel="nofollow noreferrer">this project</a> with slightly modified code to Linux I ran into some weird behaviour.</p>
<p>On Windows it runs just fine (<a href="https://youtu.be/xH6Dc6xOuow" rel="nofollow noreferrer">https://youtu.be/xH6Dc6xOuow</a>).</p>
<p>But on Ubuntu it shows some <a href="https://youtu.be/BrZtWHw1Wmk" rel="nofollow noreferrer">weird behaviour</a>.
Aside from the much higher speed, the colors start to overlap near the end.</p>
<p>The code is exactly the same for both examples (aside from the paths to the shaders, see below).
On Ubuntu I did try different drivers for my graphics card, but this problem remained.
Something which still comes to my mind, that could be wrong is the CMakeLists.txt file, as I am new to cmake.</p>
<p>So why does this behaviour occur and how can I solve it?</p>
<p>The code:</p>
<p>main.cpp</p>
<pre><code>#include &lt;glad/glad.h&gt;
#include &lt;GLFW/glfw3.h&gt;

#include &lt;glm/glm.hpp&gt;
#include &lt;glm/gtc/noise.hpp&gt; 

#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;

#include &quot;shader.h&quot;



int main() {
    int width = 640;
    int height = 480;

    if (glfwInit() == GL_FALSE) {
        std::cerr &lt;&lt; &quot;failed to init GLFW&quot; &lt;&lt; std::endl;
        return 1;
    }

    // select opengl version
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);

    // create a window
    GLFWwindow* window;
    if ((window = glfwCreateWindow(width, height, &quot;12shader_image_load_store&quot;, 0, 0)) == 0) {
        std::cerr &lt;&lt; &quot;failed to open window&quot; &lt;&lt; std::endl;
        glfwTerminate();
        return 1;
    }

    glfwMakeContextCurrent(window);

    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader(reinterpret_cast&lt;GLADloadproc&gt;(glfwGetProcAddress)))
    {
        std::cout &lt;&lt; &quot;Failed to initialize GLAD&quot; &lt;&lt; std::endl;
        return -1;
    }

    //glfwSwapInterval(1);

    Shader shader1(&quot;source.vert&quot;, &quot;source1.frag&quot;);
    Shader shader2(&quot;source.vert&quot;, &quot;source2.frag&quot;);
    

    // vao and vbo handle
    GLuint vao, vbo, ibo;

    // generate and bind the vao
    glGenVertexArrays(1, &amp;vao);
    glBindVertexArray(vao);

    // generate and bind the vertex buffer object
    glGenBuffers(1, &amp;vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // data for a fullscreen quad
    GLfloat vertexData[] = {
        //  X     Y     Z
           1.0f, 1.0f, 0.0f, // vertex 0
          -1.0f, 1.0f, 0.0f, // vertex 1
           1.0f,-1.0f, 0.0f, // vertex 2
          -1.0f,-1.0f, 0.0f, // vertex 3
    }; // 4 vertices with 3 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 3, vertexData, GL_STATIC_DRAW);


    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (char*)0 + 0 * sizeof(GLfloat));


    // generate and bind the index buffer object
    glGenBuffers(1, &amp;ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

    GLuint indexData[] = {
        0,1,2, // first triangle
        2,1,3, // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * 2 * 3, indexData, GL_STATIC_DRAW);

    // texture handle
    GLuint texture;

    // generate texture
    glGenTextures(1, &amp;texture);

    // bind the texture
    glBindTexture(GL_TEXTURE_2D, texture);

    // create some image data
    std::vector&lt;GLfloat&gt; image(4 * width * height);
    for (int j = 0; j &lt; height; ++j) {
        for (int i = 0; i &lt; width; ++i) {
            size_t index = j * width + i;
            image[4 * index + 0] = 0.0f;
            image[4 * index + 1] = 0.0f;
            image[4 * index + 2] = 0.0f;
            image[4 * index + 3] = 20.0f * glm::clamp(glm::perlin(0.006f * glm::vec2(i, j + 150)), 0.0f, 0.1f);
        }
    }

    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

    // set texture content
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &amp;image[0]);
    
    float t = 0;
    float dt = 1.0f / 60.0f;
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        t += dt;

        // reset time every 10 seconds to repeat the sequence
        if (t &gt; 20) t = 0;

        // clear first
        glClear(GL_COLOR_BUFFER_BIT);

        glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);

        // bind the vao
        glBindVertexArray(vao);

        int substeps = 5;

        shader1.use();

        shader1.setIVec2(&quot;image_size&quot;, width, height);
        shader1.setInt(&quot;image&quot;, 0);
        shader1.setFloat(&quot;dt&quot;, static_cast&lt;float&gt;(50 * dt / substeps));

        shader2.use();

        shader2.setIVec2(&quot;image_size&quot;, width, height);
        shader2.setInt(&quot;image&quot;, 0);
        shader2.setFloat(&quot;dt&quot;, static_cast&lt;float&gt;(50 * dt / substeps));

        
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
        int i = 0;
        for (; i &lt; substeps - 1; ++i) {
            shader1.use();

            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

            shader2.use();
            shader2.setFloat(&quot;t&quot;, static_cast&lt;float&gt;(t + i * dt / substeps));

            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        }

        
        shader1.use();

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

        shader2.use();
        shader2.setFloat(&quot;t&quot;, static_cast&lt;float&gt;(t + i * dt / substeps));

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        // check for errors
        GLenum error = glGetError();
        if (error != GL_NO_ERROR) {
            std::cerr &lt;&lt; error &lt;&lt; std::endl;
            break;
        }
        
        // finally swap buffers
        glfwSwapBuffers(window);
    }

    // delete the created objects

    glDeleteTextures(1, &amp;texture);

    glDeleteVertexArrays(1, &amp;vao);
    glDeleteBuffers(1, &amp;vbo);
    glDeleteBuffers(1, &amp;ibo);


    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}
</code></pre>
<p>shader.h</p>
<pre><code>#ifndef SHADER_H
#define SHADER_H

#include &lt;glad/glad.h&gt;
#include &lt;glm/glm.hpp&gt;

#include &lt;string&gt;
#include &lt;fstream&gt;
#include &lt;sstream&gt;
#include &lt;iostream&gt;

class Shader
{
public:
    unsigned int ID;
    // default constructor
    // -------------------
    Shader() { ID = -1; }
    // constructor generates the shader on the fly
    // ------------------------------------------------------------------------
    Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr)
    {
        // 1. retrieve the vertex/fragment source code from filePath
        std::string vertexCode;
        std::string fragmentCode;
        std::string geometryCode;
        std::ifstream vShaderFile;
        std::ifstream fShaderFile;
        std::ifstream gShaderFile;
        // ensure ifstream objects can throw exceptions:
        vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        try
        {
            // open files
            vShaderFile.open(vertexPath);
            fShaderFile.open(fragmentPath);
            std::stringstream vShaderStream, fShaderStream;
            // read file's buffer contents into streams
            vShaderStream &lt;&lt; vShaderFile.rdbuf();
            fShaderStream &lt;&lt; fShaderFile.rdbuf();
            // close file handlers
            vShaderFile.close();
            fShaderFile.close();
            // convert stream into string
            vertexCode = vShaderStream.str();
            fragmentCode = fShaderStream.str();
            // if geometry shader path is present, also load a geometry shader
            if (geometryPath != nullptr)
            {
                gShaderFile.open(geometryPath);
                std::stringstream gShaderStream;
                gShaderStream &lt;&lt; gShaderFile.rdbuf();
                gShaderFile.close();
                geometryCode = gShaderStream.str();
            }
        }
        catch (std::ifstream::failure const&amp; e)
        {
            std::cout &lt;&lt; &quot;ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ&quot; &lt;&lt; std::endl;
        }
        const char* vShaderCode = vertexCode.c_str();
        const char* fShaderCode = fragmentCode.c_str();
        // 2. compile shaders
        unsigned int vertex, fragment;
        // vertex shader
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &amp;vShaderCode, NULL);
        glCompileShader(vertex);
        checkCompileErrors(vertex, &quot;VERTEX&quot;);
        // fragment Shader
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &amp;fShaderCode, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, &quot;FRAGMENT&quot;);
        // if geometry shader is given, compile geometry shader
        unsigned int geometry;
        if (geometryPath != nullptr)
        {
            const char* gShaderCode = geometryCode.c_str();
            geometry = glCreateShader(GL_GEOMETRY_SHADER);
            glShaderSource(geometry, 1, &amp;gShaderCode, NULL);
            glCompileShader(geometry);
            checkCompileErrors(geometry, &quot;GEOMETRY&quot;);
        }
        // shader Program
        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        if (geometryPath != nullptr)
            glAttachShader(ID, geometry);
        glLinkProgram(ID);
        checkCompileErrors(ID, &quot;PROGRAM&quot;);
        // delete the shaders as they're linked into our program now and no longer necessery
        glDeleteShader(vertex);
        glDeleteShader(fragment);
        if (geometryPath != nullptr)
            glDeleteShader(geometry);

    }
    // activate the shader
    // ------------------------------------------------------------------------
    void use()
    {
        glUseProgram(ID);
    }
    // utility uniform functions
    // ------------------------------------------------------------------------
    void setBool(const std::string&amp; name, bool value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
    }
    // ------------------------------------------------------------------------
    void setInt(const std::string&amp; name, int value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
    }
    // ------------------------------------------------------------------------
    void setFloat(const std::string&amp; name, float value) const
    {
        glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
    }
    // ------------------------------------------------------------------------
    void setVec2(const std::string&amp; name, const glm::vec2&amp; value) const
    {
        glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]);
    }
    void setVec2(const std::string&amp; name, float x, float y) const
    {
        glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
    }
    void setIVec2(const std::string&amp; name, int x, int y) const
    {
        glUniform2i(glGetUniformLocation(ID, name.c_str()), x, y);
    }
    // ------------------------------------------------------------------------
    void setVec3(const std::string&amp; name, const glm::vec3&amp; value) const
    {
        glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]);
    }
    void setVec3(const std::string&amp; name, float x, float y, float z) const
    {
        glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
    }
    // ------------------------------------------------------------------------
    void setVec4(const std::string&amp; name, const glm::vec4&amp; value) const
    {
        glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]);
    }
    void setVec4(const std::string&amp; name, float x, float y, float z, float w)
    {
        glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
    }
    // ------------------------------------------------------------------------
    void setMat2(const std::string&amp; name, const glm::mat2&amp; mat) const
    {
        glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]);
    }
    // ------------------------------------------------------------------------
    void setMat3(const std::string&amp; name, const glm::mat3&amp; mat) const
    {
        glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]);
    }
    // ------------------------------------------------------------------------
    void setMat4(const std::string&amp; name, const glm::mat4&amp; mat) const
    {
        glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]);
    }

private:
    // utility function for checking shader compilation/linking errors.
    // ------------------------------------------------------------------------
    void checkCompileErrors(GLuint shader, std::string type)
    {
        GLint success;
        GLchar infoLog[1024];
        if (type != &quot;PROGRAM&quot;)
        {
            glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;success);
            if (!success)
            {
                glGetShaderInfoLog(shader, 1024, NULL, infoLog);
                std::cout &lt;&lt; &quot;ERROR::SHADER_COMPILATION_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; infoLog &lt;&lt; &quot;\n -- --------------------------------------------------- -- &quot; &lt;&lt; std::endl;
            }
        }
        else
        {
            glGetProgramiv(shader, GL_LINK_STATUS, &amp;success);
            if (!success)
            {
                glGetProgramInfoLog(shader, 1024, NULL, infoLog);
                std::cout &lt;&lt; &quot;ERROR::PROGRAM_LINKING_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; infoLog &lt;&lt; &quot;\n -- --------------------------------------------------- -- &quot; &lt;&lt; std::endl;
            }
        }
    }
};
#endif
</code></pre>
<p>source.vert</p>
<pre><code>#version 420

layout(location = 0) in vec4 vposition;

void main() 
{
    gl_Position = vposition;
}
</code></pre>
<p>source1.frag</p>
<pre><code>#version 420

uniform float dt;
uniform ivec2 image_size;
uniform layout(rgba32f) image2D image;
layout(location = 0) out vec4 FragColor;

void main() 
{
   ivec2 coords = ivec2(gl_FragCoord.xy);
    vec4 HE = imageLoad(image, coords);
    float Ezdx = HE.z-imageLoad(image, coords-ivec2(1, 0)).z;
    float Ezdy = HE.z-imageLoad(image, coords-ivec2(0, 1)).z;
   HE.xy += dt*vec2(-Ezdy, Ezdx);
   imageStore(image, coords, HE);
}
</code></pre>
<p>source2.frag</p>
<pre><code>#version 420

uniform float t;
uniform float dt;
uniform ivec2 image_size;
uniform layout(rgba32f) image2D image;

layout(location = 0) out vec4 FragColor;

void main() 
{
   ivec2 coords = ivec2(gl_FragCoord.xy);

    float e = 1;
    vec4 HE = imageLoad(image, coords);
    float r = HE.w;
    float Hydx = imageLoad(image, coords+ivec2(1, 0)).y
                -HE.y;
    float Hxdy = imageLoad(image, coords+ivec2(0, 1)).x
                -HE.x;

    float Eout = dt*(Hydx-Hxdy)/(e);
   HE.z = HE.z*(1-dt*r/e) + Eout;

// add source at image center
   if(coords.x == image_size.x/2 &amp;&amp; coords.y == image_size.y/2) 
    {
        HE.z += 30*sin(15*t)*exp(-20*(t-2)*(t-2));
    }

   imageStore(image, coords, HE);
   FragColor = vec4(HE.z, HE.w, -HE.z, 1);
}
</code></pre>
<p>CMakeLists.txt (in root of project)</p>
<pre><code>cmake_minimum_required(VERSION 3.15)

# Define the project.
project(hello-opengl
    LANGUAGES C CXX)


## 2. Targets
## ==========
add_subdirectory(src)
</code></pre>
<p>CMakeLists.txt (in src)</p>
<pre><code>cmake_minimum_required(VERSION 3.15)

# package dependencies
find_package(CMakeshift 3.5 REQUIRED)
find_package(glfw3 3.3.2 REQUIRED)
find_package(glm REQUIRED)
find_package(OpenGL 4.2 REQUIRED)

#add glad library
add_library(glad &quot;../include/glad/glad.h&quot; &quot;glad.c&quot;)
target_include_directories(glad PUBLIC &quot;../include&quot;)

# target
add_executable(hello-opengl
    &quot;main.cpp&quot;)

# include directory
target_include_directories(hello-opengl PRIVATE &quot;../include&quot;)

# properties
target_compile_features(hello-opengl
    PRIVATE
        cxx_std_20)

# compiler settings
include(CMakeshift/TargetCompileSettings)
cmakeshift_target_compile_settings(hello-opengl
    PRIVATE
        default)

# target dependencies
target_link_libraries(hello-opengl
    PRIVATE
        OpenGL::GL
        glad
        glfw
        glm)

# installation
install(
    TARGETS hello-opengl)
</code></pre>
<p>To the file structure.</p>
<p>On Windows all files are in the same directory.</p>
<p>On Ubuntu:</p>
<p>CMakeLists.txt</p>
<ul>
<li>inlcude -- shader.h, glad, KHR</li>
<li>shaders -- sourcer.vert, source1.frag, source2.frag</li>
<li>src     -- CMakeLists.txt, main.cpp</li>
</ul>

CC BY-SA 4.0
2020-11-04T10:33:07.490Z
If you use a time integration scheme for your simulation that is not unconditionally stable a different time delta on both systems can explain the weird behavior at the end - the system might get unstable and the solution blows up. So check the time delta you use. Also, check if both systems use the same Graphics card in case you are running it on a system (Laptop) where the CPU has a graphics processor too.
wychmaster
CC BY-SA 4.0
2020-11-05T08:35:27.413Z
Agree with @wychmaster. Try to use `glfwSwapInterval(0);` to free fps limitation, and sleep a few milliseconds as [this topic hints](https://stackoverflow.com/questions/4184468/sleep-for-milliseconds).
heLomaN
CC BY-SA 4.0
2020-11-05T12:51:42.253Z
I set `glfwSwapInterval(0);` and put my own frame limitation on the main loop. The speed of the simulation is now correct, but it still blows up near the end.
Clutterhead
CC BY-SA 4.0
2020-11-07T10:34:36.447Z
Small hint: Next time you answer a comment use `@` in combination with a user name. This will automatically inform the user that you have answered. Otherwise, he will only notice it if he visits the question again. Alternatively, use the edit button to update your question with the new information. It will bubble up on the main page and we will also know that there is new information available. ;)
wychmaster
CC BY-SA 4.0
2020-11-07T10:49:15.113Z
Regarding your question: It is hard to tell what causes the "blow-up" by simply staring at the code. I would suggest to feed some debugging tools with your code ---> [cppcheck](http://cppcheck.sourceforge.net/), [clang-tidy and some clang analyzers](https://clang.llvm.org/docs/index.html), [valgrind](https://valgrind.org/) and whatever else you find. Also, use multiple compilers (GCC, Clang, MSVC) and turn on as many warnings as you can. Maybe there is some undefined behaviour hidden in your code like an uninitialized variable. If true, this should be found quickly with the suggested actions.
wychmaster
<opengl><c++>
Different OpenGL behaviour on Windows and Ubuntu
Clutterhead
# Different OpenGL behaviour on Windows and Ubuntu

(Asked by: username_0 on 2020-11-04)

While porting [this project](https://github.com/progschj/OpenGL-Examples/blob/master/12shader_image_load_store.cpp) with slightly modified code to Linux I ran into some weird behaviour.

On Windows it runs just fine (<https://youtu.be/xH6Dc6xOuow>).

But on Ubuntu it shows some [weird behaviour](https://youtu.be/BrZtWHw1Wmk).
Aside from the much higher speed, the colors start to overlap near the end.

The code is exactly the same for both examples (aside from the paths to the shaders, see below).
On Ubuntu I did try different drivers for my graphics card, but this problem remained.
Something which still comes to my mind, that could be wrong is the CMakeLists.txt file, as I am new to cmake.

So why does this behaviour occur and how can I solve it?

The code:

main.cpp

```
#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <glm/glm.hpp>
#include <glm/gtc/noise.hpp> 

#include <iostream>
#include <string>
#include <vector>

#include "shader.h"

int main() {
    int width = 640;
    int height = 480;

    if (glfwInit() == GL_FALSE) {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // select opengl version
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);

    // create a window
    GLFWwindow* window;
    if ((window = glfwCreateWindow(width, height, "12shader_image_load_store", 0, 0)) == 0) {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }

    glfwMakeContextCurrent(window);

    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    //glfwSwapInterval(1);

    Shader shader1("source.vert", "source1.frag");
    Shader shader2("source.vert", "source2.frag");
    

    // vao and vbo handle
    GLuint vao, vbo, ibo;

    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // data for a fullscreen quad
    GLfloat vertexData[] = {
        //  X     Y     Z
           1.0f, 1.0f, 0.0f, // vertex 0
          -1.0f, 1.0f, 0.0f, // vertex 1
           1.0f,-1.0f, 0.0f, // vertex 2
          -1.0f,-1.0f, 0.0f, // vertex 3
    }; // 4 vertices with 3 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 3, vertexData, GL_STATIC_DRAW);

    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (char*)0 + 0 * sizeof(GLfloat));

    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

    GLuint indexData[] = {
        0,1,2, // first triangle
        2,1,3, // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * 2 * 3, indexData, GL_STATIC_DRAW);

    // texture handle
    GLuint texture;

    // generate texture
    glGenTextures(1, &texture);

    // bind the texture
    glBindTexture(GL_TEXTURE_2D, texture);

    // create some image data
    std::vector<GLfloat> image(4 * width * height);
    for (int j = 0; j < height; ++j) {
        for (int i = 0; i < width; ++i) {
            size_t index = j * width + i;
            image[4 * index + 0] = 0.0f;
            image[4 * index + 1] = 0.0f;
            image[4 * index + 2] = 0.0f;
            image[4 * index + 3] = 20.0f * glm::clamp(glm::perlin(0.006f * glm::vec2(i, j + 150)), 0.0f, 0.1f);
        }
    }

    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

    // set texture content
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &image[0]);
    
    float t = 0;
    float dt = 1.0f / 60.0f;
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        t += dt;

        // reset time every 10 seconds to repeat the sequence
        if (t > 20) t = 0;

        // clear first
        glClear(GL_COLOR_BUFFER_BIT);

        glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);

        // bind the vao
        glBindVertexArray(vao);

        int substeps = 5;

        shader1.use();

        shader1.setIVec2("image_size", width, height);
        shader1.setInt("image", 0);
        shader1.setFloat("dt", static_cast<float>(50 * dt / substeps));

        shader2.use();

        shader2.setIVec2("image_size", width, height);
        shader2.setInt("image", 0);
        shader2.setFloat("dt", static_cast<float>(50 * dt / substeps));

        
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
        int i = 0;
        for (; i < substeps - 1; ++i) {
            shader1.use();

            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

            shader2.use();
            shader2.setFloat("t", static_cast<float>(t + i * dt / substeps));

            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        }

        
        shader1.use();

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

        shader2.use();
        shader2.setFloat("t", static_cast<float>(t + i * dt / substeps));

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        // check for errors
        GLenum error = glGetError();
        if (error != GL_NO_ERROR) {
            std::cerr << error << std::endl;
            break;
        }
        
        // finally swap buffers
        glfwSwapBuffers(window);
    }

    // delete the created objects

    glDeleteTextures(1, &texture);

    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);

    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

```

shader.h

```
#ifndef SHADER_H
#define SHADER_H

#include <glad/glad.h>
#include <glm/glm.hpp>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

class Shader
{
public:
    unsigned int ID;
    // default constructor
    // -------------------
    Shader() { ID = -1; }
    // constructor generates the shader on the fly
    // ------------------------------------------------------------------------
    Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr)
    {
        // 1. retrieve the vertex/fragment source code from filePath
        std::string vertexCode;
        std::string fragmentCode;
        std::string geometryCode;
        std::ifstream vShaderFile;
        std::ifstream fShaderFile;
        std::ifstream gShaderFile;
        // ensure ifstream objects can throw exceptions:
        vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        try
        {
            // open files
            vShaderFile.open(vertexPath);
            fShaderFile.open(fragmentPath);
            std::stringstream vShaderStream, fShaderStream;
            // read file's buffer contents into streams
            vShaderStream << vShaderFile.rdbuf();
            fShaderStream << fShaderFile.rdbuf();
            // close file handlers
            vShaderFile.close();
            fShaderFile.close();
            // convert stream into string
            vertexCode = vShaderStream.str();
            fragmentCode = fShaderStream.str();
            // if geometry shader path is present, also load a geometry shader
            if (geometryPath != nullptr)
            {
                gShaderFile.open(geometryPath);
                std::stringstream gShaderStream;
                gShaderStream << gShaderFile.rdbuf();
                gShaderFile.close();
                geometryCode = gShaderStream.str();
            }
        }
        catch (std::ifstream::failure const& e)
        {
            std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
        }
        const char* vShaderCode = vertexCode.c_str();
        const char* fShaderCode = fragmentCode.c_str();
        // 2. compile shaders
        unsigned int vertex, fragment;
        // vertex shader
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);
        checkCompileErrors(vertex, "VERTEX");
        // fragment Shader
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, "FRAGMENT");
        // if geometry shader is given, compile geometry shader
        unsigned int geometry;
        if (geometryPath != nullptr)
        {
            const char* gShaderCode = geometryCode.c_str();
            geometry = glCreateShader(GL_GEOMETRY_SHADER);
            glShaderSource(geometry, 1, &gShaderCode, NULL);
            glCompileShader(geometry);
            checkCompileErrors(geometry, "GEOMETRY");
        }
        // shader Program
        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        if (geometryPath != nullptr)
            glAttachShader(ID, geometry);
        glLinkProgram(ID);
        checkCompileErrors(ID, "PROGRAM");
        // delete the shaders as they're linked into our program now and no longer necessery
        glDeleteShader(vertex);
        glDeleteShader(fragment);
        if (geometryPath != nullptr)
            glDeleteShader(geometry);

    }
    // activate the shader
    // ------------------------------------------------------------------------
    void use()
    {
        glUseProgram(ID);
    }
    // utility uniform functions
    // ------------------------------------------------------------------------
    void setBool(const std::string& name, bool value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
    }
    // ------------------------------------------------------------------------
    void setInt(const std::string& name, int value) const
    {
        glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
    }
    // ------------------------------------------------------------------------
    void setFloat(const std::string& name, float value) const
    {
        glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
    }
    // ------------------------------------------------------------------------
    void setVec2(const std::string& name, const glm::vec2& value) const
    {
        glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
    }
    void setVec2(const std::string& name, float x, float y) const
    {
        glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
    }
    void setIVec2(const std::string& name, int x, int y) const
    {
        glUniform2i(glGetUniformLocation(ID, name.c_str()), x, y);
    }
    // ------------------------------------------------------------------------
    void setVec3(const std::string& name, const glm::vec3& value) const
    {
        glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
    }
    void setVec3(const std::string& name, float x, float y, float z) const
    {
        glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
    }
    // ------------------------------------------------------------------------
    void setVec4(const std::string& name, const glm::vec4& value) const
    {
        glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
    }
    void setVec4(const std::string& name, float x, float y, float z, float w)
    {
        glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
    }
    // ------------------------------------------------------------------------
    void setMat2(const std::string& name, const glm::mat2& mat) const
    {
        glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
    }
    // ------------------------------------------------------------------------
    void setMat3(const std::string& name, const glm::mat3& mat) const
    {
        glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
    }
    // ------------------------------------------------------------------------
    void setMat4(const std::string& name, const glm::mat4& mat) const
    {
        glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
    }

private:
    // utility function for checking shader compilation/linking errors.
    // ------------------------------------------------------------------------
    void checkCompileErrors(GLuint shader, std::string type)
    {
        GLint success;
        GLchar infoLog[1024];
        if (type != "PROGRAM")
        {
            glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
            if (!success)
            {
                glGetShaderInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
        else
        {
            glGetProgramiv(shader, GL_LINK_STATUS, &success);
            if (!success)
            {
                glGetProgramInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
            }
        }
    }
};
#endif

```

source.vert

```
#version 420

layout(location = 0) in vec4 vposition;

void main() 
{
    gl_Position = vposition;
}

```

source1.frag

```
#version 420

uniform float dt;
uniform ivec2 image_size;
uniform layout(rgba32f) image2D image;
layout(location = 0) out vec4 FragColor;

void main() 
{
   ivec2 coords = ivec2(gl_FragCoord.xy);
    vec4 HE = imageLoad(image, coords);
    float Ezdx = HE.z-imageLoad(image, coords-ivec2(1, 0)).z;
    float Ezdy = HE.z-imageLoad(image, coords-ivec2(0, 1)).z;
   HE.xy += dt*vec2(-Ezdy, Ezdx);
   imageStore(image, coords, HE);
}

```

source2.frag

```
#version 420

uniform float t;
uniform float dt;
uniform ivec2 image_size;
uniform layout(rgba32f) image2D image;

layout(location = 0) out vec4 FragColor;

void main() 
{
   ivec2 coords = ivec2(gl_FragCoord.xy);

    float e = 1;
    vec4 HE = imageLoad(image, coords);
    float r = HE.w;
    float Hydx = imageLoad(image, coords+ivec2(1, 0)).y
                -HE.y;
    float Hxdy = imageLoad(image, coords+ivec2(0, 1)).x
                -HE.x;

    float Eout = dt*(Hydx-Hxdy)/(e);
   HE.z = HE.z*(1-dt*r/e) + Eout;

// add source at image center
   if(coords.x == image_size.x/2 && coords.y == image_size.y/2) 
    {
        HE.z += 30*sin(15*t)*exp(-20*(t-2)*(t-2));
    }

   imageStore(image, coords, HE);
   FragColor = vec4(HE.z, HE.w, -HE.z, 1);
}

```

CMakeLists.txt (in root of project)

```
cmake_minimum_required(VERSION 3.15)

# Define the project.
project(hello-opengl
    LANGUAGES C CXX)

## 2. Targets
## ==========
add_subdirectory(src)

```

CMakeLists.txt (in src)

```
cmake_minimum_required(VERSION 3.15)

# package dependencies
find_package(CMakeshift 3.5 REQUIRED)
find_package(glfw3 3.3.2 REQUIRED)
find_package(glm REQUIRED)
find_package(OpenGL 4.2 REQUIRED)

#add glad library
add_library(glad "../include/glad/glad.h" "glad.c")
target_include_directories(glad PUBLIC "../include")

# target
add_executable(hello-opengl
    "main.cpp")

# include directory
target_include_directories(hello-opengl PRIVATE "../include")

# properties
target_compile_features(hello-opengl
    PRIVATE
        cxx_std_20)

# compiler settings
include(CMakeshift/TargetCompileSettings)
cmakeshift_target_compile_settings(hello-opengl
    PRIVATE
        default)

# target dependencies
target_link_libraries(hello-opengl
    PRIVATE
        OpenGL::GL
        glad
        glfw
        glm)

# installation
install(
    TARGETS hello-opengl)

```

To the file structure.

On Windows all files are in the same directory.

On Ubuntu:

CMakeLists.txt

* inlcude -- shader.h, glad, KHR
* shaders -- sourcer.vert, source1.frag, source2.frag
* src -- CMakeLists.txt, main.cpp

**Tags:** opengl, c++

> **Comments:**
> **username_1**: If you use a time integration scheme for your simulation that is not unconditionally stable a different time delta on both systems can explain the weird behavior at the end - the system might get unstable and the solution blows up. So check the time delta you use. Also, check if both systems use the same Graphics card in case you are running it on a system (Laptop) where the CPU has a graphics processor too.  
> **username_2**: Agree with @username_1. Try to use `glfwSwapInterval(0);` to free fps limitation, and sleep a few milliseconds as [this topic hints](https://stackoverflow.com/questions/4184468/sleep-for-milliseconds).  
> **username_0**: I set `glfwSwapInterval(0);` and put my own frame limitation on the main loop. The speed of the simulation is now correct, but it still blows up near the end.  
> **username_1**: Small hint: Next time you answer a comment use `@` in combination with a user name. This will automatically inform the user that you have answered. Otherwise, he will only notice it if he visits the question again. Alternatively, use the edit button to update your question with the new information. It will bubble up on the main page and we will also know that there is new information available. ;)  
> **username_1**: Regarding your question: It is hard to tell what causes the "blow-up" by simply staring at the code. I would suggest to feed some debugging tools with your code ---> [cppcheck](http://cppcheck.sourceforge.net/), [clang-tidy and some clang analyzers](https://clang.llvm.org/docs/index.html), [valgrind](https://valgrind.org/) and whatever else you find. Also, use multiple compilers (GCC, Clang, MSVC) and turn on as many warnings as you can. Maybe there is some undefined behaviour hidden in your code like an uninitialized variable. If true, this should be found quickly with the suggested actions.  

---

## 0 answers

