简单的 WebGL 片段着色器只渲染 256 个像素中的前 150 个
Trivial WebGL fragment shader only rendering first 150 of 256 pixels
我一直在尝试调试为什么当我的纹理变大时我的着色器停止工作。在切割、切割和切割之后,我已经达到了我有一个恒定输出着色器只设法覆盖纹理的前 150 个像素的地步。
我不知道为什么在 150 处会有边界。它肯定不会出现在代码中的任何地方。它也与纹理的大小不成比例:将高度降低到 128 会给出正确的输出,将其增加到 256 仍然会在 150 处出现边界问题。
我已经尽可能地缩小了复制品。不幸的是,仍然有很多 webgl 样板文件。请注意,尽管重现省略了对 getError 的调用,但原始代码没有(并且没有触发错误):
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(""));
当我运行上面的代码片段时,控制台记录了 600 个 (600=150*4),然后是 424 个二:
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111112222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
可能是什么原因造成的?
视口不够高。不连续性为 150 像素/600 输出,因为 the default height of a canvas is 150 pixels,并且视口默认为创建 webgl 上下文时 canvas 的大小。
只需在绘制调用之前调用 gl.viewport(0, 0, w, h)
。
我一直在尝试调试为什么当我的纹理变大时我的着色器停止工作。在切割、切割和切割之后,我已经达到了我有一个恒定输出着色器只设法覆盖纹理的前 150 个像素的地步。
我不知道为什么在 150 处会有边界。它肯定不会出现在代码中的任何地方。它也与纹理的大小不成比例:将高度降低到 128 会给出正确的输出,将其增加到 256 仍然会在 150 处出现边界问题。
我已经尽可能地缩小了复制品。不幸的是,仍然有很多 webgl 样板文件。请注意,尽管重现省略了对 getError 的调用,但原始代码没有(并且没有触发错误):
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(""));
当我运行上面的代码片段时,控制台记录了 600 个 (600=150*4),然后是 424 个二:
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111112222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222
可能是什么原因造成的?
视口不够高。不连续性为 150 像素/600 输出,因为 the default height of a canvas is 150 pixels,并且视口默认为创建 webgl 上下文时 canvas 的大小。
只需在绘制调用之前调用 gl.viewport(0, 0, w, h)
。