Special Aircraft Service

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 79 80 81 [82] 83 84 85 ... 111   Go Down

Author Topic: graphics extender  (Read 321297 times)

0 Members and 4 Guests are viewing this topic.

slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #972 on: May 17, 2020, 09:45:24 AM »

@slibenli What will this be for, when it's ready? Another impressive improvement on grafics? Probably with shadows in the cockpit?

Gesendet von meinem SM-N975F mit Tapatalk

I don't know if this will ever be ready - it's just some basic groundwork.
But theoretically it could be used for self shadowing and all kinds of new features like physically based rendering.


slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #973 on: May 17, 2020, 10:45:11 AM »

I implemented a (so far) simple renderer for meshes:
https://gitlab.com/vrresto/il2ge-experimental/-/blob/cfdb3147c62785551cf5132504d5479d21e3e9fa/include/il2ge/renderer.h#L51

The interface is designed with the possibility in mind of the renderer running in an own thread.
I'd be happy for some review.
The createMesh() method would block the calling thread since the Mesh object would need to be created in the renderer thread.
A non blocking version could look like this:
Code: [Select]
// Adds the mesh to be created to a list that will be processed by the renderer thread.
// This implies that the input mesh object mustn't be modified until the result was returned by getCreatedMeshes() - UGLY :/
// This problem would be avoided by passing a copy of the input mesh - UGLY because of bigger memory consumption.
void createMesh(il2ge::mesh::MeshBase& input_mesh, string unique_id);

// To be polled by the the client thread.
// Returns the meshes created by the renderer thread in a map
// which associates the created mesh with the unique id passed to createMesh().
map<string, Mesh> getCreatedMeshes();


The actual rendering happens here:
https://gitlab.com/vrresto/il2ge-experimental/-/blob/cfdb3147c62785551cf5132504d5479d21e3e9fa/common/renderer.cpp#L122
Again, I'd be happy for some review whether it's a sound design performance wise - at least for non-transparent objects. I don't know yet how to handle transparency.

Edit: What I haven't looked into so far are hierarchical meshes and whether it would make sense to merge all submeshes into one vertex array.
One question is, whether it is possible to add/remove submeshes at run time. I think it's at least possible to toggle their visibility.

Hylo

  • member
  • Offline Offline
  • Posts: 171
Re: graphics extender
« Reply #974 on: May 18, 2020, 06:17:40 AM »

Somebody fetch Stainless :P

I don't think I'm really the right person to do this as I have no practical experience of graphics programming but here are the things I feel (barely) qualified to talk about -

I implemented a (so far) simple renderer for meshes:
https://gitlab.com/vrresto/il2ge-experimental/-/blob/cfdb3147c62785551cf5132504d5479d21e3e9fa/include/il2ge/renderer.h#L51

The interface is designed with the possibility in mind of the renderer running in an own thread.
I'd be happy for some review.
I think the most important thing to establish in the first place is the threading model that you want to have. I presume it is something like:

  • Main thread - All of the Java engine code that submits things to be rendered to il2_core and therefore il2ge
  • Renderer thread - il2ge doing actual OpenGL calls on the GLContext

I think both interfaces proposed have some blocking in the semantic sense - in the blocking impl the main thread is blocked waiting for createMesh(). In the non-blocking impl it's blocked polling getCreatedMeshes until the mesh is created I think? Although it can do other stuff in between polling right?

In this threading model, if there is frequently a dependency on something in the rendering thread finishing before the main thread can continue then I guess it either doesn't make sense to use a separate thread or there is some alteration that needs to be made to the communication model between the threads. Ideally the main thread wants to be doing "fire and forget" things.

In that case it might be worth considering whether or not you actually get any advantages from the non-blocking interface. I think running the game through the Concurrency Visualizer in VS2019 might be a good way to check thread utilization on a given scene while running a track maybe? I suppose the criteria is how much time is spent blocking on synchronous createMesh vs busy-waiting in getCreateMeshes.

I guess another angle to consider is that it might be possible to use wglShareLists and run mesh creation and loading as another completely separate thread so that the renderer thread doesn't have to stop to do it, although it looks like there are caveats to doing that, e.g. see the comment at the end of this blog post.

The actual rendering happens here:
https://gitlab.com/vrresto/il2ge-experimental/-/blob/cfdb3147c62785551cf5132504d5479d21e3e9fa/common/renderer.cpp#L122
Again, I'd be happy for some review whether it's a sound design performance wise - at least for non-transparent objects. I don't know yet how to handle transparency.

Edit: What I haven't looked into so far are hierarchical meshes and whether it would make sense to merge all submeshes into one vertex array.
One question is, whether it is possible to add/remove submeshes at run time. I think it's at least possible to toggle their visibility.
Merging submeshes - definitely possible to toggle visibility and remove submeshes as there's an int[] hideSubTrees(String) method on ActorHMesh, and also void destroyChildFiltered(Class). I don't know enough to say whether it's an important optimization to make in the long run but I probably wouldn't worry about it in a prototype implementation.

Handling transparency - I haven't read about any good way to do it other than rendering things in the right order (furthest away to closest). I'm not sure how il2ge and il2_core interact but as the game already supports transparency I can only assume it does the rendering calls for transparent objects in the right order already? Although I haven't really tried viewing things through multiple transparent objects to see how they behave when they're layered on top of each other. There are implementations of order-independent transparency but it looks really tricky. The simplest explanation of doing this in a simple way that I have found is here. In fact basically that whole website is a goldmine for everything from the simplest to the most advanced OpenGL techniques with full source code. The approach described there (using a map indexed by the distance from the viewer to store transparent objects) seems like a good approach and not too far from your existing approach of having separate lists.
Logged

slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #975 on: May 18, 2020, 08:33:56 AM »

I think the most important thing to establish in the first place is the threading model that you want to have. I presume it is something like:

  • Main thread - All of the Java engine code that submits things to be rendered to il2_core and therefore il2ge
  • Renderer thread - il2ge doing actual OpenGL calls on the GLContext

Yes, this what I had in mind. Phrased differently there would be one renderer thread and one client thread (which would be the main thread), or possibly multiple client threads which of course would make things more complicated.

I think both interfaces proposed have some blocking in the semantic sense - in the blocking impl the main thread is blocked waiting for createMesh(). In the non-blocking impl it's blocked polling getCreatedMeshes until the mesh is created I think? Although it can do other stuff in between polling right?

In this threading model, if there is frequently a dependency on something in the rendering thread finishing before the main thread can continue then I guess it either doesn't make sense to use a separate thread or there is some alteration that needs to be made to the communication model between the threads. Ideally the main thread wants to be doing "fire and forget" things.

For the non-blocking version I was thinking of a fire and forget model - the mesh simply wouldn't be rendered until it is loaded (and passing it to addToRenderList() would be the only thing the client thread would do with the mesh anyway). The getCreatedMeshes() method would only be called once per frame.

In that case it might be worth considering whether or not you actually get any advantages from the non-blocking interface. I think running the game through the Concurrency Visualizer in VS2019 might be a good way to check thread utilization on a given scene while running a track maybe? I suppose the criteria is how much time is spent blocking on synchronous createMesh vs busy-waiting in getCreateMeshes.

I haven't looked into the java code, but if all the mesh loading happens when the map is loaded, the blocking version wouldn't be a problem anyway.
There another threading model comes to mind (for which the java code would need to be changed accordingly):
One main thread, one loader thread (which would be created by java code) and one renderer thread. The loader thread would use the blocking createMesh(), but the main thread could continue to run.

I guess another angle to consider is that it might be possible to use wglShareLists and run mesh creation and loading as another completely separate thread so that the renderer thread doesn't have to stop to do it, although it looks like there are caveats to doing that, e.g. see the comment at the end of this blog post.

Using OpenGL from multiple threads always seems to be tricky - I 'd rather stay clear of that.

Merging submeshes - definitely possible to toggle visibility and remove submeshes as there's an int[] hideSubTrees(String) method on ActorHMesh, and also void destroyChildFiltered(Class). I don't know enough to say whether it's an important optimization to make in the long run but I probably wouldn't worry about it in a prototype implementation.

It could greatly reduce the number of drawing calls - if the material system is also optimized in that regard (keeping glBindTexture() to a minimum (e.g. by using texture arrays)).
But you're right - I shouldn't fall into the trap of premature optimisation.

Handling transparency - I haven't read about any good way to do it other than rendering things in the right order (furthest away to closest). I'm not sure how il2ge and il2_core interact but as the game already supports transparency I can only assume it does the rendering calls for transparent objects in the right order already? Although I haven't really tried viewing things through multiple transparent objects to see how they behave when they're layered on top of each other. There are implementations of order-independent transparency but it looks really tricky. The simplest explanation of doing this in a simple way that I have found is here. In fact basically that whole website is a goldmine for everything from the simplest to the most advanced OpenGL techniques with full source code. The approach described there (using a map indexed by the distance from the viewer to store transparent objects) seems like a good approach and not too far from your existing approach of having separate lists.

I came across an order independent method that looked interesting. I also posted a link - I'm gonna look for it.
Edit: that one: http://casual-effects.blogspot.com/2014/03/weighted-blended-order-independent.html

slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #976 on: May 18, 2020, 12:45:54 PM »

Loading hierarchical meshes now works:




Stainless

  • Modder
  • member
  • Offline Offline
  • Posts: 1537
Re: graphics extender
« Reply #977 on: May 19, 2020, 03:09:49 AM »

Bear in mind that some flavours of OpenGL cannot load textures from a child thread.... well they can but you have to jump through a lot of hoops, usually going down to the EGL layer rather than vanilla OpenGL.

So you might want to pick a minimum version of OpenGL to support , or keep the renderer on the main thread
Logged

slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #978 on: May 19, 2020, 09:05:08 AM »

Bear in mind that some flavours of OpenGL cannot load textures from a child thread.... well they can but you have to jump through a lot of hoops, usually going down to the EGL layer rather than vanilla OpenGL.

Even when all OpenGL calls happen in that child thread?

slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #979 on: May 19, 2020, 09:10:37 AM »

Rendering hierarchical meshes with textures. Transparency is still missing.




100 instances




1000 instances - too many draw calls :/


Hylo

  • member
  • Offline Offline
  • Posts: 171
Re: graphics extender
« Reply #980 on: May 19, 2020, 09:58:58 AM »

Wow, this is progressing really quick!
Logged

slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #981 on: May 19, 2020, 12:01:20 PM »

OK, I could lower the number of draw calls using instancing. The transformations of the submeshes are just slightly wrong ;)




Edit: Fixed.


Hylo

  • member
  • Offline Offline
  • Posts: 171
Re: graphics extender
« Reply #982 on: May 19, 2020, 12:48:56 PM »

Nice! One draw call per B-17 raid eh  :D
Logged

slibenli

  • member
  • Offline Offline
  • Posts: 619
    • IL-2 Graphics Extender
Re: graphics extender
« Reply #983 on: May 20, 2020, 06:50:55 AM »

Actually it's at least as many draw calls as there are submeshes (203 for the F14 although some of them should probably be invisible).
Pages: 1 ... 79 80 81 [82] 83 84 85 ... 111   Go Up
 

Page created in 0.057 seconds with 24 queries.