Questions regarding custom `EntityComponent` and `RenderFeature`


#1

Greetings everyone,

It’s a compilation of some of the issues I found failing to build a terrain with continious level of detail in Xenko. I hope that my approaches to implement it were wrong and there’s a nice and simple way to do it. I guess the main thing I struggled with is to inject custom render objects and reuse the built-in forward lighting renderer. The main goal of this issue to ask questions regarding Xenko graphic pipeline and to showcase to Xenko devs how someone might abuseuse their engine.

Task

Render terrain quads depending on the distance to the camera. There’re some more details https://proland.inrialpes.fr/doc/proland-4.0/core/html/index.html#sec-quad.
It needs to be calculated per view rather then per frame to support multiple render targets (eg. Render textures).

Implementation attemps

1. Custom EntityComponent and EntityProcessor

Xenko supports creating custom EntityComponents and assigning custom EntityProcessors to them.
I created TerrainComponent and TerrainRenderProcessor with the idea to build a quad tree per view in TerrainRenderProcessor.Draw (EntityProcessor.Draw(RenderContext)) assuming that EntityProcessor.Draw will be called per view (per camera).

public class TerrainRenderProcessor: EntityProcessor<TerrainComponent>, IEntityComponentRenderProcessor {

  public VisibilityGroup VisibilityGroup { get; set; }

  public override void Draw(RenderContext context) {
    var eye = ???;
    foreach(var terrain in ComponentDatas.Keys) {
      terrain.GetQuadTree(eye)
    }
  }
}

However, all the proper ways to get the current view at this point are not working. There’s an extension method RenderContext.GetCurrentCamera() which returns null, the current camera is not yet set. RenderContext.RenderView is also null.

It appears there’s no proper way to get the current camera from EntityProcessor.Draw to create a collection of RenderMesh depending on the camera position or is there?

2. A custom RenderFeature

Perhaps, EntityProcessors were not designed to handle this task and my initial idea would be simply a hack. However, a custom RootRenderFeature seemed to be a proper way to implement custom rendering.

TerrainRenderProcessor was changed to populate VisibilityGroup with custom RenderTerrain objects. I managed to render a flat terrain with continious LOD without lights and shadows by using a custom effect.

The next idea was to reuse the current implementation of ForwardLightingRenderFeature which is a sub feature to MeshRenderFeature that collects lights, prepares shadow maps etc.

However, there were 2 reasons why it could not be done in a straghtforward way:

I considered using a custom SubRenderFeature for MeshRenderFeature with the idea to add RenderMesh to VisibilityGroup during RenderFeature.Collect. However, it seemed too late because ShadowMapRenderer uses VisibilityGroup in Collect https://git.xenko.com/xenko/Xenko-Runtime/blob/master/sources/engine/SiliconStudio.Xenko.Engine/Rendering/Shadows/ShadowMapRenderer.cs#L97.

Questions

  1. Is EntityProcessor.Draw called per frame or per view (for example with multiple render textures)? Do you think context.GetCurrentCamera() and context.RenderView can be resolved by the time it’s called?
  2. Does ForwardLightingRenderFeature really need to be coupled with RenderMesh? Do you think it should be possible to reuse it from other custom RenderFeature?
  3. Currently, there’s a concept of SubRenderFeature but it can only be properly initialized by using an internal method. Does it mean that Xenko team considers SubRenderFeature api internal?
  4. Is it supported to render custom RenderObject with reusing the built-in lightning or will it be supported in the future?

Thanks!