为什么 gl.readPixels() 不起作用?
Why gl.readPixels() is not working?
我一直在尝试使用 WebGL 实现裁剪和封顶。为此,我必须使用模板缓冲区来限制剪切平面的绘制,以便仅绘制对象内部的部分。
首先,我一直在尝试使用模板缓冲区。我的 objective 是检查 gl.clearStencil()
和 gl.clear()
是否更新模板缓冲区的值。这是检查它的测试样本 -
var contextAttributes = gl.getContextAttributes();
var haveStencilBuffer = contextAttributes.stencil;
var bitPlane = gl.getParameter(gl.STENCIL_BITS);
gl.stencilMask(0xFF);
gl.clearStencil(10);
gl.clear(gl.STENCIL_BUFFER_BIT);
gl.enable( gl.STENCIL_TEST );
gl.stencilFunc( gl.ALWAYS, 0, 0);
var stencils = new Uint8Array((window.innerHeight/2) * (window.innerWidth/2));
gl.readPixels(0, 0, window.innerWidth/2, window.innerHeight/2, gl.STENCIL_INDEX, gl.UNSIGNED_BYTE, stencils);
我得到 haveStencil = true
和 bitPlane = 8
,因此它确认每个像素都有一个 8 位存储的模板缓冲区。
但是我发现当我把清除值设置为10
时,存储在stencils
数组中的值都是Zero
。我检查过 gl.readPixels()
函数没有填充 stencils
数组。这段代码对我来说看起来很准确。这里到底出了什么问题?
谢谢。
我不相信你可以用 gl.readPixels
阅读模板。当我尝试你的例子时,我得到
WebGL: INVALID_ENUM: readPixels: invalid format
但这里有一个模板的工作示例。也许你可以看到你做了什么不同的事情。一方面,它明确要求模板缓冲区。如果你想确保你得到一个,你应该这样做。否则由实施决定。
此代码使用剪刀测试和清除将模板缓冲区的矩形区域设置为 10。然后它关闭剪刀测试并打开模板测试并绘制全屏四边形。它应该只在模板设置为 10 的地方绘制。然后我们反转测试并用另一种颜色再次绘制,这种颜色会在任何地方绘制,但模板是 10。我使用 twgl.js 因为 WebGL 太冗长但我希望代码清晰。
// explictly ask for a stencil buffer
var gl = document.createElement("canvas").getContext(
"webgl", {stencil: true});
document.body.appendChild(gl.canvas);
// set part of the stencil (using the scissor to be easy)
gl.enable(gl.SCISSOR_TEST);
gl.scissor(10, 20, 50, 60);
gl.stencilMask(0xFF);
gl.clearStencil(10);
gl.clear(gl.STENCIL_BUFFER_BIT);
gl.disable(gl.SCISSOR_TEST);
// Now draw a fullscreen quad with the stencil test on
gl.enable(gl.STENCIL_TEST);
gl.stencilFunc(gl.EQUAL, 10, 0xFF);
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, { color: [1,0,0,1] });
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
// and again with the test reversed
gl.stencilFunc(gl.NOTEQUAL, 10, 0xFF);
twgl.setUniforms(programInfo, { color: [0,1,0,1] });
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
canvas { border: 1px solid black; }
<script id="vs" type="notjs">
attribute vec4 position;
void main() {
gl_Position = position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}
</script>
<script src="https://twgljs.org/dist/twgl.min.js"></script>
我一直在尝试使用 WebGL 实现裁剪和封顶。为此,我必须使用模板缓冲区来限制剪切平面的绘制,以便仅绘制对象内部的部分。
首先,我一直在尝试使用模板缓冲区。我的 objective 是检查 gl.clearStencil()
和 gl.clear()
是否更新模板缓冲区的值。这是检查它的测试样本 -
var contextAttributes = gl.getContextAttributes();
var haveStencilBuffer = contextAttributes.stencil;
var bitPlane = gl.getParameter(gl.STENCIL_BITS);
gl.stencilMask(0xFF);
gl.clearStencil(10);
gl.clear(gl.STENCIL_BUFFER_BIT);
gl.enable( gl.STENCIL_TEST );
gl.stencilFunc( gl.ALWAYS, 0, 0);
var stencils = new Uint8Array((window.innerHeight/2) * (window.innerWidth/2));
gl.readPixels(0, 0, window.innerWidth/2, window.innerHeight/2, gl.STENCIL_INDEX, gl.UNSIGNED_BYTE, stencils);
我得到 haveStencil = true
和 bitPlane = 8
,因此它确认每个像素都有一个 8 位存储的模板缓冲区。
但是我发现当我把清除值设置为10
时,存储在stencils
数组中的值都是Zero
。我检查过 gl.readPixels()
函数没有填充 stencils
数组。这段代码对我来说看起来很准确。这里到底出了什么问题?
谢谢。
我不相信你可以用 gl.readPixels
阅读模板。当我尝试你的例子时,我得到
WebGL: INVALID_ENUM: readPixels: invalid format
但这里有一个模板的工作示例。也许你可以看到你做了什么不同的事情。一方面,它明确要求模板缓冲区。如果你想确保你得到一个,你应该这样做。否则由实施决定。
此代码使用剪刀测试和清除将模板缓冲区的矩形区域设置为 10。然后它关闭剪刀测试并打开模板测试并绘制全屏四边形。它应该只在模板设置为 10 的地方绘制。然后我们反转测试并用另一种颜色再次绘制,这种颜色会在任何地方绘制,但模板是 10。我使用 twgl.js 因为 WebGL 太冗长但我希望代码清晰。
// explictly ask for a stencil buffer
var gl = document.createElement("canvas").getContext(
"webgl", {stencil: true});
document.body.appendChild(gl.canvas);
// set part of the stencil (using the scissor to be easy)
gl.enable(gl.SCISSOR_TEST);
gl.scissor(10, 20, 50, 60);
gl.stencilMask(0xFF);
gl.clearStencil(10);
gl.clear(gl.STENCIL_BUFFER_BIT);
gl.disable(gl.SCISSOR_TEST);
// Now draw a fullscreen quad with the stencil test on
gl.enable(gl.STENCIL_TEST);
gl.stencilFunc(gl.EQUAL, 10, 0xFF);
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, { color: [1,0,0,1] });
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
// and again with the test reversed
gl.stencilFunc(gl.NOTEQUAL, 10, 0xFF);
twgl.setUniforms(programInfo, { color: [0,1,0,1] });
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
canvas { border: 1px solid black; }
<script id="vs" type="notjs">
attribute vec4 position;
void main() {
gl_Position = position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}
</script>
<script src="https://twgljs.org/dist/twgl.min.js"></script>