Render Target Texture : update manually

Hi all

I’m playing with render target textures (RTT), and especially update the RTT on demand.
I’m encountering an issue: depending how I update the texture, the result is different. Let me explain it (I don’t succeed to reproduce it in the Playground :-/)

My scene is composed of a secondary camera used to “generate” the RTT, a quad onto I apply the RTT result, and multiple other meshes, some of them as instanced mesh.
There is also a main camera, used to show the multiple objects, and the RTT quad as a picture-in-picture. The RTT quad should display the same result as the full screen.

I tried two different configurations, one fully functional, the other one partially only.

In each of the two configurations, the scene is the same, the RTT is instantiated in the same way (except if I specify it in the following).
I use Observables both for the RTT and for the scene.

// scene configuration
public sceneConfiguration(): void {

	// scene
	this.scene.onBeforeRenderObservable.add(() => { this.onBeforeSceneRender(); });
	this.scene.onAfterRenderObservable.add(() => { this.onAfterSceneRender(); });

	// texture
	this.texture.onBeforeRenderObservable.add(() => { this.onBeforeTileRender(); });
	this.texture.onAfterRenderObservable.add(() => { this.onAfterTileRender(); });
}

private onBeforeSceneRender = (): void => {
	console.log("Before Render Scene");
}

private onAfterSceneRender = (): void => {
	console.log("After Render Scene");
	console.log("");
}

public onBeforeTileRender = (): void => {
	console.log("Before Render Tile");
}

public onAfterTileRender = (): void => {
	console.log("After Render Tile");
}

// render loop
doRender(): void {
	this.mainEngine.runRenderLoop(() => {
		this._frameID++;

		// do some stuff on meshes
		this.updateObjects();

		// render scene
		this.scene.render();
	});
}

// objects configuration
public updateObjects(): void {
	this.updateInstancedObjects();
	this.updateStaticObjects();
}

public updateInstancedObjects(): void {
	console.log("Update Instanced Objects");
	
	// manual culling, send uniforms, etc
	...
}

public updateStaticObjects(): void {
	console.log("Update Static Objects");
	
	// manual culling, send uniforms, etc
	...
}

Config 1:
The render target texture is set as automatic update

texture.refreshRate = 1;

Console logs:

Update Instanced Objects
Update Static Objects
Before Render Scene
Before Render Tile
After Render Tile
After Render Scene

Results: the RTT result is identical as the full screen result => OK

Config 2:
The render target texture is set as manual update

texture.refreshRate = -1;

The onBeforeRenderScene force the RTT to update

private onBeforeSceneRender = (): void => {
	console.log("Before Render Scene");
	this.texture.render();
}

Console logs:

Update Instanced Objects
Update Static Objects
Before Render Scene
Before Render Tile
After Render Tile
After Render Scene

Results: in the RTT result, the static meshes are displayed, but the instanced ones are missing, except for the first update => NOK

Here is the BJS version : Babylon.js v4.1.0-beta.1 - WebGL2

I know that a Playground would be useful, but I’m unable to reproduce the issue on it.
What might be interesting is to know if the automatic update and the manual update are different in their behavior (for ex: some stuff are reseted in the automatic update and not in the manual one, etc…)

Brett

In the case where it does not work, try to do the texture.render() in scene.onBeforeRenderTargetsRenderObservable instead of in scene.onBeforeRenderObservable.

There are a number of things done before this point that may help in rendering the RTT correctly (notably a call to this._evaluateActiveMeshes()).

I really thought it will solve the issue… unfortunately it doesn’t. Thank you anyway for the advice, that should be better to do the texture.render() in scene.onBeforeRenderTargetsRenderObservable instead of in scene.onBeforeRenderObservable.

I would like to correct a particular point in my setup and in the results, maybe this will give you a hint:
My scene gets multiple types of instanced mesh (let’s say 5 parents mesh) and, for each of them, there are hundreds of instances. All the instances of a same parent are not necessarily drawn simultaneously (frustum culling, …).
To reduce memory footprint, I use a pool of InstancedMesh per parent mesh, then I update their instancedBuffers before scene.render(). (Each parent mesh and, therefore, each instance are not necessarily created in the same moment of the application life.)

I said in my previous post that the instanced meshes appears only in the first frame of the RTT, but it’s not perfectly true. Indeed, I noticed that the instances of a same “parent” are visible only the first time one of the instance appears. (The same behavior for each “parents”.)

After texture.render() try to add scene.getEngine().restoreDefaultFramebuffer(); as it is what the default code is doing in the scene class.

If it’s still does not work, then I’m afraid I won’t be able to help more without a PG…

I tried your solution using scene.getEngine().restoreDefaultFramebuffer();, the issue still remains.
In a last hope, I’ve upgraded my version of BJS, going from 4.1.0-beta.1 to 4.1.0-beta.26… the issue goes away, keeping my initial configuration with manual update of the RTT.

Thank you again for your time :wink:
Brett

1 Like