SkiaSharp шум и составлениеSkiaSharp noise and composing

Загрузить образец загрузить примерDownload Sample Download the sample

Для поиска в понятном и естественном обычно простой векторной графики.Simple vector graphics tend to look unnatural. Прямых линий, кривых smooth и сплошным цветом не напоминать дефекты реальных объектов.The straight lines, smooth curves, and solid colors don't resemble the imperfections of real-world objects. При работе в графическом объекте компьютерных фильма 1982 Tron, компьютер по обработке и анализу Перлина Алексей приступил к разработке алгоритмы, которые используются для предоставления более реалистичный текстуры эти образы случайных процессов.While working on the computer-generated graphics for the 1982 movie Tron, computer scientist Ken Perlin began developing algorithms that used random processes to give these images more realistic textures. В 1997 году Алексей Перлина выиграла награду Academy для технических награду.In 1997, Ken Perlin won an Academy Award for Technical Achievement. Впоследствии получило название шума Перлина начал свою работу, и он поддерживается в SkiaSharp.His work has come to be known as Perlin noise, and it is supported in SkiaSharp. Ниже приведен пример:Here's an example:

Пример шума ПерлинаPerlin Noise sample

Как можно видеть, каждый пиксел не случайное значение цвета.As you can see, each pixel is not a random color value. Непрерывность от точки до пикселя приводит случайных фигур.The continuity from pixel to pixel results in random shapes.

Поддержка шума Перлина в Skia основан на спецификации W3C для CSS и SVG.The support of Perlin noise in Skia is based on a W3C specification for CSS and SVG. Раздел 8.20 из фильтра эффекты модуль уровня 1 включает базовых алгоритмов шума Перлина в коде C.Section 8.20 of Filter Effects Module Level 1 includes the underlying Perlin noise algorithms in C code.

Изучение шума ПерлинаExploring Perlin noise

SKShader Класс определяет две различные статические методы для создания шума Перлина: CreatePerlinNoiseFractalNoise и CreatePerlinNoiseTurbulence .The SKShader class defines two different static methods for generating Perlin noise: CreatePerlinNoiseFractalNoise and CreatePerlinNoiseTurbulence. Параметры идентичны:The parameters are identical:

public static SkiaSharp CreatePerlinNoiseFractalNoise (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed);

public static SkiaSharp.SKShader CreatePerlinNoiseTurbulence (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed);

Оба метода также существовать в перегруженные версии с дополнительным SKPointI параметра.Both methods also exist in overloaded versions with an additional SKPointI parameter. Разделе шума Перлина мозаичное заполнение рассматриваются эти перегрузки.The section Tiling Perlin noise discusses these overloads.

Два baseFrequency аргументы являются положительные значения, определенные в документации по SkiaSharp в диапазоне от 0 до 1, но может быть присвоено также более высокие значения.The two baseFrequency arguments are positive values defined in the SkiaSharp documentation as ranging from 0 to 1, but they can be set to higher values as well. Чем выше значение, тем больше изменений в образе случайных в горизонтальном и вертикальном направлениях.The higher the value, the greater the change in the random image in the horizontal and vertical directions.

numOctaves Значение должно быть целым числом, равным 1 или более поздней версии.The numOctaves value is an integer of 1 or higher. Он позволяет является фактором итерации в алгоритмах.It relates to an iteration factor in the algorithms. Каждый дополнительный октавы помогает эффект равна половине предыдущих октавы, поэтому уменьшение эффекта с более высоким значением октавы.Each additional octave contributes an effect that is half of the previous octave, so the effect decreases with higher octave values.

seed Параметра является отправной точкой для генератора случайных чисел.The seed parameter is the starting point for the random-number generator. Несмотря на то, что указано как значение с плавающей запятой, дробь усекается до того, как он используется 0 совпадает со значением 1.Although specified as a floating-point value, the fraction is truncated before it's used, and 0 is the same as 1.

Шума Перлина странице в SkiaSharpFormsDemos) образец позволяет экспериментировать с различными значениями baseFrequency и numOctaves аргументы.The Perlin Noise page in the SkiaSharpFormsDemos) sample allows you experiment with various values of the baseFrequency and numOctaves arguments. Ниже приведен файл XAML.Here's the XAML file:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Effects.PerlinNoisePage"
             Title="Perlin Noise">

    <StackLayout>
        <skia:SKCanvasView x:Name="canvasView"
                           VerticalOptions="FillAndExpand"
                           PaintSurface="OnCanvasViewPaintSurface" />

        <Slider x:Name="baseFrequencyXSlider"
                Maximum="4"
                Margin="10, 0"
                ValueChanged="OnSliderValueChanged" />

        <Label x:Name="baseFrequencyXText"
               HorizontalTextAlignment="Center" />

        <Slider x:Name="baseFrequencyYSlider"
                Maximum="4"
                Margin="10, 0"
                ValueChanged="OnSliderValueChanged" />

        <Label x:Name="baseFrequencyYText"
               HorizontalTextAlignment="Center" />

        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center"
                     Margin="10">

            <Label Text="{Binding Source={x:Reference octavesStepper},
                                  Path=Value,
                                  StringFormat='Number of Octaves: {0:F0}'}"
                   VerticalOptions="Center" />

            <Stepper x:Name="octavesStepper"
                     Minimum="1"
                     ValueChanged="OnStepperValueChanged" />
        </StackLayout>
    </StackLayout>
</ContentPage>

Он использует два Slider представления для двух baseFrequency аргументы.It uses two Slider views for the two baseFrequency arguments. Чтобы расширить диапазон меньших значений, ползунки логарифмической.To expand the range of the lower values, the sliders are logarithmic. Файл с выделенным кодом вычисляет аргументы SKShaderметоды из степеней Slider значения.The code-behind file calculates the arguments to the SKShadermethods from powers of the Slider values. Label Представлениях отображаются вычисленные значения:The Label views display the calculated values:

float baseFreqX = (float)Math.Pow(10, baseFrequencyXSlider.Value - 4);
baseFrequencyXText.Text = String.Format("Base Frequency X = {0:F4}", baseFreqX);

float baseFreqY = (float)Math.Pow(10, baseFrequencyYSlider.Value - 4);
baseFrequencyYText.Text = String.Format("Base Frequency Y = {0:F4}", baseFreqY);

Объект Slider значение 1 соответствует 0,001, Slider значение ОС 2 соответствует 0,01, Slider значения 3 соответствует 0,1 и Slider 1 соответствует значению 4.A Slider value of 1 corresponds to 0.001, a Slider value os 2 corresponds to 0.01, a Slider values of 3 corresponds to 0.1, and a Slider value of 4 corresponds to 1.

Ниже приведен файл с выделенным кодом, включающий этот код.Here's the code-behind file that includes that code:

public partial class PerlinNoisePage : ContentPage
{
    public PerlinNoisePage()
    {
        InitializeComponent();
    }

    void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnStepperValueChanged(object sender, ValueChangedEventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Get values from sliders and stepper
        float baseFreqX = (float)Math.Pow(10, baseFrequencyXSlider.Value - 4);
        baseFrequencyXText.Text = String.Format("Base Frequency X = {0:F4}", baseFreqX);

        float baseFreqY = (float)Math.Pow(10, baseFrequencyYSlider.Value - 4);
        baseFrequencyYText.Text = String.Format("Base Frequency Y = {0:F4}", baseFreqY);

        int numOctaves = (int)octavesStepper.Value;

        using (SKPaint paint = new SKPaint())
        {
            paint.Shader =
                SKShader.CreatePerlinNoiseFractalNoise(baseFreqX,
                                                       baseFreqY,
                                                       numOctaves,
                                                       0);

            SKRect rect = new SKRect(0, 0, info.Width, info.Height / 2);
            canvas.DrawRect(rect, paint);

            paint.Shader =
                SKShader.CreatePerlinNoiseTurbulence(baseFreqX,
                                                     baseFreqY,
                                                     numOctaves,
                                                     0);

            rect = new SKRect(0, info.Height / 2, info.Width, info.Height);
            canvas.DrawRect(rect, paint);
        }
    }
}

Вот программу на iOS, Android и универсальной платформы Windows (UWP) устройств.Here's the program running on iOS, Android, and Universal Windows Platform (UWP) devices. Шума фрактала отображается в верхней части холста.The fractal noise is shown in the upper half of the canvas. Пропускаемые встряски — все находится в нижней половине:The turbulence noise is in the bottom half:

Шума ПерлинаPerlin Noise

Те же аргументы всегда производят тот же шаблон, который начинается в левом верхнем углу.The same arguments always produce the same pattern that begins at the upper-left corner. Эта согласованность очевидна в том случае, если вы измените ширину и высоту окна универсальной платформы Windows.This consistency is obvious when you adjust the width and height of the UWP window. Как Windows 10 перерисовывает экрана, шаблон в верхней половине холста остается неизменным.As Windows 10 redraws the screen, the pattern in the upper half of the canvas remains the same.

Шум включает различные уровни прозрачности.The noise pattern incorporates various degrees of transparency. Прозрачность становится очевидным, если задание цвета в canvas.Clear() вызова.The transparency becomes obvious if you set a color in the canvas.Clear() call. Этот цвет становится заметной в шаблоне.That color becomes prominent in the pattern. Вы также увидите этот эффект в разделе объединение нескольких шейдеры.You'll also see this effect in the section Combining multiple shaders.

Эти шаблоны шума Перлина редко используются сами по себе.These Perlin noise patterns are rarely used by themselves. Часто они являются подвергались blend режимы и цвет фильтров, описанных в последующих статьях.Often they are subjected to blend modes and color filters discussed in later articles.

Мозаичное заполнение шума ПерлинаTiling Perlin noise

Два статических SKShader методы для создания шума Перлина также существовать в перегруженных версий.The two static SKShader methods for creating Perlin noise also exist in overload versions. CreatePerlinNoiseFractalNoise И CreatePerlinNoiseTurbulence перегрузки имеют дополнительный SKPointI параметр:The CreatePerlinNoiseFractalNoise and CreatePerlinNoiseTurbulence overloads have an additional SKPointI parameter:

public static SKShader CreatePerlinNoiseFractalNoise (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, SKPointI tileSize);

public static SKShader CreatePerlinNoiseTurbulence (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, SKPointI tileSize);

SKPointI Структуры — это целое число версия знакомого SKPoint структуры.The SKPointI structure is the integer version of the familiar SKPoint structure. SKPointI Определяет X и Y свойства типа int вместо float.SKPointI defines X and Y properties of type int rather than float.

Эти методы создают повторяющийся шаблон указанного размера.These methods create a repeating pattern of the specified size. В каждой плитке правым краем совпадает со значением левой границы и верхним краем совпадает с нижней границей.In each tile, the right edge is the same as the left edge, and the top edge is the same as the bottom edge. Эта особенность обсуждается в Мозаичная шума Перлина страницы.This characteristic is demonstrated in the Tiled Perlin Noise page. Этот файл XAML как в предыдущем примере, но имеет только Stepper представление для изменения seed аргумент:The XAML file is similar to the previous sample, but it only has a Stepper view for changing the seed argument:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Effects.TiledPerlinNoisePage"
             Title="Tiled Perlin Noise">

    <StackLayout>
        <skia:SKCanvasView x:Name="canvasView"
                           VerticalOptions="FillAndExpand"
                           PaintSurface="OnCanvasViewPaintSurface" />

        <StackLayout Orientation="Horizontal"
                     HorizontalOptions="Center"
                     Margin="10">

            <Label Text="{Binding Source={x:Reference seedStepper},
                                  Path=Value,
                                  StringFormat='Seed: {0:F0}'}"
                   VerticalOptions="Center" />

            <Stepper x:Name="seedStepper"
                     Minimum="1"
                     ValueChanged="OnStepperValueChanged" />

        </StackLayout>
    </StackLayout>
</ContentPage>

Файл с выделенным кодом определяет константу для размера мозаики.The code-behind file defines a constant for the tile size. PaintSurface Обработчик создает точечный рисунок, размер и SKCanvas для рисования в этот точечный рисунок.The PaintSurface handler creates a bitmap of that size and an SKCanvas for drawing into that bitmap. SKShader.CreatePerlinNoiseTurbulence Метод создает построитель текстуры на языке с такой размер плитки.The SKShader.CreatePerlinNoiseTurbulence method creates a shader with that tile size. Этот шейдер рисуется на точечный рисунок:This shader is drawn on the bitmap:

public partial class TiledPerlinNoisePage : ContentPage
{
    const int TILE_SIZE = 200;

    public TiledPerlinNoisePage()
    {
        InitializeComponent();
    }

    void OnStepperValueChanged(object sender, ValueChangedEventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Get seed value from stepper
        float seed = (float)seedStepper.Value;

        SKRect tileRect = new SKRect(0, 0, TILE_SIZE, TILE_SIZE);

        using (SKBitmap bitmap = new SKBitmap(TILE_SIZE, TILE_SIZE))
        {
            using (SKCanvas bitmapCanvas = new SKCanvas(bitmap))
            {
                bitmapCanvas.Clear();

                // Draw tiled turbulence noise on bitmap
                using (SKPaint paint = new SKPaint())
                {
                    paint.Shader = SKShader.CreatePerlinNoiseTurbulence(
                                        0.02f, 0.02f, 1, seed,
                                        new SKPointI(TILE_SIZE, TILE_SIZE));

                    bitmapCanvas.DrawRect(tileRect, paint);
                }
            }

            // Draw tiled bitmap shader on canvas
            using (SKPaint paint = new SKPaint())
            {
                paint.Shader = SKShader.CreateBitmap(bitmap,
                                                     SKShaderTileMode.Repeat,
                                                     SKShaderTileMode.Repeat);
                canvas.DrawRect(info.Rect, paint);
            }

            // Draw rectangle showing tile
            using (SKPaint paint = new SKPaint())
            {
                paint.Style = SKPaintStyle.Stroke;
                paint.Color = SKColors.Black;
                paint.StrokeWidth = 2;

                canvas.DrawRect(tileRect, paint);
            }
        }
    }
}

Создав растрового изображения, другой SKPaint объект используется для создания шаблона мозаики точечный рисунок вызовом SKShader.CreateBitmap.After the bitmap has been created, another SKPaint object is used to create a tiled bitmap pattern by calling SKShader.CreateBitmap. Обратите внимание, что два аргумента SKShaderTileMode.Repeat:Notice the two arguments of SKShaderTileMode.Repeat:

paint.Shader = SKShader.CreateBitmap(bitmap,
                                     SKShaderTileMode.Repeat,
                                     SKShaderTileMode.Repeat);

Этот шейдер используется для обработки на холст.This shader is used to cover the canvas. Наконец другой SKPaint объект используется для обводки прямоугольника, показывающий размер исходного растрового изображения.Finally, another SKPaint object is used to stroke a rectangle showing the size of the original bitmap.

Только seed параметр, доступный для выбора из пользовательского интерфейса.Only the seed parameter is selectable from the user interface. Если же seed шаблон используется на каждой платформе, они отобразятся в тот же шаблон.If the same seed pattern is used on each platform, they would show the same pattern. Различные seed значения привести различных шаблонов:Different seed values result in different patterns:

Мозаичная шума ПерлинаTiled Perlin Noise

Шаблон square 200 пикселей в левом верхнем углу легко перемещаются в другие плитки.The 200-pixel square pattern in the upper-left corner flows seamlessly into the other tiles.

Объединение нескольких шейдеровCombining multiple shaders

SKShader Класс включает CreateColor метод, который создает построитель текстуры на указанный сплошным цветом.The SKShader class includes a CreateColor method that creates a shader with a specified solid color. Этот шейдер не очень удобен, сам по себе, так как просто можно задать цвета Color свойство SKPaint и задайте Shader свойство равным null.This shader is not very useful by itself because you can simply set that color to the Color property of the SKPaint object and set the Shader property to null.

Это CreateColor метод полезен в другом методе, SKShader определяет.This CreateColor method becomes useful in another method that SKShader defines. Этот метод является CreateCompose , который объединяет в себе два шейдеров.This method is CreateCompose, which combines two shaders. Ниже приведен синтаксис:Here's the syntax:

public static SKShader CreateCompose (SKShader dstShader, SKShader srcShader);

srcShader (Источник шейдера) является фактически рисуется поверх dstShader (шейдера назначения).The srcShader (source shader) is effectively drawn on top of the dstShader (destination shader). Если источник шейдера сплошным цветом и градиентом без прозрачности, шейдер назначения будут полностью скрыты.If the source shader is a solid color or a gradient without transparency, the destination shader will be completely obscured.

Шейдер шума Перлина прозрачностью.A Perlin noise shader contains transparency. Если что является источником, шейдер назначения будут показаны через прозрачные области.If that shader is the source, the destination shader will show through the transparent areas.

Состоящие шума Перлина страница содержит файл XAML, который практически идентичен первому шума Перлина страницы.The Composed Perlin Noise page has a XAML file that is virtually identical to the first Perlin Noise page. Файл с выделенным кодом осуществляется аналогичным образом.The code-behind file is also similar. Но оригинал шума Перлина странице наборы Shader свойство SKPaint в шейдер, возвращаемое статическим CreatePerlinNoiseFractalNoise и CreatePerlinNoiseTurbulence методы.But the original Perlin Noise page sets the Shader property of SKPaint to the shader returned from the static CreatePerlinNoiseFractalNoise and CreatePerlinNoiseTurbulence methods. Это состоящие шума Перлина странице вызовы CreateCompose для сочетания шейдера.This Composed Perlin Noise page calls CreateCompose for a combination shader. Местом назначения является сплошная синяя шейдера, созданных с помощью CreateColor.The destination is a solid blue shader created using CreateColor. Источником является шейдера шума Перлина:The source is a Perlin noise shader:

public partial class ComposedPerlinNoisePage : ContentPage
{
    public ComposedPerlinNoisePage()
    {
        InitializeComponent();
    }

    void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnStepperValueChanged(object sender, ValueChangedEventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Get values from sliders and stepper
        float baseFreqX = (float)Math.Pow(10, baseFrequencyXSlider.Value - 4);
        baseFrequencyXText.Text = String.Format("Base Frequency X = {0:F4}", baseFreqX);

        float baseFreqY = (float)Math.Pow(10, baseFrequencyYSlider.Value - 4);
        baseFrequencyYText.Text = String.Format("Base Frequency Y = {0:F4}", baseFreqY);

        int numOctaves = (int)octavesStepper.Value;

        using (SKPaint paint = new SKPaint())
        {
            paint.Shader = SKShader.CreateCompose(
                SKShader.CreateColor(SKColors.Blue),
                SKShader.CreatePerlinNoiseFractalNoise(baseFreqX,
                                                       baseFreqY,
                                                       numOctaves,
                                                       0));

            SKRect rect = new SKRect(0, 0, info.Width, info.Height / 2);
            canvas.DrawRect(rect, paint);

            paint.Shader = SKShader.CreateCompose(
                SKShader.CreateColor(SKColors.Blue),
                SKShader.CreatePerlinNoiseTurbulence(baseFreqX,
                                                     baseFreqY,
                                                     numOctaves,
                                                     0));

            rect = new SKRect(0, info.Height / 2, info.Width, info.Height);
            canvas.DrawRect(rect, paint);
        }
    }
}

Шейдера шума фрактала размещена в верхней части; шейдер встряски — все находится в конце:The fractal noise shader is on the top; the turbulence shader is on the bottom:

Состоящее шума ПерлинаComposed Perlin Noise

Обратите внимание, что объем более синими, затем эти шейдеры, чем те, которые отображаются по шума Перлина страницы.Notice how much bluer these shaders are than the ones displayed by the Perlin Noise page. Разница показана степень прозрачности в шейдеры шума.The difference illustrates the amount of transparency in the noise shaders.

Имеется также перегрузку CreateCompose метод:There's also an overload of the CreateCompose method:

public static SKShader CreateCompose (SKShader dstShader, SKShader srcShader, SKBlendMode blendMode);

Последний параметр является членом SKBlendMode перечисления, перечисление с 29 члены, которые описаны в следующей серии статей на SkiaSharp композиции и режимы наложения.The final parameter is a member of the SKBlendMode enumeration, an enumeration with 29 members that is discussed in the next series of articles on SkiaSharp compositing and blend modes.