コード例 #1
0
        private static Entity CreateParticleRenderer(EntityManager mgr, Entity eEmitter)
        {
            Entity eParticleRenderer = mgr.CreateEntity(typeof(MeshRenderer), typeof(EmitterReferenceForRenderer), typeof(LocalToWorld), typeof(DynamicMeshData));
            var    material          = mgr.GetComponentData <ParticleMaterial>(eEmitter).Material;

            Assert.IsTrue(material != Entity.Null);
            mgr.AddComponentData(eParticleRenderer, new MeshRenderer
            {
                mesh       = eParticleRenderer,
                material   = material,
                startIndex = 0,
                indexCount = 0
            });
            mgr.AddComponentData(eParticleRenderer, new EmitterReferenceForRenderer {
                emitter = eEmitter
            });
            mgr.AddComponentData(eParticleRenderer, new LocalToWorld {
                Value = float4x4.identity
            });

            bool isLit = mgr.HasComponent <LitMaterial>(material);

            if (isLit)
            {
                mgr.AddComponentData(eParticleRenderer, new LitParticleRenderer());
            }
            else
            {
                Assert.IsTrue(mgr.HasComponent <SimpleMaterial>(material));
                mgr.AddComponentData(eParticleRenderer, new SimpleParticleRenderer());
            }

            // Particle mesh
            if (mgr.HasComponent <ParticleMesh>(eEmitter))
            {
                ParticleMesh particleMesh = mgr.GetComponentData <ParticleMesh>(eEmitter);
                Assert.IsTrue(particleMesh.Mesh != Entity.Null);
            }
            else // Billboarded
            {
                // Add mesh for 1x1 quad
                Entity mesh;
                float3 org     = new float3(-0.5f, -0.5f, 0);
                float3 du      = new float3(1, 0, 0);
                float3 dv      = new float3(0, 1, 0);
                var    builder = new BlobBuilder(Allocator.Temp);
                if (isLit)
                {
                    LitMeshRenderData lmrd;
                    MeshBounds        mb;
                    ref var           root = ref builder.ConstructRoot <LitMeshData>();
                    var vertices           = builder.Allocate(ref root.Vertices, 4).AsNativeArray();
                    var indices            = builder.Allocate(ref root.Indices, 6).AsNativeArray();
                    vertices[0] = new LitVertex {
                        Position = org, TexCoord0 = new float2(0, 1)
                    };
                    vertices[1] = new LitVertex {
                        Position = org + du, TexCoord0 = new float2(1, 1)
                    };
                    vertices[2] = new LitVertex {
                        Position = org + du + dv, TexCoord0 = new float2(1, 0)
                    };
                    vertices[3] = new LitVertex {
                        Position = org + dv, TexCoord0 = new float2(0, 0)
                    };
                    indices[0] = 0; indices[1] = 2; indices[2] = 1;
                    indices[3] = 2; indices[4] = 0; indices[5] = 3;
                    MeshHelper.ComputeNormals(vertices, indices);
                    MeshHelper.ComputeTangentAndBinormal(vertices, indices);
                    MeshHelper.SetAlbedoColor(vertices, new float4(1));
                    MeshHelper.SetMetalSmoothness(vertices, new float2(1));
                    mb.Bounds = MeshHelper.ComputeBounds(vertices);
                    lmrd.Mesh = builder.CreateBlobAssetReference <LitMeshData>(Allocator.Persistent);
                    mesh      = mgr.CreateEntity(typeof(LitMeshRenderData), typeof(MeshBounds));
                    mgr.SetComponentData(mesh, lmrd);
                    mgr.SetComponentData(mesh, mb);
                    var litMaterial = mgr.GetComponentData <LitMaterial>(material);
                    litMaterial.billboarded = true;
                    mgr.SetComponentData(material, litMaterial);
                }
コード例 #2
0
        protected override void OnUpdate()
        {
            EntityCommandBuffer  ecb       = new EntityCommandBuffer(Allocator.TempJob);
            NativeArray <Entity> renderers = m_ParticleRenderersQuery.ToEntityArray(Allocator.TempJob);

            foreach (var renderer in renderers)
            {
                var emitterReference = EntityManager.GetComponentData <EmitterReferenceForRenderer>(renderer);
                var eEmitter         = emitterReference.emitter;

                // In some cases it takes an extra frame for the particle entities that reference a destroyed emitter to be destroyed, most likely because of system state components
                if (!ParticlesUtil.EmitterIsValid(EntityManager, eEmitter))
                {
                    continue;
                }

                DynamicBuffer <Particle> particles = EntityManager.GetBuffer <DynamicParticle>(eEmitter).Reinterpret <Particle>();

                if (!EntityManager.GetEnabled(eEmitter) || particles.Length == 0)
                {
                    if (!EntityManager.HasComponent <Disabled>(renderer))
                    {
                        ecb.AddComponent(renderer, new Disabled());
                    }

                    continue;
                }

                if (EntityManager.HasComponent <Disabled>(renderer))
                {
                    ecb.RemoveComponent <Disabled>(renderer);
                }

                var        particleMesh = EntityManager.GetComponentData <ParticleMesh>(eEmitter);
                var        meshRenderer = EntityManager.GetComponentData <MeshRenderer>(renderer);
                Entity     eMesh = meshRenderer.mesh;
                var        particleEmitter = EntityManager.GetComponentData <ParticleEmitter>(eEmitter);
                var        localToWorldEmitter = particleEmitter.AttachToEmitter ? EntityManager.GetComponentData <LocalToWorld>(eEmitter).Value : float4x4.identity;
                MinMaxAABB minMaxAABB = MinMaxAABB.Empty;
                int        numVertices, numIndices;
                if (EntityManager.HasComponent <LitParticleRenderer>(renderer))
                {
                    ref LitMeshData         lmd = ref EntityManager.GetComponentData <LitMeshRenderData>(particleMesh.Mesh).Mesh.Value;
                    int                     numVertsPerParticle   = lmd.Vertices.Length;
                    int                     numIndicesPerParticle = lmd.Indices.Length;
                    NativeArray <LitVertex> particleVertices      = MeshHelper.AsNativeArray(ref lmd.Vertices);
                    NativeArray <ushort>    particleIndices       = MeshHelper.AsNativeArray(ref lmd.Indices);
                    var                     vBuffer = EntityManager.GetBuffer <DynamicLitVertex>(eMesh);
                    var                     iBuffer = EntityManager.GetBuffer <DynamicIndex>(eMesh);
                    numVertices = particles.Length * numVertsPerParticle;
                    numIndices  = particles.Length * numIndicesPerParticle;
                    vBuffer.ResizeUninitialized(numVertices); // Grow buffers as needed
                    iBuffer.ResizeUninitialized(numIndices);
                    NativeArray <LitVertex> vertices = vBuffer.AsNativeArray().Reinterpret <DynamicLitVertex, LitVertex>();
                    NativeArray <ushort>    indices  = iBuffer.AsNativeArray().Reinterpret <DynamicIndex, ushort>();
                    bool billboarded = EntityManager.GetComponentData <LitMaterial>(meshRenderer.material).billboarded;

                    for (int particleIndex = 0; particleIndex < particles.Length; particleIndex++)
                    {
                        float4x4 localToWorld            = GetParticleLocalToWorld(particles[particleIndex], localToWorldEmitter);
                        float3x3 localToWorldRS          = new float3x3(localToWorld.c0.xyz, localToWorld.c1.xyz, localToWorld.c2.xyz);
                        float3x3 modelInverseTransposeRS = math.transpose(math.inverse(localToWorldRS));
                        float4x4 modelInverseTranspose   = new float4x4(modelInverseTransposeRS, float3.zero);

                        // Postpone translate until after additional rotation for billboarding is applied in shader
                        float4x4 model = billboarded ? new float4x4(localToWorldRS, float3.zero) : localToWorld;

                        int vertexOffset = particleIndex * numVertsPerParticle;
                        for (int i = 0; i < numVertsPerParticle; i++)
                        {
                            LitVertex vertex = particleVertices[i];
                            vertex.Position            = math.transform(model, vertex.Position);
                            vertex.Normal              = math.transform(modelInverseTranspose, vertex.Normal);
                            vertex.Tangent             = math.transform(modelInverseTranspose, vertex.Tangent);
                            vertex.BillboardPos        = billboarded ? localToWorld.c3.xyz : float3.zero;
                            vertex.Albedo_Opacity      = particles[particleIndex].color;
                            vertices[vertexOffset + i] = vertex;
                            minMaxAABB.Encapsulate(vertex.Position + vertex.BillboardPos);
                        }
                        UpdateIndicesForParticle(indices, particleIndices, particleIndex, numIndicesPerParticle, vertexOffset);
                    }
                }