예제 #1
0
        /// <summary>
        /// Function called before rendering begins.
        /// </summary>
        /// <returns>
        /// TRUE to continue rendering, FALSE to exit.
        /// </returns>
        protected override bool OnBeforeRender()
        {
            GorgonRenderTargetView target = Gorgon2D.Target;

            if (_randomTexture == null)
            {
                GenerateRandomNoise();
            }

            if (target == null)
            {
                target = Gorgon2D.DefaultTarget;
            }

            switch (target.Resource.ResourceType)
            {
            case ResourceType.Buffer:
                var buffer = (GorgonBuffer)target.Resource;
                var info   = GorgonBufferFormatInfo.GetInfo(buffer.Settings.DefaultShaderViewFormat);

                _currentTargetSize = new Vector2(buffer.SizeInBytes / info.BitDepth, 1);
                break;

            case ResourceType.Texture1D:
            case ResourceType.Texture2D:
            case ResourceType.Texture3D:
                var texture = (GorgonTexture)target.Resource;
                _currentTargetSize = new Vector2(texture.Settings.Width, texture.Settings.Height);
                break;
            }

            RememberTextureSampler(ShaderType.Pixel, 1);
            RememberShaderResource(ShaderType.Pixel, 1);
            RememberConstantBuffer(ShaderType.Pixel, 1);
            RememberConstantBuffer(ShaderType.Pixel, 2);
            RememberConstantBuffer(ShaderType.Pixel, 3);

            Gorgon2D.PixelShader.Resources[1]       = _randomTexture;
            Gorgon2D.PixelShader.TextureSamplers[1] = new GorgonTextureSamplerStates
            {
                TextureFilter        = TextureFilter.Linear,
                HorizontalAddressing = TextureAddressing.Wrap,
                VerticalAddressing   = TextureAddressing.Wrap,
                DepthAddressing      = TextureAddressing.Clamp,
                MipLODBias           = 0.0f,
                MaxAnisotropy        = 1,
                ComparisonFunction   = ComparisonOperator.Never,
                BorderColor          = Color.White,
                MinLOD = -3.402823466e+38f,
                MaxLOD = 3.402823466e+38f
            };

            Gorgon2D.PixelShader.ConstantBuffers[1] = _timingBuffer;
            Gorgon2D.PixelShader.ConstantBuffers[2] = _scratchBuffer;
            Gorgon2D.PixelShader.ConstantBuffers[3] = _sepiaBuffer;

            return(base.OnBeforeRender());
        }
예제 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Gorgon2DTarget"/> struct.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="depthStencil">The depth/stencil view.</param>
        public Gorgon2DTarget(GorgonRenderTargetView target, GorgonDepthStencilView depthStencil)
        {
            Target       = target;
            DepthStencil = null;
            SwapChain    = null;
            Height       = 1;

            switch (target.Resource.ResourceType)
            {
            case ResourceType.Buffer:
                var buffer = (GorgonBuffer)target.Resource;
                var info   = GorgonBufferFormatInfo.GetInfo(buffer.Settings.DefaultShaderViewFormat);

                Width    = buffer.SizeInBytes / info.SizeInBytes;
                Viewport = new GorgonViewport(0, 0, Width, Height, 0, 1.0f);
                break;

            case ResourceType.Texture1D:
                var target1D = (GorgonRenderTarget1D)target.Resource;

                Width        = target1D.Settings.Width;
                Viewport     = target1D.Viewport;
                DepthStencil = depthStencil ?? target1D.DepthStencilBuffer;
                break;

            case ResourceType.Texture2D:
                var target2D = (GorgonRenderTarget2D)target.Resource;

                Width    = target2D.Settings.Width;
                Height   = target2D.Settings.Height;
                Viewport = target2D.Viewport;
                if (target2D.IsSwapChain)
                {
                    SwapChain = (GorgonSwapChain)target2D;
                }
                DepthStencil = depthStencil ?? target2D.DepthStencilBuffer;
                break;

            case ResourceType.Texture3D:
                var target3D = (GorgonRenderTarget3D)target.Resource;

                Width    = target3D.Settings.Width;
                Height   = target3D.Settings.Height;
                Viewport = target3D.Viewport;
                break;

            default:
                throw new GorgonException(GorgonResult.CannotBind, "Could not bind a render target.  Resource type is unknown.  Should not see this error.");
            }
        }
예제 #3
0
        /// <summary>
        /// Returns a collection of standard values for the data type this type converter is designed for when provided with a format context.
        /// </summary>
        /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that provides a format context that can be used to extract additional information about the environment from which this converter is invoked. This parameter or properties of this parameter can be null.</param>
        /// <returns>
        /// A <see cref="T:System.ComponentModel.TypeConverter.StandardValuesCollection" /> that holds a standard set of valid values, or null if the data type does not support a standard set of values.
        /// </returns>
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            var          content       = (GorgonImageContent)((ContentTypeDescriptor)context.Instance).Content;
            var          formatList    = (BufferFormat[])Enum.GetValues(typeof(BufferFormat));
            BufferFormat currentFormat = content.ImageFormat;

            var formats = (from format in formatList
                           let formatInfo = GorgonBufferFormatInfo.GetInfo(format)
                                            where (!formatInfo.HasDepth) && (!formatInfo.HasStencil) &&
                                            (!formatInfo.IsTypeless) &&
                                            (!formatInfo.IsCompressed) &&
                                            (((content.ImageType == ImageType.Image1D) && (ContentObject.Graphics.VideoDevice.Supports1DTextureFormat(format)))
                                             ||
                                             ((content.ImageType == ImageType.Image2D || content.ImageType == ImageType.ImageCube) &&
                                              (ContentObject.Graphics.VideoDevice.Supports2DTextureFormat(format))) ||
                                             ((content.ImageType == ImageType.Image3D) && (ContentObject.Graphics.VideoDevice.Supports3DTextureFormat(format)))) &&
                                            (content.Codec.SupportedFormats.Any(item => item == format)) &&
                                            ((content.MipCount == 1) ||
                                             ((content.MipCount > 1) && (ContentObject.Graphics.VideoDevice.SupportsMipMaps(format))))
                                            select format);

            return(new StandardValuesCollection(GorgonImageData.CanConvertToAny(currentFormat, formats)));
        }
예제 #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GorgonView"/> class.
 /// </summary>
 /// <param name="resource">The resource to bind to the view.</param>
 /// <param name="format">The format of the view.</param>
 protected GorgonView(GorgonResource resource, BufferFormat format)
 {
     Resource          = resource;
     Format            = format;
     FormatInformation = GorgonBufferFormatInfo.GetInfo(Format);
 }
예제 #5
0
        /// <summary>
        /// Function to perform any post processing on image data.
        /// </summary>
        internal void PostProcess(GorgonImageData data)
        {
            IImageSettings destSettings = data.Settings.Clone();
            int            width        = Width > 0 ? Width : data.Settings.Width;
            int            height       = Height > 0 ? Height : data.Settings.Height;
            int            mipCount     = MipCount > 0 ? MipCount : data.Settings.MipCount;
            BufferFormat   format       = (Format != BufferFormat.Unknown) ? Format : data.Settings.Format;
            Rectangle      newSize      = Rectangle.Empty;
            int            mipStart     = 0;
            var            sourceInfo   = GorgonBufferFormatInfo.GetInfo(data.Settings.Format);
            var            destInfo     = GorgonBufferFormatInfo.GetInfo(format);

            // First, confirm whether we can perform format conversions.
            using (var wic = new GorgonWICImage())
            {
                Guid srcPixelFormat  = wic.GetGUID(data.Settings.Format);
                Guid destPixelFormat = wic.GetGUID(format);

                // Do nothing if we can't do anything with the source format.
                if (srcPixelFormat == Guid.Empty)
                {
                    return;
                }

                // Cancel conversion if we're using the same format.
                if (srcPixelFormat == destPixelFormat)
                {
                    destPixelFormat = Guid.Empty;
                }

                // Get the new size.
                if ((width != data.Settings.Width) || (height != data.Settings.Height))
                {
                    newSize = new Rectangle(0, 0, width, height);
                }

                // Set up destination buffer settings.
                destSettings.Format   = format;
                destSettings.Width    = width;
                destSettings.Height   = height;
                destSettings.MipCount = mipCount;

                // Ensure we don't go over the maximum.
                int maxMips = GorgonImageData.GetMaxMipCount(destSettings);

                if (mipCount > maxMips)
                {
                    mipCount = maxMips;
                }

                // Nothing's going to happen here, so leave.
                if ((destPixelFormat == Guid.Empty) && (newSize == Rectangle.Empty) && (mipCount == 1))
                {
                    return;
                }

                // Create our worker buffer.
                GorgonImageData destData;
                using (destData = new GorgonImageData(destSettings))
                {
                    // The first step is to convert and resize our images:
                    if ((destPixelFormat != Guid.Empty) || (newSize != Rectangle.Empty))
                    {
                        for (int array = 0; array < destSettings.ArrayCount; array++)
                        {
                            // We're not going to copy mip levels at this point, that will come in the next step.
                            for (int depth = 0; depth < destSettings.Depth; depth++)
                            {
                                // Get our source/destination buffers.
                                var sourceBuffer = data.Buffers[0, data.Settings.ImageType == ImageType.Image3D ? depth : array];
                                var destBuffer   = destData.Buffers[0, data.Settings.ImageType == ImageType.Image3D ? depth : array];

                                var dataRect = new DataRectangle(sourceBuffer.Data.BasePointer, sourceBuffer.PitchInformation.RowPitch);

                                // Create a temporary WIC bitmap to work with.
                                using (var bitmap = new Bitmap(wic.Factory, sourceBuffer.Width, sourceBuffer.Height, srcPixelFormat, dataRect, sourceBuffer.PitchInformation.SlicePitch))
                                {
                                    wic.TransformImageData(bitmap,
                                                           destBuffer.Data.BasePointer,
                                                           destBuffer.PitchInformation.RowPitch,
                                                           destBuffer.PitchInformation.SlicePitch,
                                                           destPixelFormat,
                                                           sourceInfo.IssRGB,
                                                           destInfo.IssRGB,
                                                           Dithering,
                                                           newSize,
                                                           Clip,
                                                           Filter);
                                }
                            }
                        }

                        // Adjust the mip map starting point.
                        mipStart = 1;
                    }

                    // Next, we need to build mip maps.
                    if (destSettings.MipCount > 1)
                    {
                        // The first step is to convert and resize our images:
                        for (int array = 0; array < destSettings.ArrayCount; array++)
                        {
                            int mipDepth = destSettings.Depth;

                            for (int mip = mipStart; mip < destSettings.MipCount; mip++)
                            {
                                // We're not going to copy mip levels at this point, that will come in the next step.
                                for (int depth = 0; depth < mipDepth; depth++)
                                {
                                    // Get our source/destination buffers.
                                    var sourceBuffer = destData.Buffers[0, data.Settings.ImageType == ImageType.Image3D ? (destSettings.Depth / mipDepth) * depth : array];
                                    var destBuffer   = destData.Buffers[mip, data.Settings.ImageType == ImageType.Image3D ? depth : array];

                                    var dataRect = new DataRectangle(sourceBuffer.Data.BasePointer, sourceBuffer.PitchInformation.RowPitch);

                                    // Create a temporary WIC bitmap to work with.
                                    using (var bitmap = new Bitmap(wic.Factory, sourceBuffer.Width, sourceBuffer.Height, srcPixelFormat, dataRect, sourceBuffer.PitchInformation.SlicePitch))
                                    {
                                        wic.TransformImageData(bitmap, destBuffer.Data.BasePointer, destBuffer.PitchInformation.RowPitch, destBuffer.PitchInformation.SlicePitch,
                                                               Guid.Empty, false, false, ImageDithering.None, new Rectangle(0, 0, destBuffer.Width, destBuffer.Height), false, Filter);
                                    }
                                }

                                if (mipDepth > 1)
                                {
                                    mipDepth >>= 1;
                                }
                            }
                        }
                    }

                    // Update our data.
                    data.TakeOwnership(destData);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Function to persist image data to a stream.
        /// </summary>
        /// <param name="imageData"><see cref="GorgonLibrary.Graphics.GorgonImageData">Gorgon image data</see> to persist.</param>
        /// <param name="stream">Stream that will contain the data.</param>
        protected internal override void SaveToStream(GorgonImageData imageData, Stream stream)
        {
            // Use a binary writer.
            using (var writer = new GorgonBinaryWriter(stream, true))
            {
                // Write the header for the file.
                TGAConversionFlags conversionFlags;
                WriteHeader(imageData.Settings, writer, out conversionFlags);

                GorgonFormatPitch pitch;
                if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                {
                    pitch = new GorgonFormatPitch(imageData.Settings.Width * 3, imageData.Settings.Width * 3 * imageData.Settings.Height);
                }
                else
                {
                    var formatInfo = GorgonBufferFormatInfo.GetInfo(imageData.Settings.Format);
                    pitch = formatInfo.GetPitch(imageData.Settings.Width, imageData.Settings.Height, PitchFlags.None);
                }

                // Get the pointer to the first mip/array/depth level.
                var srcPointer = (byte *)imageData.Buffers[0].Data.UnsafePointer;
                var srcPitch   = imageData.Buffers[0].PitchInformation;

                // If the two pitches are equal, then just write out the buffer.
                if ((pitch == srcPitch) && (conversionFlags == TGAConversionFlags.None))
                {
                    writer.Write(srcPointer, srcPitch.SlicePitch);
                    return;
                }

                // If we have to do a conversion, create a worker buffer.
                using (var convertBuffer = new GorgonDataStream(pitch.SlicePitch))
                {
                    var destPtr = (byte *)convertBuffer.UnsafePointer;

                    // Write out each scan line.
                    for (int y = 0; y < imageData.Settings.Height; y++)
                    {
                        if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                        {
                            Compress24BPPScanLine(srcPointer, srcPitch.RowPitch, destPtr, pitch.RowPitch);
                        }
                        else if ((conversionFlags & TGAConversionFlags.Swizzle) == TGAConversionFlags.Swizzle)
                        {
                            SwizzleScanline(srcPointer, srcPitch.RowPitch, destPtr, pitch.RowPitch, imageData.Settings.Format, ImageBitFlags.None);
                        }
                        else
                        {
                            CopyScanline(srcPointer, srcPitch.RowPitch, destPtr, pitch.RowPitch, imageData.Settings.Format, ImageBitFlags.None);
                        }

                        destPtr    += pitch.RowPitch;
                        srcPointer += srcPitch.RowPitch;
                    }

                    // Persist to the stream.
                    writer.Write(convertBuffer.UnsafePointer, pitch.SlicePitch);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Function to perform the copying of image data into the buffer.
        /// </summary>
        /// <param name="stream">Stream containing the image data.</param>
        /// <param name="image">Image data.</param>
        /// <param name="conversionFlags">Flags used to convert the image.</param>
        private void CopyImageData(GorgonDataStream stream, GorgonImageData image, TGAConversionFlags conversionFlags)
        {
            var buffer     = image.Buffers[0];                  // Get the first buffer only.
            var formatInfo = GorgonBufferFormatInfo.GetInfo(image.Settings.Format);

            GorgonFormatPitch srcPitch = (conversionFlags & TGAConversionFlags.Expand) == TGAConversionFlags.Expand
                                                             ? new GorgonFormatPitch(image.Settings.Width * 3, image.Settings.Width * 3 * image.Settings.Height)
                                                             : formatInfo.GetPitch(image.Settings.Width, image.Settings.Height, PitchFlags.None);

            // Otherwise, allocate a buffer for conversion.
            var srcPtr  = (byte *)stream.PositionPointerUnsafe;
            var destPtr = (byte *)buffer.Data.UnsafePointer;

            // Adjust destination for inverted axes.
            if ((conversionFlags & TGAConversionFlags.InvertX) == TGAConversionFlags.InvertX)
            {
                destPtr += buffer.PitchInformation.RowPitch - formatInfo.SizeInBytes;
            }

            if ((conversionFlags & TGAConversionFlags.InvertY) != TGAConversionFlags.InvertY)
            {
                destPtr += (image.Settings.Height - 1) * buffer.PitchInformation.RowPitch;
            }

            // Get bounds of image memory.
            var   scanSize = (int)(stream.Length - stream.Position);
            byte *endScan  = (byte *)stream.PositionPointerUnsafe + scanSize;

            int opaqueLineCount = 0;

            for (int y = 0; y < image.Settings.Height; y++)
            {
                bool setOpaque;

                if ((conversionFlags & TGAConversionFlags.RLE) == TGAConversionFlags.RLE)
                {
                    setOpaque = ReadCompressed(ref srcPtr, image.Settings.Width, destPtr, endScan, image.Settings.Format, conversionFlags);
                }
                else
                {
                    setOpaque = ReadUncompressed(srcPtr, srcPitch.RowPitch, destPtr, image.Settings.Format, conversionFlags);
                    srcPtr   += srcPitch.RowPitch;
                }

                if ((setOpaque) && (SetOpaqueIfZeroAlpha))
                {
                    opaqueLineCount++;
                }

                if ((conversionFlags & TGAConversionFlags.InvertY) != TGAConversionFlags.InvertY)
                {
                    destPtr -= buffer.PitchInformation.RowPitch;
                }
                else
                {
                    destPtr += buffer.PitchInformation.RowPitch;
                }
            }

            if (opaqueLineCount != image.Settings.Height)
            {
                return;
            }

            // Set the alpha to opaque if we don't have any alpha values (i.e. alpha = 0 for all pixels).
            destPtr = (byte *)buffer.Data.UnsafePointer;
            for (int y = 0; y < image.Settings.Height; y++)
            {
                CopyScanline(destPtr, buffer.PitchInformation.RowPitch, destPtr, buffer.PitchInformation.RowPitch, image.Settings.Format, ImageBitFlags.OpaqueAlpha);
                destPtr += buffer.PitchInformation.RowPitch;
            }
        }
예제 #8
0
        /// <summary>
        /// Function to clip the sprite region from the texture.
        /// </summary>
        /// <param name="texture">Texture containing the image data to clip.</param>
        /// <returns>A rectangle for the sprite.  Or an empty rectangle if no sprite was selected.</returns>
        public unsafe Rectangle Clip(GorgonTexture2D texture)
        {
            GorgonImageData imageData = null;

            try
            {
                // Constrain our mouse to the texture.
                _startPoint.X = _startPoint.X.Max(0).Min(texture.Settings.Width - 1);
                _startPoint.Y = _startPoint.Y.Max(0).Min(texture.Settings.Height - 1);

                imageData = GorgonImageData.CreateFromTexture(texture);

                _stride        = imageData.Buffers[0].PitchInformation.RowPitch;
                _format        = imageData.Settings.Format;
                _bytesPerPixel = GorgonBufferFormatInfo.GetInfo(_format).SizeInBytes;
                _textureWidth  = imageData.Settings.Width;

                // Get a pointer to the buffer.
                byte *bytePtr = (byte *)imageData.UnsafePointer;

                if (IsMaskValue(bytePtr, _startPoint.X, _startPoint.Y))
                {
                    return(Rectangle.Empty);
                }

                Queue <ClipSpan> clipSpans = new Queue <ClipSpan>();

                _pixels = new bool[imageData.Settings.Width * imageData.Settings.Height];

                int left   = _startPoint.X;
                int top    = _startPoint.Y;
                int right  = left;
                int bottom = top;

                // Get the initial span from our starting point and add it to our queue.
                ClipSpan span = GetSpan(bytePtr, left, top);
                clipSpans.Enqueue(span);

                while (clipSpans.Count > 0)
                {
                    // Take the span off the queue.
                    span = clipSpans.Dequeue();

                    // Find the next vertical span above and below the current span.
                    int west  = span.Start;
                    int east  = span.End;
                    int north = span.Y - 1;
                    int south = span.Y + 1;

                    // Check each pixel between the start and end of the upper and lower spans.
                    for (int x = west; x <= east; ++x)
                    {
                        int pixelindex = _textureWidth * north + x;

                        if ((span.Y > 0) && (!IsMaskValue(bytePtr, x, north)) && (!_pixels[pixelindex]))
                        {
                            clipSpans.Enqueue(GetSpan(bytePtr, x, north));
                        }

                        pixelindex = _textureWidth * south + x;

                        if ((span.Y >= imageData.Settings.Height - 1) || (IsMaskValue(bytePtr, x, south)) || (_pixels[pixelindex]))
                        {
                            continue;
                        }

                        clipSpans.Enqueue(GetSpan(bytePtr, x, south));
                    }

                    // Update the boundaries.
                    left   = west.Min(left);
                    right  = (east + 1).Max(right);
                    top    = (north + 1).Min(top);
                    bottom = south.Max(bottom);
                }

                return(Rectangle.FromLTRB(left, top, right, bottom));
            }
            finally
            {
                if (imageData != null)
                {
                    imageData.Dispose();
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Function to create a default render target view.
        /// </summary>
        protected override void OnCreateDefaultRenderTargetView()
        {
            var info = GorgonBufferFormatInfo.GetInfo(Settings.DefaultShaderViewFormat);

            DefaultRenderTargetView = OnGetRenderTargetView(Settings.Format, Settings.Format, 0, Settings.SizeInBytes / info.SizeInBytes);
        }