简体   繁体   中英

Trivial WebGL fragment shader only rendering first 150 of 256 pixels

I've been trying to debug why my shaders stop working when my textures get large. After cutting and cutting and cutting I've reached the point where I have a constant-output shader only managing to overwrite the first 150 pixels of a texture.

I have no idea why there would be a boundary at 150. It certainly doesn't appear anywhere in the code. It's also not proportional to the size of the texture: decreasing the height to 128 gives a correct output, and increasing it to 256 still has the boundary issue at 150.

I've made the repro as small as I know how. Unfortunately there's still quite a lot of webgl boilerplate. Note that, although the repro omits calls to getError, the original code doesn't (and no errors were being triggered):

 let canvas = document.createElement('canvas'); let gl = canvas.getContext('webgl'); const GL = WebGLRenderingContext; let w = 1; let h = 256; // Create a texture that's initially all 2s. let twos = new Uint8Array(w*h*4); for (let i = 0; i < twos.length; i++) twos[i] = 2; let texture = gl.createTexture(); let framebuffer = gl.createFramebuffer(); gl.bindTexture(GL.TEXTURE_2D, texture); gl.bindFramebuffer(GL.FRAMEBUFFER, framebuffer); gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST); gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST); gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE); gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE); gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, w, h, 0, GL.RGBA, GL.UNSIGNED_BYTE, twos); gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, texture, 0); gl.bindBuffer(GL.ARRAY_BUFFER, gl.createBuffer()); gl.bufferData(GL.ARRAY_BUFFER, new Float32Array([-1,1,1,1,-1,-1,1,-1]), GL.STATIC_DRAW); gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, gl.createBuffer()); gl.bufferData(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,2,1,2,3,1]), GL.STATIC_DRAW); // Create a set-all-to-1s shader. let glVertexShader = gl.createShader(GL.VERTEX_SHADER); let glFragmentShader = gl.createShader(GL.FRAGMENT_SHADER); let program = gl.createProgram(); gl.shaderSource(glVertexShader, "attribute vec2 position;void main(){gl_Position = vec4(position, 0, 1);}"); gl.shaderSource(glFragmentShader, "void main(){gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0)/255.0;}"); gl.compileShader(glVertexShader); gl.compileShader(glFragmentShader); gl.attachShader(program, glVertexShader); gl.attachShader(program, glFragmentShader); gl.linkProgram(program); gl.useProgram(program); gl.enableVertexAttribArray(gl.getAttribLocation(program, 'position')); gl.vertexAttribPointer(gl.getAttribLocation(program, 'position'), 2, WebGLRenderingContext.FLOAT, false, 0, 0); // Should cause all the texture's pixels to get painted [1,1,1,1]. gl.drawElements(GL.TRIANGLES, 6, GL.UNSIGNED_SHORT, 0); // Read texture's pixels. let result = new Uint8Array(w * h * 4); gl.readPixels(0, 0, w, h, GL.RGBA, GL.UNSIGNED_BYTE, result); console.log(result.join("")); 

When I run the above snippet, the console logs 600 ones (600=150*4) followed by 424 twos:

1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111112222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222

What could be causing this?

The viewport wasn't tall enough. The discontinuity was at 150 pixels / 600 outputs because the default height of a canvas is 150 pixels , and the viewport defaults to the size of the canvas when the webgl context is created.

Just call gl.viewport(0, 0, w, h) before the draw call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM