Custom rendering - Printable Version +- AB4D Forum (https://forum.ab4d.com) +-- Forum: Products Forums (https://forum.ab4d.com/forumdisplay.php?fid=4) +--- Forum: Ab3d.DXEngine (https://forum.ab4d.com/forumdisplay.php?fid=11) +--- Thread: Custom rendering (/showthread.php?tid=4089) Pages:
1
2
|
Custom rendering - Hamish - 02-27-2018 I've seen the examples that comes with the trial, but I don't quite understand them... I'm looking to replace our existing rendering solution which is based on irrlicht lime. In irrlicht, I can subclass SceneNode and provide a Render event handler which gets called at render time. From this handler, I can set the world and view matrices and make primitive draw calls such as render tristrip and pass in an array of vertices and indices. I use this on occasion to do things like drawing some geometry "over top" of other geometry by moving it closer to the camera a smidge at render time. How can I achieve a similar effect in ab3d? RE: Custom rendering - abenedik - 02-27-2018 To provide you own rendering logic you can use CustomRenderableNode object - it is a special SceneNode object that is created with a callback action that is called when the SceneNode needs to be rendered. The Action is called with RenderingContext and other parameters and there you can set your own DirectX states and call Draw calls. When setting states, constant buffers and shaders please use the renderingContext.ContextStatesManager object - this way your custom code will work fine with other DXEngine SceneNodes. To see a sample CustomRenderableNode check the Customizations\CustomRenderingStep4.xaml.cs source in the DXEngine samples project (there are also some additional comments). You can also provide your rendering logic by specifying your own CustomActionRenderingStep - rendering steps are defined in the DXScene.RenderingSteps collection and define the steps that are executed to render one frame. By default the rendering steps are:
This can be done with the following steps:
RE: Custom rendering - Hamish - 02-27-2018 Ok, thanks for that. I did do some looking at the examples again after I posted and I think I understand it all. The problem is that it seems very complex. Like all I need to do is set a custom world matrix for some geometry and draw it. But it seems to do this I need to have my own vertex shader and set the world matrix in the constant buffer, is that correct? In irrlicht it was really nice because I could literally on the draw context object set the "world transform" and then just draw existing vertex/index buffers. No shaders were required. It was very simple. The solution in ab3d seems quite complex. Is my understanding correct, that I need to set the custom world matrix in a constant buffer and then create a custom vertex shader that consumes this matrix to transform the vertices? Thanks. RE: Custom rendering - abenedik - 02-27-2018 Uh, it would surely be an overkill to provide your own rendering logic for only custom transformation. You can set the transformation to any SceneNode with settings its Transform - this way you can provide your own world transformation. This will also work well with other parts of the engine (for example with automatic calculation of near and far camera planes). Then the DXEngine will choose the correct effect and shader based on the specified material and do the drawing - it will also set the transformation matrix to the correct constant buffer. Is this not enough for your use case or is there any other reason that you need custom rendering logic. RE: Custom rendering - Hamish - 02-27-2018 But I need to set the transform on a per-frame basis and ideally the geometry will be instanced. I assumed changing the scene node transform on a per-frame basis would be expensive... There will be potentially 10k of these things in a scene, so the overhead of a scene node per instance I assumed would be overkill. I can give it a try and see how it goes - where would be the best place to set the scene node transform just prior to rendering? RE: Custom rendering - abenedik - 02-28-2018 If you are rendering objects with the same geometry (mesh), then it is recommended to use object instancing - this gives you by far the best performance. Also, you can simply set the transformation matrix into the InstanceData array. For the next version of DXEngine I have prepared a sample that shows animated instanced arrows - on my computer it can show 1 million (!!!) animated 3D arrows with almost 60 FPS (the most time is spent to calculate new world matrix for each arrow and each frame). The sample shows that with instancing it is possible to achieve incredible performance. I am attaching the two files for the sample to this post. To test the sample, add the files to the DXEngine samples project into the DXEngine folder. The open the Samples.xml file on the root folder and add the following line (for example into line 14): <Sample Page="DXEngine/InstancedArrowsSample.xaml" Title="InstancedArrowsSample" IsNew="True" Description="" /> If you will not use instancing, you can still update Transform for each SceneNode before you call Render on DXScene (you said that you are not using DXViewportView and are calling Render manually). This should not be a serious performance problem. A bigger problem is to have 10k objects where each is defined by its own SceneNode - this requires 10k DirectX draw calls and this limit your performance because of required work on the CPU (again use DXEngineSnoop to see how much time is spent in DrawRenderTime). RE: Custom rendering - Hamish - 03-01-2018 Ok, fantastic, that makes perfect sense. I had seen the instancing functionality there, but hadn't really looked into it because it means I'll need to change the way I'm binding my data model to the visuals... Which will be a pain, but it sounds like performance-wise it'll be well worth the effort. Thanks. Regarding instancing - if I have a single DXMeshGeometry3D object that gets used by multiple MeshObjectNode objects, is that effectively instancing the underlying geometry? Or does the MeshObjectNode make a copy of the mesh data? RE: Custom rendering - Hamish - 03-01-2018 One more question, the InstancedMeshGeometryVisual3D is a wpf class... This means I can't use it if I'm rendering a DXScene directly to a winforms control, is that correct? I can't see a InstancedMeshGeometryObjectNode equivalent or anything. RE: Custom rendering - abenedik - 03-01-2018 You can use Ab3d.DirectX.Models.InstancedMeshGeometry3DNode (it is defined in the Ab3d.DXEngine.Wpf assembly). You can use constructor that takes MeshGeometry3D and then call SetInstanceData method. RE: Custom rendering - Hamish - 03-01-2018 Ok great. How come this class doesn't show up in the class hierarchy in the docs? Makes it very difficult to find. Also, why does it not have the same InstanceData property with both get and set? And lastly, it seems if there is no instance data, it crashes when rendering... In certain cases I won't have any of these instances - what is the best way to stop the node from crashing the render loop? |