Distant objects

Everything about development and the OpenMW source code.
User avatar
AnyOldName3
Posts: 1594
Joined: 26 Nov 2015, 03:25

Re: Distant objects

Post by AnyOldName3 » 08 Apr 2019, 18:29

Here's some discussion on objects-that-get-disabled-by-a-script-friendly batching system: https://pastebin.com/ycvQJ8U3. This has been pinned in a discord channel for a while, but I'm posting it here so it doesn't get lost.
AnyOldName3, Master of Shadows

User avatar
Ravenwing
Posts: 334
Joined: 02 Jan 2016, 02:51

Re: Distant objects

Post by Ravenwing » 08 Apr 2019, 21:00

I won’t pretend to understand the intricacies of that but everyone seems to feel confident it will work and seems to make sense, so I’m excited. Any chance anyone is working on this already? Or has most of the focus shifted to bug fixes and the CS?

User avatar
AnyOldName3
Posts: 1594
Joined: 26 Nov 2015, 03:25

Re: Distant objects

Post by AnyOldName3 » 08 Apr 2019, 21:33

There's a very high chance I'll start on it at some point unless someone else gets there first.
AnyOldName3, Master of Shadows

User avatar
Stomy
Posts: 47
Joined: 11 Dec 2018, 02:55
Location: Fhloston Paradise!
Contact:

Re: Distant objects

Post by Stomy » 10 May 2019, 15:01

I was thinking about this today and thought about some tricks we could emulate from Oblivion/Skyrim. These would require extra work by modders but supporting them would allow us to push static view distance much further by using pre-generated, pre-atlased assets specially tuned for distant viewing.

Billboard/Impostor Trees
Most games take this approach with distant trees anyway, and the Total War games use it for characters. Just use a 2D sprite for trees (or other objects, but trees make the most sense) at a certain distance out. The best way to support these would be if it could be done with a NiNode that vanilla would simply ignore, the same way akortunov did native graphics herbalism. Does anyone familiar with later versions of .nif know if this is how Skyrim or Oblivion handles tree impostors?

Distant-Only Statics
Rather than loading or generating and potentially atlasing each mesh in a cell at long distance, modders could hand-make a basic model for an entire cell's statics. This would only be used for really large objects that should be visible from far away like Vivec's cantons or White-Gold Tower, and loading them could allow us to ignore other statics in their cells.

Both of these could be used instead of generated distant statics or alongside them, like having full detail at short range, generated LODs at mid-range, impostors/distant-only statics at long/max-terrain range
Never attribute to bad code, that which can be adequately explained with clever hacks

User avatar
akortunov
Posts: 641
Joined: 13 Mar 2017, 13:49
Location: Samara, Russian Federation

Re: Distant objects

Post by akortunov » 10 May 2019, 17:13

Stomy wrote:
10 May 2019, 15:01
Does anyone familiar with later versions of .nif know if this is how Skyrim or Oblivion handles tree impostors?
IIRC, you need a separate DDS (handmade or generated by an external tool) as an object billboard, a one billboard per mesh.
Then you should generate a description where to place them for every object's instance in active plugins, in the similar way as MGE does.
From what I can tell, every time you modify a game world, you need to generate data again.

Also I doubt that such approach will be useful in the Morrowind - there are almost none of rotationally invariant meshes.
Otherwise MGE would use billboards instead of simplified meshes, if it would be easy to implement.

User avatar
Stomy
Posts: 47
Joined: 11 Dec 2018, 02:55
Location: Fhloston Paradise!
Contact:

Re: Distant objects

Post by Stomy » 10 May 2019, 17:54

akortunov wrote:
10 May 2019, 17:13
From what I can tell, every time you modify a game world, you need to generate data again.
That doesn't sound right, would you have to do it per-instance? It makes way more sense just to do it per-mesh, then you could substitute the billboard for the mesh at long distances. I also don't see what would prevent us from atlassing the billboards too.

If nif could be leveraged for graphics herbalism then it should be possible to do this with some well-placed extra NiStringProperties or something, we don't have to emulate the actual implementation of billboarding from later games, it might just be useful so that it could later be reused as-is for OpenOB.
akortunov wrote:
10 May 2019, 17:13
Also I doubt that such approach will be useful in the Morrowind - there are almost none of rotationally invariant meshes.
Well no, not in vanilla Vvardenfell, but all the forests in province mods like Solitude, Vorndgad, Massiquerran, most of Nibenay and Valenwood would. And don't forget all the pine trees on Solstheim, with billboards you'd be able to render Hirstaang from the West Gash without a serious performance hit.
Never attribute to bad code, that which can be adequately explained with clever hacks

User avatar
akortunov
Posts: 641
Joined: 13 Mar 2017, 13:49
Location: Samara, Russian Federation

Re: Distant objects

Post by akortunov » 10 May 2019, 18:23

Stomy wrote:
10 May 2019, 17:54
That doesn't sound right, would you have to do it per-instance?
I do not understand what do you want.
Both Morrowind and OpenMW support NiLODNode, which allows to define different detalization levels in one mesh.
You can use billboards for simplified detail levels as well (Morrowind Optimization Patch uses a similar approach for particle systems).
Unfortunately, this approach usually does not increase performance well:
1. Most of Morrowind assets are already low-poly by modern standarts. There is no points to simplify them.
2. OpenMW still renders simplified meshes on per-instance basis, without batching.
3. There is an additional overhead inside OSG to switch between LOD levels on the fly.

Again, it is not hard to get low-poly meshes and billboards, the real issue is how to batch them since even one drawable per object with large viewing distances is too much.
Stomy wrote:
10 May 2019, 17:54
Well no, not in vanilla Vvardenfell, but all the forests in province mods like Solitude, Vorndgad, Massiquerran, most of Nibenay and Valenwood would. And don't forget all the pine trees on Solstheim, with billboards you'd be able to render Hirstaang from the West Gash without a serious performance hit.
Even in this case billboards will not look good here because of levitation - a forest in the 500 meters under player and a forest in the 500 meters ahead of player should look differently.
The main benefit of billboards is to render objects near horizon (better behind of DoF), but it is not needed in our case - we want to render a quite nearby objects in 5-10 game cells (600-1200 meters).

User avatar
Stomy
Posts: 47
Joined: 11 Dec 2018, 02:55
Location: Fhloston Paradise!
Contact:

Re: Distant objects

Post by Stomy » 11 May 2019, 03:58

akortunov wrote:
10 May 2019, 18:23
Again, it is not hard to get low-poly meshes and billboards, the real issue is how to batch them since even one drawable per object with large viewing distances is too much.
What I want is to not rely on OSG to do batching when it isn't designed to, instead we do it ourselves:

1. Instead of OSG being made aware of LODs, on distant cell loads we check if the lowest LOD level of a mesh is a billboard (or however else we decide to mark it) and if so it is loaded seperately as a sprite to be drawn with the billboard renderer detailed in the following steps.
2. Each billboard atlas is drawn using its dedicated osg::Geometry, set up with alpha clipping (so no sorting) and DYNAMIC data variance.
3. We repopulate each geom's vertex buffers by hand with a new quad for each sprite. We do this every frame and OSG will upload and render with a single draw call per atlas.

MWRender::DebugDrawer is already doing something similar with wireframes, and I'm pretty confident it's what Oblivion's SpeedTree is doing too (even at close range, just with leaves instead of entire trees). There's the overhead of having to upload the vertices every frame, but that is overcome by this being a SIMD process like all modern hardware prefers, we only do one big upload and one draw call per atlas. As opposed to many draw calls with the added overhead of OSG trying to sort and batch them without context.

You could set batching up even better via glDraw*Instanced, potentially allowing you to rebuild on cell-transitions instead. Unfortunately we'd have to use OpenGL directly for that, and I haven't looked into how well OSG can support us taking control of rendering state temporarily.
akortunov wrote:
10 May 2019, 18:23
Even in this case billboards will not look good here because of levitation - a forest in the 500 meters under player and a forest in the 500 meters ahead of player should look differently.
Well for one this would determine LODs by cell, not view distance, so all of the trees directly below you would still be meshes anyway. Secondly, the majority of players don't spend the lion's share of their playtime levitating 500m above the land, the furthest most get is a test drive of the scroll of Icarian Flight which takes you barely half as high.
Never attribute to bad code, that which can be adequately explained with clever hacks

User avatar
AnyOldName3
Posts: 1594
Joined: 26 Nov 2015, 03:25

Re: Distant objects

Post by AnyOldName3 » 11 May 2019, 22:30

DYNAMIC data variance
Nope. That's banned in OpenMW as it forces OSG to do things sequentially that could otherwise be done at the same time on different threads. Instead, drawables that get updated get double buffered. Look at SceneUtil::RigGeometry for an example.

Basing ideas on what gets drawn when debugging things isn't a great idea. As we don't expect people to be running around in wireframe mode with a zillion overlays all the time, we don't mind if that forces us into single-threaded mode or is otherwise really slow.

OSG does actually support instanced rendering fairly easily. If an osg::PrimitiveSet has its _numInstances field set to anything above one, it calls glDraw*Instanced instead of the base function. Vertex attributes can be divided up between instances by using an osg::VertexAttribDivisor.

Even if it didn't setting a custom draw callback isn't that complicated either.



All that said, I'm still not convinced optimised billboards are the best use of our time when we've got no batching whatsoever. I'd be unsurprised if using the system initially discussed on the Skyrim SE Reverse Engineering Discord server (and included as a pastebin link in this thread) with one drawable per set of uniforms per cell let us load actual geometry way into the distance.
AnyOldName3, Master of Shadows

User avatar
AnyOldName3
Posts: 1594
Joined: 26 Nov 2015, 03:25

Re: Distant objects

Post by AnyOldName3 » 11 May 2019, 22:36

By the way, I've confirmed that billboards are done by uploading a new vertex buffer each frame in Oblivion, but by SSE, they'd moved on to instanced rendering. I do not have information for Fallout 3, New Vegas, Skyrim's original engine or Fallout 4, so can't pin down when the switch was made.
AnyOldName3, Master of Shadows

Post Reply