GLSL-ES3(webGL2): how to test extensions from fragment shader?

444 views Asked by At

In webGL1 it was possible to test the availability of a GLSL extension from a fragment shader using (for instance) #ifdef GL_EXT_shader_texture_lod . It seems to no longer be working in webGL2 (=GLSL-ES3.0): Extensions are not the same, but for instance #ifdef GL_EXT_color_buffer_float seems false despite https://webglreport.com/?v=2 tells that the extension is there. Or what am I doing wrong ?

1

There are 1 answers

6
gman On

It's up to the extension whether or not it adds a flag to GLSL

EXT_shader_texture_lod is specifically an extension that effects GLSL. It's spec says it adds that macro

The GLSL macro GL_EXT_shader_texture_lod is defined as 1.

EXT_color_buffer_float is not an extension that affects GLSL. It's spec does not mention any GLSL macros. No change from WebGL1

Those flags though are mostly nonsense in WebGL anyway. You can trivially do your own string manipulation

const shaderTextureLodExt = gl.getExtension('EXT_shader_texture_lod');


const shader = `
#if ${shaderTextureLodExt ? 1 : 0}
   ... code if shader texture lod exists
#else
   ... code if shader texture lod does not exist
#endif

  ...
`;

Or a thousand other ways to manipulate shader strings.

Here's another

const colorBufferFloatExt = gl.getExtension('EXT_color_buffer_float');

function replaceIfDefs(s) {
  return `
  ${colorBufferExtension ? '#define EXTENSION_color_buffer_float' : ''}
  ${s.replace(/GL_EXT_color_buffer_float/g 'EXTENSION_color_buffer_float')}
  `;
}
const shader = replaceIfDefs(`
#ifdef GL_EXT_color_buffer_float
   ...
#endif
   ...
`);

etc...

Also since there never was a GL_EXT_color_buffer_float even in OpenGL there isn't much point in calling the macro GL_EXT_color_buffer_float. In fact it would arguably be a bad idea because it would end up looking like an official specified macro even though it's not. Best to chose your own name that doesn't start with GL_ .

Also consider that using #ifdef might not even be a good idea since you can just use string manipulation. For example

const colorBufferFloatExt = gl.getExtension('EXT_color_buffer_float');

const snippet = colorBufferFloatExt
  ? `
      float decode_float(vec4 v) {
        return v;
      }
    `
  : `
      float decode_float(vec4 v) {
         vec4 bits = v * 255.0;
         float sign = mix(-1.0, 1.0, step(bits[3], 128.0));
         float expo = floor(mod(bits[3] + 0.1, 128.0)) * 2.0 +
                      floor((bits[2] + 0.1) / 128.0) - 127.0;
         float sig = bits[0] +
                     bits[1] * 256.0 +
                     floor(mod(bits[2] + 0.1, 128.0)) * 256.0 * 256.0;
         return sign * (1.0 + sig / 8388607.0) * pow(2.0, expo);
       }
   `;

const shader = `
precision highp float;

${snippet}

uniform sampler2D data;
uniform vec2 dataSize;

void main(
   vec4 d = texture2D(data, gl_FragCoord.xy / dataSize);
   vec4 v = decode_float(d) * 2.0;
   gl_FragColor = v;
}
`;


...etc...