【问题标题】:Trivial WebGL fragment shader only rendering first 150 of 256 pixels简单的 WebGL 片段着色器仅渲染 256 个像素中的前 150 个
【发布时间】:2016-07-07 12:16:29
【问题描述】:

我一直在尝试调试为什么当我的纹理变大时我的着色器停止工作。在切割、切割和切割之后,我已经达到了一个恒定输出着色器只能覆盖纹理的前 150 个像素的地步。

我不知道为什么在 150 处会有一个边界。它肯定不会出现在代码中的任何地方。它也与纹理的大小不成比例:将高度降低到 128 会得到正确的输出,而将高度增加到 256 仍然会在 150 处出现边界问题。

我已尽我所知将复制品制作得尽可能小。不幸的是,仍然有很多 webgl 样板。请注意,尽管 repro 省略了对 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(""));

当我运行上面的 sn-p 时,控制台会记录 600 个二进制 (600=150*4),然后是 424 个二进制:

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

这可能是什么原因造成的?

【问题讨论】:

  • 你注意到你需要设置视口来匹配你正在绘制的东西

标签: html webgl


【解决方案1】:

视口不够高。由于the default height of a canvas is 150 pixels,不连续性为 150 像素/600 个输出,并且视口默认为创建 webgl 上下文时画布的大小。

只需在调用之前调用gl.viewport(0, 0, w, h)

【讨论】:

  • 我的意思是你没有设置gl.viewport,它默认为 webgl 中的画布大小。因此,您的视口大小与纹理大小不匹配。如果您在示例中添加gl.viewport(0,0,w,h);,我会看到它仅记录 1s。
  • 为了清楚起见,视口默认为创建 webgl 上下文时画布的大小。所以从技术上讲,视口的默认大小不是 300x150,画布的默认大小是 300x150。换句话说,如果在调用 getContext 之前画布大小设置为 75x25,则视口将从 75x25 开始。之后,您可以根据需要将其设置为任何新尺寸。
  • @gman 啊,我明白了。当我说“那个”时,它可能意味着“画布的当前大小”或“画布的默认大小”。澄清。
猜你喜欢
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
相关资源
最近更新 更多