Esempio n. 1
0
        private AABB RotateBounds(ref float4x4 tx, ref AABB b)
        {
            WorldBounds wBounds;

            Culling.AxisAlignedToWorldBounds(ref tx, ref b, out wBounds);
            // now turn those bounds back to axis aligned..
            AABB aab;

            Culling.WorldBoundsToAxisAligned(ref wBounds, out aab);
            return(aab);
        }
        private void EncodeBox(RendererBGFXInstance *sys, bgfx.Encoder *encoder, Entity ePass, ref float4x4 tx, float3 cMin, float3 cMax, float width, float4 color)
        {
            var      pass = EntityManager.GetComponentData <RenderPass>(ePass);
            float4x4 adjustedProjection = sys->GetAdjustedProjection(ref pass);
            float2   normWidth          = new float2(width / pass.viewport.w, width / pass.viewport.h);

            for (int j = 0; j < Culling.EdgeTable.Length; j++)
            {
                float3 p0 = Culling.SelectCoordsMinMax(cMin, cMax, Culling.EdgeTable[j] & 7);
                float3 p1 = Culling.SelectCoordsMinMax(cMin, cMax, Culling.EdgeTable[j] >> 3);
                SubmitHelper.EncodeLine(sys, encoder, pass.viewId, p0, p1, color, normWidth,
                                        ref tx, ref pass.viewTransform, ref adjustedProjection);
            }
        }
Esempio n. 3
0
            public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var chunkLocalToWorld        = chunk.GetNativeArray(LocalToWorldType);
                var chunkMeshRenderer        = chunk.GetNativeArray(MeshRendererType);
                var chunkMeshReference       = chunk.GetNativeArray(LitMeshType);
                var chunkWorldBoundingSphere = chunk.GetNativeArray(WorldBoundingSphereType);
                var boundingSphere           = chunk.GetChunkComponentData(ChunkWorldBoundingSphereType).Value;
                var bounds = chunk.GetChunkComponentData(ChunkWorldBoundsType).Value;

                Entity lighte   = SharedLightingRef[chunkIndex];
                var    lighting = ComponentLightingBGFX[lighte];
                Entity rtpe     = SharedRenderToPass[chunkIndex];

                Assert.IsTrue(ThreadIndex >= 0 && ThreadIndex < MaxPerThreadData);
                bgfx.Encoder *encoder = PerThreadData[ThreadIndex].encoder;
                if (encoder == null)
                {
                    encoder = bgfx.encoder_begin(true);
                    Assert.IsTrue(encoder != null);
                    PerThreadData[ThreadIndex].encoder = encoder;
                }
                DynamicBuffer <RenderToPassesEntry> toPasses = BufferRenderToPassesEntry[rtpe];

                // we can do this loop either way, passes first or renderers first.
                // TODO: profile what is better!
                for (int i = 0; i < toPasses.Length; i++)
                {
                    Entity  ePass   = toPasses[i].e;
                    Frustum frustum = default;
                    if (ComponentFrustum.Exists(ePass))
                    {
                        frustum = ComponentFrustum[ePass]; // TODO, just make frustum a member of pass?
                        if (Culling.Cull(ref boundingSphere, ref frustum) == Culling.CullingResult.Outside)
                        {
                            continue; // nothing to do for this pass
                        }
                    }
                    Assert.IsTrue(encoder != null);
                    var pass = ComponentRenderPass[ePass];
                    for (int j = 0; j < chunk.Count; j++)
                    {
                        var wbs          = chunkWorldBoundingSphere[j];
                        var meshRenderer = chunkMeshRenderer[j];
                        var meshRef      = chunkMeshReference[j];
                        var mesh         = ComponentSimpleMeshBGFX[meshRef.mesh];
                        var tx           = chunkLocalToWorld[j].Value;
                        if (Culling.Cull(ref wbs, ref frustum) == Culling.CullingResult.Outside) // TODO: fine cull only if rough culling was !Inside
                        {
                            continue;
                        }
                        switch (pass.passType)   // TODO: we can hoist this out of the loop
                        {
                        case RenderPassType.ZOnly:
                            SubmitHelper.EncodeZOnly(BGFXSystem, encoder, pass.viewId, ref mesh, ref tx, meshRenderer.startIndex, meshRenderer.indexCount, pass.flipCulling);
                            break;

                        case RenderPassType.ShadowMap:
                            float4 bias = new float4(0);
                            SubmitHelper.EncodeShadowMap(BGFXSystem, encoder, pass.viewId, ref mesh, ref tx, meshRenderer.startIndex, meshRenderer.indexCount, (byte)(pass.flipCulling ^ 0x3), bias);
                            break;

                        case RenderPassType.Transparent:
                        case RenderPassType.Opaque:
                            var material = ComponentLitMaterialBGFX[meshRenderer.material];
                            SubmitHelper.EncodeLit(BGFXSystem, encoder, pass.viewId, ref mesh, ref tx, ref material, ref lighting, ref pass.viewTransform, meshRenderer.startIndex, meshRenderer.indexCount, pass.flipCulling, ref PerThreadData[ThreadIndex].viewSpaceLightCache);
                            break;

                        default:
                            Assert.IsTrue(false);
                            break;
                        }
                    }
                }
            }
Esempio n. 4
0
        protected override void OnUpdate()
        {
            var sys = World.GetExistingSystem <RendererBGFXSystem>();

            if (!sys.Initialized)
            {
                return;
            }
            // get all MeshRenderer, cull them, and add them to graph nodes that need them
            // any mesh renderer MUST have a shared component data that has a list of passes to render to
            // this list is usually very shared - all opaque meshes will render to all ZOnly and Opaque passes
            // this shared data is not dynamically updated - other systems are responsible to update them if needed
            // simple
            Entities.ForEach((Entity e, ref MeshRenderer mr, ref SimpleMeshReference meshRef, ref LocalToWorld tx, ref WorldBounds wb, ref WorldBoundingSphere wbs) =>
            {
                if (!EntityManager.HasComponent <RenderToPasses>(e))
                {
                    return;
                }

                RenderToPasses toPassesRef = EntityManager.GetSharedComponentData <RenderToPasses>(e);
                DynamicBuffer <RenderToPassesEntry> toPasses = EntityManager.GetBufferRO <RenderToPassesEntry>(toPassesRef.e);
                for (int i = 0; i < toPasses.Length; i++)
                {
                    Entity ePass = toPasses[i].e;
                    var pass     = EntityManager.GetComponentData <RenderPass>(ePass);
                    if (EntityManager.HasComponent <Frustum>(ePass))
                    {
                        var frustum = EntityManager.GetComponentData <Frustum>(ePass);
                        if (Culling.Cull(ref wbs, ref frustum) == Culling.CullingResult.Outside)
                        {
                            continue;
                        }
                        // double cull as example only
                        if (Culling.IsCulled(ref wb, ref frustum))
                        {
                            continue;
                        }
                    }
                    var mesh = EntityManager.GetComponentData <SimpleMeshBGFX>(meshRef.mesh);
                    switch (pass.passType)
                    {
                    case RenderPassType.ZOnly:
                        SubmitHelper.SubmitZOnlyDirect(sys, pass.viewId, ref mesh, ref tx.Value, mr.startIndex, mr.indexCount, pass.flipCulling);
                        break;

                    case RenderPassType.ShadowMap:
                        SubmitHelper.SubmitZOnlyDirect(sys, pass.viewId, ref mesh, ref tx.Value, mr.startIndex, mr.indexCount, (byte)(pass.flipCulling ^ 0x3));
                        break;

                    case RenderPassType.Transparent:
                    case RenderPassType.Opaque:
                        var material = EntityManager.GetComponentData <SimpleMaterialBGFX>(mr.material);
                        SubmitHelper.SubmitSimpleDirect(sys, pass.viewId, ref mesh, ref tx.Value, ref material, mr.startIndex, mr.indexCount, pass.flipCulling);
                        break;

                    default:
                        Assert.IsTrue(false);
                        break;
                    }
                }
            });
        }
Esempio n. 5
0
        protected override void OnUpdate()
        {
            // check if we need bounds
            bool needBounds = false;

            Entities.ForEach((Entity e, ref AutoMovingDirectionalLight amdl) =>
            {
                if (amdl.autoBounds)
                {
                    needBounds = true;
                }
            });

            // compute bounds if needed
            // TODO: separate bounds for shadow casters and receivers?
            AABB autoBounds = default;

            if (needBounds)
            {
                // TODO: use chunk bounds instead!
                float3 bbMin = new float3(float.MaxValue);
                float3 bbMax = new float3(-float.MaxValue);
                Entities.ForEach((Entity e, ref WorldBounds wb) =>
                {
                    Culling.GrowBounds(ref bbMin, ref bbMax, wb);
                });
                autoBounds = new AABB {
                    Center  = (bbMin + bbMax) * .5f,
                    Extents = (bbMax - bbMin) * .5f
                };
                if (math.any(autoBounds.Extents < 0.0f))
                {
                    autoBounds.Center  = new float3(0);
                    autoBounds.Extents = new float3(0);
                }
            }

            // do assignment
            Entities.ForEach((Entity e, ref AutoMovingDirectionalLight amdl, ref DirectionalLight dl, ref Light l, ref LocalToWorld tx) =>
            {
                if (amdl.autoBounds)
                {
                    amdl.boundsCasters   = autoBounds;
                    amdl.boundsReceivers = autoBounds;
                }

                // transform bounds into light space rotation
                float4x4 rotOnlyTx    = tx.Value;
                rotOnlyTx.c3          = new float4(0, 0, 0, 1);
                float4x4 rotOnlyTxInv = math.inverse(rotOnlyTx);

                AABB aabCasters   = RotateBounds(ref rotOnlyTx, ref amdl.boundsCasters);
                AABB aabReceivers = RotateBounds(ref rotOnlyTx, ref amdl.boundsReceivers);

                l.clipZFar = l.clipZNear + aabReceivers.Extents.z + aabCasters.Extents.z; // do not change near clip
                float3 posls;
                posls.x         = aabCasters.Center.x;
                posls.y         = aabCasters.Center.y;
                posls.z         = aabCasters.Center.z - aabCasters.Extents.z - l.clipZNear;
                tx.Value.c3.xyz = math.transform(rotOnlyTx, posls); // back to world space
                dl.size         = math.max(aabCasters.Extents.x, aabCasters.Extents.y);
            });
        }