Type Mistakes

Common Type and Qualifier Mistakes

Each mistake below was compiled in WebGL 2; the middle column quotes ANGLE 2,592 's message:

Frequent GLSL ES 3.00 errors and their fixes
Mistake ANGLE's message Fix
float f = 1; cannot convert from 'const int' to 'mediump float' 1.0
No precision line in a fragment shader No precision specified for (float) precision mediump float;
Writing to an in variable l-value required (can't modify an input "vUV") copy it to a local
gl_FragColor in a 3.00 shader 'gl_FragColor' : undeclared identifier declare out vec4
texture2D() in a 3.00 shader no matching overloaded function found texture()
float r = 5.0 % 2.0; wrong operand types - no operation '%' mod(5.0, 2.0)

Write every float literal with a decimal point, keep the precision line in a shared header, and when porting WebGL 1 code convert attribute, varying, gl_FragColor and texture2D together. One bad line often triggers follow-on messages, so fix the first error and recompile.

Six common GLSL mistakes compiled live: the compiler's message and the fixed shader's outputHTMLLive
<!doctype html>
<style>
  body { margin: 0; font: 12px system-ui, sans-serif; background: #f7f4ee; color: #333; }
  .grid { position: relative; max-width: 600px; padding-left: 70px; }
  canvas { position: absolute; left: 0; top: 0; width: 60px; height: 336px; }
  .row { height: 56px; box-sizing: border-box; padding: 4px 0; border-bottom: 1px solid #e3ddd0; overflow: hidden; }
  code { font-size: 11px; background: #fff; padding: 1px 4px; }
  .err { color: #b5452f; font-family: monospace; font-size: 11px; }
  .fix { color: #3f7d3a; }
</style>
<div class="grid"><canvas id="view" width="60" height="336"></canvas><div id="rows"></div></div>
<script>
const gl = document.getElementById('view').getContext('webgl2');
const vsSource = `#version 300 es
in vec2 aPos; out vec2 vUV;
void main() { vUV = aPos * 0.5 + 0.5; gl_Position = vec4(aPos, 0.0, 1.0); }`;
const H = '#version 300 es\nprecision mediump float;\nin vec2 vUV;\nuniform sampler2D uTex;\n';
const mistakes = [   // [broken line, broken shader, fix label, fixed shader]
  ['float f = 1;', H + 'out vec4 o;\nvoid main() { float f = 1; o = vec4(vUV * f, 0.5, 1.0); }',
   '1.0', H + 'out vec4 o;\nvoid main() { float f = 1.0; o = vec4(vUV * f, 0.5, 1.0); }'],
  ['no precision line', '#version 300 es\nin vec2 vUV; out vec4 o;\nvoid main() { o = vec4(vUV, 1.0, 1.0); }',
   'precision mediump float;', H + 'out vec4 o;\nvoid main() { o = vec4(vUV, 1.0, 1.0); }'],
  ['vUV.x += 0.25;', H + 'out vec4 o;\nvoid main() { vUV.x += 0.25; o = vec4(fract(vUV * 3.0), 0.3, 1.0); }',
   'copy it to a local', H + 'out vec4 o;\nvoid main() { vec2 uv = vUV; uv.x += 0.25; o = vec4(fract(uv * 3.0), 0.3, 1.0); }'],
  ['gl_FragColor = ...', H + 'void main() { gl_FragColor = vec4(0.12, 0.37, 0.55, 1.0); }',
   'declare out vec4', H + 'out vec4 outColor;\nvoid main() { outColor = vec4(0.12, 0.37, 0.55 + 0.4 * vUV.y, 1.0); }'],
  ['texture2D(uTex, vUV)', H + 'out vec4 o;\nvoid main() { o = texture2D(uTex, vUV); }',
   'texture()', H + 'out vec4 o;\nvoid main() { o = texture(uTex, vUV); }'],
  ['float r = 5.0 % 2.0;', H + 'out vec4 o;\nvoid main() { float r = vUV.x * 5.0 % 2.0; o = vec4(r * 0.5, 0.4, 0.2, 1.0); }',
   'mod(x, 2.0)', H + 'out vec4 o;\nvoid main() { float r = mod(vUV.x * 5.0, 2.0); o = vec4(r * 0.5, 0.4, 0.2, 1.0); }'],
];

function compile(type, src) {
  const s = gl.createShader(type);
  gl.shaderSource(s, src); gl.compileShader(s);
  return gl.getShaderParameter(s, gl.COMPILE_STATUS) ? { shader: s } : { error: gl.getShaderInfoLog(s) };
}
const vs = compile(gl.VERTEX_SHADER, vsSource).shader;

gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, 1,1, -1,-1, 1,1, -1,1]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
// A 4x4 striped texture for the texture() row.
gl.bindTexture(gl.TEXTURE_2D, gl.createTexture());
const stripes = new Uint8Array(64).map((_, i) => ((i >> 2) % 4 < 2 ? [224, 154, 16, 255] : [31, 95, 139, 255])[i % 4]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, stripes);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

gl.clearColor(0.97, 0.96, 0.93, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
let html = '';
mistakes.forEach(([line, broken, fixLabel, fixed], i) => {
  const message = compile(gl.FRAGMENT_SHADER, broken).error || 'compiled?';
  const program = gl.createProgram();
  gl.attachShader(program, vs);
  gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fixed).shader);
  gl.bindAttribLocation(program, 0, 'aPos');
  gl.linkProgram(program);
  gl.useProgram(program);
  gl.viewport(4, 336 - (i + 1) * 56 + 4, 52, 48);   // the fixed shader's output for this row
  gl.drawArrays(gl.TRIANGLES, 0, 6);
  html += `<div class="row"><code>${line}</code> <span class="fix">fix: ${fixLabel}</span><br>` +
          `<span class="err">${message.split('\n')[0].replace(/</g, '&lt;')}</span></div>`;
});
document.getElementById('rows').innerHTML = html;
</script>