Beispiel #1
0
        private void Update(EvaluationContext context)
        {
            var image    = InputImage.GetValue(context);
            var imageSrv = InputImageSrv.GetValue(context);

            if (image == null)
            {
                Log.Debug("input not completet");
                return;
            }

            var d3DDevice        = ResourceManager.Instance().Device;
            var immediateContext = d3DDevice.ImmediateContext;

            if (_imageWithCPUAccess == null ||
                _imageWithCPUAccess.Description.Format != image.Description.Format ||
                _imageWithCPUAccess.Description.Width != image.Description.Width ||
                _imageWithCPUAccess.Description.Height != image.Description.Height ||
                _imageWithCPUAccess.Description.MipLevels != image.Description.MipLevels)
            {
                var desc = new Texture2DDescription()
                {
                    BindFlags         = BindFlags.None,
                    Format            = image.Description.Format,
                    Width             = image.Description.Width,
                    Height            = image.Description.Height,
                    MipLevels         = image.Description.MipLevels,
                    SampleDescription = new SampleDescription(1, 0),
                    Usage             = ResourceUsage.Staging,
                    OptionFlags       = ResourceOptionFlags.None,
                    CpuAccessFlags    = CpuAccessFlags.Read,
                    ArraySize         = 1
                };
                Utilities.Dispose(ref _imageWithCPUAccess);
                _imageWithCPUAccess = new Texture2D(d3DDevice, desc);
            }

            if (_distanceFieldImage == null ||
                _distanceFieldImage.Description.Format != image.Description.Format ||
                _distanceFieldImage.Description.Width != image.Description.Width ||
                _distanceFieldImage.Description.Height != image.Description.Height ||
                _distanceFieldImage.Description.MipLevels != image.Description.MipLevels)
            {
                var desc = new Texture2DDescription()
                {
                    BindFlags         = BindFlags.ShaderResource,
                    Format            = image.Description.Format,
                    Width             = image.Description.Width,
                    Height            = image.Description.Height,
                    MipLevels         = 1,
                    SampleDescription = new SampleDescription(1, 0),
                    Usage             = ResourceUsage.Dynamic,
                    OptionFlags       = ResourceOptionFlags.None,
                    CpuAccessFlags    = CpuAccessFlags.Write,
                    ArraySize         = 1
                };
                Utilities.Dispose(ref _distanceFieldImage);
                _distanceFieldImage = new Texture2D(d3DDevice, desc);
            }

            // if (Changed)
            {
                immediateContext.CopyResource(image, _imageWithCPUAccess);
                int width  = image.Description.Width;
                int height = image.Description.Height;

                if (_data == null || _data.Length != width * height)
                {
                    _data      = new float[width * height];
                    _xDist     = new short[width * height];
                    _yDist     = new short[width * height];
                    _gradients = new SharpDX.Vector2[width * height];
                }

                DataStream sourceStream;
                var        sourceDataBox =
                    immediateContext.MapSubresource(_imageWithCPUAccess, 0, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None, out sourceStream);

                // Convert img into float (data)
                using (sourceStream)
                {
                    sourceStream.Position = 0;
                    float minValue = 255, maxValue = -255;
                    for (int y = 0; y < height; ++y)
                    {
                        for (int x = 0; x < width; ++x)
                        {
                            var   color = new Color4(sourceStream.Read <Int32>());
                            float v     = color.Red;
                            _data[y * width + x] = v;
                            if (v > maxValue)
                            {
                                maxValue = v;
                            }
                            if (v < minValue)
                            {
                                minValue = v;
                            }
                        }

                        sourceStream.Position += sourceDataBox.RowPitch - width * 4;
                    }

                    // Rescale image levels between 0 and 1
                    for (int i = 0; i < width * height; ++i)
                    {
                        _data[i] = (_data[i] - minValue) / maxValue;
                    }

                    // transform background (black pixels)
                    ComputeGradient(_data, width, height);
                    var outside = Edtaa3(_data, height, width);

                    // transform forground (white pixels)
                    for (int i = 0; i < width * height; ++i)
                    {
                        _data[i] = 1 - _data[i]; // invert input
                    }
                    ComputeGradient(_data, width, height);
                    var inside = Edtaa3(_data, height, width);

                    // write resulting distance field to target texture
                    DataStream destinationStream;
                    var        destinationDataBox = immediateContext.MapSubresource(_distanceFieldImage, 0, 0, MapMode.WriteDiscard,
                                                                                    SharpDX.Direct3D11.MapFlags.None, out destinationStream);
                    using (destinationStream)
                    {
                        sourceStream.Position      = 0;
                        destinationStream.Position = 0;
                        for (int y = 0; y < height; y++)
                        {
                            for (int x = 0; x < width; x++)
                            {
                                int i = y * width + x;
                                // distmap = outside - inside; % Bipolar distance field
                                var color = new Color4(sourceStream.Read <Int32>());
                                outside[i] = MathUtils.Clamp(128.0f + (outside[i] - inside[i]) * 16.0f, 0.0f, 255.0f);
                                //color.Alpha = (255 - (byte) outside[i])/255.0f;
                                float f = (255 - (byte)outside[i]) / 255.0f;
                                color.Red   = f;
                                color.Blue  = f;
                                color.Green = f;
                                float alpha = 1 - _data[i];
                                {
                                    // do alpha dilatation
                                    const int range = 1;
                                    int       xs    = Math.Max(x - range, 0);
                                    int       xe    = Math.Min(x + range, width - 1);
                                    int       ys    = Math.Max(y - range, 0);
                                    int       ye    = Math.Min(y + range, height - 1);
                                    for (int yy = ys; yy <= ye; yy++)
                                    {
                                        for (int xx = xs; xx <= xe; xx++)
                                        {
                                            alpha = Math.Max(alpha, 1 - _data[yy * width + xx]);
                                        }
                                    }
                                }

                                color.Alpha = alpha;// * 0.8f; // > 0.0f ? 0.5f : 0;

                                destinationStream.Write(color.ToRgba());
                            }

                            destinationStream.Position += destinationDataBox.RowPitch - width * 4;
                        }

                        immediateContext.UnmapSubresource(_distanceFieldImage, 0);
                    }

                    immediateContext.UnmapSubresource(_imageWithCPUAccess, 0);
                }

                // Changed = false;
            }

            Output.Value = _distanceFieldImage;
        }