Search Unity

Bug Strange behaviour: Hybrid Renderer skipping a batch due to invalid RenderMesh.

Discussion in 'Graphics for ECS' started by slushieboy99, Dec 29, 2022.

  1. slushieboy99

    slushieboy99

    Joined:
    Aug 29, 2014
    Posts:
    88
    I'm creating meshes during runtime and trying to render them with the latest version of Hybrid Renderer V2. About 50% of the meshes are instantiated correctly with the others being invisible. The odd thing is, when I click on the broken entities in the entity debugger, the Hybrid Chunk Info changes and the mesh is suddenly visible! The error I get is WARNING: Hybrid Renderer skipping a batch due to invalid RenderMesh.

    Code for generating mesh from index and triangle list:
    Code (CSharp):
    1. public void CreateMesh() {
    2.         Debug.Log("Creating Mesh");
    3.         var dataArray = Mesh.AllocateWritableMeshData(1);
    4.         var data = dataArray[0];
    5.  
    6.         data.SetVertexBufferParams(vertices.Length,
    7.             new VertexAttributeDescriptor(VertexAttribute.Position),
    8.             new VertexAttributeDescriptor(VertexAttribute.Normal, stream:1));
    9.         data.GetVertexData<Vector3>().CopyFrom(vertices.ToArray());
    10.  
    11.         data.SetIndexBufferParams(triangles.Length, IndexFormat.UInt32);
    12.         data.GetIndexData<uint>().CopyFrom(triangles.ToArray());
    13.  
    14.         data.subMeshCount = 1;
    15.         data.SetSubMesh(0, new SubMeshDescriptor(0, triangles.Length));
    16.         Mesh.ApplyAndDisposeWritableMeshData(dataArray, mesh);
    17.         mesh.name = "TerrainMesh";
    18.         mesh.RecalculateNormals();
    19.         mesh.RecalculateBounds();
    20.     }
    Code for initializing entity render mesh will be placed on:
    Code (CSharp):
    1. entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    2.         EntityArchetype terrainSubMeshArchetype = entityManager.CreateArchetype(
    3.                 typeof(Translation),
    4.                 typeof(LocalToWorld),
    5.                 typeof(RenderMesh),
    6.                 typeof(PhysicsCollider),
    7.                 typeof(Rotation),
    8.                 typeof(CompositeScale),
    9.                 typeof(PerInstanceCullingTag),
    10.                 typeof(WorldToLocal_Tag),
    11.                 typeof(BlendProbeTag),
    12.                 typeof(BuiltinMaterialPropertyUnity_LightData),
    13.                 typeof(BuiltinMaterialPropertyUnity_RenderingLayer),
    14.                 typeof(BuiltinMaterialPropertyUnity_WorldTransformParams),
    15.                 typeof(PhysicsWorldIndex),
    16.                 typeof(RenderBounds),
    17.                 typeof(TerrainTag)
    18.             );
    19.         meshEntity = entityManager.CreateEntity(terrainSubMeshArchetype);
    20.         entityManager.SetComponentData(meshEntity, new Translation { Value = new float3(xCoord, 0, yCoord) });
    21.         entityManager.SetComponentData(meshEntity, new Rotation { Value = Quaternion.Euler(0, 0, 0)});
    22.         entityManager.SetComponentData(meshEntity, new RenderBounds { Value = new AABB { Center = new float3(xCoord, 0, yCoord), Extents = new float3((MapGenerator.mapChunkSize * 2) * TerrainData.uniformScale, 5000, (MapGenerator.mapChunkSize * 2) * TerrainData.uniformScale) } });
    23.         entityManager.SetComponentData(meshEntity, new CompositeScale { Value = new float4x4(new float4(TerrainData.uniformScale, 0, 0, 0), new float4(0, TerrainData.uniformScale, 0, 0), new float4(0, 0, TerrainData.uniformScale, 0), new float4(0, 0, 0, 1))});
    24.         entityManager.SetComponentData(meshEntity, new BuiltinMaterialPropertyUnity_LightData { Value = new float4(0, 0, 1, 0) });
    25.         entityManager.SetComponentData(meshEntity, new BuiltinMaterialPropertyUnity_RenderingLayer { Value = new uint4(8, 0, 1, 0) });
    26.         entityManager.SetComponentData(meshEntity, new BuiltinMaterialPropertyUnity_WorldTransformParams { Value = new float4(0, 0, 0, 1) });
    27.         entityManager.SetSharedComponentData(meshEntity, new PhysicsWorldIndex { Value = 0 });
    Code for creating render mesh:
    Code (CSharp):
    1. RenderMesh rm = new RenderMesh {
    2.                     mesh = meshData.GetMesh(),
    3.                     material = this.material,
    4.                     layer = 8,
    5.                     layerMask = 8,
    6.                     receiveShadows = true,
    7.                     castShadows = UnityEngine.Rendering.ShadowCastingMode.TwoSided,
    8.                 };
    9.  
    10.                 if(rm.material == null) Debug.LogError("Applying Null Material to RenderMesh2");
    11.  
    12.                 entityManager.SetSharedComponentData(meshEntity, rm);
    13.                 entityManager.SetComponentData(meshEntity, new RenderBounds { Value = meshData.GetMesh().bounds.ToAABB()});
    14.  
     
  2. Fribur

    Fribur

    Joined:
    Jan 5, 2019
    Posts:
    136
    Completely ignore RenderMesh. You need to register the Mesh with the BatchRenderGroup (BRG), and use the ID you get to create MaterialMeshInfo, which you use instead of RenderMesh. More info in in this thread where I had similar questions.
     
  3. slushieboy99

    slushieboy99

    Joined:
    Aug 29, 2014
    Posts:
    88
    I should have mentioned I'm using Entities 0.51. Is there a fix for this in ECS 0.51 or do I need to update?
     
  4. slushieboy99

    slushieboy99

    Joined:
    Aug 29, 2014
    Posts:
    88
    For anyone who needs it I made a bandaid for this which forces the rendermesh to update


    Code (CSharp):
    1. public partial class FixRenderBoundsSystem : SystemBase
    2. {
    3.     protected override void OnUpdate() {
    4.         Entities.WithStructuralChanges().WithAll<TerrainTag, DebugNeedsRenderMeshUpdateTag>().ForEach((Entity e, in RenderMesh renderMesh) => {
    5.             //hci.CullingData.StartIndex += 30;
    6.             //Debug.Log("Updating Render mesh");
    7.             RenderMesh renderMesh2 = renderMesh;
    8.             renderMesh2.mesh = renderMesh.mesh;
    9.             renderMesh2.mesh.MarkModified();
    10.             renderMesh2.needMotionVectorPass = true;
    11.             renderMesh2.mesh.Optimize();
    12.             EntityManager.SetSharedComponentData<RenderMesh>(e, renderMesh2);
    13.             EntityManager.RemoveComponent<DebugNeedsRenderMeshUpdateTag>(e);
    14.         }).WithoutBurst().Run();
    15.     }
    16. }
    Where DebugNeedsRenderMeshUpdateTag should be added to the entity when the rendermesh is added.