I am creating a prototype Entity in a monobehavior and then instantiating that entity and assigning it the necessary components to then assign a mesh using a SystemBase. I can also see the entities with the necessary components in the Entity hierarchy. Here are the relevant code pieces:
void Start()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
currentPlayerChunk = GetChunkCoordinateFromPosition(player.position);
var desc = new RenderMeshDescription(shadowCastingMode: ShadowCastingMode.Off, receiveShadows: false);
var renderMeshArray = new RenderMeshArray(new Material[] { material }, new Mesh[] { new Mesh() });
prototype = entityManager.CreateEntity(); // create prototype
RenderMeshUtility.AddComponents(
prototype,
entityManager,
desc,
renderMeshArray,
MaterialMeshInfo.FromRenderMeshArrayIndices(0, 0));
entityManager.AddComponentData(prototype, new LocalToWorld());
using (var builder = new BlobBuilder(Allocator.Temp))
{
ref var meshData = ref builder.ConstructRoot<MeshData>();
var verticesArray = builder.Allocate(ref meshData.Vertices, vertexPool.Length);
var trianglesArray = builder.Allocate(ref meshData.Triangles, trianglePool.Length);
var uvsArray = builder.Allocate(ref meshData.UVs, uvPool.Length);
for (int i = 0; i < vertexPool.Length; i++)
{
verticesArray[i] = vertexPool[i];
}
for (int i = 0; i < trianglePool.Length; i++)
{
trianglesArray[i] = trianglePool[i];
}
for (int i = 0; i < uvPool.Length; i++)
{
uvsArray[i] = uvPool[i];
}
var blobAsset = builder.CreateBlobAssetReference<MeshData>(Allocator.Persistent);
entityManager.AddComponentData(prototype, new MeshComponent { MeshData = blobAsset });
entityManager.AddComponentData(prototype, new Chunk { self = prototype, material = MaterialManager.GetMaterialIndex(material) });
}
UpdateChunks();
}
void CreateTerrainChunkEntity(Vector2Int chunkCoord, NativeArray<Vector3> vertices, NativeArray<int> triangles, NativeArray<Vector2> uvs, int resolution, Material material)
{
var ecb = new EntityCommandBuffer(Allocator.Temp, PlaybackPolicy.MultiPlayback);
var chunkInstance = ecb.Instantiate(prototype);
Debug.Log("Entity: " + chunkInstance + " has been spawned");
BlobAssetReference<MeshData> blobAsset;
using (var builder = new BlobBuilder(Allocator.Temp))
{
ref var meshData = ref builder.ConstructRoot<MeshData>();
var verticesArray = builder.Allocate(ref meshData.Vertices, vertices.Length);
var trianglesArray = builder.Allocate(ref meshData.Triangles, triangles.Length);
var uvsArray = builder.Allocate(ref meshData.UVs, uvs.Length);
for (int i = 0; i < vertices.Length; i++)
{
verticesArray[i] = vertices[i];
}
for (int i = 0; i < triangles.Length; i++)
{
trianglesArray[i] = triangles[i];
}
for (int i = 0; i < uvs.Length; i++)
{
uvsArray[i] = uvs[i];
}
blobAsset = builder.CreateBlobAssetReference<MeshData>(Allocator.Persistent);
}
ecb.AddComponent(chunkInstance, new MeshComponent { MeshData = blobAsset });
ecb.AddComponent(chunkInstance, new Chunk { self = chunkInstance, material = MaterialManager.GetMaterialIndex(material) });
ecb.AddComponent(chunkInstance, new LocalTransform { Position = new float3(chunkCoord.x * chunkSize, 0, chunkCoord.y * chunkSize) });
//ecb.AddComponent(chunkInstance, new Parent { Value = parentEntity });
ecb.SetName(chunkInstance, $"Chunk_{chunkCoord.x}_{chunkCoord.y}");
ecb.Playback(entityManager);
ecb.Dispose();
//blobAsset.Dispose();
}
using Unity.Entities;
using Unity.Entities.Graphics;
using Unity.Mathematics;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;
using UnityEngine.Rendering;
public partial class ChunkSystem2 : SystemBase
{
private EntitiesGraphicsSystem _entitiesGraphicsSystem;
private EndSimulationEntityCommandBufferSystem _endSimulationEcbSystem;
protected override void OnCreate()
{
RequireForUpdate<MeshComponent>();
_endSimulationEcbSystem = World.GetOrCreateSystemManaged<EndSimulationEntityCommandBufferSystem>();
_entitiesGraphicsSystem = World.GetOrCreateSystemManaged<EntitiesGraphicsSystem>();
}
protected override void OnUpdate()
{
var ecb = _endSimulationEcbSystem.CreateCommandBuffer().AsParallelWriter();
foreach ((RefRO<MeshComponent> meshComponent, RefRO<Chunk> chunkData) in SystemAPI.Query<RefRO<MeshComponent>, RefRO<Chunk>>())
{
Debug.Log($"Entity World: {World.DefaultGameObjectInjectionWorld}");
Mesh mesh = new Mesh
{
vertices = meshComponent.ValueRO.MeshData.Value.Vertices.ToArray(),
triangles = meshComponent.ValueRO.MeshData.Value.Triangles.ToArray(),
uv = meshComponent.ValueRO.MeshData.Value.UVs.ToArray()
};
Debug.Log($"Vertices Count: {mesh.vertexCount}, Triangles Count: {mesh.triangles.Length / 3}, UVs Count: {mesh.uv.Length}");
mesh.RecalculateNormals();
mesh.RecalculateBounds();
// GameObject.Find("Sphere").GetComponent<MeshFilter>().mesh = mesh;
//mesh = GenerateLargeGridMesh(1000, 1000);
BatchMeshID meshID = _entitiesGraphicsSystem.RegisterMesh(mesh);
Debug.Log(MaterialManager.GetMaterialByIndex(chunkData.ValueRO.material));
var materialID = _entitiesGraphicsSystem.RegisterMaterial(MaterialManager.GetMaterialByIndex(chunkData.ValueRO.material));
Entity chunk = chunkData.ValueRO.self;
ecb.AddComponent<RenderMeshUnmanaged>(1, chunk, new RenderMeshUnmanaged
{
mesh = mesh
});
ecb.SetComponent<MaterialMeshInfo>(1, chunk, new MaterialMeshInfo
{
MaterialID = materialID,
MeshID = meshID,
});
Debug.Log($"Chunk Entity: {chunk.Index}");
ecb.RemoveComponent<Chunk>(1, chunk);
}
}
}
Also here the shader:
Shader "Custom/Terrain2"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_GradientColor1 ("Gradient Color 1", Color) = (0, 0, 1, 1) // Blue
_GradientColor2 ("Gradient Color 2", Color) = (0, 1, 0, 1) // Green
_GradientColor3 ("Gradient Color 3", Color) = (1, 1, 0, 1) // Yellow
_GradientColor4 ("Gradient Color 4", Color) = (1, 0, 0, 1) // Red
_Height1 ("Height 1", Range(-256, 1024)) = 85
_Height2 ("Height 2", Range(0, 1024)) = 170
_Height3 ("Height 3", Range(0, 1024)) = 700
_Height4 ("Height 4", Range(0, 1024)) = 1024
_DetailTex1 ("Detail Texture 1", 2D) = "white" {}
_DetailTex2 ("Detail Texture 2", 2D) = "white" {}
_DetailTex3 ("Detail Texture 3", 2D) = "white" {}
_DetailTex4 ("Detail Texture 4", 2D) = "white" {}
_NoiseTex1 ("Noise Texture1", 2D) = "white" {} // New noise texture
_NoiseTex2 ("Noise Texture2", 2D) = "white" {} // New noise texture
_NoiseScale1 ("Noise Scale1", Range(0.1, 10.0)) = 1.0 // Noise scale control
_NoiseScale2 ("Noise Scale2", Range(0.1, 100.0)) = 1.0 // Noise scale control
_NoiseInfluence1 ("Noise Influence1", Range(0, 1)) = 0.5
_NoiseInfluence2 ("Noise Influence2", Range(0, 1)) = 0.5
_ColorFog ("Fog Color", Color) = (0.5, 0.5, 0.5, 1)
_FogStartDistance ("Fog Start Distance", Range(0, 20000)) = 100
_FogEndDistance ("Fog End Distance", Range(0, 20000)) = 300
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#pragma target 4.5
#pragma instancing_options renderinglayer
#pragma multi_compile _ DOTS_INSTANCING_ON
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "HLSLSupport.cginc"
CBUFFER_START(UnityPerMaterial)
half4 _Color;
half _Glossiness;
half _Metallic;
float4 _GradientColor1;
float4 _GradientColor2;
float4 _GradientColor3;
float4 _GradientColor4;
float _Height1;
float _Height2;
float _Height3;
float _Height4;
float _FogStartDistance;
float _FogEndDistance;
float4 _ColorFog;
float _NoiseScale1;
float _NoiseScale2;
float _NoiseInfluence1;
float _NoiseInfluence2;
CBUFFER_END
#if defined(UNITY_DOTS_INSTANCING_ENABLED)
UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
UNITY_DOTS_INSTANCED_PROP(float4, _Color)
UNITY_DOTS_INSTANCED_PROP(half, _Glossiness)
UNITY_DOTS_INSTANCED_PROP(half, _Metallic)
UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor1)
UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor2)
UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor3)
UNITY_DOTS_INSTANCED_PROP(float4, _GradientColor4)
UNITY_DOTS_INSTANCED_PROP(float, _Height1)
UNITY_DOTS_INSTANCED_PROP(float, _Height2)
UNITY_DOTS_INSTANCED_PROP(float, _Height3)
UNITY_DOTS_INSTANCED_PROP(float, _Height4)
UNITY_DOTS_INSTANCED_PROP(float4, _ColorFog)
UNITY_DOTS_INSTANCED_PROP(float, _FogStartDistance)
UNITY_DOTS_INSTANCED_PROP(float, _FogEndDistance)
UNITY_DOTS_INSTANCED_PROP(float, _NoiseScale1)
UNITY_DOTS_INSTANCED_PROP(float, _NoiseScale2)
UNITY_DOTS_INSTANCED_PROP(float, _NoiseInfluence1)
UNITY_DOTS_INSTANCED_PROP(float, _NoiseInfluence2)
UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)
#define _Color UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _Color)
#define _Glossiness UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(half, _Glossiness)
#define _Metallic UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(half, _Metallic)
#define _GradientColor1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor1)
#define _GradientColor2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor2)
#define _GradientColor3 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor3)
#define _GradientColor4 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _GradientColor4)
#define _Height1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height1)
#define _Height2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height2)
#define _Height3 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height3)
#define _Height4 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _Height4)
#define _ColorFog UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _ColorFog)
#define _FogStartDistance UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _FogStartDistance)
#define _FogEndDistance UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _FogEndDistance)
#define _NoiseScale1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseScale1)
#define _NoiseScale2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseScale2)
#define _NoiseInfluence1 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseInfluence1)
#define _NoiseInfluence2 UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float, _NoiseInfluence2)
#endif
sampler2D _MainTex;
sampler2D _DetailTex1;
sampler2D _DetailTex2;
sampler2D _DetailTex3;
sampler2D _DetailTex4;
sampler2D _NoiseTex1;
sampler2D _NoiseTex2;
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
float3 position : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float2 uv : TEXCOORD0;
float4 positionHCS : SV_POSITION;
float height : TEXCOORD1;
float3 normal : NORMAL;
float3 worldPos : TEXCOORD2;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
Varyings vert(Attributes IN)
{
Varyings OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.uv = IN.uv;
OUT.height = IN.positionOS.y;
float3 normal = float3(0.0, 1.0, 0.0); // Assume upwards-facing normal
OUT.normal = normal;
// Store the world position for fog calculations
OUT.worldPos = IN.positionOS.xyz;
return OUT;
}
fixed4 frag(Varyings i) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(i)
//return float4(i.worldPos / 100.0, 1.0);
float noiseValue1 = tex2D(_NoiseTex1, i.uv * _NoiseScale1).r;
float noiseValue2 = tex2D(_NoiseTex2, i.uv * _NoiseScale2).r;
float modifiedHeight = i.height + (noiseValue1 * _NoiseInfluence1 * 100) + (noiseValue2 * _NoiseInfluence2 * 100);
float3 gradientColor;
fixed4 detailColor;
if (modifiedHeight < _Height1)
{
gradientColor = _GradientColor1.rgb;
detailColor = tex2D(_DetailTex1, i.uv);
}
else if (modifiedHeight < _Height2)
{
gradientColor = lerp(_GradientColor1.rgb, _GradientColor2.rgb, (modifiedHeight - _Height1) / (_Height2 - _Height1));
detailColor = tex2D(_DetailTex2, i.uv);
}
else if (modifiedHeight < _Height3)
{
gradientColor = lerp(_GradientColor2.rgb, _GradientColor3.rgb, (modifiedHeight - _Height2) / (_Height3 - _Height2));
detailColor = tex2D(_DetailTex3, i.uv);
}
else if (modifiedHeight < _Height4)
{
gradientColor = lerp(_GradientColor3.rgb, _GradientColor4.rgb, (modifiedHeight - _Height3) / (_Height4 - _Height3));
detailColor = tex2D(_DetailTex4, i.uv);
}
else
{
gradientColor = _GradientColor4.rgb;
detailColor = tex2D(_DetailTex4, i.uv);
}
float3 lightDir = normalize(float3(1, 1, -1));
float lightIntensity = max(dot(i.normal, lightDir), 0.0);
float fogDistance = length(i.worldPos - _WorldSpaceCameraPos);
float fogFactor = saturate((fogDistance - _FogStartDistance) / (_FogEndDistance - _FogStartDistance));
fixed4 baseColor = tex2D(_MainTex, i.uv) * fixed4(gradientColor, 1.0) * _Color * detailColor * lightIntensity;
fixed4 fogColor = fixed4(_ColorFog.rgb, 1.0);
return lerp(baseColor, fogColor, fogFactor);
}
ENDHLSL
}
}
FallBack "Diffuse"
}
My camera has everything on it’s culling layer, my entities do have a renderMeshUnmanaged, my vertex count is 289, my uv count is 289 my trianglecount/3 is 512 and my shader works on other baked entities.
So why am I not seeing anything beeing rendered? I even tried replacing the mesh with a custom grid mesh and it didn’t work.
I don’t know if it’s relevant but I also found out that my when my Camera looks at (0,0,0) but isn’t at (0,0,0) itself the tris count increases from like 4k to 500k. And generally the tris count even when not looking at (0,0,0) increases as I increase the renderdistance.