示例#1
0
 public static int GetBlockLight(this AlphaBlockCollection blocks, LocalBlockPosition position)
 {
     return(blocks.GetBlockLight(position.X, position.Y, position.Z));
 }
示例#2
0
        // ReSharper disable once FunctionComplexityOverflow
        // *** I do ^ because this function is the 'hottest' block of code in the program, and saving cycles during execution is ridiculously important here.
        void RenderChunk(ChunkRef Chunk, ParallelLoopState LoopState)
        {
            // *** Track how many chunks have been processed, for user feedback
            Interlocked.Increment(ref _ProcessedChunks);
            Interlocked.Increment(ref _ActiveRenderThreads);
#if !DEBUG && !FAST
            // *** In release mode, gracefully handle bad chunks.  Explode in debug mode so I can track down the issue.
            try
            {
#endif

            int[][] DepthOpacities = _ColourPalette.DepthOpacities;

            // *** Cancellation logic for parallel processing
            if (LoopState != null && _Cancellation.IsCancellationRequested)
            {
                LoopState.Stop();
            }

            if (LoopState != null && LoopState.IsStopped)
            {
                Interlocked.Decrement(ref _ActiveRenderThreads);
                return;
            }

            // *** Hold off on rendering if the user needs to attend to an issue
            while (_PauseRendering > 0)
            {
                Thread.Sleep(50);
            }

            // *** Load the chunk from disk here
            AlphaBlockCollection Blocks = Chunk.Blocks;

            for (int X = 0; X < 16; X++)
            {
                for (int Z = 0; Z < 16; Z++)
                {
                    // *** Start by finding the topmost block to render
                    int EndY = _RenderStartY(Blocks, X, Z);
                    int Y    = EndY;

                    if (Y < 0)
                    {
                        continue; // *** No valid renderable blocks in this column, so continue with the next column
                    }
                    // *** Drill into the column to determine how many blocks down to render
                    int RenderVal = 255;
                    while (RenderVal > 0)
                    {
                        RenderVal -= DepthOpacities[Blocks.GetID(X, Y, Z)][Blocks.GetData(X, Y, Z)];
                        if (Y == 0) // *** If we've hit the bottom of the map, don't try and keep going.
                        {
                            break;  // *** It wouldn't end well.
                        }
                        Y--;
                    }

                    Colour SetColour = Colour.Transparent; // *** What colour to set the current column's pixel to.

                    // *** The Block-Metadata palette for this column's biome
                    Colour[][] BiomePalette = _ColourPalette.FastPalette[Chunk.Biomes.GetBiome(X, Z)];

                    for (; Y <= EndY; Y++) // *** Now render up from the lowest block to the starting block
                    {
                        // *** For each block we render, grab its palette entry.
                        Colour Entry = BiomePalette[Blocks.GetID(X, Y, Z)][Blocks.GetData(X, Y, Z)];

                        // *** If it has an associated entity colours list, then it needs special consideration to get its colour
                        if ((Entry.Color & 0xFFFF0000U) == 0x00FF0000U) // *** Check for the flag value (0 Alpha, 255 Red - Blue and Green form the 0-65535 index)
                        {
                            PaletteEntry Entry2 = _ColourPalette.GetPaletteEntry((int)(Entry.Color & 0x0000FFFFU)).First(e => e.IsMatch(Blocks.GetData(X, Y, Z), Blocks.SafeGetTileEntity(X, Y, Z)));
                            if (Entry2 != null)
                            {
                                Entry = Entry2.Color;
                            }
                        }

                        if (Entry.A == 0)
                        {
                            continue; // *** If we're trying to render air, let's not.
                        }
                        // *** Blend in our working colour to the column's pixel, after applying altitude and light-level blends.
                        SetColour.Blend(Entry.Copy().LightLevel((uint)Math.Max(_Config.MinLightLevel, Blocks.GetBlockLight(X, Math.Min(Y + 1, 255), Z))).Altitude(Y));
                    }

                    Marshal.WriteInt32(_RenderTarget.Scan0 + (_Stride * (((Chunk.Z - _Config.SubregionChunks.Y) << 4) + Z)) + ((((Chunk.X - _Config.SubregionChunks.X) << 4) + X) << 2), (int)SetColour.FullAlpha().Color);
                }
            }
#if !DEBUG && !FAST // *** When not running in debug mode, chunks that fail to render should NOT crash everything.
        }

        catch (Exception Ex)
        {
            Interlocked.Increment(ref _PauseRendering);

            _CorruptChunks = true;
            RenderingErrorEventArgs E = new RenderingErrorEventArgs
            {
                ErrorException   = Ex,
                IsFatal          = false,
                UserErrorMessage = "A chunk failed to render",
                ErrorCode        = ErrorBadChunk
            };

            if (RenderError != null)
            {
                RenderError.Invoke(this, E);
            }

            Interlocked.Decrement(ref _PauseRendering);
        }
#endif
            Interlocked.Decrement(ref _ActiveRenderThreads);
        }