3

I'm having an issue trying to compile a fragment shader. I keep getting this error:

Uncaught Error: Fragment Shader Compiler Error: ERROR: 0:21: '[' :
array index for gl_FragData must be constant zero ERROR: 0:21: '[' :
array index for gl_FragData must be constant zero ERROR: 0:21: '[' :
array index for gl_FragData must be constant zero

This is the code:

#ifdef GL_EXT_draw_buffers
#extension GL_EXT_draw_buffers : require
#endif
#ifdef GL_ES
precision highp float;
#endif
void main() {
    gl_FragData[0] = vec4(1.,2.,3.,4.);
    gl_FragData[1] = vec4(1.,2.,3.,4.);
    gl_FragData[2] = vec4(1.,2.,3.,4.);
    gl_FragData[3] = vec4(1.,2.,3.,4.);
}

The whole setup works fine if I'm setting gl_FragColor (with the 4 textures attached to the frame buffer), but trying to do the code above (indexing the buffers to output to) seems to not compile. I have seen this working fine in WebGL1 using extensions. I'm using WebGL2, so perhaps something is different in this context? (I'm trying it in the latest version of Chrome).

gman
  • 100,619
  • 31
  • 269
  • 393
James Wilkins
  • 6,836
  • 3
  • 48
  • 73
  • 1
    If you use WebGL2 I think you have to change your syntax radically to fit the GLSL 3.3 standard... look here : http://io7m.com/documents/fso-tta/ at the `GLSL 3.30 (OpenGL 3.3)` chapter, also that say : "On OpenGL [3.3, 4.4] and OpenGL ES 3.0, assign to named fragment shader outputs, associating the named outputs with numbered draw buffers by using layout qualifiers." –  Oct 14 '17 at 09:48
  • 2
    WebGL2 does not support GLSL 3.3. It supports [GLSL ES 3.0](https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf). It would be very confusing to reference the GLSL 3.3 spec only to find that tons of things don't work because it's the wrong spec. – gman Oct 15 '17 at 02:44

1 Answers1

3

So it appears there's some changes to consider going from WebGL1 to WebGL2. Given @gman's comment I thought it best to link to his article, since I know he's really the expert here. ;)

WebGL 1 to WebGL 2 conversion: https://webgl2fundamentals.org/webgl/lessons/webgl1-to-webgl2.html

I also found it helpful to remember the version differences:

WebGL 1.0 is based on OpenGL ES 2.0 and provides an API for 3D graphics. It uses the HTML5 canvas element and is accessed using Document Object Model (DOM) interfaces.

WebGL 2.0 is based on OpenGL ES 3.0 and made guaranteed availability of many optional extensions of WebGL 1.0 and exposes new APIs.

In a nutshell (referring also to the first link on the history):

  1. My shader code was designed for examples I've seen for WebGL 1 (OpenGL ES 2) using extensions. This worked fine because OpenGL 2.0 supported multiple color values via gl_FragData.

  2. Switching to WebGL 2 (OpenGL ES 3) this is depreciated in favour of a different way. Now there are out declarations required, like out vec4 out_0; main(void) { out_0 = vec4(1.0, 0.0, 0.0, 1.0); }. But I was still having some problems. It seems I needed to specify the buffer locations. Also, I was getting this error:

    ERROR: must explicitly specify all locations when using multiple fragment outputs

    Which means that I needed to add #version 300 es to the top of my program, so the correct code for WebGL 2 looks more like this:

    #version 300 es
    layout(location = 0) out vec4 out_0;
    layout(location = 1) out vec4 out_1;
    main(void) {
        out_0 = vec4(1.0, 0.0, 0.0, 1.0);
        out_1 = vec4(1.0, 0.0, 0.0, 1.0);
    }
    

    At one point I had the wrong version, which caused this error:

    invalid version directive ERROR: 0:24: 'out' : storage qualifier supported in GLSL ES 3.00 and above only

    But I found out that the version for WebGL 2 specifically is #version 300 es (notice the es part), which worked!

    Note: The version specifier must be on the FIRST line, and, unfortunately, cannot be in a preprocessor directive (i.e. #ifdef), so I had to dynamically change the string before sending it to be compiled. If not, you'll get this:

    #version directive must occur before anything else, except for comments and white space

  3. For vertex shaders, if compiled for WebGL 2 (ES 3) note that attribute is now in instead. The version of the vertex shader must ALSO match that of the fragment being compiled, or else you'll get this:

    ERROR: Shader Linking Error: Versions of linked shaders have to match.

I hope glueing all this confusion together helps save someone else lots of time. ;)

James Wilkins
  • 6,836
  • 3
  • 48
  • 73
  • Here is no history of *breaking changes*. That document linked to has absolutely nothing to do with WebGL or WebGL2. It's all about OpenGL which is not the same thing nor is it even related to WebGL. WebGL and WebGL2 are related to OpenGL **ES**. Sedenion didn't point you in the right direction. He pointed you in the wrong direction. You just got lucky it helped you figure out your issues. That first link in your answer is about OpenGL not OpenGL ES. OpenGL has nothing to do with WebGL. Referencing it only causes confusion. Your answer shows that where you tried various OpenGL related versions – gman Oct 15 '17 at 02:48
  • You also linked to an OpenGL ES conversion article but you're using WebGL2 not OpenGL ES so you should really be looking at a [WebGL2 conversion article](https://webgl2fundamentals.org/webgl/lessons/webgl1-to-webgl2.html) – gman Oct 15 '17 at 02:54
  • Thanks for the details. I'm starting to get back into all this after being away from it too long and it's all fuzzy. Writing these answers (where I cannot find any good one already) helps me learn also. Had I come across your articles earlier it would have saved me lots of time I think lol. ;) – James Wilkins Oct 15 '17 at 04:46