Ejemplo n.º 1
0
        /// <summary>
        /// Draws a bilboard rectangle with depth. Rendering is clipped against a Y buffer.
        /// </summary>
        /// <param name="dst">Target PixelBuffer.</param>
        /// <param name="centerX">X Coordinate of the rectangle's center</param>
        /// <param name="distance">Distance from the camera to render.</param>
        /// <param name="width">Width of the rectangle at distance = 1</param>
        /// <param name="height">Height of the rectangle at distance = 1</param>
        /// <param name="y_buffer">A ray buffer to do distance clipping against.</param>
        /// <param name="color">The color to render the rectangle.</param>
        public static void rectDepth(PixelBuffer dst, int centerX, float distance, int width, int height, RayData[] y_buffer, Rgba color)
        {
            width  = (int)(width / distance);
            height = (int)(height / distance);
            int hw = (int)((width >> 1));
            int hh = (int)((height >> 1));

            clipRect.x = centerX - hw;
            clipRect.y = (dst.height >> 1) - hh;
            clipRect.w = width;
            clipRect.h = height;
            rect(dst, clipRect.x, clipRect.y, clipRect.w, clipRect.h, clippedColor);

            clipRect.left  = Math.Max(clipRect.x, 0);
            clipRect.right = Math.Min(clipRect.x + clipRect.w, dst.width - 1);
            clipRect.top   = clipRect.y;
            clipRect.bot   = clipRect.y + clipRect.h;
            // clip left
            for (int i = clipRect.left; i < clipRect.right; i++)
            {
                if (y_buffer[i].dis <= distance)
                {
                    clipRect.left = i;
                }
                else
                {
                    break;
                }
            }
            // clip right
            for (int i = clipRect.left + 1; i < clipRect.right; i++)
            {
                if (y_buffer[i].dis <= distance)
                {
                    clipRect.right = i;
                    break;
                }
            }
            rect(dst, clipRect.left, clipRect.top, clipRect.right - clipRect.left, clipRect.bot - clipRect.top, color);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Draw a wall column using a texture for pixel colors and use fog calculations.
        /// </summary>
        /// <param name="dst">Target PixelBuffer</param>
        /// <param name="x">X coordinate to render the wall on.</param>
        /// <param name="z">View height (but does nothing at the moment) </param>
        /// <param name="distance">Distance of the wall from the camera</param>
        /// <param name="textureOffset">Offset of the source texture to render from</param>
        /// <param name="src">Source texture to render from</param>
        public static void wallColumn(PixelBuffer dst, int x, float z, float distance, float textureOffset, PixelBuffer src, Rgba fogColor)
        {
            // Calculate initial source texture position.
            int fp_Src = (int)(src.height * textureOffset);

            fp_Src = fp_Src * src.width;
            fp_Src = fp_Src << 8;

            // Calculate the height of the column render.
            int colHeight = dst.height;

            if (distance != 0)
            {
                colHeight = (int)(dst.height / distance);
            }

            // Calculate view offset
            int viewOfs = (int)(colHeight * (z - 1));

            // Calculate base step ratio for source texture read.
            int fp_srcStep = (src.width << 8) / colHeight;

            // Handle columns too tall for the screen.
            if (colHeight > dst.height || distance == 0)
            {
                // Adjust the source texture data offset.
                fp_Src += fp_srcStep * ((colHeight - dst.height) >> 1);
                // Clip the column height to screen height.
                colHeight = dst.height;
            }
            // Calculate the destination data offset for the write.
            int dstIdx = (x * BPP) + ((((dst.height + viewOfs) - colHeight) >> 1) * dst.stride);

            // Calcualte shading values
            // Fixed point rgba maths
            int fp_r;
            int fp_g;
            int fp_b;
            int fp_fogCol = (int)(distance * 16f);

            fp_fogCol += fogColor.a;
            if (fp_fogCol > 0x0100)
            {
                fp_fogCol = 0x0100;
            }

            //Console.WriteLine(fp_fogCol.ToString("X8"));
            int fog_r = fp_fogCol * (fogColor.r);
            int fog_g = fp_fogCol * (fogColor.g);
            int fog_b = fp_fogCol * (fogColor.b);

            int fp_srcCol = 0x0100 - fp_fogCol;

            int srcIdx;

            if (fp_srcStep >= 0x10000)
            {
                // Draw the column.
                for (int i = 0; i < colHeight; i++)
                {
                    srcIdx = (fp_Src >> 8) << 2;
                    if (dstIdx < 0 || dstIdx >= dst.height)
                    {
                        break;
                    }

                    fp_r = (src.pixels[srcIdx] * fp_srcCol) + fog_r;
                    fp_g = (src.pixels[srcIdx + 1] * fp_srcCol) + fog_g;
                    fp_b = (src.pixels[srcIdx + 2] * fp_srcCol) + fog_b;

                    dst.pixels[dstIdx]     = (byte)(fp_r >> 8);
                    dst.pixels[dstIdx + 1] = (byte)(fp_g >> 8);
                    dst.pixels[dstIdx + 2] = (byte)(fp_b >> 8);
                    dst.pixels[dstIdx + 3] = 255;
                    fp_Src += fp_srcStep;
                    dstIdx += dst.stride;
                }
            }
            else
            {
                // Compressed Column Drawing
                int  fp_nextSrc;
                byte r, g, b;
                // Draw the column.
                for (int i = 0; i < colHeight;)
                {
                    fp_nextSrc = (fp_Src + 0x100) & 0xFFFFF00;
                    srcIdx     = (fp_Src >> 8) << 2;
                    fp_r       = ((src.pixels[srcIdx] * fp_srcCol) + fog_r) >> 8;
                    fp_g       = ((src.pixels[srcIdx + 1] * fp_srcCol) + fog_g) >> 8;
                    fp_b       = ((src.pixels[srcIdx + 2] * fp_srcCol) + fog_b) >> 8;
                    r          = (byte)fp_r;
                    g          = (byte)fp_g;
                    b          = (byte)fp_b;
                    while (fp_Src < fp_nextSrc && i < colHeight)
                    {
                        // HACK: Nearsided renderer should really not have to do this.
                        if (dstIdx >= 0 && dstIdx < dst.pixels.Length)
                        {
                            dst.pixels[dstIdx]     = r;
                            dst.pixels[dstIdx + 1] = g;
                            dst.pixels[dstIdx + 2] = b;
                            dst.pixels[dstIdx + 3] = 255;
                        }
                        fp_Src += fp_srcStep;
                        dstIdx += dst.stride;
                        i++;
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Draw a rectangle.
        /// </summary>
        /// <param name="x">Left edge coordinate of the rectangle</param>
        /// <param name="y">Top edge coordinate of teh rectangle</param>
        /// <param name="width">Width in pixels</param>
        /// <param name="height">Height in pixels</param>
        /// <param name="color">The desired RGBA color</param>
        public static void rect(PixelBuffer dst, int x, int y, int width, int height, Rgba color)
        {
            // Find clipping rectangle.
            int left  = Math.Max(x, 0);
            int right = Math.Min(x + width, dst.width - 1);
            int top   = Math.Max(y, 0);
            int bot   = Math.Min(y + height, dst.height - 1);
            int clipH = bot - top;
            int clipW = right - left;

            if (clipH <= 0 || clipW <= 0)
            {
                return;
            }

            int dy   = top * dst.stride;
            int dstA = dy + (left << 2);
            int dstB = dy + (right << 2);
            // Draw pixel with alpha blending.
            int fp8_dstBlend = 0xFF - color.a;
            int ar           = color.r * color.a;
            int ag           = color.g * color.a;
            int ab           = color.b * color.a;

            // Draw cols.
            for (int i = 0; i < clipH; i++)
            {
                if (left == x)
                {
                    dst.pixels[dstA + 0] = (byte)(((dst.pixels[dstA + 0] * fp8_dstBlend) + ar) >> 8);
                    dst.pixels[dstA + 1] = (byte)(((dst.pixels[dstA + 1] * fp8_dstBlend) + ag) >> 8);
                    dst.pixels[dstA + 2] = (byte)(((dst.pixels[dstA + 2] * fp8_dstBlend) + ab) >> 8);
                    dst.pixels[dstA + 3] = 255;
                }
                if (right == x + width)
                {
                    dst.pixels[dstB + 0] = (byte)(((dst.pixels[dstB + 0] * fp8_dstBlend) + ar) >> 8);
                    dst.pixels[dstB + 1] = (byte)(((dst.pixels[dstB + 1] * fp8_dstBlend) + ag) >> 8);
                    dst.pixels[dstB + 2] = (byte)(((dst.pixels[dstB + 2] * fp8_dstBlend) + ab) >> 8);
                    dst.pixels[dstB + 3] = 255;
                }
                dstA += dst.stride;
                dstB += dst.stride;
            }

            dstB = dy + (left << 2);
            // Draw rows
            for (int i = 0; i < clipW; i++)
            {
                if (bot == (y + height))
                {
                    dst.pixels[dstA + 0] = (byte)(((dst.pixels[dstA + 0] * fp8_dstBlend) + ar) >> 8);
                    dst.pixels[dstA + 1] = (byte)(((dst.pixels[dstA + 1] * fp8_dstBlend) + ag) >> 8);
                    dst.pixels[dstA + 2] = (byte)(((dst.pixels[dstA + 2] * fp8_dstBlend) + ab) >> 8);
                    dst.pixels[dstA + 3] = 255;
                }
                if (top == y)
                {
                    dst.pixels[dstB + 0] = (byte)(((dst.pixels[dstB + 0] * fp8_dstBlend) + ar) >> 8);
                    dst.pixels[dstB + 1] = (byte)(((dst.pixels[dstB + 1] * fp8_dstBlend) + ag) >> 8);
                    dst.pixels[dstB + 2] = (byte)(((dst.pixels[dstB + 2] * fp8_dstBlend) + ab) >> 8);
                    dst.pixels[dstB + 3] = 255;
                }
                dstA += BPP;
                dstB += BPP;
            }
        }