I’m trying to use FramebufferTexture
to map to a plane mesh basic material. Below is the simplified version of my code. Any help would be appreciated!
// For simplicity sake, defined these const:
// renderBuffer = THREE.WebGLRenderTarget
// mainScene = THREE.Scene
// bufferScene = THREE.Scene
// renderer = THREE.WebGLRenderer
// camera = THREE.OrthographicCamera
// bufferTex = THREE.FramebufferTexture
renderer.setAnimationLoop(animLoop);
function animLoop() {
renderer.setRenderTarget(renderBuffer);
renderer.render(bufferScene, camera);
// this gives me error
renderer.copyFramebufferToTexture(bufferTex, new THREE.vector2());
renderer.setRenderTarget(null);
renderer.render(mainScene, camera);
}
The error in question:
Chromium 127.0.6533.89
GL_INVALID_OPERATION: Invalid copy texture format combination.
Firefox 127.0.2
WebGL warning: copyTexSubImage: Implementation bug, please file at https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Canvas%A+WebGL! ANGLE is particular about CopyTexSubImage formats matching exactly.
I’ve tried following this example with no success:
https://github.com/mrdoob/three.js/blob/817a222f2d12baf44a38baf256bc9d4f65d82465/examples/webgl_framebuffer_texture.html
Three version: 0.166.1
I’ve never used copyFramebufferToTexture
because I always do it with the renderTarget. But what I see is that your frameBuffer has no width and no height. Your new THREE.Vector2() is empty. In the example you can see that the vector is filled first and only then is copyFramebufferToTexture
rendered with the filled vector. In your case width and height are undefined
and that leads to an error.
new THREE.vector2()
You need
new THREE.vector2(width, height);
So that the vector doesn’t have to be recreated in every render loop, it’s best to set it in the init. So try it with width and height, then it will definitely be better
An alternative way to render a scene into a texture is to use a renderTarget
//in the init
let frameBuffer = new THREE.WebGLRenderTarget(width, height, {
format: THREE.RGBAFormat,
minFilter: THREE.LinearMipmapLinearFilter,
magFilter: THREE.LinearFilter,
generateMipmaps: true,
wrapS: THREE.RepeatWrapping,
wrapT: THREE.RepeatWrapping
});
let target = frameBuffer.texture;
//renderloop
renderer.setRenderTarget(frameBuffer);
renderer.render(bufferScene, camera);
renderer.setRenderTarget(null);
renderer.render(mainScene, camera);
By the way, you don’t necessarily need a bufferScene. You can render your planemesh directly if it is the only thing you want rendered in the bufferScene.
So that’s how:
renderer.render(planemesh, camera);
You can imagine this as if you had glued the planemesh to the camera lens.
1 Like
renderTarget works perfectly! + I followed your optimizations. It’s very performant now. You have no idea how much time I’ve spent on this. Thank you!
1 Like