Search code examples
javascriptwebgltextures

webgl texture invalid combination of format, type and internalFormat


I'm trying to render a tile map onto a single quad. To do this, I'm trying to use a texture, which contains the column/row of the tile to be sampled from the tileset. The column/row are unsigned, 8-bit integers.

The problem is, I don't know which format/type combination to use. I've looked through the spec, but nothing seems to work.

Here is how I upload the data:

// Some data, representing a 2x2 tile grid
const columns = 2;
const rows = 2;
const data = [
//  col, row, -, -,
    205, 205, 0, 0,
    104, 104, 0, 0,
    104, 104, 0, 0,
    205, 205, 0, 0,
];
const buffer = new Uint8Array(data);
// pretend this creates a HTMLImageElement from the data
const image = Image.from(buffer, columns, rows);

const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 
    /* internalformat */ gl.RGBA8UI, 
    /* format */ gl.RGBA,
    /* type */ gl.UNSIGNED_BYTE,
    /* data */ image);
gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

// ... then at some point
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, texture);
tileMapShader.uniforms.uTILEMAP.set(0); // pretend this exists

This is how I try to render the data (without any tileset sampling):

#version 300 es
precision mediump float;
precision mediump usampler2D;

uniform usampler2D uTILEMAP;

in vec2 vTEXCOORD;

out vec4 oFRAG;

void main()
{
    uvec4 data = texture(uTILEMAP, vTEXCOORD);
    oFRAG = vec4(data.r / 255u, data.g / 255u, data.b / 255u, data.a / 255u);
}

The shader's vertex shader works correctly, I tested it by rendering a flat color. With the above fragment shader, I see a black screen, and I get a warning:

GL_INVALID_OPERATION: Invalid combination of format, type and internalFormat.

What would be a valid combination?


Solution

  • I went ahead and brute-forced it by trying as many combinations as I could, and it seems like the combination of

    gl.texImage2D(gl.TEXTURE_2D, 
        /* internalformat */ gl.RGBA8UI, 
        /* format */ gl.RGBA_INTEGER,
        /* type */ gl.UNSIGNED_BYTE,
        /* data */ image);
    

    works, so the problem was the supplied format had to be RGBA_INTEGER.