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:
-
SubRenderFeature
has an internal AttachRootRenderFeature. There’s a way to overcome it by creating a class inheriting fromSubRenderFeature
and basically duplicateAttachRootRenderFeature
in order to populateRootRenderFeature
but it feels hacky. -
ForwardLightingRenderFeature
can only work withRenderMesh
. It castsRenderObject
toRenderMesh
- https://git.xenko.com/xenko/Xenko-Runtime/blob/master/sources/engine/SiliconStudio.Xenko.Engine/Rendering/Lights/ForwardLightingRenderFeature.cs#L286-289
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
- Is
EntityProcessor.Draw
called per frame or per view (for example with multiple render textures)? Do you thinkcontext.GetCurrentCamera()
andcontext.RenderView
can be resolved by the time it’s called? - Does
ForwardLightingRenderFeature
really need to be coupled withRenderMesh
? Do you think it should be possible to reuse it from other customRenderFeature
? - 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 considersSubRenderFeature
api internal? - Is it supported to render custom
RenderObject
with reusing the built-in lightning or will it be supported in the future?
Thanks!