示例#1
0
    static unsafe void DrawSegments(
        NativeArray <SegmentData> segments,
        World *worldLODs,
        CameraData camera,
        int screenWidth,
        int screenHeight,
        float2 vanishingPointScreenSpace,
        RayBuffer.Native rayBufferTopDown,
        RayBuffer.Native rayBufferLeftRight,
        RayBuffer rayBufferTopDownManaged,
        RayBuffer rayBufferLeftRightManaged
        )
    {
        float2 screen = new float2(screenWidth, screenHeight);

        Profiler.BeginSample("Segment setup overhead");
        DrawSegmentRayJob.DrawContext drawContext = new DrawSegmentRayJob.DrawContext
        {
            camera    = camera,
            screen    = screen,
            worldLODs = worldLODs
        };

        NativeArray <DrawSegmentRayJob.SegmentContext> segmentContexts = new NativeArray <DrawSegmentRayJob.SegmentContext>(4, Allocator.TempJob, NativeArrayOptions.ClearMemory);

        DrawSegmentRayJob.SegmentContext *segmentContextPtr = (DrawSegmentRayJob.SegmentContext *)segmentContexts.GetUnsafePtr();
        int totalRays = 0;

        for (int segmentIndex = 0; segmentIndex < segments.Length; segmentIndex++)
        {
            DrawSegmentRayJob.SegmentContext *context = segmentContextPtr + segmentIndex;
            context->segment = segments[segmentIndex];
            totalRays       += segments[segmentIndex].RayCount;

            if (segments[segmentIndex].RayCount <= 0)
            {
                continue;
            }

            context->axisMappedToY         = (segmentIndex > 1) ? 0 : 1;
            context->segmentRayIndexOffset = 0;
            if (segmentIndex == 1)
            {
                context->segmentRayIndexOffset = segments[0].RayCount;
            }
            if (segmentIndex == 3)
            {
                context->segmentRayIndexOffset = segments[2].RayCount;
            }

            int2 nextFreePixel;
            if (segmentIndex < 2)
            {
                context->activeRayBufferFull = rayBufferTopDown;
                if (segmentIndex == 0)                   // top segment
                {
                    nextFreePixel = int2(clamp(Mathf.RoundToInt(vanishingPointScreenSpace.y), 0, screenHeight - 1), screenHeight - 1);
                }
                else                     // bottom segment
                {
                    nextFreePixel = int2(0, clamp(Mathf.RoundToInt(vanishingPointScreenSpace.y), 0, screenHeight - 1));
                }
            }
            else
            {
                context->activeRayBufferFull = rayBufferLeftRight;
                if (segmentIndex == 3)                   // left segment
                {
                    nextFreePixel = int2(0, clamp(Mathf.RoundToInt(vanishingPointScreenSpace.x), 0, screenWidth - 1));
                }
                else                     // right segment
                {
                    nextFreePixel = int2(clamp(Mathf.RoundToInt(vanishingPointScreenSpace.x), 0, screenWidth - 1), screenWidth - 1);
                }
            }

            context->originalNextFreePixelMin = nextFreePixel.x;
            context->originalNextFreePixelMax = nextFreePixel.y;
            context->seenPixelCacheLength     = (int)ceil(drawContext.screen[context->axisMappedToY]);
        }

        Profiler.EndSample();

        rayBufferTopDownManaged.Prepare(segments[0].RayCount + segments[1].RayCount);
        rayBufferLeftRightManaged.Prepare(segments[2].RayCount + segments[3].RayCount);

        NativeArray <DrawSegmentRayJob.RayContext> rayContext = new NativeArray <DrawSegmentRayJob.RayContext>(
            totalRays, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
        NativeArray <DrawSegmentRayJob.RayDDAContext> rayDDAContext = new NativeArray <DrawSegmentRayJob.RayDDAContext>(
            totalRays, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
        NativeList <DrawSegmentRayJob.RayContinuation> rayContinuations = new NativeList <DrawSegmentRayJob.RayContinuation>(
            totalRays, Allocator.TempJob);

        DrawSegmentRayJob.RaySetupJob raySetupJob = new DrawSegmentRayJob.RaySetupJob()
        {
            contexts = segmentContexts,
            rays     = rayContext
        };

        DrawSegmentRayJob.DDASetupJob ddaSetupJob = new DrawSegmentRayJob.DDASetupJob()
        {
            raysInput   = rayContext,
            raysOutput  = rayDDAContext,
            drawContext = drawContext,
        };

        DrawSegmentRayJob.TraceToFirstColumnJob firstColumnJob = new DrawSegmentRayJob.TraceToFirstColumnJob
        {
            drawContext = drawContext,
            inRays      = rayDDAContext,
            outRays     = rayContinuations.AsParallelWriter()
        };

        DrawSegmentRayJob.RenderJob renderJob = new DrawSegmentRayJob.RenderJob
        {
            rays           = rayContinuations,
            DrawingContext = drawContext,
        };

        JobHandle setup       = raySetupJob.Schedule(totalRays, 64);
        JobHandle ddaSetup    = ddaSetupJob.Schedule(totalRays, 64, setup);
        JobHandle firstColumn = firstColumnJob.Schedule(totalRays, 4, ddaSetup);
        JobHandle render      = renderJob.Schedule(totalRays, 1, firstColumn);

        render.Complete();

        rayContext.Dispose();
        segmentContexts.Dispose();
        rayDDAContext.Dispose();
        rayContinuations.Dispose();

        rayBufferTopDownManaged.UploadCompletes();
        rayBufferLeftRightManaged.UploadCompletes();
    }