<p>As mentioned on a comment, after talking about it on IRC, they helped me realize the bug was in the geometry shader that was being used for Stereo 3D.</p>

<p>Due to the way it was conceived (which was apparently a really bad idea), the shader was always compiled and linked if the hardware reported supporting OpenGL3.30 and <strong>GL_arb_viewport_array</strong>.</p>

<p>When the stereo3d option was disabled, via a very hacky solution, the shader was put into a "pass-through" mode which is supposed to do nothing but (still not sure if it's a bug in the shader itself or a hardware/driver issue) it was sending a lot of undefined values to the fragment shader, instead.</p>

<p>Here's the offending code:</p>

<pre><code>#version 330 core
#extension GL_ARB_viewport_array : require

uniform float sepFactor;
uniform float z0;

layout(triangles) in;
layout(triangle_strip, max_vertices = 6) out;

struct vData {
    vec3 lightDir;
    vec2 texCoord;
    vec3 normal;
    vec4 color;
};

in vData vertex[];
out vData fragv;

void passthru(int i) {
    gl_Position = gl_in[i].gl_Position;
    fragv = vertex[i];
}

// Process all the vertices, applying code to them before emitting (do-while to convince Nvidia of the code getting executed)
#define PROCESS(code) i = 0; do { passthru(i); code; EmitVertex(); } while (++i &lt; 3); EndPrimitive();

void main() {
    int i = 0;
    if (sepFactor == 0.0) {
        gl_ViewportIndex = 0; PROCESS(;); // No stereo
    } else {
        gl_ViewportIndex = 1; PROCESS(gl_Position.x -= sepFactor * (gl_Position.z - z0));  // Left eye
        gl_ViewportIndex = 2; PROCESS(gl_Position.x += sepFactor * (gl_Position.z - z0));  // Right eye
    }
}
</code></pre>

<p>I have sort-of solved it by actually recompiling and relinking the shaders to include the geometry shader or not when stereo3d is toggled.</p>

<p>I've also rewritten the shader to look like this (it still produces skewed geometry but atleast akin to the first screenshot, instead of the second),</p>

<pre><code>#version 330 core
#extension GL_ARB_viewport_array : require

uniform highp float sepFactor;
uniform highp float z0;

layout(triangles) in;
layout(triangle_strip, max_vertices = 6) out;

in vData {
    highp vec3 lightDir;
    highp vec2 texCoord;
    highp vec3 normal;
    highp vec4 color;
} vertices[];

out vData {
    highp vec3 lightDir;
    highp vec2 texCoord;
    highp vec3 normal;
    highp vec4 color;
} fragv;

void passthru(int vp, int i) {
        gl_Position = gl_in[i].gl_Position;
        gl_ViewportIndex = (sepFactor == 0.0) ? 0 : vp;
        gl_Position.x -= (sepFactor * (gl_Position.z - z0));
        fragv.lightDir = vertices[i].lightDir;
        fragv.texCoord = vertices[i].texCoord;
        fragv.normal = vertices[i].normal;
        fragv.color = vertices[i].color;
}

void main() {
        // Render the left eye
    int i = 0;
    do {
        passthru(1, i);
        gl_Position.x -= (sepFactor * (gl_Position.z - z0));
        EmitVertex();       
        } while (++i &lt; 3);
        EndPrimitive();

    i = 0;
        // Render the right eye
    do {
        passthru(2, i);
        gl_Position.x += (sepFactor * (gl_Position.z - z0));
        EmitVertex();       
        } while (++i &lt; 3);
        EndPrimitive();
}
</code></pre>

<p>In order to provide a more complete answer, in case somebody faces the same issue: I finally realized the issue appears to be with the way the loop was written. For some reason, not defining i in the loop itself resulted in trying to access undefined members of <code>vertices</code></p>

<p>Rewriting as follows fixed the issue:</p>

<pre><code>for (int i=0; i &lt; gl_in.length(); i++) {
    passthru(1, i);
    gl_Position = gl_in[i].gl_Position;
    gl_Position.x -= (sepFactor * (gl_in[i].gl_Position.z - z0));
    EmitVertex();   
}
</code></pre>

CC BY-SA 4.0
2018-07-12T16:22:25.850Z
2018-07-17T00:57:14.143Z
2018-07-17T00:57:14.143Z
Gregorio Litenstein
<p>I'm not sure this is the best place to post this, but it <em>definitely</em> seemed more appropriate than programming. I'm one of the developers of Performous, essentially a karaoke (and instruments) game. We use mostly 2D graphics in OpenGL, I don't think anything particularly strange.</p>

<p>On most machines, everything works perfectly. There's a subset of Intel iGPUs (from what I've been able to ascertain, certain models ranging from around the Ivy Bridge generation to somewhere around Broadwell) that render incredibly distorted, on Windows machines. I've seen it happen on Windows 7 and 10 (presumably it also does on Win8)... never in Linux or OSX, I attempted to reproduce it on a mac mini (that should have been affected) running bootcamp, and was unable to.</p>

<p>P.S. If you want to see the code, it's on github at <a href="https://github.com/performous/performous" rel="nofollow noreferrer">https://github.com/performous/performous</a></p>

<p>Relevant files most likely would be (under game/) <code>video_driver.cc/hh, surface.cc/hh, glutil.cc/hh, glshader.cc/hh</code> and the actual shaders that live in <code>data/shaders</code></p>

<p><a href="https://i.sstatic.net/fF2Af.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/fF2Af.jpg" alt="Distorted graphics on a win7 PC"></a></p>

<p>Edit: actual drawing call, </p>

<pre class="lang-cpp prettyprint-override"><code>void VertexArray::draw(GLint mode) {
    GLErrorChecker glerror("VertexArray::draw");
    if (empty()) return;
    unsigned stride = sizeof(VertexInfo);
    GLint program;
    glGetIntegerv(GL_CURRENT_PROGRAM, &amp;program);
    GLint vertPos = glGetAttribLocation(program, "vertPos");
    GLint vertTexCoord = glGetAttribLocation(program, "vertTexCoord");
    GLint vertNormal = glGetAttribLocation(program, "vertNormal");
    GLint vertColor = glGetAttribLocation(program, "vertColor");
    glerror.check("program and attribs");
    glBindVertexArray(m_vao);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VertexInfo) * size(), &amp;m_vertices.front(), GL_STATIC_DRAW);
    glerror.check("bind");
    if (vertPos != -1) {
        glEnableVertexAttribArray(vertPos);
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, position) : &amp;m_vertices[0].position;
        glVertexAttribPointer(vertPos, 3, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertTexCoord != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, texCoord) : &amp;m_vertices[0].texCoord;
        glEnableVertexAttribArray(vertTexCoord);
        glVertexAttribPointer(vertTexCoord, 2, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertNormal != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, normal) : &amp;m_vertices[0].normal;
        glEnableVertexAttribArray(vertNormal);
        glVertexAttribPointer(vertNormal, 3, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertColor != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, color) : &amp;m_vertices[0].color;
        glEnableVertexAttribArray(vertColor);
        glVertexAttribPointer(vertColor, 4, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    glerror.check("enable arrays");
    glDrawArrays(mode, 0, size());

    if (vertPos != -1) glDisableVertexAttribArray(vertPos);
    if (vertTexCoord != -1) glDisableVertexAttribArray(vertTexCoord);
    if (vertNormal != -1) glDisableVertexAttribArray(vertNormal);
    if (vertColor != -1) glDisableVertexAttribArray(vertColor);
    if (m_vbo) glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}
</code></pre>

<p>Client-side vertex struct:</p>

<pre class="lang-cpp prettyprint-override"><code>struct VertexInfo {
    glmath::vec3 position{};
    glmath::vec2 texCoord{};
    glmath::vec3 normal{};
    glmath::vec4 color{ 1.0, 1.0, 1.0, 1.0 };
};
</code></pre>

<p><a href="https://i.sstatic.net/2X29q.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/2X29q.png" alt="Distorted graphics on a win10 laptop"></a></p>

<p><a href="https://i.sstatic.net/G6biw.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/G6biw.png" alt="Expected appearance, on my mac"></a></p>

CC BY-SA 4.0
2018-06-17T16:26:16.797Z
My first guess would be overflows in one of the shaders. OpenGL numbers don't have the same range on different implementations and it's easy to get caught out that way. Check your shaders don't deliberately rely on overflow being a modulo, and try increasing everything to `highp` and see if the behaviour changes.
Dan Hulme
CC BY-SA 4.0
2018-07-08T18:25:13.870Z
I hadn't had a chance to actually look into this. I just did, I'm not really sure what to look for in the shaders, but I ran a project-wide search and found only a couple uses of mod, fmod, % (mostly used as a literal in strings) and for some reason C remainder used mostly in unrelated things. There was a line using modulo to normalize coordinates but I tried reverting that commit (from 2010 or so) and behavior was largely the same. Using highp also didn't really change anything.
Gregorio Litenstein
CC BY-SA 4.0
2018-07-09T06:19:53.347Z
Were is the vertex format specified and were are vertices prepared on the CPU side, that would be the first place I would look.
PaulHK
CC BY-SA 4.0
2018-07-09T15:03:49.263Z
game/glutil.hh and glutil.cc. As I said on the bounty explanation, I know I'm currently doing some outdated/inefficient things but I'd rather fix it first and then correct those.
Gregorio Litenstein
CC BY-SA 4.0
2018-07-09T15:25:20.420Z
Yesterday I was playing around with using colors as debugging (as explained on several answers scattered around the web) and noticed that I'm getting widly different values (and representations for most things when comparing MacOS and Windows) Also, while using colors I see them making out the shapes of the distorted graphics as they were in the first screenshot. Definitely the vertex position is being affected as is the normal. In mac, normals are always 0, in Windows, they're... not.
Gregorio Litenstein
CC BY-SA 4.0
2018-07-09T19:05:04.243Z
If this is the draw call issued every frame then providing buffer with data and then pointing this buffer to vao and disabling it every frame doesn't make much sense, it should be done once. Also, I'd suggest splitting your buffer into multiple buffers containing positions, normals etc to simplify stride and pointers to your data.
mdkdy
CC BY-SA 4.0
2018-07-09T23:58:26.373Z
@narthex I know it doesn't make much sense; and I intend to fix it eventually; I just haven't gotten around to it because on a previous attempt to port the code to Core OpenGL 3.3 (now living on a stale branch here, https://github.com/performous/performous/tree/issue/migrate_to_opengl_33/game) I fixed those issues but it did nothing for the issue posed in the original question.
Gregorio Litenstein
CC BY-SA 4.0
2018-07-12T11:21:23.207Z
Try using apitrace to see any errors you missed. You can also inspect the GL state at each API call with this tool. Maybe also GLSL Debugger could help.
Ruslan
CC BY-SA 4.0
2018-07-12T16:10:34.847Z
@Ruslan I was asking around #OpenGL on freenode the other day, and they helped me realize the bug is in the geometry shader used for Stereo3D (one of the devs REALLY likes stereo 3d).
Gregorio Litenstein
<opengl><c++><gpu><2d>
Distorted OpenGL graphics in certain models of Intel GPUs under Windows; possible causes?
Gregorio Litenstein
# Distorted OpenGL graphics in certain models of Intel GPUs under Windows; possible causes?

(Asked by: username_0 on 2018-06-17)

I'm not sure this is the best place to post this, but it *definitely* seemed more appropriate than programming. I'm one of the developers of Performous, essentially a karaoke (and instruments) game. We use mostly 2D graphics in OpenGL, I don't think anything particularly strange.

On most machines, everything works perfectly. There's a subset of Intel iGPUs (from what I've been able to ascertain, certain models ranging from around the Ivy Bridge generation to somewhere around Broadwell) that render incredibly distorted, on Windows machines. I've seen it happen on Windows 7 and 10 (presumably it also does on Win8)... never in Linux or OSX, I attempted to reproduce it on a mac mini (that should have been affected) running bootcamp, and was unable to.

P.S. If you want to see the code, it's on github at <https://github.com/performous/performous>

Relevant files most likely would be (under game/) `video_driver.cc/hh, surface.cc/hh, glutil.cc/hh, glshader.cc/hh` and the actual shaders that live in `data/shaders`

[![Distorted graphics on a win7 PC](https://i.sstatic.net/fF2Af.jpg)](https://i.sstatic.net/fF2Af.jpg)

Edit: actual drawing call,

```cpp
void VertexArray::draw(GLint mode) {
    GLErrorChecker glerror("VertexArray::draw");
    if (empty()) return;
    unsigned stride = sizeof(VertexInfo);
    GLint program;
    glGetIntegerv(GL_CURRENT_PROGRAM, &program);
    GLint vertPos = glGetAttribLocation(program, "vertPos");
    GLint vertTexCoord = glGetAttribLocation(program, "vertTexCoord");
    GLint vertNormal = glGetAttribLocation(program, "vertNormal");
    GLint vertColor = glGetAttribLocation(program, "vertColor");
    glerror.check("program and attribs");
    glBindVertexArray(m_vao);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VertexInfo) * size(), &m_vertices.front(), GL_STATIC_DRAW);
    glerror.check("bind");
    if (vertPos != -1) {
        glEnableVertexAttribArray(vertPos);
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, position) : &m_vertices[0].position;
        glVertexAttribPointer(vertPos, 3, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertTexCoord != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, texCoord) : &m_vertices[0].texCoord;
        glEnableVertexAttribArray(vertTexCoord);
        glVertexAttribPointer(vertTexCoord, 2, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertNormal != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, normal) : &m_vertices[0].normal;
        glEnableVertexAttribArray(vertNormal);
        glVertexAttribPointer(vertNormal, 3, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertColor != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, color) : &m_vertices[0].color;
        glEnableVertexAttribArray(vertColor);
        glVertexAttribPointer(vertColor, 4, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    glerror.check("enable arrays");
    glDrawArrays(mode, 0, size());

    if (vertPos != -1) glDisableVertexAttribArray(vertPos);
    if (vertTexCoord != -1) glDisableVertexAttribArray(vertTexCoord);
    if (vertNormal != -1) glDisableVertexAttribArray(vertNormal);
    if (vertColor != -1) glDisableVertexAttribArray(vertColor);
    if (m_vbo) glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

```

Client-side vertex struct:

```cpp
struct VertexInfo {
    glmath::vec3 position{};
    glmath::vec2 texCoord{};
    glmath::vec3 normal{};
    glmath::vec4 color{ 1.0, 1.0, 1.0, 1.0 };
};

```

[![Distorted graphics on a win10 laptop](https://i.sstatic.net/2X29q.png)](https://i.sstatic.net/2X29q.png)

[![Expected appearance, on my mac](https://i.sstatic.net/G6biw.png)](https://i.sstatic.net/G6biw.png)

**Tags:** opengl, c++, gpu, 2d

> **Comments:**
> **username_1**: My first guess would be overflows in one of the shaders. OpenGL numbers don't have the same range on different implementations and it's easy to get caught out that way. Check your shaders don't deliberately rely on overflow being a modulo, and try increasing everything to `highp` and see if the behaviour changes.  
> **username_0**: I hadn't had a chance to actually look into this. I just did, I'm not really sure what to look for in the shaders, but I ran a project-wide search and found only a couple uses of mod, fmod, % (mostly used as a literal in strings) and for some reason C remainder used mostly in unrelated things. There was a line using modulo to normalize coordinates but I tried reverting that commit (from 2010 or so) and behavior was largely the same. Using highp also didn't really change anything.  
> **username_2**: Were is the vertex format specified and were are vertices prepared on the CPU side, that would be the first place I would look.  
> **username_0**: game/glutil.hh and glutil.cc. As I said on the bounty explanation, I know I'm currently doing some outdated/inefficient things but I'd rather fix it first and then correct those.  
> **username_0**: Yesterday I was playing around with using colors as debugging (as explained on several answers scattered around the web) and noticed that I'm getting widly different values (and representations for most things when comparing MacOS and Windows) Also, while using colors I see them making out the shapes of the distorted graphics as they were in the first screenshot. Definitely the vertex position is being affected as is the normal. In mac, normals are always 0, in Windows, they're... not.  
> **username_3**: If this is the draw call issued every frame then providing buffer with data and then pointing this buffer to vao and disabling it every frame doesn't make much sense, it should be done once. Also, I'd suggest splitting your buffer into multiple buffers containing positions, normals etc to simplify stride and pointers to your data.  
> **username_0**: @narthex I know it doesn't make much sense; and I intend to fix it eventually; I just haven't gotten around to it because on a previous attempt to port the code to Core OpenGL 3.3 (now living on a stale branch here, https://github.com/performous/performous/tree/issue/migrate_to_opengl_33/game) I fixed those issues but it did nothing for the issue posed in the original question.  
> **username_4**: Try using apitrace to see any errors you missed. You can also inspect the GL state at each API call with this tool. Maybe also GLSL Debugger could help.  
> **username_0**: @username_4 I was asking around #OpenGL on freenode the other day, and they helped me realize the bug is in the geometry shader used for Stereo3D (one of the devs REALLY likes stereo 3d).  

---

## 1 answers

### Answer by username_0 on 2018-07-12. Score: 1 | Accepted answer

As mentioned on a comment, after talking about it on IRC, they helped me realize the bug was in the geometry shader that was being used for Stereo 3D.

Due to the way it was conceived (which was apparently a really bad idea), the shader was always compiled and linked if the hardware reported supporting OpenGL3.30 and **GL\_arb\_viewport\_array**.

When the stereo3d option was disabled, via a very hacky solution, the shader was put into a "pass-through" mode which is supposed to do nothing but (still not sure if it's a bug in the shader itself or a hardware/driver issue) it was sending a lot of undefined values to the fragment shader, instead.

Here's the offending code:

```
#version 330 core
#extension GL_ARB_viewport_array : require

uniform float sepFactor;
uniform float z0;

layout(triangles) in;
layout(triangle_strip, max_vertices = 6) out;

struct vData {
    vec3 lightDir;
    vec2 texCoord;
    vec3 normal;
    vec4 color;
};

in vData vertex[];
out vData fragv;

void passthru(int i) {
    gl_Position = gl_in[i].gl_Position;
    fragv = vertex[i];
}

// Process all the vertices, applying code to them before emitting (do-while to convince Nvidia of the code getting executed)
#define PROCESS(code) i = 0; do { passthru(i); code; EmitVertex(); } while (++i < 3); EndPrimitive();

void main() {
    int i = 0;
    if (sepFactor == 0.0) {
        gl_ViewportIndex = 0; PROCESS(;); // No stereo
    } else {
        gl_ViewportIndex = 1; PROCESS(gl_Position.x -= sepFactor * (gl_Position.z - z0));  // Left eye
        gl_ViewportIndex = 2; PROCESS(gl_Position.x += sepFactor * (gl_Position.z - z0));  // Right eye
    }
}

```

I have sort-of solved it by actually recompiling and relinking the shaders to include the geometry shader or not when stereo3d is toggled.

I've also rewritten the shader to look like this (it still produces skewed geometry but atleast akin to the first screenshot, instead of the second),

```
#version 330 core
#extension GL_ARB_viewport_array : require

uniform highp float sepFactor;
uniform highp float z0;

layout(triangles) in;
layout(triangle_strip, max_vertices = 6) out;

in vData {
    highp vec3 lightDir;
    highp vec2 texCoord;
    highp vec3 normal;
    highp vec4 color;
} vertices[];

out vData {
    highp vec3 lightDir;
    highp vec2 texCoord;
    highp vec3 normal;
    highp vec4 color;
} fragv;

void passthru(int vp, int i) {
        gl_Position = gl_in[i].gl_Position;
        gl_ViewportIndex = (sepFactor == 0.0) ? 0 : vp;
        gl_Position.x -= (sepFactor * (gl_Position.z - z0));
        fragv.lightDir = vertices[i].lightDir;
        fragv.texCoord = vertices[i].texCoord;
        fragv.normal = vertices[i].normal;
        fragv.color = vertices[i].color;
}

void main() {
        // Render the left eye
    int i = 0;
    do {
        passthru(1, i);
        gl_Position.x -= (sepFactor * (gl_Position.z - z0));
        EmitVertex();       
        } while (++i < 3);
        EndPrimitive();

    i = 0;
        // Render the right eye
    do {
        passthru(2, i);
        gl_Position.x += (sepFactor * (gl_Position.z - z0));
        EmitVertex();       
        } while (++i < 3);
        EndPrimitive();
}

```

In order to provide a more complete answer, in case somebody faces the same issue: I finally realized the issue appears to be with the way the loop was written. For some reason, not defining i in the loop itself resulted in trying to access undefined members of `vertices`

Rewriting as follows fixed the issue:

```
for (int i=0; i < gl_in.length(); i++) {
    passthru(1, i);
    gl_Position = gl_in[i].gl_Position;
    gl_Position.x -= (sepFactor * (gl_in[i].gl_Position.z - z0));
    EmitVertex();   
}

```


---

