我们正在Webgl 1中工作,并尝试使用模具渲染到立方体贴图。单独渲染到立方体贴图效果很好。当我们添加DEPTH_STENCIL
渲染缓冲区时,它将停止写入立方体贴图,并且不会发出错误。
TEXTURE_2D
而不是TEXTURE_CUBE_MAP
不会发生这种情况。framebufferRenderbuffer
的电话中断了它。这是一种最低限度的娱乐活动。如您所见,我们将获得控制台输出,其中前三个调用的值正确,而最后一个调用的值为零。
为什么会发生这种情况,而使渲染缓冲区与多维数据集映射一起使用,我们还缺少什么呢?
const canvas = document.createElement("canvas");
const gl = canvas.getContext("webgl");
console.log(TEST(false, false));
console.log(TEST(false, true));
console.log(TEST(true, false));
console.log(TEST(true, true));
function TEST(useCubemap, useBuffer) {
const size = 512;
const textureType = useCubemap ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
// SETUP THE PROGRAM
{
const program = gl.createProgram();
const vertShader = gl.createShader(gl.VERTEX_SHADER);
const fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertShader, `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.2, 1.0);
}
`);
gl.compileShader(vertShader);
gl.attachShader(program, vertShader);
gl.shaderSource(fragShader, `
void main() {
gl_FragColor = vec4(0.1, 0.2, 0.3, 0.4);
}
`);
gl.compileShader(fragShader);
gl.attachShader(program, fragShader);
gl.linkProgram(program);
gl.useProgram(program);
}
// SETUP THE QUAD
{
const posBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, +1, -1, -1, +1, +1, +1, -1]), gl.STATIC_DRAW);
}
// SETUP THE FRAMEBUFFER
{
const fb = gl.createFramebuffer();
const targetTexture = gl.createTexture();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.bindTexture(textureType, targetTexture);
gl.texParameteri(textureType, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(textureType, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(textureType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(textureType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// SWITCH TEXTURE TYPE
if (textureType === gl.TEXTURE_2D) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, targetTexture, 0);
} else {
for (let i = 0; i < 6; i++) gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, targetTexture, 0);
}
}
// SETUP THE RENDER BUFFER
{
const rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, size, size);
// TAKING THIS OUT MAKES IT WORK
if (useBuffer) gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb);
}
// DISABLE THE OBVIOUS CULPRITS
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.STENCIL_TEST);
gl.disable(gl.SCISSOR_TEST);
// DO A RENDERYFUCK
gl.viewport(0, 0, size, size);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
// GET THE OUTFUCK
const pixels = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
return pixels;
}
答案 0 :(得分:0)
对我有用。在您发布的代码中,所有4个调用的值都相同。您正在使用什么OS / GPU /驱动程序?如果您使用的是Chrome,是否可以粘贴about:gpu
的内容?
这听起来像是驱动程序中的错误。这可能是WebGL规范中的一个错误。
OpenGL ES规范不不需要任何帧缓冲区附件的组合才能工作(零,zilch,nada)。 WebGL规范需要3种组合才能起作用。来自the spec, section 6.8:
以下所有帧缓冲对象附件的组合,当所有附件都是完整的帧缓冲附件,非零且具有相同的宽度和高度时,必须导致帧缓冲完整:
- COLOR_ATTACHMENT0 = RGBA / UNSIGNED_BYTE纹理
- COLOR_ATTACHMENT0 = RGBA / UNSIGNED_BYTE纹理+ DEPTH_ATTACHMENT = DEPTH_COMPONENT16渲染缓冲区
- COLOR_ATTACHMENT0 = RGBA / UNSIGNED_BYTE纹理+ DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL渲染缓冲区
但是请查看WebGL一致性测试only TEXTURE_2D
is tested。
因此,首先,这表明您的驱动程序/ GPU不支持与多维数据集映射结合使用。通过调用gl.checkFramebufferStatus
进行测试。如果未返回gl.FRAMEBUFFER_COMPLETE
,则您的设置不支持渲染到具有深度模具附件的立方体贴图。
const canvas = document.createElement("canvas");
const gl = canvas.getContext("webgl");
TEST("TEXTURE_2D", "DEPTH_COMPONENT16");
TEST("TEXTURE_2D", "DEPTH_STENCIL");
TEST("TEXTURE_CUBE_MAP", "DEPTH_COMPONENT16");
TEST("TEXTURE_CUBE_MAP", "DEPTH_STENCIL");
function TEST(target, depthBufferFormat) {
const size = 16;
const textureType = gl[target];
// SETUP THE FRAMEBUFFER
{
const fb = gl.createFramebuffer();
const targetTexture = gl.createTexture();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.bindTexture(textureType, targetTexture);
gl.texParameteri(textureType, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(textureType, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(textureType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(textureType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// SWITCH TEXTURE TYPE
if (textureType === gl.TEXTURE_2D) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, targetTexture, 0);
} else {
for (let i = 0; i < 6; i++) gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, targetTexture, 0);
}
}
// SETUP THE RENDER BUFFER
{
const rb = gl.createRenderbuffer();
const format = gl[depthBufferFormat];
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, format, size, size);
// TAKING THIS OUT MAKES IT WORK
const attachmentPoint = depthBufferFormat === "DEPTH_COMPONENT16"
? gl.DEPTH_ATTACHMENT
: gl.DEPTH_STENCIL_ATTACHMENT;
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentPoint, gl.RENDERBUFFER, rb);
}
const success = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
console.log(target, depthBufferFormat, success ? "PASS" : "**FAIL**");
}
您需要模具还是仅深度缓冲器? this sample run是否适合您?它使用的是DEPTH_COMPONENT16
附件。