layout(location=n) 可以跳过 WebGL 中 drawBuffers 的索引吗?
Can an layout(location=n) out skip an index for drawBuffers in WebGL?
我正在我的图形引擎中处理 MRT。
我正在(并旨在修复)的一个有趣的点是我生成的片段着色器吐出:
layout(location = 0) out vec4 thing1;
layout(location = 2) out vec4 thing2;
应用端的drawBuffers调用是这样的:
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT1]);
但是,我遇到了一个错误:
WebGL: INVALID_OPERATION: drawBuffers: COLOR_ATTACHMENTi_EXT or NONE
很明显,这似乎是不允许的。从我从一篇讨论它的维基百科文章中读到的文档中:
https://www.khronos.org/opengl/wiki/Fragment_Shader
它指出指定的布局位置是指从 drawBuffers 调用指定的数组索引。所以,理论上我会认为这个着色器配置是有效的。
我的理解中缺少什么导致这不起作用?
我主要请求理解而不是修复我的程序,我的生成器将在我完成后更正索引 'correct' 没有位置索引跳过。
更新:如下所述,您可以跳过着色器中的布局位置。我的问题是 drawBuffers 调用的格式不正确,我在索引中有 COLOR_ATTACHMENT1,其中只有 COLOR_ATTACHMENT2 有效。
这是错误的
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT1]);
第 i 第一个附件必须是 gl.NONE
或 gl.COLOR_ATTACHMENT
我
所以必须是这个
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT2]);
function main() {
const gl = document.querySelector('canvas').getContext('webgl2');
const vs = `#version 300 es
void main() {
gl_Position = vec4(0, 0, 0, 1);
gl_PointSize = 100.0;
}
`;
const fs = `#version 300 es
precision highp float;
layout(location = 0) out vec4 thing1;
layout(location = 2) out vec4 thing2;
void main () {
thing1 = vec4(1, 0, 0, 1);
thing2 = vec4(0, 0, 1, 1);
}
`;
const prg = twgl.createProgram(gl, [vs, fs]);
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
createTextureAndAttach(gl, gl.COLOR_ATTACHMENT0);
createTextureAndAttach(gl, gl.COLOR_ATTACHMENT2);
gl.drawBuffers([
gl.COLOR_ATTACHMENT0,
gl.NONE,
gl.COLOR_ATTACHMENT2,
]);
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status !== gl.FRAMEBUFFER_COMPLETE) {
console.error("can't render to this framebuffer combo");
return;
}
gl.useProgram(prg);
gl.viewport(0, 0, 1, 1);
gl.drawArrays(gl.POINTS, 0, 1);
checkError();
read(gl.COLOR_ATTACHMENT0);
read(gl.COLOR_ATTACHMENT2);
checkError();
function checkError() {
const err = gl.getError();
if (err) {
console.error(twgl.glEnumToString(gl, err));
}
}
function read(attachmentPoint) {
gl.readBuffer(attachmentPoint);
const pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log(Array.from(pixel).join(','));
}
function createTextureAndAttach(gl, attachmentPoint) {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, tex, 0);
}
}
main();
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>
注意:为 WebGL 引用 OpenGL 文档通常是错误的 and/or 误导 WebGL。您需要为 WebGL2
引用 OpenGL 3.0 ES spec
我正在我的图形引擎中处理 MRT。
我正在(并旨在修复)的一个有趣的点是我生成的片段着色器吐出:
layout(location = 0) out vec4 thing1;
layout(location = 2) out vec4 thing2;
应用端的drawBuffers调用是这样的:
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT1]);
但是,我遇到了一个错误:
WebGL: INVALID_OPERATION: drawBuffers: COLOR_ATTACHMENTi_EXT or NONE
很明显,这似乎是不允许的。从我从一篇讨论它的维基百科文章中读到的文档中:
https://www.khronos.org/opengl/wiki/Fragment_Shader
它指出指定的布局位置是指从 drawBuffers 调用指定的数组索引。所以,理论上我会认为这个着色器配置是有效的。
我的理解中缺少什么导致这不起作用?
我主要请求理解而不是修复我的程序,我的生成器将在我完成后更正索引 'correct' 没有位置索引跳过。
更新:如下所述,您可以跳过着色器中的布局位置。我的问题是 drawBuffers 调用的格式不正确,我在索引中有 COLOR_ATTACHMENT1,其中只有 COLOR_ATTACHMENT2 有效。
这是错误的
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT1]);
第 i 第一个附件必须是 gl.NONE
或 gl.COLOR_ATTACHMENT
我
所以必须是这个
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.NONE, gl.COLOR_ATTACHMENT2]);
function main() {
const gl = document.querySelector('canvas').getContext('webgl2');
const vs = `#version 300 es
void main() {
gl_Position = vec4(0, 0, 0, 1);
gl_PointSize = 100.0;
}
`;
const fs = `#version 300 es
precision highp float;
layout(location = 0) out vec4 thing1;
layout(location = 2) out vec4 thing2;
void main () {
thing1 = vec4(1, 0, 0, 1);
thing2 = vec4(0, 0, 1, 1);
}
`;
const prg = twgl.createProgram(gl, [vs, fs]);
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
createTextureAndAttach(gl, gl.COLOR_ATTACHMENT0);
createTextureAndAttach(gl, gl.COLOR_ATTACHMENT2);
gl.drawBuffers([
gl.COLOR_ATTACHMENT0,
gl.NONE,
gl.COLOR_ATTACHMENT2,
]);
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status !== gl.FRAMEBUFFER_COMPLETE) {
console.error("can't render to this framebuffer combo");
return;
}
gl.useProgram(prg);
gl.viewport(0, 0, 1, 1);
gl.drawArrays(gl.POINTS, 0, 1);
checkError();
read(gl.COLOR_ATTACHMENT0);
read(gl.COLOR_ATTACHMENT2);
checkError();
function checkError() {
const err = gl.getError();
if (err) {
console.error(twgl.glEnumToString(gl, err));
}
}
function read(attachmentPoint) {
gl.readBuffer(attachmentPoint);
const pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log(Array.from(pixel).join(','));
}
function createTextureAndAttach(gl, attachmentPoint) {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, tex, 0);
}
}
main();
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>
注意:为 WebGL 引用 OpenGL 文档通常是错误的 and/or 误导 WebGL。您需要为 WebGL2
引用 OpenGL 3.0 ES spec