Clone WebGLRenderTarget.texture

Hi !

I have a little problem when I want to clone my WebGLRenderTarget.texture.
I correctly render my scene in the correct renderTarget. Then I store my texture in an array that I use just later to define my material map.
When I use it without cloning, I get the texture I just rendered. But when I try to clone it, the texture becomes black.

Can someone help me to figure out how can I bypass this problem ?

Thanks for your help !

If you have a minimal live example, that can be edited and debugged, people could at least check whether they observe the same problem. Although this will not solve it, it could at least indicate whether there is some fundamental bug, or it is a mere local issue of your platform (browser/OS).

I tried to use this
const frameTexture = new THREE.FramebufferTexture(1024 * 2, 128);.
This works but my the whole loop to render my texture takes twice as long.
It is sadly not possible for my application :frowning:

First, I can share you how I set up my RenderTarget and how I am processing it.

        let renderTarget = new THREE.WebGLRenderTarget(1024 * 2, 128, {
			wrapS: THREE.MirroredRepeatWrapping,
			wrapT: THREE.MirroredRepeatWrapping,
			minFilter: THREE.NearestMipmapLinearFilter,
			format: THREE.RGBAFormat,
			stencilBuffer: false,
			generateMipmaps: true,
		});

		Render.renderer.setRenderTarget(renderTarget);
		Render.renderer.clear();
		Render.renderer.render(scene, camera);
		Render.renderer.setRenderTarget(null);
		textureMap.push(renderTarget.texture);

And then, I simply apply my texture into my material map property :

mat.map = textureMap[textureMap.length - 1];

When I try the following code :

mat.map = textureMap[textureMap.length - 1].clone();

I get this error :

THREE.WebGLState: TypeError: WebGL2RenderingContext.texSubImage2D: Argument 7 is not valid for any of the 7-argument overloads.

Thank you for your help !

I’m not sure if that’s possible. A texture is in the GPU and the .clone() command only works on objects on the CPU side. I clone a texture with compute shaders and that always means a rendering process whereby the copied texture data then ends up in the GPU.

Thanks for your reply, I completely understand what you means. And that’s completely logical.

So, the only wait to clone it is to copy it in a FrameBufferTexture, as I already tested ? Then my texture would be on the CPU and I can clone it

Yes, that is the right way in WebGL. You can then simply assign the texture to be cloned to a screenquad and create a simple camera for it. You don’t even need a scene because you then render the quad and since nothing other than the quad exists for the texture camera, you don’t need a scene. And so you can clone the texture with a renderTarget.

const VS = `

	in vec2 uv;
	in vec3 position;
	out vec2 vUv;
 
	void main() { 
		vUv = uv;
		gl_Position = vec4(position, 1.0);
}`;


const FS  = `

	precision highp float;
	precision highp int;
	precision highp sampler2D;
	
	in vec2 vUv;
	out vec4 outColor;

	uniform sampler2D srcTexture;

	void main(){

		outColor = texture(srcTexture, vUv);
	}
`;
	
	
	
const textureCamera = new THREE.Camera();	
const screenQuad = new THREE.Mesh(new THREE.PlaneGeometry(2, 2));

const material = new THREE.RawShaderMaterial({ 
	glslVersion: THREE.GLSL3,
	uniforms: { 
	  //maybe other uniforms if you wish
		srcTexture: //assign texture which you want to clone
	}, 
	vertexShader: VS, 
	fragmentShader: FS, 
	depthTest: false,
	blending: 0
});

const framebuffer = new THREE.WebGLRenderTarget(size, size);

screenQuad.material = material;
//maybe some uniforms if you want
material.uniformsNeedUpdate = true;			
renderer.setRenderTarget(framebuffer);
renderer.render(screenQuad, textureCamera);
renderer.setRenderTarget(null);

Something like that. Adapt this to your needs. You don’t even need the shaders if you don’t want to make any modifications to the textures. Then all you need is a material to which you give your texture. I made the format square here but you can adjust that too.

1 Like

Oh wow, thank you so much. I will try it !

I already render my texture in a customShader. But I didn’t know that I don’t need a new scene for my quad to be rendered. I will improve my implementation under your advise :smiley: