Jump to content

[1.12.x] Parallax - PBR Terrain and Surface Objects [2.0.2]


Gameslinx
 Share

Recommended Posts

So I know a lot of you have experienced the floating / sinking bug on various planets, and since I'm coming close to finishing the scatter system I decided to rewrite the code that's responsible for applying Parallax to make it more efficient.

The old code was 1058 lines and took ~5ms of frame time, usually CPU limiting the framerate. Not ideal at all. After the rewrite, with a mere 208 lines not only is it much more efficient but it also completely eliminates the various problems with the subdivision method. So that means the terrain won't disappear at times, the craft won't float or sink into the terrain, and the performance gain is significant. I got a ~35 FPS increase.

Looking forward to releasing soon :) 

Link to comment
Share on other sites

Posted (edited)
38 minutes ago, The Dressian Exploder said:

Really great to hear about significant performance improvements! Our brethren on crappy laptops will be able to share this beautiful mod without experiencing quite so much spontaneous combustion! Page 69 btw, nice.

Me too. From my estimates this new version (with scatters enabled) will run just as good if not better than the current version. Fingers crossed.

For reference, with tessellation enabled in a densely populated area on Kerbin with a lot of trees and grass , I'm getting ~100 fps at 1440p using an RTX 2080S. With tessellation off it's around 150, so it should absolutely be fast enough assuming everything goes to plan lol

(Although the scatter system does have a fair memory impact)

Edited by Gameslinx
Link to comment
Share on other sites

15 hours ago, Gameslinx said:

So I know a lot of you have experienced the floating / sinking bug on various planets, and since I'm coming close to finishing the scatter system I decided to rewrite the code that's responsible for applying Parallax to make it more efficient.

The old code was 1058 lines and took ~5ms of frame time, usually CPU limiting the framerate. Not ideal at all. After the rewrite, with a mere 208 lines not only is it much more efficient but it also completely eliminates the various problems with the subdivision method. So that means the terrain won't disappear at times, the craft won't float or sink into the terrain, and the performance gain is significant. I got a ~35 FPS increase.

Looking forward to releasing soon :) 

Stop being such a tease then and release it already  I'm not much of a coding-savvy guy, but I am still interested in how you managed to remove 4/5 of the lines and still achieve the same result as before. Different algorithms? Shortcuts that you didn't know at the time you wrote the original code?

Link to comment
Share on other sites

18 minutes ago, OJT said:

I am still interested in how you managed to remove 4/5 of the lines and still achieve the same result as before. Different algorithms? Shortcuts that you didn't know at the time you wrote the original code?

In the current update the code is really convoluted. Here's the explanation, but there's a bit of history:

Spoiler

The goal of "Advanced Subdivision" (which is the name of the part of Parallax responsible) is to subdivide the nearest parts of the terrain to achieve a higher vertex density. Basically, I want more points on the model near the craft. Tessellation (which is what the shader uses) does this on the GPU but it has a drawback. It can only tessellate a mesh up to a factor of 64, and for Kerbal Space Program the size of terrain quads (chunks, basically) are too large for this factor to reach a satisfactory level of detail. The tessellation is responsible for the cool displaced terrain, but it needs some help from some additional subdivision CPU-side to get to the detail required.

So the bottom line is we need more mesh detail near the craft. Early version of parallax used a helper function called MeshHelper which subdivides a mesh linearly given a factor. This was perfect, but it still couldn't quite achieve the detail I wanted. It had another downside - It subdivided the entire mesh, which means even if you will only be looking at a certain part of the mesh, the entire thing is rendered and with the level of detail we need, that's a lot of geometry to render. It's very inefficient, not to mention that subdividing up to that amount of detail takes a long time and would stutter when flying around.

What if there was a way, like tessellation, to subdivide the mesh only in an area we are interested in? This would be an area around the craft where the camera would be close to the ground. Here's a visual representation:

68747470733a2f2f692e696d6775722e636f6d2f514c746579654c2e706e67

In this diagram each cross where a line intersects is a vertex defining a square. You can see that with the old method of subdividing the entire quad, you end up with over twice as many vertices overall yet a lower vertex density in a given area than the second approach, which doesn't even double the vertex count.

The original implementation of Advanced Subdivision back in Parallax 1.3.0 worked on a per-vertex basis, meaning I use the mesh vertices to check where the craft is, which ones are nearby and which ones to select to subdivide. The approach was as follows:

  • I am interested in a 4x4 vertex square around the craft (around 250 x 250 meters in-game) to subdivide
  • Find what square of vertices the craft is in
  • Find the top-left-most vertex in that square to use as a reference point and take its index in the vertex array
  • Count back by the square root of the dimension of the vertex array to get the top-left-most vertex in the 4x4 grid
  • Obtain the other 15 vertices that make up that square
  • Create a new mesh with just those vertices and create the geometry (which means triangulating them)
  • Cut out that same mesh from the original mesh to avoid Z-fighting
  • Subdivide the new mesh to obtain the level of detail required

You can see that the approach is very complicated and confusing. It has a lot of edge cases such as:

  1. What if the craft is at the edge of a quad? There is not a 4x4 grid around the craft - Part of that grid is in another quad, which we have to process independently
  2. What if the craft isn't even in the quad?
  3. How do we account for the height of the quad? The quad is in 3D space, not 2D, making distance calculations potentially return the wrong vertex and offset the grid
  4. What if the craft is at a corner of the quad? Now we have to account for 3 more quads nearby and each have different cases for where those vertices that make up the grid lie
  5. What happens if only 2 vertices are in range? We need 3 to create a triangle - This is what lead to the terrain disappearing at times, or exceptions in the log and low FPS
  6. What if the winding order of the quad mesh changes? Now we need two methods of triangulating the mesh - This is what lead to the sinking/floating bug

Even if the above was taken care of, that's a lot of stuff to process - and this needs processing often because the craft will move and the grid needs updating so that the mesh detail is still highest around the craft. This is the result of this approach:

Introducing Advanced Subdivision 2

Now that I've learned a lot more about meshes from developing the scatter system I realized there was a much easier way to implement this - processing each triangle instead of each vertex.

The new approach is as follows:

  • When the quad is created, create an array of triangles which stores the triangle's center, its 3 vertices and the index in the triangle array that points to those vertices
  • Define a distance and check which triangles are within this distance from the craft
  • Append each triangle to a list of triangles that are in range - These will be cut out to make the new object
    • Otherwise, append each triangle to a list of triangles - These will form the original mesh, but with the triangles in range missing (same as before, to prevent Z-fighting)
  • Once that has run, create the mesh from the triangles. Here I use a hash list to store only unique vertices
  • Subdivide the new mesh to obtain the level of detail required

This approach has a speed of O(n) where n is the number of vertices, as opposed to the previous version which was roughly xO(n^2) which is much less efficient.

In a unity project, this ran at 1600 FPS when performing this calculation every frame without subdividing. When subdividing, it ran at around 200FPS (because subdividing is a lengthy operation). In KSP, I run it once every two seconds. There is no noticeable frame hitch.

So tl;dr, the code is much more efficient, less can go wrong, and it works regardless of mesh topology or terrain height or any such nonsense.

 

Link to comment
Share on other sites

On 8/24/2022 at 12:50 PM, Gameslinx said:

Me too. From my estimates this new version (with scatters enabled) will run just as good if not better than the current version. Fingers crossed.

For reference, with tessellation enabled in a densely populated area on Kerbin with a lot of trees and grass , I'm getting ~100 fps at 1440p using an RTX 2080S. With tessellation off it's around 150, so it should absolutely be fast enough assuming everything goes to plan lol

(Although the scatter system does have a fair memory impact)

This is amazing! Performance problems is the main reason I've put off playing my Beyond Home saving until the new patch.

Link to comment
Share on other sites

4 minutes ago, Artyloo said:

Performance problems is the main reason I've put off playing my Beyond Home saving until the new patch.

Ehh, well, this isn't coming to Beyond Home straight away sadly. @ballisticfox0 has been handling that but I'm not sure if they have plans to update it to the upcoming version or not. I don't have the time to do that myself, so it could be some time before this update reaches BH

Link to comment
Share on other sites

On 8/26/2022 at 12:58 PM, Gameslinx said:

Ehh, well, this isn't coming to Beyond Home straight away sadly. @ballisticfox0 has been handling that but I'm not sure if they have plans to update it to the upcoming version or not. I don't have the time to do that myself, so it could be some time before this update reaches BH

Oh, that's disappointing. But eh, can't complain about free mods. Awesome job on Parallax (and BH).

Edited by Artyloo
Link to comment
Share on other sites

On 7/10/2022 at 6:58 PM, Gameslinx said:

I've finished Gilly and Eeloo's scatters. Only 4 more celestial bodies to go!

I also added a Fresnel effect to the terrain which is noticeable especially on Eeloo. It makes the ice look shinier and behaves more realistically. I can't believe this wasn't included for Parallax's first release, it's a really nice effect

unknown.png

unknown.png

unknown.png

Finally, a nice picture I took on Kerbin

unknown.png

 

 

Wow, I might need to lie down a bit. Its hard to believe this is Kerbal Space Program and not an open-world survival craft game. I'm looking forward to seeing the final product!

Link to comment
Share on other sites

Near Kerbin's poles, you will be able to find ice sheets and the occasional iceberg. And yes, you can send a Kerbal on a hike up the bergs, or land a plane on the sheets ;)

lGa6czV.png

And also, here's a picture of what you might find under the ice sheets on Laythe:

unknown.png

Or on Kerbin

unknown.png

 

Link to comment
Share on other sites

14 minutes ago, Gameslinx said:

Near Kerbin's poles, you will be able to find ice sheets and the occasional iceberg. And yes, you can send a Kerbal on a hike up the bergs, or land a plane on the sheets ;)

lGa6czV.png

And also, here's a picture of what you might find under the ice sheets on Laythe:

unknown.png

Or on Kerbin

unknown.png

 

My guy, you didn't need to recreate No Man's Sky and Subnautica. All you had to do was put touchable rocks on the mun :(

Link to comment
Share on other sites

So in effect, the Kerbin heightmap could be altered to remove the whole land mass on the Northern polar region, and replace it with ice sheets that have traversable water underneath, instead? Amazing.

Link to comment
Share on other sites

25 minutes ago, Poodmund said:

So in effect, the Kerbin heightmap could be altered to remove the whole land mass on the Northern polar region, and replace it with ice sheets that have traversable water underneath, instead? Amazing.

Yes! I won't be doing this straight away though. The ice sheets are currently just there to mask the awful cliff around the edge of the actual poles lol

Link to comment
Share on other sites

6 hours ago, Gameslinx said:

Near Kerbin's poles, you will be able to find ice sheets and the occasional iceberg. And yes, you can send a Kerbal on a hike up the bergs, or land a plane on the sheets ;)

lGa6czV.png

And also, here's a picture of what you might find under the ice sheets on Laythe:

unknown.png

Or on Kerbin

unknown.png

 

You gotta be joking right? This can't be real. What's next, sand dunes changing shapes during dust storms?
This looks lit!

Link to comment
Share on other sites

20 hours ago, Entropian said:

Just install it with RSS, RSS has configs.

I have had it installed but don't see anything different on surfaces, they look vanilla-RSS to me.

So I was one step short of the ultra setting. Working now. Noobs gonna noob.

 

Wanted to upload a photo, but forum says to liquid off.

 

Edited by Jimbodiah
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...