微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

渲染到纹理时黑屏

如何解决渲染到纹理时黑屏

我正在尝试执行以下操作:

  1. 在第一次将场景绘制到我创建的帧缓冲区中。
  2. 获取附加到创建的帧缓冲区的纹理并将其绘制到平面上,以便它可以显示在屏幕上。
  3. 做一些后期处理。

仅使用认帧缓冲区,场景如下所示:

scene with the default framebuffer

目前我无法让第 1 部分和第 2 部分工作。我得到的只是黑屏。但是,平面已正确放置在场景中(通过使用 gl.LINE_STRIP 查看线框确认)。我不确定这是由于我在代码中犯的错误,还是由于对帧缓冲区的工作方式缺乏了解(webgl 对我来说是新手)。

以下是相关代码摘录:

// ======== FRAMEBUFFER PHASE ======== //
const framebuffer = gl.createFramebuffer();

gl.bindFramebuffer(gl.FRAMEBUFFER,framebuffer);

const texture = gl.createTexture();

gl.bindTexture(gl.TEXTURE_2D,texture);

gl.texImage2D(
  gl.TEXTURE_2D,gl.RGB,canvas.clientWidth,canvas.clientHeight,gl.UNSIGNED_BYTE,null // don't fill it with pixel data just yet
);

gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);

gl.framebufferTexture2D(
  gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,texture,0
);

// ======== END FRAMEBUFFER PHASE ======== //

// =========== RENDERBUFFER PHASE ============== //

const renderBuffer = gl.createRenderbuffer();

gl.bindRenderbuffer(gl.RENDERBUFFER,renderBuffer);

gl.renderbufferStorage(
  gl.RENDERBUFFER,gl.DEPTH_STENCIL,canvas.clientHeight
);

gl.framebufferRenderbuffer(
  gl.FRAMEBUFFER,gl.DEPTH_STENCIL_ATTACHMENT,gl.RENDERBUFFER,renderBuffer
);

// =========== END RENDERBUFFER PHASE ============== //

// =========== CHECK FRAMEBUFFER STATUS ============== //

const framebufferState = gl.checkFramebufferStatus(gl.FRAMEBUFFER);

if (framebufferState !== gl.FRAMEBUFFER_COMPLETE) {
  throw new Error(
    `Framebuffer status is not complete: ${framebufferState}`
  );
}

// =========== END CHECK FRAMEBUFFER STATUS ============== //

// =========== FirsT PASS RENDERING ============ //

gl.bindFramebuffer(gl.FRAMEBUFFER,framebuffer);
gl.clearColor(0.1,0.1,1.0);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);

// this sets up the green quad and draws it to the screen
const objectModel = setupObjectModel({
  position: [100.0,-10.0,0.0],colour: [0.734345265462,0.89624528765,0.9868589658,1.0],gl,canvas,});

objectModel.draw({
  shaderProgram: mainShaderProgram,camera: updatedCamera,currentTime,deltaTime,});

// =========== END FirsT PASS RENDERING ============ //

// =========== SECOND PASS RENDERING ============ //

// back to rendering with the default framebuffer
gl.bindFramebuffer(gl.FRAMEBUFFER,null);
gl.clearColor(1.0,1.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.disable(gl.DEPTH_TEST);

gl.useProgram(frameBufferShaderProgram);

// prettier-ignore
const verts = [
  // positions  // texCoords
  -1.0,0.0,-1.0,1.0
];

// prettier-ignore-end
const screenQuad = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER,screenQuad);

gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(verts),gl.STATIC_DRAW);

const aPosAttributeLocation = gl.getAttribLocation(
  frameBufferShaderProgram,"aPos"
);

gl.enabLevertexAttribArray(aPosAttributeLocation);
gl.vertexAttribPointer(
  aPosAttributeLocation,2,gl.FLOAT,false,Float32Array.BYTES_PER_ELEMENT * 4,0
);

const aTexCoordsAttributeLocation = gl.getAttribLocation(
  frameBufferShaderProgram,"aTexCoords"
);

gl.enabLevertexAttribArray(aTexCoordsAttributeLocation);
gl.vertexAttribPointer(
  aTexCoordsAttributeLocation,Float32Array.BYTES_PER_ELEMENT * 2
);

const screenTexture = gl.getUniformlocation(
  frameBufferShaderProgram,"screenTexture"
);

gl.uniform1i(screenTexture,0);

gl.drawArrays(gl.TRIANGLES,6);

这里是帧缓冲着色器程序:

// vertex shader 
precision mediump float;

attribute vec2 aPos; 
attribute vec2 aTexCoords; 

varying vec2 TexCoords; 

void main() {
    gl_Position = vec4(aPos.x,aPos.y,1.0);
    TexCoords = aTexCoords;
}
// fragment shader
precision mediump float;

uniform sampler2D screenTexture; 
varying vec2 TexCoords;

void main() {
    // the texture coordinates are fine here,it's the screen texture that's the issue
    gl_FragColor = texture2D(screenTexture,TexCoords.xy);
}

解决方法

这是一个常见的错误。 WebGL 1.0 基于 OpenGL ES 2.0。与 mipmap 相同的规则适用于纹理帧缓冲区附件。帧缓冲区纹理的大小必须是 2 的幂。请参阅 Texture Completeness and Non-Power-Of-Two Textures

创建一个大小等于 2 的幂的帧缓冲区(例如 1024x1024):

    it('BigTile hover check',()=>{
        const { container } = render(<BigTile />)
        const elem = container.querySelector<HTMLElement>('.MuiPaper-root')
        if (!elem) fail("Element is null.")
        fireEvent.mouseOver(elem);
        const elemAfterHover = container.querySelector<HTMLElement>('.MuiPaper-root')
        if (!elemAfterHover) fail("Element after hover is null.")
        console.log(elemAfterHover.style)
    })

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。