示例#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();
    }
示例#2
0
    public unsafe void DrawWorld(Material blitMaterial, World[] worldLODs, Camera camera, Camera actualCamera, float[] LODDistances)
    {
        Mesh blitMesh = blitMeshes[bufferIndex];

        Debug.DrawLine(new Vector2(0f, 0f), new Vector2(screenWidth, 0f));
        Debug.DrawLine(new Vector2(screenWidth, 0f), new Vector2(screenWidth, screenHeight));
        Debug.DrawLine(new Vector2(screenWidth, screenHeight), new Vector2(0f, screenHeight));
        Debug.DrawLine(new Vector2(0f, screenHeight), new Vector2(0f, 0f));

        Profiler.BeginSample("Setup VP");
        float3 vanishingPointWorldSpace  = CalculateVanishingPointWorld(camera);
        float2 vanishingPointScreenSpace = ProjectVanishingPointScreenToWorld(camera, vanishingPointWorldSpace);

        Profiler.EndSample();
        float2 screen = new float2(screenWidth, screenHeight);

        NativeArray <SegmentData> segments = new NativeArray <SegmentData>(4, Allocator.Temp, NativeArrayOptions.ClearMemory);

        Profiler.BeginSample("Setup segment params");
        if (vanishingPointScreenSpace.y < screenHeight)
        {
            segments[0] = GetGenericSegmentParameters(camera, screen, vanishingPointScreenSpace, screenHeight - vanishingPointScreenSpace.y, new float2(0, 1), 1, worldLODs[0].DimensionY);
        }

        if (vanishingPointScreenSpace.y > 0f)
        {
            segments[1] = GetGenericSegmentParameters(camera, screen, vanishingPointScreenSpace, vanishingPointScreenSpace.y, new float2(0, -1), 1, worldLODs[0].DimensionY);
        }

        if (vanishingPointScreenSpace.x < screenWidth)
        {
            segments[2] = GetGenericSegmentParameters(camera, screen, vanishingPointScreenSpace, screenWidth - vanishingPointScreenSpace.x, new float2(1, 0), 0, worldLODs[0].DimensionY);
        }

        if (vanishingPointScreenSpace.x > 0f)
        {
            segments[3] = GetGenericSegmentParameters(camera, screen, vanishingPointScreenSpace, vanishingPointScreenSpace.x, new float2(-1, 0), 0, worldLODs[0].DimensionY);
        }
        Profiler.EndSample();
        RayBuffer activeRaybufferTopDown   = rayBufferTopDown[bufferIndex];
        RayBuffer activeRaybufferLeftRight = rayBufferLeftRight[bufferIndex];

        RayBuffer.Native topDownNative   = activeRaybufferTopDown.GetNativeData(Allocator.TempJob);
        RayBuffer.Native leftRightNative = activeRaybufferLeftRight.GetNativeData(Allocator.TempJob);

        commandBuffer.Clear();

        CameraData camData = new CameraData(camera, LODDistances, screen);

        Profiler.BeginSample("Draw planes");
        fixed(World *worldPtr = worldLODs)
        {
            DrawSegments(segments,
                         worldPtr,
                         camData,
                         screenWidth,
                         screenHeight,
                         vanishingPointScreenSpace,
                         topDownNative,
                         leftRightNative,
                         activeRaybufferTopDown,
                         activeRaybufferLeftRight
                         );
        }

        Profiler.EndSample();

        topDownNative.Dispose();
        leftRightNative.Dispose();

        Profiler.BeginSample("Apply textures");
        activeRaybufferTopDown.ApplyPartials(commandBuffer);
        activeRaybufferLeftRight.ApplyPartials(commandBuffer);
        Profiler.EndSample();

        Profiler.BeginSample("Blit raybuffer");
        BlitSegments(
            camera,
            blitMaterial,
            blitMesh,
            activeRaybufferTopDown.FinalTexture,
            activeRaybufferLeftRight.FinalTexture,
            segments,
            vanishingPointScreenSpace,
            screen,
            commandBuffer
            );
        Profiler.EndSample();

        actualCamera.RemoveAllCommandBuffers();
        actualCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, commandBuffer);
    }