Poor jagged rendering with Lazarus in never version of Castle

I have this issue with poor quality jagged renderings when I use Castle Gaming Engine in new versions of Lazarus. I’m not sure if this is related to being a newer version of Lazarus or because I have had to use a newer version of CGE (6.92).

This has come about because I have been using an old Lazarus version for all my application development (Lazarus 2.0.6) so I want to use a newer version of Lazarus but quite a number of my applications use CGE for rendering varies things like industrial machine simulation/visualization. The challenge using newer versions of Lazarus is that I then need to use a newer version of CGE. When I originally wrote the apps in CGE, I used the TCastleControl.SceneManager for managing TCastleScene’s but this method is no longer supported in the newer version of CGE so I have had to update the code to use TCastleViewPort (as in the model_3d_viewer example).
This is when I noticed this issue.

Originally I though that I must be doing something wrong but I then tested a model that I’m using in my projects in the model_3d_viewer example project in both Lazarus 2.0.6 (CGE 6.5) and Lazarus 2.2.4/3.4 (CGE 6.92).

The same issue appears in the model_3d_viewer example project using Lazarus 2.2.4/3.4 (CGE 6.92). Below are screen shots for the same model. If you look closely, you can see that the posts are not rendering properly in the second image.

Lazarus 2.0.6 (CGE 6.5)

Lazarus 2.2.4/3.4 (CGE 6.92)

Another example is our machine graphics in one of the my applications. This below is what it used to look like in Lazarus 2.0.6 (CGE 6.5).

This is what the same application compiled in Lazarus 2.2.4 or Lazarus 3.4 using CGE 6.92, looks like.

I’m also noticing a much higher GPU and CPU usage on the same application compiled in Lazarus 2.2.4 or Lazarus 3.4 using CGE 6.92 (shown below).

I’m not sure if this is CGE or a Lazarus issue but any help in pointing me in the right direction would be much appreciated.

Hi!

  1. You mention you use CGE with the version of Lazarus packages 6.92.

    Note that there’s an even newer version available, since the last Wednesday, see news: 7.0-alpha.3 release: physics, blending, batching, shadows, Delphi (packages, Linux), UI masks, lots of editor UX, Android, iOS work, float textures, VS Code, Sketchfab, more… – Castle Game Engine . The full name of new version is 7.0-alpha.3, though Lazarus packages are marked as 6.93.

    So, please upgrade :slight_smile: Though I think it will not fix the issue you report, I think I know what’s the issue (see AD 2), but upgrading is anyway advised.

  2. The cause of the issue is likely that we changed the default ProjectionNear in Castle Game Engine. This was done in July 2022 (see this news ). The ProjectionNear determines the “near clipping plane” of your camera. It also affects the precision of depth values (and thus their comparison).

    • In the old engine versions, ProjectionNear was auto-calculated (to be large for worlds with large dimensions, and to be small for small worlds).

    • In the new engine versions, it is just assumed 1.0, by default (and you can adjust it). More on “why” and “how to cope” below.

    What you show on your screenshots, implies you that the precision of Z-buffer is too bad and you experience “Z-fighting”. Note: I’m using here some internal terms – you can read e.g. wikipedia about Z-fighting or just ignore this technical jargon and jump to solution below :slight_smile:

    This likely means you have large objects (their dimensions are large, e.g. width / height / depth 10000). In this case, you should set ProjectionNear to something larger. This will improve the precision of Z-buffer, and thus avoid Z-fighting.

    Why did we change it in the engine? Because auto-calculating ProjectionNear was causing other bugs, and they were quite tricky. Namely, if something was animated and could fly far away (e.g. an arrow shoots into infinity) then ProjectionNear was getting larger and larger as the application runs, and suddenly Z-fighting “appears in the middle of the simulation”. Ultimately, we decided it’s better to not do this auto-calculation (though you can always do it youself, see below), and let the user set it explicitly. Other engines (like Unity) also don’t auto-calculate the equivalenet property.

    How to cope with this?

    • The most important thing is to test. Just increase the TCastleCamera.ProjectionNear. You likely access it like MyViewport.Camera.ProjectionNear. You can manipulate it both in editor and from Pascal code. Try larger values than 1: 2, 8, 16, maybe even larger.

    • If you want, you can just hardcode this larger ProjectionNear, like 10, and that’s it. You found a good value for your large models, it’s good.

    • Or, if you want, you can auto-calculate it, just like CGE was doing in the past. Use a code like this: castle-model-viewer/castle_model_viewer.dpr at 6d7b1978dca6ba0e711c14e8e3bc7ac81e45432e · castle-engine/castle-model-viewer · GitHub .

      The shorter version of this routine is just this:

      MyViewport.Camera.ProjectionNear := 
        MyViewport.BoundingBox.AverageSize(false, 1.0) * 0.005 * 0.6;
      

      (in the code above, I inlined values of 2 constants, WorldBoxSizeToRadius, RadiusToProjectionNear; there’s nothing special about them, they are just “good enough heuristics” so feel free to adjust).

    This should fix the main issue you report. Let me know if it helps – or not, we can debug it more, though I think my guess is right :slight_smile:

  3. This is harder to debug, as it can be caused by many things.

    • Make sure you have Appliaction.LimitFPS at 100 (or even lower, like 60).

    • Both TCastleControl and internal Lazarus code around processing events changed a lot in that time. It’s hard to guess here what’s the cause.

    • A worthy test is to see if applications using TCastleWindow (like default projects, created from editor “New Project”) also have this.

    • Do you have a laptop with 2 GPUs? Maybe the application is running on a slower GPU, and you can force it to run on a faster one. We do it automatically for new applications created from editor “New Project”, see Dedicated GPU | Manual | Castle Game Engine .

    • Admittedly, this is hard to guess. If you have the time, “bi-secting” the issue (i.e. testing with older commits of Castle Game Engine) will give the answer. Naturally first you must have the Lazarus version “unchanging” and confirm that the problem is not coming from Lazarus change.

@michalis that you very much for your detailed reply. I had suspected that it was something to do with the projection scaling but just didn’t know what property I was looking for.

Initially after seeing your reply I immediately tried setting the ProjectionNear in my project but it had no effect. I had to not use ‘AutoCamera’ for it work properly. I assume this must means that the ‘AutoCamera’ resets the ProjectionNear back to it’s default value.

In regards to the high CPU, like you say I’ll need to dig into that some more to figure out if it’s something in Lazarus or CGE.

Again, thank you for your quick and comprehensive reply. Hopefully this topic might be able to help someone in the future with the same issue.

1 Like

Ah indeed – you need to turn off (deprecated now) AutoCamera for my answer to be valid. Good catch! I’m happy it’s solved.

Details: When AutoCamera is true, we override ProjectionNear with the value that we try to derive from TCastleViewport contents (we look at Viewpoint node inside viewport’s MainScene, use camera radius from it, and from camera radius we derive projection near). This “auto detection” done by AutoCamera turned out to be often an unexpected nuisance (like here), that’s why we deprecate AutoCamera and recommend to just specify all camera settings explicitly.