unexpected result after a for loop in a shader

46 views Asked by At

Here are two fragment shaders.
They do the same thing, except the 2nd has a "for" loop.
What I'm wondering about is that the one with the "for" loop doesn't work on my 11th Gen Intel® Core™ i7-11370H×8 laptop.

const gl = document.querySelector('canvas').getContext('webgl2');

const vs = `#version 300 es
  void main() {
    gl_PointSize = 300.0;
    gl_Position = vec4(0, 0, 0, 1);
  }`;

const fs = `#version 300 es
  precision mediump float;
  uniform sampler2D tex[3];
  out vec4 outColor;
  void main() {
    vec4 colors[3];

    // you can't index textures with non-constant integer expressions
    // in WebGL2 (you can in WebGL1 lol)
    colors[0] = texture(tex[0], vec2(0));
    colors[1] = texture(tex[1], vec2(0));
    colors[2] = texture(tex[2], vec2(0));
 
    vec4 color = vec4(0);
    float x = gl_PointCoord.x * 3.0;
    int i=0;
    float amount = step(float(i), x) * step(x, float(i + 1));
    color = mix(color, colors[i], amount);
    
    i=1;
    amount = step(float(i), x) * step(x, float(i + 1));
    color = mix(color, colors[i], amount);

    i=2;
    amount = step(float(i), x) * step(x, float(i + 1));
    color = mix(color, colors[i], amount);
 
    outColor = vec4(color.rgb, 1);
  }`;
  
let vertex = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertex, vs);
gl.compileShader(vertex);
let fragment = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragment, fs);
gl.compileShader(fragment);
const program = gl.createProgram();
gl.attachShader(program,vertex);
gl.attachShader(program,fragment);
gl.linkProgram(program);
gl.useProgram(program);

const tex1 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex1);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([255, 0, 0, 255]));

const tex2 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex2);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 255, 0, 255]));

const tex3 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex3);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 0, 255, 255]));

const textureLoc = gl.getUniformLocation(program, "tex[0]");
gl.uniform1iv(textureLoc, [0, 1, 2]);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tex1);

gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, tex2);

gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, tex3);

gl.drawArrays(gl.POINTS, 0, 1);
<canvas id="canvas"></canvas>

here is a screenshot taken on the machine which gives the correct result. result without the for loop

const gl = document.querySelector('canvas').getContext('webgl2');

const vs = `#version 300 es
  void main() {
    gl_PointSize = 300.0;
    gl_Position = vec4(0, 0, 0, 1);
  }
  `;

  const fs = `#version 300 es
  precision mediump float;
  uniform sampler2D tex[3];
  out vec4 outColor;
  void main() {
    vec4 colors[3];

    // you can't index textures with non-constant integer expressions
    // in WebGL2 (you can in WebGL1 lol)
    colors[0] = texture(tex[0], vec2(0));
    colors[1] = texture(tex[1], vec2(0));
    colors[2] = texture(tex[2], vec2(0));
 
   //
   //THIS "FOR" LOOP DOES NOT WORK ON ONE OF MY COMPUTERS
   //
    vec4 color = vec4(0);
    for (int i = 0; i < 3; ++i) { 
      float x = gl_PointCoord.x * 3.0;
      float amount = step(float(i), x) * step(x, float(i + 1));
      color = mix(color, colors[i], amount);
    }
    
    outColor = vec4(color.rgb, 1);
  }
  `;
  
let vertex = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertex, vs);
gl.compileShader(vertex);
let fragment = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragment, fs);
gl.compileShader(fragment);
const program = gl.createProgram();
gl.attachShader(program,vertex);
gl.attachShader(program,fragment);
gl.linkProgram(program);
gl.useProgram(program);

const tex1 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex1);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([255, 0, 0, 255]));

const tex2 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex2);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 255, 0, 255]));

const tex3 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex3);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 0, 255, 255]));

const textureLoc = gl.getUniformLocation(program, "tex[0]");
gl.uniform1iv(textureLoc, [0, 1, 2]);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tex1);

gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, tex2);

gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, tex3);

gl.drawArrays(gl.POINTS, 0, 1);
<canvas id="canvas"></canvas>

here is a screenshot taken on the other machine...

result with the for loop

I add that the machine giving the bad result runs on Ubuntu, could this be the cause of this bug ?

So I wonder if other users will experience the same bug.

How and where to report this bug ?

0

There are 0 answers