Coder Social home page Coder Social logo

ecslinerenderer's Introduction

ECS Line Renderer

screenshot

ECS approach to render a line I made for personal use on commissioned non-game visualization work. The feature is not quite enough but I decided to open source it.

Coded with mostly archetype chunk iteration API since it will be the most resistant to API changes in this preview phase. So if you want to contribute, please try to stick to chunk iteration if it is a main thread work, and IJobChunk for worker thread. Thank you! (With IJobChunk instead of IJobForEach, we could control chunk version bumps and add some DidChange optimizations.)

How to include with GitHub functionality of Unity Package Manager

Add this line "com.e7.ecs.line-renderer": "git://github.com/5argon/ECSLineRenderer.git", to your manifest.json

It does not update automatically when I push fixes to this repo. You must remove the lock in your manifest.

Core idea

I want to find a new way to render an imperfect yet efficient line by trying to leverage geometry instancing and ECS together.

A typical line renderer works by triangulation of a set of connecting points. For example Unity's LineRenderer always create 2 triangles per one pair of point regardless of their angle.

line

Per 1 line with any number of points Unity generated 1 unique mesh. But, this mesh is unlikely to be the same as other lines, it could not be rendered by instancing due to different mesh. (Even though they could be batched by the same material.) Also if you want to animate line's points, every little movement would need an entire mesh regenerated.

In this package, I want to try using the same mesh as much as possible to assemble a line that could be instanced. I am aware that this may produce an ugly looking line especially the corner if I decided to just overlap rectangles (and it wouldn't work well for non-solid material), but I think it is an interesting experiment and could be useful for some cases, like a line small enough that the defects aren't that visible in exchange of performance. And lastly, I would like to be able to move each point on the line without mesh regeneration at all. Application includes an efficient wireframe, a good base for application like animated graphs, or just drawing grids/tables in general.

The top image has overlapping corner which produces jagged look, but it looks acceptable at glance because the line is white and its width is small enough. Only when extremely zoomed in that you start to notice defects.

See this issue for details.

How it works here

It generate 1 piece of a thin rectangle mesh that goes 1 unit in the Z axis. We could use z scale as line length, x scale as line width, position as line from, and rotation as line to. Assuming that this is only one segment of a line.

LineSegment contains from-to absolute position in world coordinate. To construct complex lines, we create many LineSegment entity with connecting from-to. They should be render instanced as they are using the same mesh. Line width is also on this component.

The line then need a material. So you specify that on LineStyle ISharedComponentData. Without both LineSegment and LineStyle my systems will not work on them.

Finally all lines should be rotated to face the main camera in billboard rendering style. The system will find a "main camera" and take the camera's transform into calculation.

// ECSLineRenderer

LineSegment -> Transform + NonUniformScale
LineStyle -> RenderMesh
Main Camera -> Rotation

// Unity's built-in TransformSystemGroup

Transform + Rotation + NonUniformScale -> LocalToWorld

// Unity's Hybrid Renderer Package

LocalToWorld + RenderMesh -> You see things on screen.

billboard

Rendering

The rendering is handled by HybridRenderer package, by generating RenderMesh shared component data for all your lines. So this package's work are all in simulation system group.

For someone that is always looking for "pure ECS" approach to everything, no, it is not possible to see something on the screen in pure currently. Even the package is named hybrid renderer. I suggest you just drop the pure/hybrid wording altogether and just use what's the best.

Minimum code to get a line from nothing

var e = EntityManager.CreateEntity();
EntityManager.AddComponentData(e, new LineSegment(math.float3(1, 1, 1), math.float3(1, 2, 1)));
var mat = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>("Assets/ECSLineRenderer/YellowLineMaterial.mat");
EntityManager.AddSharedComponentData(e, new LineStyle { material = mat });

Info

  • Line width is in Unity's standard grid unit.
  • If position from and to are the same the system will not update the line. (Stays at previous position)

GameObject Conversion / SubScene support

This is a new and preferred way to author ECS content. GameObjectEntity has a performance problem to maintain a link to GameObject. ConvertToEntity has a problem that things disappear when you enter play mode if you want pure ECS at runtime (without inject mode, which would arrive the same performance problem) and also it is a problem in edit time that you don't know how it would end up.

SubScene is the best of both worlds. Things with IConvertGameObjectToEntity inside SubScene get converted in play mode like ConvertToEntity, but they remains touchable in Hierarchy and anytime you do something they will get reconverted seamlessly. It feels like old GameObjectEntity approach except instead of synchronization it keeps reconverting in one way, then in the real build it works like pure ECS since you cannot touch Hierarchy in the real build.

I have added LineAuthoring : IConvertGameObjectToEntity for this. See the green line in sample scene how this get converted to LineSegment and LineStyle. Since all systems here has [ExecuteAlways], you can turn on DOTS > Live Link Mode > Live Link Conversion in Edit Mode then choose SceneView mode you like to see SubScene in action even in edit mode.

Systems

  • LineSegmentRegistrationSystem : Having both LineSegment and LineStyle on the same Entity will qualify for a registration, which you will get a RenderMesh with migrated material from your LineStyle plus other TRS components.
  • LineSegmentTransformSystem : Calculate TRS which would then turns into LocalToWorld then RenderMesh use it. Based on information in LineSegment. Move your line by changing LineSegment's data before this system.

Limitations + problems

Please see Issues section. For instance, currently the billboard rotation is wrong. If anyone understand http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/ you can send PR.. thanks.

This asset is sponsored by

My other assets.. other than pull requests you can contribute by getting these. Thank you.

  • Introloop - Easily play looping music with intro section (without physically splitting them) (Unity 2017.0+)
  • Native Audio - Lower audio latency via OS's native audio library. (Unity 2017.1+, iOS uses OpenAL / Android uses OpenSL ES)

ecslinerenderer's People

Contributors

5argon avatar andrew-raphael-lukasik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ecslinerenderer's Issues

Deprecation apocalypse

If anyone not noticed already, this whole repo was made around preview.23 but after preview.28-30 there is a big deprecation that changes everything. It is still not fixed for that yet.

Material block property support

Until HybridRenderer package supports it, this repo will render according to what you set on the material i.e. one solid color in most case. A proper line would be able to do gradients and stuff over the length while using the same material.

LineSegment is not a proper line

The LineSegment is just a rectangle. But what is a "real line" as in we dragged a pencil over a piece of paper? Surely it doesn't look like a rectangle. It need two more things : line cap and line corner.

LineSegment will not support rendering corner or end cap mesh even in the future, but I am thinking of making CornerSegment and LineEndCap for those, and assemble 3 of them into a complete line with one another component (with a list of corner points instead of start-end). In all, line renderer will render 3 kind of meshes in batches. (Assuming vertex resolution of corners and caps are fixed, which you should for batching performance)

Billboard rotation is wrong

It is currently only do a look at from line to camera position, it doesn't take account of camera's rotation yet. You could see the section I commented in LineSegmentTransformSystem.cs if you wanna try tackle this.

Entities 0.5.1 billboard issue

Using Unity 2019.3.0f6 and Entities 0.5.1

Editor will spam this error upon exiting playmode, if BillboardcameraProxy is used.
a work around is to disable all (of the scripts added by BillcamProxy) but GameObjectEntity after adding BillboardcameraProxy to the main camera.

NullReferenceException: Object reference not set to an instance of an object Unity.Entities.EntityQuery.CreateArchetypeChunkArray (Unity.Collections.Allocator allocator) (at Library/PackageCache/[email protected]/Unity.Entities/Iterators/EntityQuery.cs:574) Unity.Entities.Editor.EntityListView.BuildRows (UnityEditor.IMGUI.Controls.TreeViewItem root) (at Library/PackageCache/[email protected]/Unity.Entities.Editor/EntityDebugger/EntityListView.cs:142) UnityEditor.IMGUI.Controls.TreeView+TreeViewControlDataSource.FetchData () (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.IMGUI.Controls.TreeViewDataSource.ReloadData () (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.IMGUI.Controls.TreeView+TreeViewControlDataSource.ReloadData () (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.IMGUI.Controls.TreeViewController.ReloadData () (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.IMGUI.Controls.TreeView.Reload () (at <6f28216fea9f453abf2e05b770ed3ee4>:0) Unity.Entities.Editor.EntityListView.ReloadIfNecessary () (at Library/PackageCache/[email protected]/Unity.Entities.Editor/EntityDebugger/EntityListView.cs:105) Unity.Entities.Editor.EntityDebugger.OnGUI () (at Library/PackageCache/[email protected]/Unity.Entities.Editor/EntityDebugger/EntityDebugger.cs:523) System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <437ba245d8404784b9fbab9b439ac908>:0) Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation. System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <437ba245d8404784b9fbab9b439ac908>:0) System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <437ba245d8404784b9fbab9b439ac908>:0) UnityEditor.HostView.Invoke (System.String methodName, System.Object obj) (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.HostView.Invoke (System.String methodName) (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition, UnityEngine.Rect viewRect) (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.DockArea.DrawView (UnityEngine.Rect viewRect, UnityEngine.Rect dockAreaRect) (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEditor.DockArea.OldOnGUI () (at <6f28216fea9f453abf2e05b770ed3ee4>:0) UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Boolean canAffectFocus) (at <a6a3aac9b47844afbb8dcc407683ae01>:0) UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

Line sink into the mesh

As seen from the screenshot, the line is really a rectangle and no care is taken regarding to its draw order. The line rotate to billboard to the camera, and when it is placed near something else it is possible for some of its width to sink into those meshes. I don't know if this should be the case or could we do something with it.

The bright side is that all the lines are properly behind and in front of things like a real 3D object. For example if those meshes are translucent, we could see through to the lines like this.

56749330_2179370048820212_2137408311853580288_n

(And you see the "sinking" effect more obviously here)

Full Example?

Now that the burst compiler is standard with the new 2019 version of Unity, would it be possible to provide a demo scene with everything set-up to try? That would be very helpful. I haven't been able to find other examples of Unity ECS lines. Thanks.

Create GitHub release (git tag)

Hi @5argon ,

Thanks for creating the awesome package. Would please create a github release v1.0.0? So the package can be included in upcoming openupm registry (sneak preview), which is a service that build package directly from git tags that conform semver.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.