leota

Antialiasing rendering issue on Angular 5

Recommended Posts

Hi there,

I'm trying to run babylon on an Angular 5 application, but the quality of the rendering is very low (see image below).

This is what I've done:

  • Install babylon through npm: npm i --save babylonjs
  • Then I had some warning during compiling process. It couldn't find cannon, earcut and oimo, so I added them through npm too.
  • Then I created my scene (following the relevant code): 
     init(canvasId: string, canvasWidth: number) {
        const canvas = <HTMLCanvasElement>document.getElementById(canvasId);
        this.engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
        this.createScene(canvas);
      }  
    
    createScene(canvas: HTMLCanvasElement): void {
        this.scene = new BABYLON.Scene(this.engine);
        this.scene.clearColor = new BABYLON.Color4(0.5, 0.5, 0.5, 1);
        this.camera = new BABYLON.ArcRotateCamera('Camera', Math.PI / 2, Math.PI / 2, 2, BABYLON.Vector3.Zero(), this.scene);
        this.camera.attachControl(canvas, true);
        // Create default pipeline and enable dof with Medium blur level
        this.renderingPipeline = new BABYLON.DefaultRenderingPipeline('default', true, this.scene, [this.scene.activeCamera]);
        this.renderingPipeline.samples = 4;
        this.renderingPipeline.fxaaEnabled = true;
    
        // Add lights to the scene
        const light1 = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(1, 1, 0), this.scene);
        const light2 = new BABYLON.PointLight('light2', new BABYLON.Vector3(0, 1, -1), this.scene);
    
        const sphere = BABYLON.MeshBuilder.CreateSphere('sphere', { diameter: 2 }, this.scene);
    
        this.animate();
      }
    
      private animate(): void {
        // run the render loop
        this.engine.runRenderLoop(() => {
          this.scene.render();
        });
    
        // the canvas/window resize event handler
        window.addEventListener('resize', () => {
          this.engine.resize();
        });
      }
    

    Everything runs without error, but the render quality is very bad. How is this possible? Are there any specific steps to do when working with Angular? Unfortunately same code works fine in PG, so I did not create one as the problem seems to be related to angular.

Screen Shot 2018-07-18 at 21.20.37.png

Share this post


Link to post
Share on other sites

Have you tried the 4th engine option - defaults to false.  Try true:
http://doc.babylonjs.com/api/classes/babylon.engine#constructor
edit: your second Engine constructor param of 'true' puts antialias on the EngineOptions, so that's not it...  I wouldn't imagine it has anything to do with Angular.  If that doesn't work, how do you declare your canvas element - ie: list the canvas element attributes and CSS.

Share this post


Link to post
Share on other sites

That was fast.  Check my edit above to request more info.  I've seen this as well with explicit width/height on canvas or other CSS. Also, is that screenshot from your PC?

edit: How the Engine is instantiated in your first post is the same as default playground, so that was definitely not it - I got curious how the engine was created for playgrounds... :)
https://github.com/BabylonJS/Babylon.js/blob/master/Playground/js/index.js#L557

Share this post


Link to post
Share on other sites
12 minutes ago, brianzinn said:

That was fast.  Check my edit above to request more info.  I've seen this as well with explicit width/height on canvas or other CSS. Also, is that screenshot from your PC?

Yes that's a screenshot from my PC.

This is the html:

<canvas class="viewport" id="viewport"></canvas>

and related CSS:

:host {
    z-index: 1;
}

.viewport {
    width: 100%;
    height: 100%;
    touch-action: none;
}

EDIT: @brianzinn you're right, I'm using explicit width for the host element: 

<app-viewport [canvasWidth]="canvasWidth$ | async" [style.width.px]="canvasWidth$ | async"></app-viewport>

The thing is that the window is made of two panels, one containing the canvas and another contains the GUI. The GUI panel can be closed so I need to resize the canvas when that happen. I can't find another way rather then the one shown above

Share this post


Link to post
Share on other sites

that looks fine.  I've only seen meta tags messing it up otherwise - so, your class and id names caught my attention.

<meta name="viewport" content=...>

I would use the inspector to look more at the canvas to see how it's being treated.  I've found issues before and compared them to ie: engine.getRenderHeight() and window.devicePixelRatio stuff.  Maybe somebody else has idea?  Share if you have more details.  cheers.

Share this post


Link to post
Share on other sites

I'm using it in two angular projects, one angular 5, one angular1. Def not angular problem, however could be related to canvas size as stated above. One other thing to check is scene.getEngine().getHardwareScalingLevel(). 1 is the default, anything < 1 = higher quality, anything > 1 = lower quality

 I would also take the postprocess out of the equation for now as well

 

Share this post


Link to post
Share on other sites

Your new info gives me another idea.  The thing about SPA apps, is that your resize handler won't be triggered when DOM elements resize. ie:

window.addEventListener('resize', () => {
   this.engine.resize();
});

Can you attach the resize to your canvas or parent element that is resizing?  I've seen custom angular directives for that for elements, too.  Also, if you use percentage CSS (of parent element) then canvas should resize automatically as well.

Share this post


Link to post
Share on other sites

Hey guys thanks for suggestions. Unfortunately I'm at work and not able to try them :( 

I'll check asap, and if nothing works I'll try to replicate the project on stackblitz, so you can put the hands on it. 

Thanks for the support already given :)

Share this post


Link to post
Share on other sites
15 minutes ago, SvenFrankson said:

Hi,

You can add a resize after the first frame, it will be ok.


this.animate();
setTimeout(
    () => {
        this.engine.resize();
    },
    100
);

(but it's a fix, I don't really understand why the issue happens in the first place, I also experience it quite often)

Awesome! Situation is getting very interesting here 🤔

Hope someone can give an explaination regarding this issue

Share this post


Link to post
Share on other sites
5 hours ago, leota said:

Hope someone can give an explaination regarding this issue

From my post above about resize - it's important to call engine.resize() when the canvas changes size.  Not just when the browser window resizes.

I think the reason for that is that the DOM elements are still moving around while the page is loading (after DOM element is loaded) - I haven't run into that before.  The resize on timeout is only a partial fix, because the engine.resize() is only called when the browser window is resized.  I think on your side panel handler you will also need to resize. ie: try with

this.sidePanelWidth = (this.isSidePanelOpen) ? 600 : 10;

More noticeable with a wider side panel.  With the side panel open resize the browser window. Then close the side panel and you will see the issue.

Share this post


Link to post
Share on other sites
13 minutes ago, brianzinn said:

From my post above about resize - it's important to call engine.resize() when the canvas changes size.  Not just when the browser window resizes.

I think the reason for that is that the DOM elements are still moving around while the page is loading (after DOM element is loaded) - I haven't run into that before.  The resize on timeout is only a partial fix, because the engine.resize() is only called when the browser window is resized.  I think on your side panel handler you will also need to resize. ie: try with


this.sidePanelWidth = (this.isSidePanelOpen) ? 600 : 10;

More noticeable with a wider side panel.  With the side panel open resize the browser window. Then close the side panel and you will see the issue.

Yep you're right, callling engine.resize() on every canvas change works fine. Still have the issue at the first frame but I've fixed it calling the engine.resize() when the DOM has been fully rendered:

ngAfterViewInit() {
  this.scene.engine.resize();
}

like this I can get rid of the setTimeout() fix.

Thanks everyone for the support 😃

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.