Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
OBI Assets do not work with Octane Render
#1
I'm using Octane paid version however you can just as easily reproduce this with the free version of Octane Render from the Unity Asset Store.

Simply install Octane Free version and add a PBR render target to the sample scene. The press render and next hit play.

In the screenshots below I've shown the game window on the left and the Octane rendered version on the right. (I would have attached higher res screenshots but your 100K file size limit prevents me)

   

   

   

   

I've tried reaching out to Octane customer support but their response was that they cannot support the particle render methods which OBI use.
Which if you look at it from their point of view I do understand. It would not be feasible for them to try to support every asset on the asset store
Their response is below copied verbatim:


Quote:Taking a look into the plugins, it appears that they do not use standard Unity geometry (the Obi rope specifically uses a unique type of particle to achieve it's end result).


It is worth noting that Unity is primarily designed to work with native Unity elements, as well as widely used external elements (i.e. fbx, obj, etc). Certain things, such as billboards. UI elements, and particles, cannot be rendered with OctaneRender.
Third Party/Custom made elements may or may not work with Octane - unfortunately it would not be feasible for us to account for all cases of third-party mesh/material/shader types beyond the well-known and widely used, though some who manage to stay sufficiently close to native Unity implementation may innately work (one example was "SpeedTree") - even in those cases we cannot assure ongoing support for positive cases, as their development roadmaps and workflow are beyond our control.

Making changes and improvements to improve upon these third-party limitations may still be possible to implement on our end, but these may require extensive refactoring or at least a long investigation period. We are always open to feedback, and may consider making a focused efforts into certain third party cases based on popular demand.

Would it be possible to build support for Octane. The reason I ask is because Unity HDRP path tracing which although it is a decent ray tracer does not have a denoiser and unless you flood every scene with full lighting from all directions it is not possible to get decent renders out of it. Which means for the short film production path using Unity Octane is pretty much the only choice.

From this point of view what I'm looking for is: Do your plugins have a hook / method where we can extract the final geometry and spin up a custom mesh based on that instead of the particle render. I know this is expensive but the animation pipeline does NOT need realtime. As a matter of fact rendering one frame in Octane can easily take a minute or two so the overhead of custom mesh generation is really not a big deal.

Also OBI is the best and probably only Rope, Cloth and Soft Body engine for Unity.

Actually I just checked the code in OBI

You do not seem to be using a particle renderer. The response from Octane support seems to be just a fob off cause they maybe can't be bothered producing a complete product for Unity.

Am I reading this right ? based on the following code you are merely modifying a standard mesh at runtime.

Code:
        [HideInInspector] [NonSerialized] public Mesh extrudedMesh;

        private void ClearMeshData()
        {
            extrudedMesh.Clear();
            vertices.Clear();
            normals.Clear();
            tangents.Clear();
            uvs.Clear();
            vertColors.Clear();
            tris.Clear();
        }

        private void CommitMeshData()
        {
            extrudedMesh.SetVertices(vertices);
            extrudedMesh.SetNormals(normals);
            extrudedMesh.SetTangents(tangents);
            extrudedMesh.SetColors(vertColors);
            extrudedMesh.SetUVs(0, uvs);
            extrudedMesh.SetTriangles(tris, 0, true);
        }
Reply
#2
The following code change to ObiRopeExtrudedRenderer is a brute force that makes it work with Octane.
Variant of the same strategy works for OBI Cloth as well.
But this should not be needed.
Is there anything that you can think of that's not as horrible as saving the runtime mesh to an asset file on every frame?

Code:
        public bool RealtimeMode = true;
        private string SaveFile;
        private bool MeshFileSaved = false;
        [SerializeField] private bool DebugOnePass = false;
        private void ClearMeshData()
        {
            extrudedMesh.Clear();
            vertices.Clear();
            normals.Clear();
            tangents.Clear();
            uvs.Clear();
            vertColors.Clear();
            tris.Clear();
        }

        private void CommitMeshData()
        {
            extrudedMesh.SetVertices(vertices);
            extrudedMesh.SetNormals(normals);
            extrudedMesh.SetTangents(tangents);
            extrudedMesh.SetColors(vertColors);
            extrudedMesh.SetUVs(0, uvs);
            extrudedMesh.SetTriangles(tris, 0, true);
            extrudedMesh.MarkModified(); //This should work. But does not
            extrudedMesh.UploadMeshData(false); //Adding this should definitely make it work but it does not

            #region Brute Force Method
            // This brute force method works
            // But this is really bad brute force and should not be needed.
            if (DebugOnePass ||((!RealtimeMode) && Application.isPlaying))
            {
                if (DebugOnePass)
                {
                    SaveFile = string.Empty;
                }
                DebugOnePass = false;
                if (string.IsNullOrEmpty(SaveFile))
                {
                    SaveFile = System.Guid.NewGuid().ToString().Replace(@"-", string.Empty);
                    SaveFile = string.Concat(SaveFile, @".asset");
                }
                if (MeshFileSaved)
                {
                    AssetDatabase.DeleteAsset(SavePath);
                }
                AssetDatabase.CreateAsset(extrudedMesh, SavePath);
                MeshFileSaved = true;
            }
            #endregion

        }
        private string SavePath
        {
            get
            {
                return string.Concat(@"Assets/DynamicMeshTemp/", SaveFile);
            }
        }

        private void OnDestroy()
        {
            if (!string.IsNullOrEmpty(SaveFile))
            {
                if (MeshFileSaved)
                {
                    AssetDatabase.DeleteAsset(SavePath);
                }
            }
        }
Reply
#3
Hi there,

Quote:Taking a look into the plugins, it appears that they do not use standard Unity geometry (the Obi rope specifically uses a unique type of particle to achieve it's end result).

Except for ObiFluid -which uses screen space ellipsoid splatting-, all Obi assets use standard Unity geometry for rendering. No "particle rendering" methods are used whatsoever, not for ropes, not for cloth, not for softbodies. For all I know, it should work with Octane out of the box since nothing weird or out of the ordinary is being done under the hood. It's all standard Unity stuff.

Quote:Do your plugins have a hook / method where we can extract the final geometry and spin up a custom mesh based on that instead of the particle render.

Simply grab the mesh directly from the MeshRenderer component. There's no other output being generated.

Quote:You do not seem to be using a particle renderer. The response from Octane support seems to be just a fob off cause they maybe can't be bothered producing a complete product for Unity.

Am I reading this right ? based on the following code you are merely modifying a standard mesh at runtime.

Correct. All Obi does is move the vertices of a standard mesh around.

Based on your finding that unless a mesh its saved as an asset it won't render, my guess is that Octane takes mesh assets and performs some sort of pre-process on them to be able to render them (local BVH or some other sort of acceleration structure?). If a mesh is altered at runtime in some way, these changes won't be picked up. Seems to be the case since they mention billboards and particles aren't supported by Octane. This is very limiting as it excludes any form of procedural geometry from working.

I'd ask them again if this assumption is correct and if so, maybe they can provide any alternative that allows for dynamic geometry to be rendered.
Reply
#4
After some back and forth I finally received a reply from Octane support:


Quote:With further communications with the developer, the core issue with procedural generation basically came down to how the core Octane Renderer receives and processes data.

Without going into detail about the internal workflows of OctaneRender - aligning Octane with lower-level functionalities within Unity resulted in various unwanted outcomes (e.g. rapidly overflowing GPU Memory usage), and resolving these related issues required both time and a degree of maturation from both sides of the integration. Octane's primary workflow for handling procedural meshes has been via VDB files - which most 3D modelling applications (e.g. Blender, Cinema4D, etc) support, but Unity does not (at least not in a sufficiently robust manner for our purposes).

Since you have a much higher technical knowledge of Unity. Do you have any ideas / suggestions that I can try? The brute force method I described above is not reliable and does not work consistently.


From what I can see the gap is that Octane seems to cache scene mesh geometry and does not update that when meshes are modified. However if a new mesh is instantiated then it will read that. As a naive approach I was thinking is maybe if I disable the mesh renderer on say OBI Rope. And modify ObiRopeExtrudedRenderer such that after generating the mesh it clones the mesh and instantiates a new game object with the cloned mesh. Each frame it will be deleting and recreating the clone.

Do you have any better ideas ?
Reply
#5
Ok, so no CPU procedural geometry of any kind is supported then.  Indeciso I can only assume any geometry modified/created on the GPU isn't either, so no geometry shader/vertex shader/compute shader stuff will be picked up by Octane. That's a showstopper.

Depending on how/when they cache mesh data (when a Mesh object is created, when a Mesh object is stored as an asset, when the sharedMesh property of a renderer is set... etc), there's multiple possible workarounds. All of them are quite expensive though, and none of them are clean or elegant. To know for sure which one works best I would need to know exactly how Octane works internally, though. As it stands, all I can do is guess.

One thing you can try is to instantiate the rope mesh in CommitMeshData() (essentially creating a copy of the mesh) and then setting the mesh renderer's sharedMesh property to this mesh copy, every frame. This should be enough to trick Octane into thinking a new mesh has been created. If it isn't, then it means they don't pick up new meshes that only exist in memory, and they require the mesh to exist as an asset. In that case, your original attempt would be the one closest to working.
Reply
#6
Folks seriously you need to ugrade / update / trash your spam filtering or whatever plugin your running on this forum cause its a real piece of junk.

First my IP is banned because apparently I am on a high spam network. Which does not make sense at all. Cause I have a residential fiber gigabit internet connection in New Zealand with a fixed static IP.

So to get around that nonsense I use bit defender VPN. But then when I try to post a message with code snippets the stupid retarded thing tells me the message is SPam and therefore forbidden

But seriously please trash that retarded junkware cause it is a real pain.
Reply
#7
Hi there,

We use CleanTalk (https://cleantalk.org/blacklists) which generally works really well. In some specific cases it can be troublesome, though, but we can manually override it and approve specific posts, whitelist users, etc. In the past users have posted images as raw base64 data, posted bits and fragments of SQL queries, and all sorts of weird stuff. I have flagged a previous message of yours as "not spam", which will hopefully prevent the filter from blocking you in the future.

I'm sorry that it picked up your IP. According to the their database records, the reason why it's blacklisted is it has been routinely used for mass email sending which categorizes as spam. At least that's what their database says, whether or not this is true I have no way of knowing.

If you experience any more issues, please let me know via support(at)virtualmethodstudio.com. I'll do anything within my reach to help you.
Reply
#8
Thanks for doing that really appreciate it. So now hoping I can post this.

The following modification to OBI Rope works seamlessly. I will do the same for cloth soon.

I was hoping that you could maybe merge this method into Obi Rope / Cloth / SoftBody etc... with some kind of flag to enable / disable it.

Note: the strategy I used is to disable the primary mesh renderer on the Obi Rope
Then create a child object parented to OBI Rope in this case with zero local rotation and position.
This child object is destroyed (destroyimmediate) and re created on each frame.
The meshfilter, and the mesh renderer are added to the child each time it is created, the materials are set on the renderer. And a new mesh is created with a clone of the geometry of your normal mesh.

Essentially all we are doing is creating a pipeline to feed custom geometry into Octane.

Before anyone stares at this in absolute horror, Octane render is for creating animations, not for realtime rendering. One 1080P frame can take a few seconds to a few minutes to render depending on scene complexity. Therefore the garbage overhead of destroying and creating objects each frame is really a non issue here. We are not doing this 30 times per second. We are doing this one time per many seconds or minutes.

Note: in the code below OBI_OctaneMode is linking to a singleton helper that I created to allow me to control the two modes of all the ropes from a single place.


Code:
        [HideInInspector] [NonSerialized] public Mesh extrudedMesh;
        [HideInInspector] [NonSerialized] public Mesh extrudedMeshOctane;
        [HideInInspector] [NonSerialized] public MeshRenderer PrimaryRenderer;
        [HideInInspector] [NonSerialized] public Material[] PrimaryRendererMaterials;
        [HideInInspector] [NonSerialized] public GameObject OctaneRenderGO;

        private bool OBI_OctaneMode
        {
            get
            {
                if (OBIParams.Instance== null) { return false; }
                return OBIParams.Instance.OBI_OctaneMode;
            }
        }

        private void CreateMeshIfNeeded()
        {
            if (extrudedMesh == null)
            {
                extrudedMesh = new Mesh();
                extrudedMesh.name = "extrudedMesh";
                extrudedMesh.MarkDynamic();
                GetComponent<MeshFilter>().mesh = extrudedMesh;
            }
        }

        private void ClearMeshData()
        {
            extrudedMesh.Clear();
            vertices.Clear();
            normals.Clear();
            tangents.Clear();
            uvs.Clear();
            vertColors.Clear();
            tris.Clear();
        }

        private void CommitMeshData()
        {
            extrudedMesh.SetVertices(vertices);
            extrudedMesh.SetNormals(normals);
            extrudedMesh.SetTangents(tangents);
            extrudedMesh.SetColors(vertColors);
            extrudedMesh.SetUVs(0, uvs);
            extrudedMesh.SetTriangles(tris, 0, true);

            #region Octane Brute Force Method
            // This brute force method works
            // But this is really bad brute force and should not be needed.
            if (OBI_OctaneMode && Application.isPlaying)
            {
                if (PrimaryRenderer == null)
                {
                    PrimaryRenderer = GetComponent<MeshRenderer>();
                    PrimaryRendererMaterials = PrimaryRenderer.sharedMaterials;
                }
                PrimaryRenderer.enabled = false;

                if (OctaneRenderGO != null)
                {
                    GameObject.DestroyImmediate(OctaneRenderGO);
                    OctaneRenderGO = null;
                }

                OctaneRenderGO = new GameObject();
                OctaneRenderGO.transform.parent = transform;
                OctaneRenderGO.transform.localPosition = Vector3.zero;
                OctaneRenderGO.transform.localRotation = Quaternion.Euler(Vector3.zero);

                extrudedMeshOctane = new Mesh();
                extrudedMeshOctane.name = "ExtrudedMeshOctane";
                extrudedMeshOctane.MarkDynamic();

                extrudedMeshOctane.SetVertices(vertices);
                extrudedMeshOctane.SetNormals(normals);
                extrudedMeshOctane.SetTangents(tangents);
                extrudedMeshOctane.SetColors(vertColors);
                extrudedMeshOctane.SetUVs(0, uvs);
                extrudedMeshOctane.SetTriangles(tris, 0, true);

                MeshFilter NewFilter;
                NewFilter = OctaneRenderGO.AddComponent<MeshFilter>();
                NewFilter.mesh = extrudedMeshOctane;

                MeshRenderer NewRenderer;
                NewRenderer = OctaneRenderGO.AddComponent<MeshRenderer>();
                NewRenderer.sharedMaterials = PrimaryRendererMaterials;

            }
            #endregion

        }
Reply
#9
Also some feedback on your earlier comment
Simply creating a new mesh and assigning that to an existing game object / renderer does not work reliably.
a new game object must be deleted and recreated on each frame along with the mesh / meshfilter / renderer

I'm guessing this is because when a new object is created octane detects this as a new object and fetches the mesh from the scene graph.

If you could please please add this permutation to OBI rope / cloth / softbody etc... maybe with a config setting to enable octane mode. The reason is because others will run into this and maybe just give up. Also if I ever update to a new version of OBI components I would have to redo the patch each time

Thanks and Regards
Tikiri
Reply
#10
(13-08-2021, 12:25 PM)tcwicks Wrote: Also some feedback on your earlier comment
Simply creating a new mesh and assigning that to an existing game object / renderer does not work reliably.
a new game object must be deleted and recreated on each frame along with the mesh / meshfilter / renderer

I'm guessing this is because when a new object is created octane detects this as a new object and fetches the mesh from the scene graph.

If you could please please add this permutation to OBI rope / cloth / softbody etc... maybe with a config setting to enable octane mode. The reason is because others will run into this and maybe just give up. Also if I ever update to a new version of OBI components I would have to redo the patch each time

Thanks and Regards
Tikiri

Hi Tikiri,

I get your point of view. Obi is primarily a realtime physics engine, I can't really develop with third-party offline rendering engines in mind. This would result in bloated code that's harder to maintain and slower to evolve, specially for a one-man army like me. Dealing with Unity's 3 physics engines and 3 rendering pipelines is hard enough.

Octane says they can't be bothered to make their engine work with all existing third-party assets for Unity, because these might deviate from Unity's standard stuff/practices. Thing is, Obi isn't really doing anything non-standard or exotic: it's well within the realm of the ordinary.

Creating and modifying meshes at runtime is an extremely common use case: oceans, fur, particle systems, trails, billboards, deformers, and pretty much any vfx you can think of requires this. If they want to market Octane as a Unity-compliant renderer, I think it's their responsibility to properly support common use cases. Otherwise everyone else is doomed to jump trough hoops in order to work with their renderer.
Reply