GUI elements not correctly placed when taking screenshots with Render Target

Hello guys,
I am trying to capture some screenshots with a custom RenderTargetTexture and sometimes the GUI elements are misplaced on the screenshot even though I add a timer to make sure everything has rendered. Tried setting the timer to a higher value but didn’t make a difference. What could cause this? I think it is worth noting that I take screenshots in a loop and change the camera position to get different views. Also the GUI elements are linked to meshes which are also not positioned correctly. This does not happen on all screenshots. Adding a picture to show how it looks cause I cannot replicate it in a playground.

Hello! It’s a bit hard to tell without a playground :confused: any chance you can share your project with us?

I cannot share the entire project but basically I am calling this method in a loop for each different point of view:

 async createRTT(camera, pdfResult) {
        let self = this;
        this.editor.sceneComponent.engine.flushFramebuffer();
        camera.attachControl(this.editor.canvas, true);
        this.editor.sceneComponent.get().activeCameras.push(camera);
        const rtt = new RenderTargetTexture(
            'screenShot',

            {
                width: this.editor.sceneComponent.engine.getRenderWidth(),
                height: this.editor.sceneComponent.engine.getRenderHeight(),
            },
            this.editor.sceneComponent.get()
        );

        camera.outputRenderTarget = rtt;

        await new Promise((resolve, reject) => {
            window.setTimeout(() => {
                rtt.readPixels(undefined, undefined, undefined, true).then((data) => {
                    const { width, height } = rtt.getSize();
                    Tools.DumpData(
                        width,
                        height,
                        data,
                        async function (fileData) {
                            const jpgImage = await pdfResult.embedPng(fileData);
                            const page = pdfResult.addPage();
                            self.setPageOrientation(page);
                            const newSize = jpgImage.scaleToFit(page.getWidth(), page.getHeight());

                            const heightIn = newSize.height;
                            const widthIn = newSize.width;
                            page.drawImage(jpgImage, {
                                x: page.getWidth() / 2 - parseInt(widthIn) / 2,
                                y: page.getHeight() / 2 - parseInt(heightIn) / 2,
                                width: parseInt(widthIn),
                                height: parseInt(heightIn),
                            });
                        },
                        undefined,
                        undefined,
                        true
                    );
                });
                rtt.dispose();
                rtt.disposeFramebufferObjects();
                rtt.clearPostProcesses(true);
                camera.outputRenderTarget = null;
                this.editor.sceneComponent.get().activeCameras = [this.camera];
                resolve();
            }, 5000);
        });
    }

This is how I create and position the camera:

async placeCameraInFrontOfWall(wall) {    
         const screenshotCamera = new FreeCamera(
            'UniversalCamera',
            new Vector3(roomCenter.x, 20, roomCenter.y),
            this.editor.sceneComponent.get()
        ); 

        this.editor.sceneComponent.addToActiveCameras(screenshotCamera);

        screenshotCamera.mode = Camera.ORTHOGRAPHIC_CAMERA;
        const wallDirection = wall.getDirection();
        const middleOfWall = wall.baseInnerCornerB.clone().add(wallDirection.scale(wall.length / 2));
        const roomCorners = this.editor.sceneInfo.corners.concat(this.editor.sceneInfo.corners[0]);
        const margin = 2;
        const distance = wall.length + margin;

        const rect = this.editor.sceneComponent.engine.getRenderingCanvasClientRect();
        const aspect = rect.height / rect.width;

        screenshotCamera.orthoLeft = -distance;
        screenshotCamera.orthoRight = distance;
        screenshotCamera.orthoTop = 2 * distance * aspect;
        screenshotCamera.orthoBottom = -2 * aspect;

        //Calculates a position in front of the wall to place the camera 
        const shiftedPosition = Utilities.calculateShiftValue(middleOfWall, -distance, roomCorners, wall);

        screenshotCamera.position = shiftedPosition;
        screenshotCamera.target = middleOfWall;
    }

I don’t even know how to debug this because it doesn’t happen to all the screenshots.

So, just to confirm the flow of what’s happening, you already have a scene with a GUI, then you call this loop for a list of points, and for each point:

  • call placeCamera…
  • call createRTT

Is that right?

One thing that caught my eye is that placeCamera is an async method, even through it doesn’t seem to be performing any async operation?

Yes that’s right. Basically I have a room and I need to take a screenshot of each wall. placeCamera(wall) positions the camera in front of the wall and sets the ortho values based on the wall length. Then createRTT is called in a loop for each wall.
You are right I just removed the async. Doesn’t make any difference to my issue though

I should’ve mentioned that I have other issues with the positioning of GUI elements in other parts of the software after upgrading to version 5.0. They have some kind of offset to their position.

That’s even stranger o.o are you able to reproduce this on the Playground?

The disappearing lines were a matter of the gray mesh overlapping with the lines. While the position of the GUI elements in this case was a bug related to some specific logic in the project. Thank you for taking your time to check this out :slight_smile:

2 Likes