using System;
using System.Collections.Generic;
using System.Drawing;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;

namespace Afterwarp
{
  public partial struct API
  {
    /// Epsilon value for functions that work with single 32-bit floating-point precision.
    internal const float Epsilon = 1e-6f;
  }

  /// Type of graphics technology used in the application.
  public enum DeviceTechnology : byte
  {
    /// The technology has not yet been established.
    Unknown,

    /// Microsoft Direct3D technology.
    Direct3D,

    /// OpenGL by Khronos Group.
    OpenGL,

    /// OpenGL ES by Khronos Group.
    OpenGL_ES,

    /// Vulkan API by Khronos Group.
    Vulkan,

    /// Metal API by Apple.
    Metal,

    /// WebGL by Khronos Group.
    WebGL,

    /// Software rasterizer.
    Software,

    /// Private proprietary technology.
    Proprietary
  }

  /// Type of OS platform the application is running on.
  public enum DevicePlatform : byte
  {
    /// The platform could not be properly identified.
    Unknown,

    /// Microsoft Windows platform.
    Windows,

    /// Linux platform.
    Linux,

    /// Generic Unix platform.
    Unix,

    /// Apple OS X platform.
    OSX,

    /// Apple iOS platform.
    iOS,

    /// Google Android platform.
    Android
  }

  /// Defines how individual pixels and their colors are encoded in images and textures.
  public enum PixelFormat : byte
  {
    /// Unknown pixel format.
    Unknown,

    // Unsigned Normalized formats.

    /// 8-bit unsigned normalized format with red channel only.
    R8,

    /// 16-bit format with 8-bit unsigned normalized red and green channels.
    RG8,

    /// 32-bit format with 8-bit unsigned normalized red, green, blue and alpha channels.
    RGBA8,

    /// 8-bit unsigned normalized format with red channel only.
    R16,

    /// 32-bit format with 8-bit unsigned normalized red and green channels.
    RG16,

    /// 64-bit ARGB pixel format with each channel having 16 bits.
    RGBA16,

    // Signed Normalized formats.

    /// 8-bit signed normalized format with red channel only.
    R8S,

    /// 16-bit format with 8-bit signed normalized red and green channels.
    RG8S,

    /// 32-bit format with 8-bit signed normalized red, green, blue and alpha channels.
    RGBA8S,

    /// 16-bit signed normalized format with red channel only.
    R16S,

    /// 32-bit format with 16-bit signed normalized red and green channels.
    RG16S,

    /// 64-bit format with 16-bit signed normalized red, green, blue and alpha channels.
    RGBA16S,

    // Unsigned formats.

    /// 8-bit format with 8-bit unsigned integer red channel.
    R8U,

    /// 16-bit format with 8-bit unsigned integer red and green channels.
    RG8U,

    /// 32-bit format with 8-bit unsigned integer red and green channels.
    RGBA8U,

    /// 16-bit format with 16-bit unsigned integer red channel.
    R16U,

    /// 32-bit format with 16-bit unsigned integer red and green channels.
    RG16U,

    /// 64-bit format with 16-bit unsigned integer red and green channels.
    RGBA16U,

    /// 32-bit format with 32-bit unsigned integer red channel.
    R32U,

    /// 64-bit format with 32-bit unsigned integer red and green channels.
    RG32U,

    /// 128-bit format with 32-bit unsigned integer red and green channels.
    RGBA32U,

    // Signed formats.

    /// 8-bit format with 8-bit signed integer red channel.
    R8I,

    /// 16-bit format with 8-bit signed integer red and green channels.
    RG8I,

    /// 32-bit format with 8-bit signed integer red and green channels.
    RGBA8I,

    /// 16-bit format with 16-bit signed integer red channel.
    R16I,

    /// 32-bit format with 16-bit signed integer red and green channels.
    RG16I,

    /// 64-bit format with 16-bit signed integer red and green channels.
    RGBA16I,

    /// 32-bit format with 32-bit signed integer red channel.
    R32I,

    /// 64-bit format with 32-bit signed integer red and green channels.
    RG32I,

    /// 128-bit format with 16-bit unsigned integer red and green channels.
    RGBA32I,

    // Floating-point formats.

    /// 16-bit floating-point pixel format, which has only one component.
    R16F,

    /// 32-bit floating-point pixel format containing two components with 16 bits each.
    RG16F,

    /// 64-bit floating-point ARGB pixel format with each component having 16 bits.
    RGBA16F,

    /// 32-bit floating-point pixel format, which has only one component.
    R32F,

    /// 64-bit floating-point pixel format containing two components with 32 bits each.
    RG32F,

    /// 128-bit floating-point ARGB pixel format with each component having 32 bits.
    RGBA32F,

    // Specialized floating-point formats.

    /// 32-bit format with 11-bit unsigned floating-point red and green channels, and 10-bit blue channel.
    RG11B10F,

    /// 32-bit format with 9-bit floating-point red, green and blue channels with shared 5-bit exponent.
    RGB9E5F,

    // Specialized color formats.

    /// 32-bit format with 10-bit unsigned normalized red, green and blue channels, and 2-bit alpha-channel.
    RGB10A2,

    /// 32-bit format with 10-bit unsigned integer red, green and blue channels, and 2-bit alpha-channel.
    RGB10A2U,

    /// 32-bit format with 8-bit unsigned normalized red, green and blue channels (8 bits unused).
    RGBX8,

    /// 32-bit format with 8-bit unsigned normalized red, green, blue and alpha channels with sRGB curve.
    RGBA8_SRGB,

    /// 32-bit format with 8-bit unsigned normalized blue, green, red and alpha channels.
    BGRA8,

    /// 32-bit format with 8-bit unsigned normalized blue, green and red channels (8 bits unused).
    BGRX8,

    /// 32-bit format with 8-bit unsigned normalized blue, green, red and alpha channels with sRGB curve.
    BGRA8_SRGB,

    /// 32-bit format with 10-bit unsigned normalized blue, green and red channels, and 2-bit alpha-channel.
    BGR10A2,

    /// 32-bit format with 10-bit unsigned normalized blue, green and red channels (2 bits unused).
    BGR10X2,

    /// 16-bit format with 4-bit unsigned normalized blue, green, red and alpha channels.
    BGRA4,

    /// 16-bit format with 4-bit unsigned normalized blue, green and red channels (4 bits unused).
    BGRX4,

    /// 16-bit format with 5-bit unsigned normalized blue and red, and 6 bits for green channels.
    B5G6R5,

    /// 16-bit format with 5-bit unsigned normalized blue, green and red, 1 bit for alpha channels.
    BGR5A1,

    /// 16-bit format with 5-bit unsigned normalized blue, green and red channels (1 bit unused).
    BGR5X1,

    // Storage formats (not hardware accelerated).

    /// 24-bit format with 8-bit unsigned normalized red, green and blue channels.
    RGB8,

    /// 24-bit format with 8-bit unsigned normalized blue, green and red channels.
    BGR8,

    // Luminance and alpha formats that might require channel swizzling in shader.

    /// 8-bit alpha-channel pixel format.
    A8,

    /// 8-bit luminance pixel format.
    L8,

    /// 16-bit luminance pixel format.
    L16,

    /// 8-bit luminance/alpha pixel format with 4 bits per channel.
    LA4,

    /// 16-bit luminance/alpha pixel format with 8 bits per channel.
    LA8,

    // Legacy pallette formats.

    /// 8-bit palette indexed format.
    I8,

    // Compressed formats.

    /// Compressed format with red channel only.
    R_BC,

    /// Compressed format with red and green channels.
    RG_BC,

    /// Compressed format with red, green and blue channels.
    RGB_BC,

    /// Compressed format with red, green, blue and alpha channels.
    RGBA_BC,

    /// Compressed format with red, green and blue channels with sRGB curve.
    RGB_BC_SRGB,

    /// Compressed format with red, green and blue channels with sRGB curve, and an alpha-channel.
    RGBA_BC_SRGB,

    // Depth/stencil formats.

    /// Depth/stencil format with 16-bit (unsigned normalized) depth values and no storage for stencil.
    D16,

    /// Depth/stencil format with 24-bit (unsigned normalized) depth values and 8 bits for stencil.
    D24S8,

    /// Depth/stencil format with 32-bit (floating-point) depth values and no storage for stencil.
    D32F,

    /// Depth/stencil format with 32-bit (floating-point) depth values and 8 bits for stencil.
    D32S8F
  }

  /// Type of surface layer that should be cleared.
  public struct DeviceClear
  {
    /// Color buffer.
    public const byte Color = 0x01;

    /// Depth buffer.
    public const byte Depth = 0x02;

    /// Stencil buffer.
    public const byte Stencil = 0x04;
  }

  /// Device behavior attributes that define the rendering code path.
  public struct DeviceBehavior
  {
    /// Graphics hardware supports executing fragment shader per each MSAA sample.
    public const uint PerSampleShading = 0x00000001;

    /// 3D clip space uses negative values for depth in range of [-1, 1] instead of [0, 1].
    /// This typically occurs on OpenGL (ES) backend that do not support clip control functions.
    public const uint DepthClipNegative = 0x00000002;

    /// Compute shader support is available.
    public const uint Compute = 0x00000004;

    /// Tessellation shader support is available.
    public const uint Tessellation = 0x00000008;

    /// Direct3D 11: Variable Rate Refresh (VRR) display support is available.
    public const uint VariableRateRefresh = 0x00000100;

    /// OpenGL: ARB_post_depth_coverage, Direct3D 11: PostZCoverageEnable through NvAPI.
    public const uint PostDepthCoverage = 0x00000200;

    /// OpenGL / Intel HD Graphics bug workaround: always unbind buffers before updating their contents.
    public const uint ForceBufferUnbind = 0x00001000;

    /// Direct3D 11 / Parallels bug workaround: clear depth buffer with value lower than one.
    public const uint DepthClearBadPrecision = 0x00002000;

    /// Direct3D 11 / VMware bug workaround: avoid signed normalized integer formats.
    public const uint SignedNormIntFormatBugged = 0x00004000;
  }

  /// Defines how alpha-channel should be handled in the loaded image.
  public enum AlphaFormatRequest : byte
  {
    /// Alpha-channel can be handled either way.
    DontCare,

    /// Alpha-channel in the image should not be premultiplied. Under normal circumstances, this is the
    /// recommended approach as it preserves RGB color information in its original form. However, when using
    /// mipmapping for images that have alpha-channel, Premultiplied gives more accurate results.
    NonPremultiplied,

    /// Alpha-channel in the image should be premultiplied. Under normal circumstances, this is not
    /// recommended as the image would lose information after RGB components are premultiplied by alpha (and
    /// for smaller alpha values, less information is preserved). However, when using mipmapping for images
    /// that have alpha-channel, this gives more accurate results.
    Premultiplied
  }

  /// Format in which a single value of the given element is represented.
  public enum ElementFormat : ushort
  {
    /// Undefined element format (VertexElement::count will define number of actual bytes).
    Undefined,

    /// 32-bit floating-point format.
    Float,

    /// 16-bit floating-point format.
    HalfFloat,

    /// 64-bit floating-point format.
    Double,

    /// 32-bit signed integer format.
    Int,

    /// 32-bit unsigned integer format.
    UnsignedInt,

    /// 16-bit signed integer format.
    Short,

    /// 16-bit unsigned integer format.
    UnsignedShort,

    /// 8-bit signed integer format.
    Byte,

    /// 8-bit unsigned integer format.
    UnsignedByte,

    /// 32-bit storage for two 11-bit and one 10-bit floating-point numbers.
    /// The number of elements for this format must always be set to three (3).
    Float_11_11_10
  }

  /// Type of shader in graphics rendering pipeline.
  public enum ShaderType : byte
  {
    /// Undefined or unknown shader.
    Undefined,

    /// Fragment (pixel) shader.
    Fragment,

    /// Vertex shader.
    Vertex,

    /// Geometry shader.
    Geometry,

    /// Compute shader.
    Compute,

    /// Hull shader.
    Hull,

    /// Domain shader.
    Domain
  }

  /// Type that characterizes shader element.
  public enum ShaderElement : byte
  {
    /// Undefined element type.
    Undefined,

    /// Element is a texture.
    Texture,

    /// Element is a constant buffer (uniform buffer object).
    ConstantBuffer,

    /// Element is a typed buffer (TBO / Buffer). Shares channels with textures.
    TypedBuffer,

    /// Element is a typed buffer (TBO / RWBuffer). Shares channels with textures.
    /// For writing under OpenGL, this is bound as ImageBuffer (not TBO).
    /// For writing under Direct3D, this is bound as an Unordered Access View (UAV).
    RWTypedBuffer,

    /// Element is a compute shader buffer (SSBO / StructuredBuffer).
    StructuredBuffer,

    /// Element is a compute shader buffer (SSBO / RWStructuredBuffer).
    RWStructuredBuffer
  }

  /// Type of triangle face that should have operation applied to.
  public enum TriangleFace : byte
  {
    /// Neither back nor front faces should be processed.
    None,

    /// Back faces should be processed.
    Back,

    /// Front faces should be processed.
    Front,

    /// Both back and front faces should be processed.
    Both
  }

  /// Function that defines how depth/stencil operands should be compared.
  public enum ComparisonFunc : byte
  {
    /// Comparison is always true.
    Always,

    /// Comparison results true when source is less than destination.
    Less,

    /// Comparison results true when source is less than or equal to destination.
    LessEqual,

    /// Comparison results true when source is greater than destination.
    Greater,

    /// Comparison results true when source is greater than or equal to destination.
    GreaterEqual,

    /// Comparison results true when source equals to destination.
    Equal,

    /// Comparison results true when source is not equal to destination.
    NotEqual,

    /// Comparison is always false.
    Never
  }

  /// Operation that should be performed on stencil value.
  public enum StencilOp : byte
  {
    /// Preserve destination value.
    Keep,

    /// Set destination value to zero.
    Zero,

    /// Replace destination value with the source one.
    Replace,

    /// Invert the destination value.
    Invert,

    /// Increment the destination value by the source one and clamp, if necessary.
    Increment,

    /// Decrement the destination value by the source one and clamp, if necessary.
    Decrement,

    /// Increment the destination value by the source one with wrap-around.
    IncrementWarp,

    /// Decrement the destination value by the source one with wrap-around.
    DecrementWarp
  }

  /// Factor that determines how alpha-blending operand is considered.
  public enum BlendFactor : byte
  {
    /// Blending factor is a constant that equals to one.
    One,

    /// Blending factor is a constant that equals to zero.
    Zero,

    /// Source color is used as a blending factor.
    SourceColor,

    /// One minus source color is used as a blending factor.
    InvSourceColor,

    /// Source alpha value is used as a blending factor.
    SourceAlpha,

    /// One minus source alpha value is used as a blending factor.
    InvSourceAlpha,

    /// Destination color is used as a blending factor.
    DestColor,

    /// One minus destination color is used as a blending factor.
    InvDestColor,

    /// Destination alpha value is used as a blending factor.
    DestAlpha,

    /// One minus destination alpha value is used as a blending factor.
    InvDestAlpha,

    /// Blending factor is calculated as min(SrcAlpha, InvDestAlpha).
    SourceAlphaSat,

    /// Blending factor is a user-defined color constant.
    ConstantColor,

    /// Blending factor is one minus user-defined color constant.
    InvConstantColor,

    /// Blending factor is an alpha value from user-defined color constant.
    ConstantAlpha,

    /// Blending factor is one minus alpha value from user-defined color constant.
    InvConstantAlpha,

    /// Source color (from 2nd pixel shader output) is used as a blending factor.
    SourceColor1,

    /// One minus source color (from 2nd pixel shader output) is used as a blending factor.
    InvSourceColor1,

    /// Source alpha value (from 2nd pixel shader output) is used as a blending factor.
    SourceAlpha1,

    /// One minus source alpha (from 2nd pixel shader output) value is used as a blending factor.
    InvSourceAlpha1
  }

  /// Operation that should be performed between two blending operands.
  public enum BlendOp : byte
  {
    /// Add source and destination values.
    Add,

    /// Subtract source value from destination value.
    Subtract,

    /// Subtract destination value from source value.
    InvSubtract,

    /// Calculate minimum between source and destination values.
    Minimum,

    /// Calculate maximum between source and destination values.
    Maximum
  }

  /// Parameters that define depth, stencil, rasterizer and blending operations.
  public struct RenderingState
  {
    /// State flags that can be combined together to form a rendering operation state.
    public struct State
    {
      /// Depth testing should be performed. If this state is not present, depth writing is also disabled.
      public const uint DepthTest = 0x0001u;

      /// Depth values should be written to Depth Buffer.
      public const uint DepthWrite = 0x0002u;

      /// Stencil testing should be performed.
      /// If this state is not present, no other stencil operation will occur.
      public const uint StencilTest = 0x0004u;

      /// Geometry should be clipped by the corresponding depth limits.
      public const uint DepthClip = 0x0008u;

      /// Geometry should be clipped by the corresponding scissor rectangles.
      public const uint ScissorClip = 0x0010u;

      /// Primitives should be rendered in a wireframe mode.
      public const uint Wireframe = 0x0020u;

      /// Triangles having vertices in clockwise order would be culled. If this flag is not set, then triangles
      /// having vertices in counter-clockwise order would be culled.
      public const uint CullClockwise = 0x0040u;

      /// Geometry should be rendered with multisampling.
      public const uint Multisampling = 0x0080u;

      /// Standard 3D lines should be rendered with antialiasing.
      public const uint LineAntialias = 0x0100u;

      /// Writing to color buffer should be performed.
      public const uint ColorWrite = 0x0200u;

      /// Blending operation should be performed.
      public const uint BlendEnable = 0x0400u;

      /// Alpha channel should be converted to coverage samples.
      public const uint AlphaToCoverage = 0x0800u;

      /// Cube Maps should be sampled from neighbor faces at seams.
      public const uint CubeMapSeamless = 0x1000u;

      /// Enables fragment shader execution for each individual MSAA sample.
      /// This has only effect on OpenGL (ES) based implementations.
      public const uint PerSampleShading = 0x2000u;
    }

    /// Stencil state that is independent for each front and back facing.
    public struct StencilState
    {
      /// Creates stencil state structure with the given values.
      public StencilState(ComparisonFunc func, StencilOp failOp, StencilOp depthFailOp,
        StencilOp depthPassOp)
      {
        Func = func;
        FailOp = failOp;
        DepthFailOp = depthFailOp;
        DepthPassOp = depthPassOp;
      }

      /// Returns default stencil state.
      public static StencilState Default => new(ComparisonFunc.Always, StencilOp.Keep, StencilOp.Keep,
        StencilOp.Keep);

      /// Stencil test function.
      public ComparisonFunc Func;

      /// Action to take when stencil test fails.
      public StencilOp FailOp;

      /// Action to take when stencil test passes but depth test fails.
      public StencilOp DepthFailOp;

      /// Action to take when both stencil and depth tests pass, or when stencil test passes and either there
      /// is no depth buffer or depth testing is disabled.
      public StencilOp DepthPassOp;
    }

    /// Blending parameters that are specific to a certain component, or a portion of color.
    public struct Blend
    {
      /// Creates blending parameters structure with the given values.
      public Blend(BlendFactor source, BlendFactor dest, BlendOp op)
      {
        Source = source;
        Dest = dest;
        Op = op;
      }

      /// Returns default blending parameters.
      public static Blend Default => new(BlendFactor.One, BlendFactor.Zero, BlendOp.Add);

      /// Blending factor used for the source component.
      public BlendFactor Source;

      /// Blending factor used for the destination component.
      public BlendFactor Dest;

      /// Blending operation used between source and destination components.
      public BlendOp Op;
    }

    /// Creates a rendering state with the given values.
    public RenderingState(uint states, TriangleFace cullFace, ComparisonFunc depthFunc, float depthBias,
      float slopeDepthBias, float clampDepthBias, byte stencilRefValue, byte stencilRefMask,
      byte stencilWriteMask, Vector4 blendConstant, StencilState stencilFront, StencilState stencilBack,
      Blend blendColor, Blend blendAlpha)
    {
      States = states;
      CullFace = cullFace;
      DepthFunc = depthFunc;
      DepthBias = depthBias;
      SlopeDepthBias = slopeDepthBias;
      ClampDepthBias = clampDepthBias;
      StencilRefValue = stencilRefValue;
      StencilRefMask = stencilRefMask;
      StencilWriteMask = stencilWriteMask;
      BlendConstant = blendConstant;
      StencilFront = stencilFront;
      StencilBack = stencilBack;
      BlendColor = blendColor;
      BlendAlpha = blendAlpha;
    }

    /// Internal default rendering state.
    private static readonly RenderingState _default = new(
      State.Multisampling | State.ColorWrite, TriangleFace.None, ComparisonFunc.Less, 0.0f, 0.0f, 0.0f, 0,
      byte.MaxValue, byte.MaxValue, Vector4.One, StencilState.Default, StencilState.Default, Blend.Default,
      Blend.Default);

    /// Default rendering state.
    public static readonly RenderingState Default = _default;

    /// Combination of state flags that define rendering operation.
    public uint States;

    /// How triangle faces should be culled.
    public TriangleFace CullFace;

    /// Depth buffer comparison function.
    public ComparisonFunc DepthFunc;

    /// Constant offset added to depth to alleviate z-fighting issues.
    public float DepthBias;

    /// Slope coefficient used for relative depth when calculating depth bias.
    public float SlopeDepthBias;

    /// Value to clamp depth bias, preventing artifacts on very high slopes.
    public float ClampDepthBias;

    /// Reference value for the stencil test.
    public byte StencilRefValue;

    /// Mask that is applied to reference value and stored value after the test.
    public byte StencilRefMask;

    /// Mask that is used to enable or disable writing of individual bits to stencil buffer.
    public byte StencilWriteMask;

    /// Custom alpha-blending constant.
    public Vector4 BlendConstant;

    /// Stencil function and operation that are performed for front-facing triangles.
    public StencilState StencilFront;

    /// Stencil function and operation that are performed for back-facing triangles.
    public StencilState StencilBack;

    /// Blending parameters that should be applied to color portion of components.
    public Blend BlendColor;

    /// Blending parameters that should be applied to alpha portion of components.
    public Blend BlendAlpha;
  }

  /// Type of data that a generic buffer contains.
  public enum BufferDataType : byte
  {
    /// Vertex information is stored in the buffer (Vertex Buffer).
    Vertex,

    /// Index information is stored in the buffer (Index Buffer).
    Index,

    /// Shader constant information is stored in the buffer (Constant Buffer).
    Constant,

    /// Read-only shader buffer contained typed information (TBO / Buffer).
    Typed,

    /// Read-only shader buffer contained typed information (TBO / RWBuffer).
    RWTyped,

    /// Read-only shader buffer containing structured information (SSBO / StructuredBuffer).
    Structured,

    /// Read/write shader buffer containing structured information (SSBO / RWStructuredBuffer).
    RWStructured
  }

  /// Type of access that is performed with mesh buffer.
  public enum BufferAccessType : byte
  {
    /// The contents of buffer are updated occasionally.
    Default,

    /// The contents of buffer are defined during construction and typically remain unchanged.
    Static,

    /// The contents of buffer are changed very frequently.
    Dynamic,

    /// The contents of the buffer are used by GPU exclusively.
    Compute,

    /// The buffer is used for asynchronous transfers from GPU back to CPU.
    Staging
  }

  /// Structure that describes the layout of a single buffer element.
  public struct VertexElement
  {
    /// Special bit added to vertex element channel indicating that the integer values are normalized.
    public const uint ChannelNormalized = 0x80000000u;

    /// Special channel number that corresponds to index buffer.
    public const uint ChannelIndexBuffer = 0x7FFFFFFFu;

    /// Creates a vertex element structure with the given values.
    public VertexElement(string name, ElementFormat format, int count, uint channel = 0, uint offset = 0)
    {
      NameBytes = Encoding.UTF8.GetBytes(name);
      Array.Resize(ref NameBytes, 64);

      Format = format;
      Count = count;
      Channel = channel;
      Offset = offset;
    }

    /// Name of the component (variable name in GLSL or semantic name in HLSL).
    public string Name
    {
      readonly get => Encoding.UTF8.GetString(NameBytes).TrimEnd('\0');

      set
      {
        NameBytes = Encoding.UTF8.GetBytes(value);
        Array.Resize(ref NameBytes, 64);
      }
    }

    /// UTF-8 encoded name of the component.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    public byte[] NameBytes;

    /// Data format of each value in this element.
    public ElementFormat Format;

    /// Number of values used by this element.
    /// If "format" is "Undefined", this indicates number of bytes the element occupies.
    public int Count;

    /// Channel to which the values of this element will be bound to. The most significant bit of this field
    /// has a special purpose, meaning that the data values are normalized (applies only to integers), so the
    /// number of channel is stored in first 31 bits.
    public uint Channel;

    /// Offset in bytes relative to origin of the first buffer element to the current one.
    public uint Offset;
  }

  /// Structure that describes a single physical element of shader program.
  public struct ProgramElement
  {
    /// Creates a program element structure with the given values.
    public ProgramElement(string name, ShaderElement element, ShaderType shader, uint channel, int index,
      uint size)
    {
      NameBytes = Encoding.UTF8.GetBytes(name);
      Array.Resize(ref NameBytes, 64);

      Element = element;
      Shader = shader;
      Channel = channel;
      Index = index;
      Size = size;
    }

    /// Name of the element (e.g. variable, buffer or texture name).
    public string Name
    {
      readonly get => Encoding.UTF8.GetString(NameBytes).TrimEnd('\0');

      set
      {
        NameBytes = Encoding.UTF8.GetBytes(value);
        Array.Resize(ref NameBytes, 64);
      }
    }

    /// UTF-8 encoded name of the element.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    public byte[] NameBytes;

    /// Type of shader element.
    public ShaderElement Element;

    /// Shader to which this element belongs to.
    public ShaderType Shader;

    /// A virtual channel index, which will be associated with the appropriate buffer attached to that channel.
    public uint Channel;

    /// Index of physical slot to which the element should be bound to. This can be either an actual binding
    /// point or a register number.
    public int Index;

    /// Size of element in bytes.
    public uint Size;
  }

  /// Structure that describes a single (uniform) variable in a shader program.
  public struct ProgramVariable
  {
    /// Creates a new program variable structure with the given values.
    public ProgramVariable(string name, int index, ShaderType shader, ElementFormat format, int count,
      uint size, uint offset)
    {
      NameBytes = Encoding.UTF8.GetBytes(name);
      Array.Resize(ref NameBytes, 64);

      Index = index;
      Shader = shader;
      Format = format;
      Count = count;
      Size = size;
      Offset = offset;
    }

    /// Name of the element (e.g. variable, buffer or texture name).
    public string Name
    {
      readonly get => Encoding.UTF8.GetString(NameBytes).TrimEnd('\0');

      set
      {
        NameBytes = Encoding.UTF8.GetBytes(value);
        Array.Resize(ref NameBytes, 64);
      }
    }

    /// UTF-8 encoded name of the element.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    public byte[] NameBytes;

    /// Index that uniquely identifies this variable.
    public int Index;

    /// Shader to which this element belongs to.
    public ShaderType Shader;

    /// Data format of each value in this variable.
    public ElementFormat Format;

    /// Number of values used by this variable.
    /// If "format" is "Undefined", this indicates number of bytes the element occupies.
    public int Count;

    /// Size of variable in bytes.
    public uint Size;

    /// Offset in a buffer where variable starts.
    public uint Offset;
  }

  /// Compute program texture access type.
  public enum ComputeTextureAccess : byte
  {
    /// Texture will be read from, no writes allowed.
    Read,

    /// Texture will only be written to, no reads allowed.
    Write,

    /// Texture will be read from and written to.
    ReadWrite
  }

  /// Compute texture binding parameters.
  public struct ComputeBindTextureFormat
  {
    /// Creates new binding parameters with the given values.
    public ComputeBindTextureFormat(uint channel, int mipLevel, int layer, ComputeTextureAccess access,
      PixelFormat format)
    {
      Channel = channel;
      MipLevel = mipLevel;
      Layer = layer;
      Access = access;
      Format = format;
    }

    /// Channel to which the texture is bound to.
    public uint Channel;

    /// Number of mipmap level that should be attached.
    public int MipLevel;

    /// Layer number from a volume or array texture to bound (-1 means an entire texture should be bound).
    public int Layer;

    /// Type of access that will be used with the texture.
    public ComputeTextureAccess Access;

    /// Format of the texture's pixels.
    public PixelFormat Format;
  }

  /// Filtering mode that defines how colors are sampled from the texture.
  public enum TextureFilter : byte
  {
    /// No filtering is performed (applies only to mipmap filter, in which case it gets disabled).
    None,

    /// Nearest integer sample filtering.
    Nearest,

    /// Linear interpolation filtering.
    Linear,

    /// Linear anisotropic filtering.
    Anisotropic
  }

  /// Addressing mode that defines how texture coordinates outside of [0, 1] range are treated.
  public enum TextureAddress : byte
  {
    /// Texture coordinates are wrapped; that is, only fractional part is considered.
    Wrap,

    /// Texture coordinates are clamped to stay within [0, 1] range.
    Clamp,

    /// Texture coordinates are mirrored in each odd cycle (e.g. from 1 to 2, from 3 to 4 and so on).
    Mirror,

    /// Texture coordinates are mirrored for one cycle and then clamped.
    MirrorOnce,

    /// When texture coordinates are outside of [0, 1] range, a separate border color will be used instead.
    Border
  }

  /// Rendering primitive topology.
  public enum PrimitiveTopology : byte
  {
    /// Unknown (undefined) topology.
    Unknown,

    /// Points or point lists.
    Points,

    /// Lines or line lists.
    Lines,

    /// Line strips.
    LineStrip,

    /// Triangles or triangle lists.
    Triangles,

    /// Triangle strips.
    TriangleStrip,

    /// Lines or line lists with adjacency information.
    LinesAdjacency,

    /// Line strips with adjacency information.
    LineStripAdjacency,

    /// Triangles or triangle lists with adjacency information.
    TrianglesAdjacency,

    /// Triangle strips with adjacency information.
    TriangleStripAdjacency,

    /// Tessellation patches.
    Patches
  }

  /// Path commands and attribute bits.
  public struct PathCommand
  {
    /// Close path, connecting previous position to the first position in the path.
    public const byte Close = 0x00;

    /// Move position to the given coordinates.
    /// This is followed by a pair of (x, y) coordinates.
    public const byte MoveTo = 0x01;

    /// Draw a line from current position to the given coordinates.
    /// This is followed by a pair of (x, y) coordinates.
    public const byte LineTo = 0x02;

    /// Draw a cubic Bezier curve from current position to the given coordinates and with the given control
    /// points. This is followed by three pairs of (x, y) coordinates, the first two being control points and
    /// last one being the destination position.
    public const byte CurveTo = 0x03;

    /// Draw a quadratic Bezier curve from current position to the given coordinates and with the given control
    /// point. This is followed by two pairs of (x, y) coordinates, the first one being a control point and
    /// last one being the destination position.
    public const byte QuadCurveTo = 0x04;

    /// Change "flatness" value used for converting Bezier curves into line segments. This is followed by
    /// a single value. Default value is "0.25". Note: if "Relative" flag is set, then "length" field is
    /// interpreted as a 16-bit floating-point (float16 or "half float"), and it is assumed that no additional
    /// values are following this command.
    public const byte Flatness = 0x1A;

    /// Change angle tolerance for Bezier curves to the given value. This is followed by a single value.
    /// A value of zero or less means angle tolerance is not checked. Default value is zero. A typical value
    /// for this would be something like PI / 7. Note: if "Relative" flag is set, then "length" field is
    /// interpreted as a 16-bit floating-point (float16 or "half float"), and it is assumed that no additional
    /// values are following this command.
    public const byte ToleranceAngle = 0x1B;

    /// Change cusp limit angle for Bezier curves to the given value. This is followed by a single value.
    /// A value of zero or less means cust limit angle is not checked. Default value is zero.
    /// Note: if "Relative" flag is set, then "length" field is interpreted as a 16-bit floating-point
    /// (float16 or "half float"), and it is assumed that no additional values are following this command.
    public const byte LimitCusp = 0x1C;

    /// A bit flag that indicates that command should take previous control point mirrored around previous
    /// position and use it as the first control point for the command that requires it. This only applies
    /// to Bezier curves. If this flag is specified, then there will be one less control point following
    /// the command declaration (so for "CurveTo", it'll be just one control point, and for "QuadCurveTo"
    /// there will be no control points).
    public const byte Smooth = 0x40;

    /// A bit flag that indicates that command is relative to previous position. If this is the first command
    /// in the path, then it would be considered as absolute (or relative to zero, which would be the same).
    /// This flag has also special meaning when changing tolerances and angles (see above).
    public const byte Relative = 0x80;
  }

  /// A single element in path declaration.
  public struct PathElement
  {
    /// A single 32-bit floating-point value of the path coordinates.
    public float Value;

    /// Path command enumeration combined with one of its attribute bits.
    public byte Command
    {
      readonly get => (byte)(BitConverter.ToUInt32(BitConverter.GetBytes(Value), 0) & 0x000000FFu);

      set
      {
        uint bits = (BitConverter.ToUInt32(BitConverter.GetBytes(Value), 0) & 0xFFFFFF00u) | value;
        Value = BitConverter.ToSingle(BitConverter.GetBytes(bits), 0);
      }
    }

    /// Number of "Value" elements that follows this declaration.
    public ushort Length
    {
      readonly get => (ushort)(BitConverter.ToUInt32(BitConverter.GetBytes(Value), 0) >> 16);

      set
      {
        uint bits = (BitConverter.ToUInt32(BitConverter.GetBytes(Value), 0) & 0x0000FFFFu) |
          ((uint)value << 16);
        Value = BitConverter.ToSingle(BitConverter.GetBytes(bits), 0);
      }
    }

    /// Creates path element equal to a given floating-point value.
    public PathElement(float value = 0.0f) { Value = value; }

    /// Creates path element being a specific command with an optional length parameter.
    public PathElement(byte command, ushort length = 0)
    {
      uint bits = command | ((uint)length << 16);
      Value = BitConverter.ToSingle(BitConverter.GetBytes(bits), 0);
    }
  }

  /// A container and helper module to facilitate creation of path elements.
  public class PathBuilder
  {
    /// Creates an empty container.
    public PathBuilder()
    {
      elements = new List<PathElement>();
      lastCommand = 0xFF;
      lastIndex = -1;
    }

    /// Removes all existing elements.
    public void Clear()
    {
      elements.Clear();
      lastCommand = 0xFF;
      lastIndex = -1;
    }

    /// Closes current path.
    public void ClosePath()
    {
      if (lastIndex != -1 && lastCommand != PathCommand.Close)
      {
        elements.Add(new PathElement(PathCommand.Close));
        lastCommand = PathCommand.Close;
        lastIndex = elements.Count - 1;
      }
    }

    /// Moves position to the given coordinates. This basically means creating a new sub-path.
    public void MoveTo(Vector2 position, bool relative = false)
    {
      PassCommandPoints((byte)(PathCommand.MoveTo | (relative ? PathCommand.Relative : 0)), position);
    }

    /// Produces a line between previous position and the given coordinates, adjusting current position
    /// accordingly.
    public void LineTo(Vector2 position, bool relative = false)
    {
      PassCommandPoints((byte)(PathCommand.LineTo | (relative ? PathCommand.Relative : 0)), position);
    }

    /// Produces a cubic Bezier curve between previous position, mirrored previous control point and the given
    /// control point and coordinates, adjusting current position accordingly.
    public void CurveTo(Vector2 controlPoint1, Vector2 controlPoint2, Vector2 position, bool relative = false)
    {
      PassCommandPoints((byte)(PathCommand.CurveTo | (relative ? PathCommand.Relative : 0)),
        controlPoint1, controlPoint2, position);
    }

    /// Produces a cubic Bezier curve between previous position, mirrored previous control point and the given
    /// control point and coordinates, adjusting current position accordingly.
    public void SmoothCurveTo(Vector2 controlPoint2, Vector2 position, bool relative = false)
    {
      PassCommandPoints((byte)(PathCommand.CurveTo | PathCommand.Smooth |
        (relative ? PathCommand.Relative : 0)), controlPoint2, position);
    }

    /// Produces a quadratic Bezier curve between previous position, two control points and the given
    /// coordinates, adjusting current position accordingly.
    public void QuadCurveTo(Vector2 controlPoint, Vector2 position, bool relative = false)
    {
      PassCommandPoints((byte)(PathCommand.QuadCurveTo | (relative ? PathCommand.Relative : 0)),
        controlPoint, position);
    }

    /// Produces a quadratic Bezier curve between previous position, mirrored previous control point and
    /// the given coordinates, adjusting current position accordingly.
    public void SmoothQuadCurveTo(Vector2 position, bool relative = false)
    {
      PassCommandPoints((byte)(PathCommand.QuadCurveTo | PathCommand.Smooth |
        (relative ? PathCommand.Relative : 0)), position);
    }

    /// Produces a new rectangle path at the given coordinates.
    public void Rectangle(RectF rectangle, bool clockwise = false, bool relative = false)
    {
      MoveTo(rectangle.TopLeft, relative);

      if (clockwise)
      {
        LineTo(new Vector2(rectangle.Width, 0.0f), true);
        LineTo(new Vector2(0.0f, rectangle.Height), true);
        LineTo(new Vector2(-rectangle.Width, 0.0f), true);
        LineTo(new Vector2(0.0f, -rectangle.Height), true);
      }
      else
      {
        LineTo(new Vector2(0.0f, rectangle.Height), true);
        LineTo(new Vector2(rectangle.Width, 0.0f), true);
        LineTo(new Vector2(0.0f, -rectangle.Height), true);
        LineTo(new Vector2(-rectangle.Width, 0.0f), true);
      }
      ClosePath();
    }

    /// Produces a new circle path at the given coordinates.
    public void Circle(Vector2 center, float radius, bool clockwise = false, bool relative = false)
    {
      float theta = 0.551915f;

      if (radius > 0.0f)
      {
        if (clockwise)
        {
          MoveTo(new Vector2(center.X, center.Y - radius), relative);
          CurveTo(new Vector2(radius * theta, 0.0f), new Vector2(radius, radius - radius * theta),
            new Vector2(radius, radius), true);
          SmoothCurveTo(new Vector2(radius * theta - radius, radius), new Vector2(-radius, radius), true);
          SmoothCurveTo(new Vector2(-radius, radius * theta - radius), new Vector2(-radius, -radius), true);
          SmoothCurveTo(new Vector2(radius - radius * theta, -radius), new Vector2(radius, -radius), true);
        }
        else
        {
          MoveTo(new Vector2(center.X, center.Y + radius), relative);
          CurveTo(new Vector2(radius * theta, 0.0f), new Vector2(radius, radius * theta - radius),
            new Vector2(radius, -radius), true);
          SmoothCurveTo(new Vector2(radius * theta - radius, -radius), new Vector2(-radius, -radius), true);
          SmoothCurveTo(new Vector2(-radius, radius - radius * theta), new Vector2(-radius, radius), true);
          SmoothCurveTo(new Vector2(radius - radius * theta, radius), new Vector2(radius, radius), true);
        }
      }
      ClosePath();
    }

    /// Produces a new rotated quadrilateral (diamond-shaped) path at the given coordinates.
    public void Diamond(Vector2 center, float radius, bool clockwise = false, bool relative = false)
    {
      if (radius > 0.0f)
      {
        if (clockwise)
        {
          MoveTo(new Vector2(center.X, center.Y - radius), relative);
          LineTo(new Vector2(radius, radius), true);
          LineTo(new Vector2(-radius, radius), true);
          LineTo(new Vector2(-radius, -radius), true);
        }
        else
        {
          MoveTo(new Vector2(center.X, center.Y + radius), relative);
          LineTo(new Vector2(radius, -radius), true);
          LineTo(new Vector2(-radius, -radius), true);
          LineTo(new Vector2(-radius, radius), true);
        }
        ClosePath();
      }
    }

    /// Produces a new gear-looking shape at the given coordinates.
    public void Gear(Vector2 center, float radius, float amplitude, int steps, int teeth,
      bool clockwise = false)
    {
      if (radius > 0.0f)
      {
        for (int i = 0; i < steps; ++i)
        {
          float theta = clockwise ? (float)i / steps : 1.0f - (float)i / steps;
          float angle = theta * MathF.PI * 2.0f;
          float distance = radius + API.SineTransform(API.SineCycle(theta * teeth)) * amplitude;

          Vector2 position = new(
            center.X + MathF.Cos(angle) * distance,
            center.Y - MathF.Sin(angle) * distance);

          if (i == 0)
            MoveTo(position);
          else
            LineTo(position);
        }
      }
      ClosePath();
    }

    /// Changes flatness (distance tolerance for Bezier curves) for the path. This will take effect for
    /// the following commands.
    public void Flatness(float flatness)
    {
      if (lastIndex == -1 || lastCommand != PathCommand.Flatness ||
        elements[lastIndex].Length >= ushort.MaxValue - 1)
      {
        elements.Add(new PathElement(PathCommand.Flatness, 1));
        elements.Add(new PathElement(flatness));
        lastCommand = PathCommand.Flatness;
        lastIndex = elements.Count - 2;
      }
      else
      {
        elements.Add(new PathElement(flatness));
        elements[lastIndex] = new PathElement(elements[lastIndex].Command,
          (ushort)(elements[lastIndex].Length + 1));
      }
    }

    /// Adds a command and variable number of points.
    private void PassCommandPoints(byte command, params Vector2[] points)
    {
      int valueCount = points.Length * 2;

      if (lastIndex == -1 || lastCommand != command ||
        elements[lastIndex].Length >= ushort.MaxValue - valueCount)
      { // Create a new command.
        elements.Add(new PathElement(command, (ushort)valueCount));

        foreach (Vector2 point in points)
        {
          elements.Add(new PathElement(point.X));
          elements.Add(new PathElement(point.Y));
        }
        lastCommand = command;
        lastIndex = elements.Count - (valueCount + 1);
      }
      else
      { // Add additional data to an existing command.
        foreach (Vector2 point in points)
        {
          elements.Add(new PathElement(point.X));
          elements.Add(new PathElement(point.Y));
        }
        elements[lastIndex] = new PathElement(lastCommand, (ushort)(elements[lastIndex].Length + valueCount));
      }
    }

    /// Returns the resulting array of path elements.
    public PathElement[] Elements => elements.ToArray();

    /// Internal list of path elements.
    private readonly List<PathElement> elements;

    /// Last command that was issued.
    private byte lastCommand;

    /// Index for a last command element.
    private int lastIndex;
  }

  /// Type of joint for connecting path lines.
  public enum PathJoint : byte
  {
    /// No joint is produced, lines on each joint end with a butt cap.
    None,

    /// Simple interpolated joint that does not guarantee correct line width on sharp corners.
    Simple,

    /// Miter joint with angular corners.
    Miter,

    /// Beveled joint.
    Bevel,

    /// Round joint.
    Round,

    /// Miter joint unless the miter would extend beyond its limit multiplied by half thickness.
    MiterBevel
  }

  /// Type of caps that covers line end points.
  public enum LineCaps : byte
  {
    /// Cap that starts and ends exactly at the center of end points.
    Butt,

    /// Cap that extends by half thickness after the end points.
    Square,

    /// Round cap with a radius equal to half thickness with center being each line end point.
    Round
  }

  /// Shape of point primitive.
  public enum PointShape : byte
  {
    /// Square point.
    Square,

    /// Round point.
    Round,

    /// Equilateral triangle point.
    Triangle,

    /// 5-sided star point.
    Star,

    /// Cross point.
    Cross
  }

  /// Sampler parameters that are associated with a particular texture unit.
  public struct SamplerState
  {
    /// Creates new sampler state with the given values.
    public SamplerState(TextureFilter filterMin, TextureFilter filterMag, TextureFilter filterMip,
      TextureAddress addressU, TextureAddress addressV, TextureAddress addressW, FloatColor borderColor,
      int anisotropy, float minLOD, float maxLOD, float biasLOD, ComparisonFunc compareFunc,
      bool compareToRef)
    {
      FilterMin = filterMin;
      FilterMag = filterMag;
      FilterMip = filterMip;
      AddressU = addressU;
      AddressV = addressV;
      AddressW = addressW;
      BorderColor = borderColor;
      Anisotropy = anisotropy;
      MinLOD = minLOD;
      MaxLOD = maxLOD;
      BiasLOD = biasLOD;
      CompareFunc = compareFunc;
      CompareToRef = compareToRef;
    }

    /// Internal sampler state with default values.
    private static readonly SamplerState _default = new (TextureFilter.Linear, TextureFilter.Linear,
      TextureFilter.Linear, TextureAddress.Clamp, TextureAddress.Clamp, TextureAddress.Clamp,
      FloatColor.White, 1, -float.MaxValue, float.MaxValue, 0.0f, ComparisonFunc.Never, false);

    /// Returns sampler state with default values.
    public static SamplerState Default => _default;

    /// Minification texture filtering.
    public TextureFilter FilterMin;

    /// Magnification texture filtering.
    public TextureFilter FilterMag;

    /// Mipmapping texture filtering.
    public TextureFilter FilterMip;

    /// Texture coordinate addressing for U coordinate.
    public TextureAddress AddressU;

    /// Texture coordinate addressing for V coordinate.
    public TextureAddress AddressV;

    /// Texture coordinate addressing for W coordinate.
    public TextureAddress AddressW;

    /// Special color constant to be used for TextureAddress::Border addressing mode.
    public FloatColor BorderColor;

    /// Total number of samples to be used with anisotropic filtering.
    public int Anisotropy;

    /// Minimum level of detail for texture mipmap range.
    public float MinLOD;

    /// Maximum level of detail for texture mipmap range.
    public float MaxLOD;

    /// Offset from the calculated mipmap level.
    public float BiasLOD;

    /// Comparison function for texture values.
    public ComparisonFunc CompareFunc;

    /// Indicates whether comparison should be made against a particular reference value or simply fetched.
    [MarshalAs(UnmanagedType.U1)]
    public bool CompareToRef;
  }

  /// Type of texture that defines how it is composed.
  public enum TextureType : byte
  {
    /// Standard 2D texture surface.
    Surface,

    /// Cube Map consisting of 6 individual 2D faces.
    CubeMap,

    /// Layered 3D volume texture.
    Volume
  }

  /// Texture parameters and characteristics.
  public struct TextureParameters
  {
    /// Creates a new set of texture parameters with the given values.
    public TextureParameters(int width, int height, int layers, PixelFormat format,
      TextureType type = TextureType.Surface, uint attributes = 0, int multisamples = 0,
      PixelFormat depthStencil = PixelFormat.Unknown)
    {
      Width = width;
      Height = height;
      Layers = layers;
      Format = format;
      Type = type;
      Attributes = attributes;
      Multisamples = multisamples;
      DepthStencil = depthStencil;
    }

    /// Texture width (in pixels).
    public int Width;

    /// Texture height (in pixels).
    public int Height;

    /// Number of texture layers in case of Texture Array or depth in case of 3D textures.
    public int Layers;

    /// Format of the texture's pixels.
    public PixelFormat Format;

    /// Texture type that defines how it is composed.
    public TextureType Type;

    /// Attributes that define the characteristics of the texture.
    public uint Attributes;

    /// Number of multisamples used in the render target.
    public int Multisamples;

    /// Depth/stencil format that will be used to create an associated buffer.
    public PixelFormat DepthStencil;
  }

  /// Blending effect that defines how primitives are rendered on drawing surface.
  public enum BlendingEffect : byte
  {
    /// Undefined blending effect. Canvas does not change blending parameters configured in the device
    /// context and uses whatever configuration is currently active.
    Undefined = 0,

    /// "Normal" blending effect: Cd = (Cs * As) + (Cd * (1 - As).
    Normal,

    /// "Shadow drawing" effect: Cd = Cd * (1 - As).
    Shadow,

    /// Additive blending effect: Cd = (Cs * As) + Cd.
    Add,

    /// Subtractive blending effect: Cd = (Cs * As) - Cd.
    Subtract,

    /// Multiplication blending effect: Cd = Cs * Cd.
    Multiply,

    /// Inverse multiplication effect: Cd = (1 - Cs) * Cd.
    InverseMultiply,

    /// Source color blending effect: Cd = (Cs * Cs) + (Cd * (1 - Cs)).
    SourceColor,

    /// Source color additive blending effect: Cd = (Cs * Cs) + Cd.
    SourceColorAdd,

    /// Alpha-blending disabled, drawing is just a copy operation.
    Copy = 254,

    /// Custom alpha-blending as set up through device directly.
    Custom = 255
  }

  /// One of possible defined context states that can be pre-configured by the canvas.
  public enum CanvasContextState : byte
  {
    /// Geometric shapes and images rendered in a flat 2D scene.
    FlatScene,

    /// Text rendered in a flat 2D scene.
    FlatText,

    /// Geometric shapes, images and text rendered in a 3D surface projection.
    Projected,

    /// Undefined context state.
    Undefined = 255
  }

  /// Type of super-sampling used for rendering Signed Distance Field (SDF).
  public enum SuperSampleSDF : byte
  {
    /// Non-supersampled rendering (for low-performance systems). Note that if outline is enabled, its color
    /// will be calculated using simplified scheme, where luma is calculated as usual, chroma is calculated
    /// in a simple fashion and hue is not affected.
    NoSuperSample,

    /// 4x super-sampled rendering.
    SuperSample4x,

    /// 16x super-sampled rendering.
    SuperSample16x
  }

  /// Signed Distance Field (SDF) parameters.
  public struct SignedDistanceField
  {
    /// Creates signed distance field parameters with the given values.
    public SignedDistanceField(SuperSampleSDF superSampleSDF, float signedFieldDistance,
      Vector3 outlineOffsetSDF, float outlineDistanceMinSDF, float outlineDistanceMaxSDF)
    {
      SuperSampleSDF = superSampleSDF;
      SignedFieldDistance = signedFieldDistance;
      OutlineOffsetSDF = outlineOffsetSDF;
      OutlineDistanceMinSDF = outlineDistanceMinSDF;
      OutlineDistanceMaxSDF = outlineDistanceMaxSDF;
    }

    /// Returns default signed distance field (SDF) parameters.
    public static SignedDistanceField Default => new(SuperSampleSDF.SuperSample16x, 1.0f,
      new Vector3(0.0f, 1.0f, 0.0f), 0.25f, 0.425f);

    /// Type of super-sampling for the field's rendering.
    public SuperSampleSDF SuperSampleSDF;

    /// Distance that was used for generating the field.
    public float SignedFieldDistance;

    /// Color offset in YCH color space for rendering the shape's outline.
    public Vector3 OutlineOffsetSDF;

    /// Minimum field distance for the shape's outline.
    public float OutlineDistanceMinSDF;

    /// Maximum field distance for the shape's outline.
    public float OutlineDistanceMaxSDF;
  }

  /// Sampler parameters that can be easily configured by the canvas.
  public struct CanvasSamplerState
  {
    /// Creates canvas sampler parameters with the given values.
    public CanvasSamplerState(TextureFilter filterMin, TextureFilter filterMag,
      TextureFilter filterMip = TextureFilter.None, TextureAddress addressU = TextureAddress.Wrap,
      TextureAddress addressV = TextureAddress.Wrap, uint borderColor = 0xFFFFFFFFu)
    {
      FilterMin = filterMin;
      FilterMag = filterMag;
      FilterMip = filterMip;
      AddressU = addressU;
      AddressV = addressV;
      BorderColor = borderColor;
    }

    /// Internal default canvas sampler parameters.
    private static readonly CanvasSamplerState _default = new(TextureFilter.Nearest, TextureFilter.Nearest,
      TextureFilter.None, TextureAddress.Wrap, TextureAddress.Wrap, 0xFFFFFFFFu);

    /// Returns default canvas sampler parameters.
    public static CanvasSamplerState Default => _default;

    /// Minification texture filtering.
    public TextureFilter FilterMin;

    /// Magnification texture filtering.
    public TextureFilter FilterMag;

    /// Mipmapping texture filtering.
    public TextureFilter FilterMip;

    /// Horizontal texture coordinate addressing.
    public TextureAddress AddressU;

    /// Vertical texture coordinate addressing.
    public TextureAddress AddressV;

    /// Special color constant to be used for TextureAddress::Border addressing mode.
    public uint BorderColor;
  }

  /// An image region defined by its texture number and bounding rectangle on that texture.
  public struct ImageRegion
  {
    // Modifier flags that can be combined together.

    /// Flip region vertically.
    public const uint Flip = 0x01u;

    /// Mirror region horizontally.
    public const uint Mirror = 0x02u;

    /// Rotate region by 90 degrees clockwise.
    public const uint Rotate = 0x04u;

    /// Creates new image region structure with the given values.
    public ImageRegion(int left, int top, int width, int height, int index)
    {
      Left = (ushort)left;
      Top = (ushort)top;
      Width = (ushort)width;
      Height = (ushort)height;
      Index = (ushort)index;
    }

    /// Left position of the region.
    public ushort Left;

    /// Top position of the region.
    public ushort Top;

    /// Width of the region.
    public ushort Width;

    /// Height of the region.
    public ushort Height;

    /// Texture index associated with this region.
    public ushort Index;
  }

  /// Weight of the font (apparent thickness of glyphs).
  public enum FontWeight : byte
  {
    /// Letters should appear as thin as technically possible.
    Thin,

    /// Letters should appear very thin.
    ExtraLight,

    /// Letters should appear even thinner.
    Light,

    /// Letters should have slightly lighter thickness.
    SemiLight,

    /// Letters should appear normal (default thickness).
    Normal,

    /// Letters should have medium thicness, which is slightly above than normal.
    Medium,

    /// Letters should appear semi-bold.
    SemiBold,

    /// Letters should appear as bold.
    Bold,

    /// Letters should appear as extra thick.
    ExtraBold,

    /// Letters should appear very thick.
    Heavy,

    /// Letters should appear as thick as technically possible.
    ExtraHeavy
  }

  /// Relative width of the font.
  public enum FontStretch : byte
  {
    /// Ultra-condensed width.
    UltraCondensed,

    /// Extra-condensed width.
    ExtraCondensed,

    /// Condensed width.
    Condensed,

    /// Semi-condensed width.
    SemiCondensed,

    /// Normal width.
    Normal,

    /// Semi-expanded width.
    SemiExpanded,

    /// Expanded width.
    Expanded,

    /// Extra-expanded width.
    ExtraExpanded,

    /// Ultra-expanded width.
    UltraExpanded
  }

  /// Font slant styles.
  public enum FontSlant : byte
  {
    /// Upright font.
    None,

    /// Slanted font in a roman style.
    Oblique,

    /// Slanted in an italic style.
    Italic
  }

  /// Border that outlines text glyph's shapes.
  public enum FontBorder : byte
  {
    /// No border will appear around letters.
    None,

    /// A light border will appear around letters.
    Normal,

    /// A semi-heavy border will appear around letters.
    SemiHeavy,

    /// A heavy border will appear around letters.
    Heavy
  }

  /// Font attribute flags that define some visual characteristics.
  public struct FontAttribute
  {
    /// Flip region vertically.
    public const byte Underline = 0x01;

    /// Font with strike-out text.
    public const byte StrikeOut = 0x02;
  }

  /// Text alignment when drawing with certain functions.
  public enum TextAlignment : byte
  {
    /// Text should be aligned to the beginning (either top or left depending on context).
    Start,

    /// Text should be centered in the middle.
    Middle,

    /// Text should be aligned to the end (either bottom or right depending on context).
    End
  }

  /// Individual text entry that will appear as rendered.
  public struct TextEntryRect
  {
    /// Starting character position inside the text (for Unicode, first byte).
    public nint Position;

    /// Character's rectangle.
    public RectF Rectangle;
  }

  /// Modifier attributes that can be applied to the rendered text.
  public struct TextRenderModifiers
  {
    /// Creates new text rendering modifier parameters with the given values.
    public TextRenderModifiers(float scale, float interleave = 0.0f, float verticalSpace = 0.0f,
      BlendingEffect effect = BlendingEffect.Undefined)
    {
      Scale = scale;
      Interleave = interleave;
      VerticalSpace = verticalSpace;
      Effect = effect;
    }

    /// Global font scale that is applied to the whole rendered text. A default value of zero means that font
    /// scale will not be modified. Using values other than zero or one would likely result in not
    /// pixel-perfect text rendering, appearing blurry. However, this can be used for real-time text
    /// animations.
    public float Scale;

    /// Global spacing that will be added horizontally between text letters. This can be used to expand or
    /// shrink the text.
    public float Interleave;

    /// Global spacing that will be added vertically when drawing multiple lines of text.
    public float VerticalSpace;

    /// Blending effect to use (if left \c undefined, \c normal blending effect will be used).
    public BlendingEffect Effect;
  }

  /// Attributes and characteristics that define how font glyphs are rasterized.
  public struct FontEffect
  {
    /// Creates font effect structure with the given values.
    public FontEffect(float fillBrightness, float fillOpacity, FontBorder borderType, float borderThickness,
      float borderBrightness, float borderOpacity, float shadowSmoothness, Vector2 shadowDistance,
      float shadowBrightness, float shadowOpacity, float signedFieldDistance)
    {
      FillBrightness = fillBrightness;
      FillOpacity = fillOpacity;
      BorderType = borderType;
      BorderThickness = borderThickness;
      BorderBrightness = borderBrightness;
      BorderOpacity = borderOpacity;
      ShadowSmoothness = shadowSmoothness;
      ShadowDistance = shadowDistance;
      ShadowBrightness = shadowBrightness;
      ShadowOpacity = shadowOpacity;
      SignedFieldDistance = signedFieldDistance;
    }

    /// Internal default font effect parameters.
    private static readonly FontEffect _default = new (1.0f, 1.0f, FontBorder.None, 1.0f, 0.25f, 0.75f,
      3.0f, new Vector2(2.0f, 2.0f), 0.15f, 0.0f, 0.0f);

    /// Returns default font effect parameters.
    public static FontEffect Default => _default;

    /// Brightness of the letter's fill in range of [0, 1], where zero means the letter will appear completely
    /// dark and one means that letter will appear completely white.
    public float FillBrightness;

    /// Opacity of the letter's fill in range of [0, 1], where zero means the letter will appear completely
    /// transparent (that is, not appear at all) and one means that the letter will appear completely opaque.
    public float FillOpacity;

    /// Type of border that will appear around the text.
    public FontBorder BorderType;

    /// Thickness of the font's border in pixels.
    public float BorderThickness;

    /// Brightness of the font's border in range of [0, 1], where zero means the border will appear
    /// completely dark and one means that the border will appear completely white.
    public float BorderBrightness;

    /// Opacity of the font's border in range of [0, 1], where zero means the border will appear completely
    /// transparent (that is, not appear at all) and one means that the border will appear completely opaque.
    public float BorderOpacity;

    /// How strong the blur should be applied to letter's shadow (number of steps).
    public float ShadowSmoothness;

    /// Distance between letter and its shadow in pixels.
    public Vector2 ShadowDistance;

    /// Brightness of the letter's shadow in range of [0, 1], where zero means the shadow will appear
    /// completely dark and one means that the shadow will appear completely white.
    public float ShadowBrightness;

    /// Opacity of the letter's shadow in range of [0, 1], where zero means the shadow will appear completely
    /// transparent (that is, not appear at all) and one means that the shadow will appear completely opaque.
    public float ShadowOpacity;

    /// Distance in pixels for generation of Signed Distance Field (SDF) font glyphs. This parameter must be
    /// greater or equal to zero. If the value is not zero, then the font is considered SDF.
    public float SignedFieldDistance;
  }

  /// Parameters that define the appearance and important characteristics of the font.
  public struct FontParameters
  {
    /// Creates new font parameters structure with the given values.
    public FontParameters(string family, float size, FontWeight weight = FontWeight.Normal,
      FontStretch stretch = FontStretch.Normal, FontSlant slant = FontSlant.None, byte attributes = 0)
    {
      FamilyBytes = Encoding.UTF8.GetBytes(family);
      Array.Resize(ref FamilyBytes, 128);

      Size = size;
      Weight = weight;
      Stretch = stretch;
      Slant = slant;
      Attributes = attributes;
      Effect = FontEffect.Default;
    }

    /// Font family (e.g. "Helvetica").
    public string Family
    {
      readonly get => Encoding.UTF8.GetString(FamilyBytes).TrimEnd('\0');

      set
      {
        FamilyBytes = Encoding.UTF8.GetBytes(value);
        Array.Resize(ref FamilyBytes, 128);
      }
    }

    /// Font family described as an array of UTF-8 encoded bytes.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public byte[] FamilyBytes;

    /// Size of the font.
    public float Size;

    /// Font letter weight.
    public FontWeight Weight;

    /// Font letter stretch.
    public FontStretch Stretch;

    /// Font letter slant.
    public FontSlant Slant;

    /// Additional font attributes.
    public byte Attributes;

    /// Effect parameters that contribute to font rasterization.
    public FontEffect Effect;
  }

  /// Notification event regarding mesh loading or saving process. The notification callback must return 0 to
  /// indicate that the process should continue; a non-zero value means that the loading process should be
  /// interrupted.
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  internal delegate int MeshLoadSaveFeedback([MarshalAs(UnmanagedType.LPStr), In] string message,
    int progress, IntPtr user);

  /// Format to be used as target for color dithering.
  public enum ColorDitheringFormat : byte
  {
    /// Red, green and blue channels have 8 bits each (16M colors).
    RGB8,

    /// Red, green and blue channels have 6 bits each (256K colors).
    RGB6,

    /// Red and blue channels have 5 bits each, while green channel has 6 bits (64K colors).
    R5G6B5,

    /// Red, green and blue channels have 4 bits each (4K colors).
    RGB4,

    /// Red and green channels have 3 bits each, while blue channel has 2 bits (256 colors).
    RG3B2
  }

  /// Defines type of formula used in fog calculation.
  public enum FogFormula : byte
  {
    /// Fog calculated as (far - d) / (far - near).
    Linear,

    /// Fog calculated as c x e^(-(d x b)^2).
    Exponential,

    /// Ground fog with linear density and exponential depth.
    Ground
  }

  /// Defines how distance is calculated for depth fog.
  public enum DepthFogDistance : byte
  {
    /// Distance is based on depth.
    ZBased,

    /// Distance is relative to camera position.
    EyeRelative
  }

  /// Structure containing spatial fog characteristics.
  public struct FogParameters
  {
    /// Creates new fog parameters structure with the given values.
    public FogParameters(FloatColor color, float opacity, Vector4 groundPlane, float densityGround,
      float distance, float bias)
    {
      Color = color;
      Opacity = opacity;
      GroundPlane = groundPlane;
      DensityGround = densityGround;
      Distance = distance;
      Bias = bias;
    }

    /// Returns default fog parameters.
    public static FogParameters Default => new(FloatColor.White, 1.0f, Vector4.Zero, 0.003f, 1000.0f, 0.5f);

    /// Fog color.
    public FloatColor Color;

    /// Fog opacity.
    public float Opacity;

    /// Equation of the plane for ground fog.
    public Vector4 GroundPlane;

    /// Ground fog density factor.
    public float DensityGround;

    /// A distance (far plane) for linear fog.
    public float Distance;

    /// A bias for linear fog.
    public float Bias;

    /// An in-scattering parameter for exponential fog.
    public float Scattering { readonly get { return Distance; } set { Distance = value; } }

    /// An extinction parameter for exponential fog.
    public float Extinction { readonly get { return Bias; } set { Bias = value; } }
  }

  /// Lighting technique.
  public enum TechniqueLighting : byte
  {
    /// Traditional Phong lighting.
    Phong,

    /// Minnaert lighting.
    Minnaert,

    /// Cook-Torrance lighting.
    CookTorrance,

    /// Oren-Nayer lighting.
    OrenNayer
  }

  /// Shadow rendering technique.
  public enum TechniqueShadows : byte
  {
    /// No shadows are rendered or used.
    None,

    /// Exponential Shadow Maps (ESM) using a single depth component.
    ESM,

    /// Exponential Shadow Maps (ESM) using two depth components for positive and negative parts.
    ESM_Warp,

    /// Exponential Variance Shadow Maps (EVSM) using four depth components.
    EVSM
  }

  /// Light culling mode for clustered shading.
  public enum ClustersCullingMode : byte
  {
    /// High-quality mode supporting up to 1024 simultaneous lights per cluster.
    Quality,

    /// Performance mode supporting up to 4 simultaneous lights per cluster.
    Performance
  }

  /// Determines the choice of pixel formats for the container.
  public enum TextureFidelity : byte
  {
    /// Use lowest quality texture formats, which may reduce GPU memory consumption and potentially improve
    /// performance slightly at expense of visual quality.
    Low,

    /// Use standard quality texture formats suitable for most common usage scenarios.
    Medium,

    /// High quality texture formats, producing accurate and exceptionally looking images.
    High,

    /// Excessively high quality texture formats, typically useful for generating images to be printed,
    /// screenshots and presentations. This may increase GPU memory consumption and impact performance.
    Extreme
  }

  /// Texture type used in the scene.
  public enum TextureCabinetType : byte
  {
    /// Depth buffer of the scene.
    Depth = 0,

    /// Texture containing information about screen-space normals.
    Normals = 1,

    /// High dynamic range color accumulation buffer.
    ColorHDR = 4,

    /// Color buffer of the scene (non-MSAA).
    Color = 5,

    /// Linear depths (MSAA).
    LinearDepths = 11,

    /// Color accumulation buffer.
    GlassyColor = 12,

    /// Count accumulation buffer.
    GlassyCounts = 13,

    /// Auxiliary texture used for compositioning.
    GlassyComposite = 14
  }

  /// Rendering pass that defines what textures are being used and how they are cleared.
  public enum TextureCabinetPass : byte
  {
    /// Main color scene pass.
    Color,

    /// Order-independent transparency (OIT) post-pass.
    Glassy,

    /// Depth (and normals) pre-pass.
    Depth
  }

  /// Filter type that defienes how textures are processed.
  public enum TextureCabinetFilterType : byte
  {
    /// Ambient occlusion computation.
    Occlusion,

    /// Bloom (glare) effect processing.
    Bloom,

    /// Order-independent transparency (OIT) composition.
    Glassy,

    /// Spatial fog effects for order-independent transparency (OIT) composition.
    GlassyFog
  }

  /// Type of texture used by the scene.
  public enum SceneTextureType : byte
  {
    /// Albedo texture.
    Albedo,

    /// Normal Map texture.
    NormalMap,

    /// Displacement Map texture for Parallax Mapping technique.
    ParallaxMap
  }

  /// Type of sampler used by the scene.
  public enum SceneSamplerType : byte
  {
    /// Albedo sampler.
    Albedo,

    /// Normal Map sampler.
    NormalMap,

    /// Displacement Map sampler for Parallax Mapping technique.
    ParallaxMap,

    /// Shadow Map sampler.
    ShadowMap
  }

  /// Parameters that define how shadows are rendered.
  public struct ShadowParameters
  {
    /// Creates new shadow parameters with the given values.
    public ShadowParameters(float exponent1, float exponent2, float variance, float bleedSigma, float bias,
      float blurSigma, int blurSamples)
    {
      Exponent1 = exponent1;
      Exponent2 = exponent2;
      Variance = variance;
      BleedSigma = bleedSigma;
      Bias = bias;
      BlurSigma = blurSigma;
      BlurSamples = blurSamples;
    }

    /// Returns default shadow parameters.
    public static ShadowParameters Default => new(40.0f, 5.0f, 1e-7f, 0.05f, 0.25f, 2.0f, 9);

    /// Primary exponent for ESM and EVSM techniques.
    public float Exponent1;

    /// Secondary exponent for ESM and EVSM techniques.
    public float Exponent2;

    /// Maximum variance delimiter used with VSM and EVSM techniques.
    public float Variance;

    /// Light bleeding sigma for reducing light bleeding artifacts with VSM and EVSM techniques.
    public float BleedSigma;

    /// Bias parameter that is applied to depth derivatives in VSM technique.
    public float Bias;

    /// Sigma value for shadow map's gaussian blur.
    public float BlurSigma;

    /// Number of samples for shadow map's gaussian blur.
    public int BlurSamples;
  }

  /// Parameters that define behavior of tone-mapping and bloom effects.
  public struct ToneMappingBloom
  {
    /// Creates tone-mapping and bloom parameters with the given values.
    public ToneMappingBloom(float bloomThreshold, float bloomGamma, Vector3 bloomCoefficients,
      float bloomColorShift, float bloomBlurSigma, int bloomBlurSamples, float toneWhite,
      Vector3 toneFactors, float frostedPower, float glassyBuckets)
    {
      BloomThreshold = bloomThreshold;
      BloomGamma = bloomGamma;
      BloomCoefficients = bloomCoefficients;
      BloomColorShift = bloomColorShift;
      BloomBlurSigma = bloomBlurSigma;
      BloomBlurSamples = bloomBlurSamples;
      ToneWhite = toneWhite;
      ToneFactors = toneFactors;
      FrostedPower = frostedPower;
      GlassyBuckets = glassyBuckets;
    }

    /// Returns default tone-mapping and bloom parameters.
    public static ToneMappingBloom Default => new(1.0f, 0.45454546f, new Vector3(0.33333334f), 0.75f, 3.0f,
      15, 1.0f, new Vector3(0.29889531f, 0.58662247f, 0.11448222f), 2.0f, 4.0f);

    /// Amount to be subtracted from initial HDR colors to determine bloom.
    public float BloomThreshold;

    /// Inverse gamma power to adjust the bloom color after threshold.
    public float BloomGamma;

    /// Grayscale coefficients for red, green and blue components.
    public Vector3 BloomCoefficients;

    /// Amount of color to shift into grayscale.
    public float BloomColorShift;

    /// Sigma value of Gaussian Blur for bloom pixels.
    public float BloomBlurSigma;

    /// Number of bloom pixels to sample during Gaussian blur.
    public int BloomBlurSamples;

    /// Maximum allowed level of white for tone-mapping.
    public float ToneWhite;

    /// Conversion coefficients to calculate Luma from RGB during tone-mapping.
    public Vector3 ToneFactors;

    /// Power used to adjust the curve of frosted glass equation.
    public float FrostedPower;

    /// Number of buckets per pixel for OIT technique.
    public float GlassyBuckets;
  }

  /// Parameters that define how ambient occlusion is performed.
  public struct AmbientOcclusionParameters
  {
    /// Creates new ambient occlusion parameters with the given values.
    public AmbientOcclusionParameters(float radius, int samples, float attenuation, float contrast,
      float depthBias, float kernelBias, float blurSigma, float blurFallOff, float strength)
    {
      Radius = radius;
      Samples = samples;
      Attenuation = attenuation;
      Contrast = contrast;
      DepthBias = depthBias;
      KernelBias = kernelBias;
      BlurSigma = blurSigma;
      BlurFallOff = blurFallOff;
      Strength = strength;
    }

    /// Returns default ambient occlusion parameters.
    public static AmbientOcclusionParameters Default => new(16.0f, 64, 1.0f, 3.0f, 0.001f, 0.02f,
      2.0f, 1.0f, 0.75f);

    /// Radius of the occlusion.
    public float Radius;

    /// Number of kernel samples.
    public int Samples;

    /// Linear attenuation.
    public float Attenuation;

    /// Contrast of the occlusion.
    public float Contrast;

    /// Bias value to resolve depth precision issues.
    public float DepthBias;

    /// Bias value to prevent sampling close to tangent surface.
    public float KernelBias;

    /// Sigma coefficient for blur filter.
    public float BlurSigma;

    /// Fall-off coefficient for detecting depth discontinuities in blur filter.
    public float BlurFallOff;

    /// Strength of the effect.
    public float Strength;
  }

  /// Parameters that define how parallax mapping is performed.
  public struct ParallaxMappingParameters
  {
    /// Creates new parallax mapping parameters with the given values.
    public ParallaxMappingParameters(float scale, int samplesMin, int samplesMax, float occlusion)
    {
      Scale = scale;
      SamplesMin = samplesMin;
      SamplesMax = samplesMax;
      Occlusion = occlusion;
    }

    /// Returns default parallax mapping parameters.
    public static ParallaxMappingParameters Default => new(0.1f, 8, 32, 0.75f);

    /// Scale that defines how height value from parallax map translates into 3D depth.
    public float Scale;

    /// Minimum number of samples to read per pixel.
    public int SamplesMin;

    /// Maximum number of samples to read per pixel.
    public int SamplesMax;

    /// Occlusion strength applied from Occlusion Map (alpha-channel of Normal Map).
    public float Occlusion;
  }

  /// Light source parameters in 3D scene.
  public struct SceneLight
  {
    /// Creates a new light structure with the given values.
    public SceneLight(FloatColorRGB ambientColor, FloatColorRGB albedoColor, FloatColorRGB specularColor,
      Vector3 position, Vector3 direction, float specularExponent = 1.0f, float intensity = 1.0f,
      float attenuationStart = float.MaxValue, float attenuationEnd = float.MaxValue,
      float angle = (float)Math.PI, float angleCutoff = (float)Math.PI, int shadowCaster = -1,
      uint bitmask = 0, IntPtr payload = new IntPtr())
    {
      AmbientColor = ambientColor;
      AlbedoColor = albedoColor;
      SpecularColor = specularColor;
      Position = position;
      Direction = direction;
      SpecularExponent = specularExponent;
      Intensity = intensity;
      AttenuationStart = attenuationStart;
      AttenuationEnd = attenuationEnd;
      Angle = angle;
      AngleCutoff = angleCutoff;
      ShadowCaster = shadowCaster;
      Bitmask = bitmask;
      Reserved = 0;
      Payload = payload;
    }

    /// Internal default light parameters.
    private static readonly SceneLight _default = new (new FloatColorRGB(0.0f, 0.0f, 0.0f),
      new FloatColorRGB(1.0f, 1.0f, 1.0f), new FloatColorRGB(1.0f, 1.0f, 1.0f),
      new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 0.0f), 1.0f, 1.0f, float.MaxValue,
      float.MaxValue, (float)Math.PI, (float)Math.PI, -1, 0);

    /// Returns default light parameters.
    public static SceneLight Default => _default;

    /// Ambient color.
    public FloatColorRGB AmbientColor;

    /// Range at which light attenuation starts (FLT_MAX means no attenuation should be applied).
    public float AttenuationStart;

    /// Albedo color.
    public FloatColorRGB AlbedoColor;

    /// Range at which light attenuation ends. This must be equal to or higher than \c attenuationStart.
    public float AttenuationEnd;

    /// Specular color.
    public FloatColorRGB SpecularColor;

    /// Exponent for specular light reflections.
    public float SpecularExponent;

    /// Position of the light source.
    public Vector3 Position;

    /// Intensity of the light.
    public float Intensity;

    /// Direction of the light source (non-zero value indicates a spotlight, zero values means omni-light).
    public Vector3 Direction;

    /// Angle at which spotlight starts to fade in range of [0, PI).
    public float Angle;

    /// Angle after which spotlight is completely dark. This should be equal to or higher than \c angle.
    public float AngleCutoff;

    /// Index of the shadow caster associated with the light source.
    /// A value of -1 indicates light source does not cast shadows.
    public int ShadowCaster;

    /// Bitmask that defines what objects are affected by this light.
    /// A value of zero means that light affects all objects.
    public uint Bitmask;

    /// Reserved, must be set to zero.
    public uint Reserved;

    /// Custom payload value.
    public IntPtr Payload;
  }

  /// Material that describes a particular object in 3D world.
  public struct ObjectMaterial
  {
    /// Creates new instance of object material with the given values.
    public ObjectMaterial(TechniqueLighting technique, FloatColorRGB ambientColor, FloatColor albedoColor,
      FloatColorRGB specularColor, float specularExponent, FloatColorRGB emissiveColor, Vector3 roughness,
      float shadows = 0.5f, float occlusion = 0.0f, uint bitmask = 0, float frostedGlass = 0.0f,
      IntPtr payload = new IntPtr())
    {
      Technique = technique;
      AmbientColor = ambientColor;
      AlbedoColor = albedoColor;
      SpecularColor = specularColor;
      SpecularExponent = specularExponent;
      EmissiveColor = emissiveColor;
      Roughness = roughness;
      Shadows = shadows;
      Occlusion = occlusion;
      Bitmask = bitmask;
      FrostedGlass = frostedGlass;
      Payload = payload;
    }

    /// Internal material with default parameters.
    private static readonly ObjectMaterial _default = new (TechniqueLighting.Phong,
      new FloatColorRGB(0.0f, 0.0f, 0.0f), new FloatColor(1.0f, 1.0f, 1.0f),
      new FloatColorRGB(0.0f, 0.0f, 0.0f), 4.0f, new FloatColorRGB(0.0f, 0.0f, 0.0f),
      new Vector3(0.8f, 1.2f, 0.4f), 0.5f, 0.0f, 0, 0.0f, new IntPtr());

    /// Returns material with default parameters.
    public static ObjectMaterial Default => _default;

    /// Technique that describes how light is reflected off the object's surface.
    public TechniqueLighting Technique;

    /// Ambient color that is always received by the object regardless the position of light.
    public FloatColorRGB AmbientColor;

    /// Strength of received shadows. A value of zero means no shadows will be received.
    public float Shadows;

    /// Albedo color, where alpha-channel is typically a Bloom Factor (glare from strong reflections).
    public FloatColor AlbedoColor;

    /// Specular color, which is added depending on reflected vector from material's surface.
    public FloatColorRGB SpecularColor;

    /// Specular Exponent that defines how short or wide specular reflection appears.
    public float SpecularExponent;

    /// Emissive color, which is always added before any lights.
    public FloatColorRGB EmissiveColor;

    /// Strength of ambient occlusion. A value of zero means no occlusion will be received.
    public float Occlusion;

    /// Roughness of the object's surface that defines how light is reflected.
    public Vector3 Roughness;

    /// A bitmask that defines what lights affect this object.
    /// A value of zero means that this object is affected by all lights.
    public uint Bitmask;

    /// Strength of Frosted Glass effect when rendering order-independent transparency.
    public float FrostedGlass;

    /// Custom payload value.
    public IntPtr Payload;
  }

  /// Parameters that define the appearance of waves simulation.
  public struct OceanWavesParameters
  {
    /// Creates new ocean wave simulation parameters with the give nvalues.
    public OceanWavesParameters(int resolution, Vector2 wind, float waveSize, float choppiness)
    {
      Resolution = resolution;
      Wind = wind;
      WaveSize = waveSize;
      Choppiness = choppiness;
    }

    /// Returns default ocean wave simulation parameters.
    public static OceanWavesParameters Default => new(512, new Vector2(10.0f, 10.0f), 250.0f, 1.5f);

    /// Resolution of the simulation textures.
    public int Resolution;

    /// General direction in which the waves propagate.
    public Vector2 Wind;

    /// Size of the generated waves.
    public float WaveSize;

    /// Choppiness of the generated waves.
    public float Choppiness;
  }

  /// Material that describes ocean water surface in a 3D simulation.
  public struct OceanMaterial
  {
    /// Creates new ocean material with the given values.
    public OceanMaterial(FloatColorRGB ambientColor, float fresnel, FloatColor albedoColor,
      FloatColorRGB specularColor, float specularExponent, FloatColorRGB emissiveColor, float extinction,
      float shadows, uint bitmask)
    {
      AmbientColor = ambientColor;
      Fresnel = fresnel;
      AlbedoColor = albedoColor;
      SpecularColor = specularColor;
      SpecularExponent = specularExponent;
      EmissiveColor = emissiveColor;
      Extinction = extinction;
      Shadows = shadows;
      Bitmask = bitmask;
    }

    /// Internal default ocean material.
    private static readonly OceanMaterial _default = new(new FloatColorRGB(0.002941f, 0.083333f, 0.117647f),
      0.5f, new FloatColor(0.011765f, 0.333333f, 0.470588f, 1.0f), new FloatColorRGB(1.0f, 1.0f, 1.0f),
      10.0f, new FloatColorRGB(0.0f, 0.0f, 0.0f), 0.023f, 0.75f, 0);

    /// Returns default ocean material.
    public static OceanMaterial Default => _default;

    /// Ambient color.
    public FloatColorRGB AmbientColor;

    /// Fresnel Coefficient (reflectance at normal incidence).
    public float Fresnel;

    /// Ambient color that is always received by the ocean regardless the position of light.
    public FloatColor AlbedoColor;

    /// Specular color, which is added depending on reflected vector from ocean's surface.
    public FloatColorRGB SpecularColor;

    /// Specular color, which is added depending on reflected vector from ocean's surface.
    public float SpecularExponent;

    /// Emissive color, which is always added before any lights.
    public FloatColorRGB EmissiveColor;

    /// Extinction of the ocean's surface, which determines its transparency.
    public float Extinction;

    /// Strength of a shadows when projected to the object's surface.
    /// A value of zero means shadows are not rendered and/or ignored.
    public float Shadows;

    /// A bitmask that defines what lights affect this object.
    /// A value of zero means that this object is affected by all lights.
    public uint Bitmask;
  }

  /// Parameters that define how selection highlight technique is performed.
  public struct SelectionHighlightParameters
  {
    /// Creates new selection highlight parameters with the given values.
    public SelectionHighlightParameters(FloatColorRGB outlineColor, float outlineStart, float glowIntensity,
      int blurPasses, Vector2 blurOffset)
    {
      OutlineColor = outlineColor;
      OutlineStart = outlineStart;
      GlowIntensity = glowIntensity;
      BlurPasses = blurPasses;
      BlurOffset = blurOffset;
    }

    /// Returns default selection highlight parameters.
    public static SelectionHighlightParameters Default => new(FloatColorRGB.Black, 2.0f / 3.0f, 3.0f, 2,
      Vector2.One);

    /// Color of the selection glow's outline.
    public FloatColorRGB OutlineColor;

    /// At which position outline begins (values of 1 or higher mean no outline).
    public float OutlineStart;

    /// How intense should the glow appear.
    public float GlowIntensity;

    /// Number of passes for the blur effect.
    public int BlurPasses;

    /// Offset for the blur effect.
    public Vector2 BlurOffset;
  }

  /// Texture type used by the technique.
  public enum SelectionHighlightTextureType : byte
  {
    /// Texture that contains the selection highlight, to be rendered on top of the scene.
    Highlight,

    /// Texture that contains the highlight mask, that can be optionally rendered on top of the scene.
    HighlightMask
  }

  /// Type of the mesh meta-tag.
  public struct MeshMetaTagType
  {
    /// Tag type is not determined.
    public const byte Indeterminate = 0;

    /// Tag represents a geometry group.
    public const byte Geometry = 1;

    /// Tag represents an object group.
    public const byte Object = 2;
  }

  /// A portion of the mesh corresponding to a particular tag.
  public struct MeshMetaTagPortion
  {
    /// Creates a new portion of mesh meta-tag.
    public MeshMetaTagPortion(int firstIndex, int indexCount, int firstVertex, int vertexCount,
      Vector3 boundsMin, Vector3 boundsMax)
    {
      FirstIndex = firstIndex;
      IndexCount = indexCount;
      FirstVertex = firstVertex;
      VertexCount = vertexCount;
      BoundsMin = boundsMin;
      BoundsMax = boundsMax;
    }

    /// Starting index of the tag.
    public int FirstIndex;

    /// Number of indices of the tag.
    public int IndexCount;

    /// Starting vertex of the tag.
    public int FirstVertex;

    /// Number of vertices of the tag.
    public int VertexCount;

    /// Tag's minimum boundaries.
    public Vector3 BoundsMin;

    /// Tag's maximum boundaries.
    public Vector3 BoundsMax;
  }

  /// Shading parameters for scene mesh material.
  public struct SceneMeshMaterialShading
  {
    /// Creates a structure with the given values.
    public SceneMeshMaterialShading(FloatColorRGB ambient, float bloom, FloatColor diffuse,
      FloatColorRGB specular, float specularExponent, FloatColorRGB emissive, int lighting,
      Vector3 roughness)
    {
      Ambient = ambient;
      Bloom = bloom;
      Diffuse = diffuse;
      Specular = specular;
      SpecularExponent = specularExponent;
      Emissive = emissive;
      Lighting = lighting;
      Roughness = roughness;
      Reserved = 0.0f;
    }

    /// Ambient color.
    /// If one of the values is NaN or Infinity, then ambient color should be deduced from diffuse color.
    public FloatColorRGB Ambient;

    /// Bloom (glare) factor.
    /// If this value is NaN or Infinity, then bloom factor is deduced from object material.
    public float Bloom;

    /// Diffuse color (alpha-channel denotes transparency).
    public FloatColor Diffuse;

    /// Specular color.
    public FloatColorRGB Specular;

    /// Specular exponent.
    public float SpecularExponent;

    /// Emissive color.
    public FloatColorRGB Emissive;

    /// Lighting (0: Compatibility, 1: Default, 2: Phong, 3: Minnaert, 4: Cook-Torrance, 5: Oren-Nayar)
    /// Compatibility mode ignores ambient color, specular color and specular exponent: ambient color is
    /// deduced from diffuse color, whereas specular color and exponent are taken from object material.
    /// Default mode considers all colors and factors, but multiplies them with the corresponding values from
    /// object material. Starting at value of 2 (Phong) and higher, all colors and factors are considered and
    /// they are considered exclusively, overriding corresponding parameters from object material.
    public int Lighting;

    /// Roughness values for non-Phong lighting models.
    /// If a certain value is NaN or Infinity, then that value is deduced from object material.
    public Vector3 Roughness;

    /// Reserved value (should be set to zero).
    public float Reserved;
  }

  /// A range of indices in the mesh that a material applies to.
  public struct SceneMeshMaterialRange
  {
    /// Creates a structure with the given values.
    public SceneMeshMaterialRange(int indexStart, int indexCount)
    {
      IndexStart = indexStart;
      IndexCount = indexCount;
    }

    /// Starting index.
    public int IndexStart;

    /// Number of indices.
    public int IndexCount;
  }

  /// Type of texture used in scene mesh material.
  public enum SceneMeshTexture : byte
  {
    /// Diffuse color texture.
    Diffuse = 0,

    /// Normal-mapping texture.
    Normals = 1,

    /// Parallax-mapping texture.
    Parallax = 2
  }

  /// Type of latch used in the 3D scene mesh.
  public struct SceneMeshLatchType
  {
    /// Bone joint connection.
    public const byte Joint = 0x01;

    /// Movement waypoint.
    public const byte Waypoint = 0x02;
  }

  /// A latch in 3D scene mesh, which describes a bone joint connection or a movement waypoint.
  public struct SceneMeshLatch
  {
    /// Name of the latch.
    public string Name
    {
      readonly get => Encoding.UTF8.GetString(NameBytes).TrimEnd('\0');

      set
      {
        NameBytes = Encoding.UTF8.GetBytes(value);
        Array.Resize(ref NameBytes, 256);
      }
    }

    /// Name of the latch described as an array of UTF-8 encoded bytes.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public byte[] NameBytes;

    /// Size of the font.
    public Vector3 Position;

    /// Type of the latch.
    public ushort Type;

    /// Group of the latch.
    public ushort Group;

    /// Orientation of the latch.
    public Quaternion Orientation;
  }

  /// Non-exclusive options passed and/or returned from native mesh loader.
  public struct MeshLoadingOption
  {
    /// Material diffuse colors should be mapped to vertex colors.
    public const uint MaterialVertexColor = 0x01;

    /// Assume "MaterialVertexColor" option only when the model would reasonably look the same as if it would
    /// have been rendered with its materials. This requires that all model materials do not use texturing,
    /// have no emissive color, no lighting technique, no bloom factor specified or have these at their
    /// default values.
    public const uint MaterialVertexColorPreferred = 0x02;

    /// One or more material texture could not be loaded.
    public const uint MaterialTextureMissing = 0x80;

    /// Include vertex normals in the exported file.
    public const uint ExportNormals = 0x100;

    /// Include vertex tangents in the exported file.
    public const uint ExportTangents = 0x200;

    /// Include vertex texture coordinates in the exported file.
    public const uint ExportTexCoords = 0x400;

    /// Include vertex colors in the exported file.
    public const uint ExportColors = 0x800;

    /// Include vertex weights in the exported file.
    public const uint ExportWeights = 0x1000;

    /// Strip names for geometry and object nodes when saving in OBJ format.
    public const uint StripGeometryNames = 0x2000;
  }

  /// Cumulative options that can be passed to one of scene mesh "AutoDraw" helper functions.
  public struct AutoDrawOption
  {
    /// Unbind the rendering buffers after issuing draw call. This can help resolve racing conditions under
    /// buggy drivers (mostly OpenGL) at the expense of reduced performance.
    public const uint PostUnbind = 0x01;

    /// Reset scene textures after issuing draw call. For performance reasons, the textures should be reset
    /// after rendering all objects.
    public const uint ResetTextures = 0x02;

    /// Ignore materials integrated into the mesh if such are present, using object material and/or vertex
    /// colors instead. This has no impact on "ObjectSkip___HavingMaterials" options functionality.
    public const uint MaterialIgnore = 0x04;

    /// Alpha-channel from the scene mesh materials should be assigned to alpha-channel of the scene
    /// material (which normally corresponds to bloom factor). This is typically used when rendering
    /// semi-transparent objects.
    public const uint MaterialTransparency = 0x08;

    /// Portions of the mesh that have semi-transparent materials should be skipped.
    public const uint MaterialSkipTransparent = 0x10;

    /// Portions of the mesh that have opaque materials should be skipped.
    public const uint MaterialSkipOpaque = 0x20;

    /// Skips objects that have transparent attribute set.
    public const uint ObjectSkipTransparent = 0x40;

    /// Skips objects that do not have transparent attribute set.
    public const uint ObjectSkipNonTransparent = 0x80;

    /// Skips objects that have mesh materials present.
    public const uint ObjectSkipHavingMaterials = 0x100;

    /// Skips objects that do not have mesh materials present.
    public const uint ObjectSkipNotHavingMaterials = 0x200;

    /// Draws objects that have a highlight color assigned.
    public const uint ObjectHighlighted = 0x400;

    /// Do not use instancing to render multiple objects simultaneously.
    public const uint ObjectDisableInstancing = 0x800;
  }

  /// Type of transform as used by object models.
  public enum ModelTransform : byte
  {
    /// Local object transform.
    Local,

    /// Local Model object transform (for rendering).
    LocalModel,

    /// Local Volume object transform (OOBB Unity Cube).
    LocalVolume,

    /// Global object transform.
    Global,

    /// Global Model object transform (for rendering).
    GlobalModel,

    /// Global Volume object transform (OOBB Unity Cube).
    GlobalVolume
  }

  /// Axis alignment that determines the placement of mesh around its model.
  public enum MeshAlign : byte
  {
    /// Mesh is aligned from the edge of positive axis.
    Positive,

    /// Mesh is aligned in the middle of axis origin.
    Origin,

    /// Mesh is aligned from the edge of negative axis.
    Negative,

    /// Mesh is unaligned on the axis.
    Unaligned
  }

  /// Alignment for all three axes that determine the placement of mesh around its model.
  public struct MeshAligns
  {
    /// Creates mesh alignment structure with the given values.
    public MeshAligns(MeshAlign x, MeshAlign y, MeshAlign z, float bias)
    {
      X = x;
      Y = y;
      Z = z;
      Bias = bias;
    }

    /// Returns default mesh alignment values.
    public static readonly MeshAligns Default = new(MeshAlign.Origin, MeshAlign.Positive,
      MeshAlign.Origin, 0.1f);

    /// Alignment for X axis.
    public MeshAlign X;

    /// Alignment for Y axis.
    public MeshAlign Y;

    /// Alignment for Z axis.
    public MeshAlign Z;

    /// Bias value used for volume size adjustment.
    public float Bias;
  }

  /// Type of comparison applied to an ordered list of objects.
  public enum ObjectModelViewCompare : byte
  {
    /// Objects are compared by their depth.
    Depth,

    /// Objects are compared by their depth in reverse (for rendering transparency without OIT).
    DepthReverse,

    /// Objects are compared first by their order index, then by depth.
    Ordered,

    /// Objects are compared first by their mesh and then by depth.
    Meshes,

    /// Objects are sorted by their instance type id, mesh and then material.
    Objects
  }

  /// Comparison function for a pair of objects in a 3D scene.
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  internal delegate int ObjectModelCompareFunc(IntPtr object1, IntPtr object2, IntPtr user);

  /// Mesh voxel rendering function.
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  internal delegate void MeshVoxelVisualizeFunc([In] ref Vector3 position, [In] ref Vector3 size,
    [In] ref FloatColor color, IntPtr user);

  /// Camera movement/rotation command.
  public enum CameraCommand : byte
  {
    /// Start camera movement on XZ plane.
    Movement,

    /// Start camera dragging.
    Dragging,

    /// Start camera rotation.
    Rotation,

    /// Update camera movement/rotation.
    Update,

    /// Stop camera movement/rotation.
    Stop
  }

  /// Camera position, rotation and distance constraints. If the difference between min and max constraint on
  /// a particular axis is almost zero or less, then no constraint is applied.
  public struct CameraConstraints
  {
    /// Creates new camera constraints with the given values.
    public CameraConstraints(Vector4 positionMin, Vector4 positionMax, Vector4 rotationMin,
      Vector4 rotationMax)
    {
      PositionMin = positionMin;
      PositionMax = positionMax;
      RotationMin = rotationMin;
      RotationMax = rotationMax;
    }

    /// Minimum position allowed for camera positioning. "w" component is a minimum distance constraint.
    public Vector4 PositionMin;

    /// Maximum position allowed for camera positioning. "w" component is a maximum distance constraint.
    public Vector4 PositionMax;

    /// Minimum camera rotation angles. "w" component is a minimum angle for Lenticular printing rotation.
    public Vector4 RotationMin;

    /// Maximum camera rotation angles. "w" component is a maximum angle for Lenticular printing rotation.
    public Vector4 RotationMax;
  }

  /// Application's window state enumeration.
  public enum ApplicationWindowState : byte
  {
    /// Windows appears normally with its title and border.
    Windowed,

    /// Window appears minimized, iconic or hidden.
    Minimized,

    /// Window appears maximized to fill the screen's client area.
    Maximized,

    /// Window appears occupying the entire screen.
    FullScreen
  }

  /// Type of mouse event corresponding to the notification.
  public enum MouseEvent : byte
  {
    /// Mouse button is pressed.
    Down,

    /// Mouse cursor is being moved.
    Move,

    /// Mouse button is de-pressed.
    Up,

    /// Mouse wheel has been rotated up.
    WheelUp,

    /// Mouse wheel has been rotated down.
    WheelDown,

    /// Mouse has entered component's area.
    Enter,

    /// Mouse has left component's area.
    Leave,

    /// Mouse double-click event.
    DoubleClick
  }

  /// Type of mouse button that corresponds to the notification.
  public enum MouseButton : byte
  {
    /// None or unknown button (typically specified during mouse move event).
    None,

    /// Left mouse button.
    Left,

    /// Right mouse button.
    Right,

    /// Middle mouse button.
    Middle
  }

  /// Type of keyboard event corresponding to the notification.
  public enum KeyEvent : byte
  {
    /// Key has been pressed.
    Pressed,

    /// Key has been released.
    Released,

    /// Key is being typed (for Unicode input).
    Typing
  }

  /// Type of application event corresponding to the notification.
  public enum ApplicationEvent : byte
  {
    /// Application has been activated.
    Activate,

    /// Application has been de-activated.
    Deactivate,

    /// Application has been minimized.
    Minimize,

    /// Application has been restored.
    Restore,

    /// DPI changed or user switched between dark/white styles.
    Appearance
  }

  /// Type of file chooser dialog type.
  public enum FileChooserDialog : byte
  {
    /// Open file dialog.
    OpenFile,

    // Save file dialog.
    SaveFile,

    /// Select directory dialog.
    Directory
  }

  /// Storage type for portable key constants.
  public enum Key : byte
  {
    Null = 0x00,
    // 0x01: SOH (Start of Heading)
    Home = 0x02, // STX (Start of Text)
    End = 0x03, // ETX (End of Text)
    // 0x04: EOT (End of Transmission)
    PrintScreen = 0x05, // ENQ (Enquiry)
    // 0x06: ACK (Acknowledge)
    // 0x07: BEL (Bell)
    Backspace = 0x08,
    Tab = 0x09,
    Linefeed = 0x0A, // LF, NL (Newline)
    Clear = 0x0B, // VT (Vertical Tab)
    // 0x0C: FF (NP form feed, new page)
    Return = 0x0D, // Enter, CR (Carriage Return)
    PageUp = 0x0E, // SO (Shift Out)
    PageDown = 0x0F, // SI (Shift In)
    // 0x10: DLE (Data Link Escape)
    CapsLock = 0x11, // DC1 (Device Control 1)
    NumLock = 0x12, // DC2 (Device Control 2)
    Pause = 0x13, // Hold, DC3 (Device Control 3)
    ScrollLock = 0x14, // DC4 (Device Control 4)
    SysReq = 0x15, // SysRq, NAK (Negative Acknowledge)
    // 0x16: SYN (Synchronous Idle)
    // 0x17: ETB (End of Trans. Block)
    Cancel = 0x18,
    // 0x19: EM (End of Medium)
    Insert = 0x1A, // SUB (Substitute)
    Escape = 0x1B,
    Left = 0x1C, // 0x1C: FS (File Separator)
    Up = 0x1D, // 0x1D: GS (Group Separator)
    Right = 0x1E, // 0x1E: RS (Record Separator)
    Down = 0x1F, // 0x1F: US (Unit Separator)
    Space = 0x20,
    // 0x21 - 0x7E: ASCII characters.
    KeyA = 0x61,
    KeyB = 0x62,
    KeyC = 0x63,
    KeyD = 0x64,
    KeyE = 0x65,
    KeyF = 0x66,
    KeyG = 0x67,
    KeyH = 0x68,
    KeyI = 0x69,
    KeyJ = 0x6A,
    KeyK = 0x6B,
    KeyL = 0x6C,
    KeyM = 0x6D,
    KeyN = 0x6E,
    KeyO = 0x6F,
    KeyP = 0x70,
    KeyQ = 0x71,
    KeyR = 0x72,
    KeyS = 0x73,
    KeyT = 0x74,
    KeyU = 0x75,
    KeyV = 0x76,
    KeyW = 0x77,
    KeyX = 0x78,
    KeyY = 0x79,
    KeyZ = 0x7A,
    Delete = 0x7F, // DEL
    // Extended keys
    F1 = 0x80,
    F2 = 0x81,
    F3 = 0x82,
    F4 = 0x83,
    F5 = 0x84,
    F6 = 0x85,
    F7 = 0x86,
    F8 = 0x87,
    F9 = 0x88,
    F10 = 0x89,
    F11 = 0x8A,
    F12 = 0x8B,
    // 0x8C - 0x97 (F13-F24 keys)
    // Control keys
    ShiftLeft = 0x98,
    ShiftRight = 0x99,
    CtrlLeft = 0x9A,
    CtrlRight = 0x9B,
    AltLeft = 0x9C,
    AltRight = 0x9D,
    SuperLeft = 0x9E, // Left Windows key
    SuperRight = 0x9F, // Right Windows key
    // Numpad keys
    Numpad0 = 0xA0,
    Numpad1 = 0xA1,
    Numpad2 = 0xA2,
    Numpad3 = 0xA3,
    Numpad4 = 0xA4,
    Numpad5 = 0xA5,
    Numpad6 = 0xA6,
    Numpad7 = 0xA7,
    Numpad8 = 0xA8,
    Numpad9 = 0xA9,
    // Numpad operators
    Multiply = 0xAA,
    Divide = 0xAB,
    Add = 0xAC,
    Subtract = 0xAD,
    // Numpad misc
    Separator = 0xAE,
    Decimal = 0xAF,
    // 0xB0 - 0xBF: reserved
    // Power keys
    Sleep = 0xC0,
    // 0xC1 - 0xCB: reserved
    VolumeUp = 0xCC,
    VolumeDown = 0xCE,
    VolumeMute = 0xCF,
    // Media playback keys
    MediaNextTrack = 0xD0,
    MediaPrevTrack = 0xD1,
    MediaStop = 0xD2,
    MediaPlayPause = 0xD3,
    // 0xD4 - 0xDF: reserved
    // Misc keys
    Select = 0xE0,
    Print = 0xE1,
    Execute = 0xE2,
    Help = 0xE3,
    Apps = 0xE4, // Applications key
    // 0xE5 - 0xFE: reserved
    // 0xFF: reserved
  }

  /// Application cursor enumeration.
  public enum AppCursor : byte
  {
    /// Blank (invisible) cursor.
    Blank = 0x00,

    /// Standard arrow cursor.
    Arrow = 0x01,

    /// Text selection cursor.
    TextSelect,

    // Vertical text selection cursor.
    TextSelectVertical,

    /// Wait cursor.
    Wait,

    /// Arrow cursor with wait icon.
    ArrowWait,

    /// Crosshair cursor.
    CrossHair,

    /// Cell cursor.
    Cell,

    /// Hyperlink selection cursor.
    LinkSelect,

    /// Not allowed cursor.
    NotAllowed,

    /// Help cursor.
    Help,

    /// Move cursor.
    Move,

    /// Drag cursor.
    Drag,

    /// Dragging cursor.
    Dragging,

    /// Vertical resize cursor.
    ResizeVert,

    /// Horizontal resize cursor.
    ResizeHoriz,

    /// Diagonal north-east south-west resize cursor.
    Resize1,

    /// Diagonal north-west south-east resize cursor.
    Resize2,

    /// Top resize cursor.
    ResizeTop,

    /// Bottom resize cursor.
    ResizeBottom,

    /// Left resize cursor.
    ResizeLeft,

    /// Right resize cursor.
    ResizeRight,

    /// Top/left resize cursor.
    ResizeTopLeft,

    /// Top/right resize cursor.
    ResizeTopRight,

    /// Bottom/right resize cursor.
    ResizeBottomRight,

    /// Bottom/left resize cursor.
    ResizeBottomLeft,

    /// Undefined or unspecified cursor.
    Undefined = 255
  }

  /// Structure that contains all the parameters necessary to create a new application and its window.
  public struct ApplicationConfiguration
  {
    /// Creates a structure with the given values.
    public ApplicationConfiguration(string windowClassName, Point size,
      ApplicationWindowState state = ApplicationWindowState.Windowed, Point? position = null,
      IntPtr instance = new IntPtr(), IntPtr iconSmall = new IntPtr(), IntPtr iconBig = new IntPtr())
    {
      WindowClassNameBytes = Encoding.UTF8.GetBytes(windowClassName);
      Array.Resize(ref WindowClassNameBytes, 128);

      Size = size;
      State = state;
      Position = position ?? new Point(int.MaxValue, int.MaxValue);
      Instance = instance;
      IconSmall = iconSmall;
      IconBig = iconBig;
    }

    /// Name of application window class.
    public string WindowClassName
    {
      readonly get => Encoding.UTF8.GetString(WindowClassNameBytes).TrimEnd('\0');

      set
      {
        WindowClassNameBytes = Encoding.UTF8.GetBytes(value);
        Array.Resize(ref WindowClassNameBytes, 32);
      }
    }

    /// Initial size of the application window.
    public Point Size;

    /// Initial state of application window.
    public ApplicationWindowState State;

    /// Initial position of application window. If both X and Y are set to INT32_MAX, then a default position
    /// will  be used.
    public Point Position;

    /// Handle of application's instance.
    public IntPtr Instance;

    /// Handle of application's "small" icon.
    public IntPtr IconSmall;

    /// Handle of application's "big" icon.
    public IntPtr IconBig;

    /// Nul-terminated string for application class name.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
    public byte[] WindowClassNameBytes;
  }

  /// Events that are invoked by the application. Each of these fields is optional, so if a particular event
  /// is set to null, it will not be invoked and default handler will be used.
  internal struct ApplicationEvents
  {
    /// Basic application event.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void EventFunc(IntPtr application, IntPtr user);

    /// Application creation event.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.U1)]
    public delegate bool BoolFunc(IntPtr application, IntPtr user);

    /// Application mouse handling event.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void MouseFunc(IntPtr application, MouseEvent mouseEvent, MouseButton button,
      [In] ref Point position, IntPtr user);

    /// Application keyboard handling event.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void KeyboardFunc(IntPtr application, KeyEvent keyEvent, int virtualKey, ushort keyCode,
      IntPtr user);

    /// Event function for application status change events.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void StatusFunc(IntPtr application, ApplicationEvent appEvent, IntPtr user);

    /// Custom application message handling event.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void EventHookFunc(IntPtr application, IntPtr eventData, IntPtr user);

    /// Creates a structure with the given values.
    public ApplicationEvents(BoolFunc eventCreate, EventFunc eventDestroy, EventFunc eventRender,
      MouseFunc eventMouse, KeyboardFunc eventKey, StatusFunc eventStatus, BoolFunc eventIdle,
      EventFunc eventResize, EventHookFunc eventHook)
    {
      EventCreate = eventCreate;
      EventDestroy = eventDestroy;
      EventRender = eventRender;
      EventMouse = eventMouse;
      EventKey = eventKey;
      EventStatus = eventStatus;
      EventIdle = eventIdle;
      EventResize = eventResize;
      EventHook = eventHook;
    }

    /// Event invoked during startup to load application resources. If this function returns \c false,
    /// application creation will fail.
    public BoolFunc EventCreate;

    /// Event invoked during application shutdown to release the resources.
    public EventFunc EventDestroy;

    /// Event invoked when application needs to render contents of the window.
    public EventFunc EventRender;

    /// Event invoked when a mouse event has been registered.
    public MouseFunc EventMouse;

    /// Event invoked when a key event has been registered.
    public KeyboardFunc EventKey;

    /// Event invoked when an application status has changed.
    public StatusFunc EventStatus;

    /// Event invoked every time the application is idle.
    public BoolFunc EventIdle;

    /// Event invoked when application window is resized.
    public EventFunc EventResize;

    /// Event hook invoked to process application events.
    public EventHookFunc EventHook;
  }

  /// Widget's external callback event type.
  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  [return: MarshalAs(UnmanagedType.U1)]
  internal delegate bool WidgetExternalEvent(IntPtr widget,
    [MarshalAs(UnmanagedType.LPStr), In] string _event, IntPtr user);

  /// Alignment of the widget respective its parent.
  public enum WidgetAlignment : byte
  {
    /// No alignment is applied to widget.
    None,

    /// Widget occupies the entire client area.
    Client,

    /// Widget is placed on the left occupying the entire client height.
    Left,

    /// Widget is placed on the top occupying the entire client width.
    Top,

    /// Widget is placed on the right occupying the entire client height.
    Right,

    /// Widget is placed on the bottom occupying the entire client width.
    Bottom
  }

  /// Type of property that defines its purpose.
  public enum WidgetPropertyType : byte
  {
    /// Unknown or undefined type. This may also refer to an event rather than property.
    None,

    /// 32-bit signed integer.
    Integer,

    /// 64-bit signed integer.
    Int64,

    /// 32-bit floating-point type.
    Float,

    /// 64-bit floating-point type.
    Real,

    /// Boolean value (either yes/no or true/false).
    Boolean,

    /// Floating-point 2D vector.
    Point,

    /// Floating-point 3D vector.
    Vector,

    /// Rectangle defined by four floating-point values: left, top, width and height.
    Rect,

    /// Margins defined by four floating-point values: left, top, right and bottom.
    Margins,

    /// Color value.
    Color,

    /// A pair of two colors.
    ColorPair,

    /// A set of four colors.
    ColorRect,

    /// Enumeration (e.g. alignment) that is represented as a single byte.
    Enumeration,

    /// UTF-8 encoded string.
    String,

    /// Text font.
    Font
  }

  /// Behavior of the property.
  public enum WidgetPropertyBehavior : byte
  {
    /// Standard property behavior.
    Normal,

    /// Property wraps an existing variable of the parent.
    Static,

    /// Property is accessed through callback events.
    Indirect,

    /// Property is considered temporary or "volatile".
    Volatile,

    /// Property represents an event.
    Event
  }

  /// Information about a widget property.
  public struct WidgetProperty
  {
    /// Name of the property.
    public string Name
    {
      readonly get => Encoding.UTF8.GetString(NameBytes).TrimEnd('\0');

      set
      {
        NameBytes = Encoding.UTF8.GetBytes(value);
        Array.Resize(ref NameBytes, 256);
      }
    }

    /// Name of the property described as an array of UTF-8 encoded bytes.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public byte[] NameBytes;

    /// Data type of the property.
    public WidgetPropertyType Type;

    /// Behavior of the property.
    public WidgetPropertyBehavior Behavior;

    /// Additional attributes of the property.
    public ushort Attributes;

    /// Location of the property in the list of existing properties. This is an opaque value that loosely
    /// determines next property to be iterated. The actual value is temporary and valid only during
    /// continuous iteration. Any change to properties invalidates all previous iteration values.
    /// A value of zero indicates an invalid or "undefined" location.
    public ushort Location;

    /// Reserved bits, must be set to zero.
    public ushort Reserved;

    /// Contents of the property.
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 184)]
    public byte[] DataBytes;
  }

  /// Texture type used for the compositioning.
  public enum WidgetManagerTextureType : byte
  {
    /// Texture with multisampling that is used for rendering using canvas.
    Canvas,

    /// Final compositioning texture.
    Screen,

    /// Texture containing relief stripes.
    Stripes
  }

  /// Widget manager cumulative attribute flags that define its behavior.
  public struct WidgetManagerAttribute
  {
    /// Widgets support of composition effects such as glass and blur.
    public const uint Composition = 0x01;

    /// Design mode bit that enables additional functionality for creating interfaces on the fly.
    public const uint Design = 0x80;
  }

  public partial struct Utility
  {
    /// Converts Windows Forms button to UI button type.
    public static MouseButton ToUI(MouseButtons button) => button switch
    {
      MouseButtons.Left => MouseButton.Left,
      MouseButtons.Right => MouseButton.Right,
      MouseButtons.Middle => MouseButton.Middle,
      _ => MouseButton.None
    };

    /// Converts Windows Forms key code to UI key enumeration.
    public static Key ToUI(Keys key) => key switch
    {
      Keys.Home => Key.Home,
      Keys.End => Key.End,
      Keys.PrintScreen => Key.PrintScreen,
      Keys.Back => Key.Backspace,
      Keys.Tab => Key.Tab,
      Keys.LineFeed => Key.Linefeed,
      Keys.Clear => Key.Clear,
      Keys.Return => Key.Return,
      Keys.PageUp => Key.PageUp,
      Keys.PageDown => Key.PageDown,
      Keys.CapsLock => Key.CapsLock,
      Keys.NumLock => Key.NumLock,
      Keys.Pause => Key.Pause,
      Keys.Scroll => Key.ScrollLock,
      Keys.Cancel => Key.Cancel,
      Keys.Insert => Key.Insert,
      Keys.Escape => Key.Escape,
      Keys.Left => Key.Left,
      Keys.Up => Key.Up,
      Keys.Right => Key.Right,
      Keys.Down => Key.Down,
      Keys.Space => Key.Space,
      Keys.Delete => Key.Delete,
      Keys.LShiftKey => Key.ShiftLeft,
      Keys.RShiftKey => Key.ShiftRight,
      Keys.LControlKey => Key.CtrlLeft,
      Keys.RControlKey => Key.CtrlRight,
      Keys.LMenu => Key.AltLeft,
      Keys.RMenu => Key.AltRight,
      Keys.ShiftKey => Key.ShiftLeft,
      Keys.ControlKey => Key.CtrlLeft,
//      Keys.Alt => Key.AltLeft,
      Keys.LWin => Key.SuperLeft,
      Keys.RWin => Key.SuperRight,
      Keys.Multiply => Key.Multiply,
      Keys.Divide => Key.Divide,
      Keys.Add => Key.Add,
      Keys.Subtract => Key.Subtract,
      Keys.Separator => Key.Separator,
      Keys.Decimal => Key.Decimal,
      Keys.Sleep => Key.Sleep,
      Keys.VolumeUp => Key.VolumeUp,
      Keys.VolumeDown => Key.VolumeDown,
      Keys.VolumeMute => Key.VolumeMute,
      Keys.MediaNextTrack => Key.MediaNextTrack,
      Keys.MediaPreviousTrack => Key.MediaPrevTrack,
      Keys.MediaStop => Key.MediaStop,
      Keys.MediaPlayPause => Key.MediaPlayPause,
      Keys.Select => Key.Select,
      Keys.Print => Key.Print,
      Keys.Execute => Key.Execute,
      Keys.Help => Key.Help,
      Keys.Apps => Key.Apps,
      Keys i when i >= Keys.F1 && i <= Keys.F12 => (Key)((int)Key.F1 + (int)i - (int)Keys.F1),
      Keys i when i >= Keys.NumPad0 && i <= Keys.NumPad9 => (Key)((int)Key.Numpad0 + (int)i - (int)Keys.NumPad0),
      Keys i when i >= Keys.A && i <= Keys.Z => (Key)i,
      _ => Key.Null
    };

    /// Converts UI application cursor type to Windows Forms cursor.
    public static Cursor FromUI(AppCursor cursor) => cursor switch
    {
      AppCursor.Blank => null,
      AppCursor.TextSelect => Cursors.IBeam,
      AppCursor.TextSelectVertical => Cursors.IBeam,
      AppCursor.Wait => Cursors.WaitCursor,
      AppCursor.ArrowWait => Cursors.AppStarting,
      AppCursor.CrossHair => Cursors.Cross,
      AppCursor.Cell => Cursors.Cross,
      AppCursor.LinkSelect => Cursors.Hand,
      AppCursor.NotAllowed => Cursors.No,
      AppCursor.Help => Cursors.Help,
      AppCursor.Move => Cursors.SizeAll,
      AppCursor.ResizeVert => Cursors.SizeNS,
      AppCursor.ResizeHoriz => Cursors.SizeWE,
      AppCursor.Resize1 => Cursors.SizeNWSE,
      AppCursor.Resize2 => Cursors.SizeNESW,
      AppCursor.ResizeTop => Cursors.SizeNS,
      AppCursor.ResizeBottom => Cursors.SizeNS,
      AppCursor.ResizeLeft => Cursors.SizeWE,
      AppCursor.ResizeRight => Cursors.SizeWE,
      AppCursor.ResizeTopLeft => Cursors.SizeNWSE,
      AppCursor.ResizeTopRight => Cursors.SizeNESW,
      AppCursor.ResizeBottomRight => Cursors.SizeNWSE,
      AppCursor.ResizeBottomLeft => Cursors.SizeNESW,
      _ => Cursors.Arrow
    };
  }

  /// A combination of two colors, primarily used for displaying text with the first color being on top and
  /// the second being on bottom. The format for specifying colors is defined as ARGB8).
  public struct ColorPair
  {
    /// Creates a new color pair with a given color.
    public ColorPair(uint color) { First = color; Second = color; }

    /// Creates a new color pair with a given values.
    public ColorPair(uint first, uint second) { First = first; Second = second; }

    /// Internal pair of black colors.
    private static ColorPair _black = new (0xFF000000u);

    /// Internal pair of white colors.
    private static ColorPair _white = new (0xFFFFFFFFu);

    /// Internal pair of translucent black colors.
    private static ColorPair _translucentBlack = default;

    /// Internal pair of translucent white colors.
    private static ColorPair _translucentWhite = new (0x00FFFFFFu);

    /// Returns a pair of opaque Black colors.
    public static ColorPair Black => _black;

    /// Returns a pair of opaque White colors.
    public static ColorPair White => _white;

    /// Returns a pair of translucent Black colors.
    public static ColorPair TranslucentBlack => _translucentBlack;

    /// Returns a pair of translucent White colors.
    public static ColorPair TranslucentWhite => _translucentWhite;

    /// First color entry, which can be reinterpreted as top or left color depending on context.
    public uint First;

    /// Second color entry, which can be reinterpreted as bottom or right color depending on context.
    public uint Second;
  }

  /// A rectangle of four colors, primarily used for displaying colored quads, where each color corresponds
  /// to top/left, top/right, bottom/right and bottom/left accordingly (clockwise). The format for specifying
  /// colors is defined as ARGB8.
  public struct ColorRect
  {
    /// Creates a color rectangle with all values set to zero.
    //public ColorRect() { TopLeft = 0; TopRight = 0; BottomRight = 0; BottomLeft = 0; }

    /// Creates a color rectangle with four colors having the same component in each corner.
    public ColorRect(uint color)
    {
      TopLeft = color;
      TopRight = color;
      BottomRight = color;
      BottomLeft = color;
    }

    /// Creates a color rectangle with a given values.
    public ColorRect(uint topLeft, uint topRight, uint bottomRight, uint bottomLeft)
    {
      TopLeft = topLeft;
      TopRight = topRight;
      BottomRight = bottomRight;
      BottomLeft = bottomLeft;
    }

    /// Creates a color rectangle of four colors from two color pair to create horizontal gradient.
    public static ColorRect GradientX(ColorPair colors) => new (colors.First, colors.Second,
      colors.Second, colors.First);

    /// Creates a color rectangle of four colors from two color values to create horizontal gradient.
    public static ColorRect GradientX(uint left, uint right) => new (left, right, right, left);

    /// Creates a color rectangle of four colors from two color pair to create vertical gradient.
    public static ColorRect GradientY(ColorPair colors) => new (colors.First, colors.First,
      colors.Second, colors.Second);

    /// Creates a color rectangle of four colors from two color values to create vertical gradient.
    public static ColorRect GradientY(uint top, uint bottom) => new (top, top, bottom, bottom);

    /// Internal rectangle with black colors.
    private static ColorRect _black = new (0xFF000000u);

    /// Internal rectangle with white colors.
    private static ColorRect _white = new (0xFFFFFFFFu);

    /// Internal rectangle with translucent black colors.
    private static ColorRect _translucentBlack = default;

    /// Internal rectangle with translucent white colors.
    private static ColorRect _translucentWhite = new (0x00FFFFFFu);

    /// Returns a color rectangle with opaque Black color.
    public static ColorRect Black => _black;

    /// Returns a color rectangle with opaque White color.
    public static ColorRect White => _white;

    /// Returns a color rectangle with translucent Black color.
    public static ColorRect TranslucentBlack => _translucentBlack;

    /// Returns a color rectangle with translucent White color.
    public static ColorRect TranslucentWhite => _translucentWhite;

    /// Color corresponding to top / left corner.
    public uint TopLeft;

    /// Color corresponding to top / right corner.
    public uint TopRight;

    /// Color corresponding to bottom / right corner.
    public uint BottomRight;

    /// Color corresponding to bottom / left corner.
    public uint BottomLeft;
  }

  /// A three-component special high-precision color value that has each individual component represented
  /// as 32-bit floating-point value in range of [0, 1]. Although components may have values outside of
  /// aforementioned range, such colors cannot be reliably displayed on the screen.
  public struct FloatColorRGB
  {
    /// Creates new floating-color RGB structure with the given values.
    public FloatColorRGB(float red, float green, float blue)
    {
      Red = red;
      Green = green;
      Blue = blue;
    }

    /// Creates new floating-color RGB structure from an unsigned 24-bit color value.
    public FloatColorRGB(uint color)
    {
      Red = (color & 0xFFu) / 255.0f;
      Green = ((color >> 8) & 0xFFu) / 255.0f;
      Blue = ((color >> 16) & 0xFFu) / 255.0f;
    }

    /// Returns a sum of two colors.
    public static FloatColorRGB operator + (FloatColorRGB color1, FloatColorRGB color2)
    {
      return new FloatColorRGB(
        color1.Red + color2.Red,
        color1.Green + color2.Green,
        color1.Blue + color2.Blue);
    }

    /// Subtracts one color from another.
    public static FloatColorRGB operator - (FloatColorRGB color1, FloatColorRGB color2)
    {
      return new FloatColorRGB(
        color1.Red - color2.Red,
        color1.Green - color2.Green,
        color1.Blue - color2.Blue);
    }

    /// Multiplies one color by another.
    public static FloatColorRGB operator * (FloatColorRGB color1, FloatColorRGB color2)
    {
      return new FloatColorRGB(
        color1.Red * color2.Red,
        color1.Green * color2.Green,
        color1.Blue * color2.Blue);
    }

    /// Divides one color by another.
    public static FloatColorRGB operator / (FloatColorRGB color1, FloatColorRGB color2)
    {
      return new FloatColorRGB(
        color1.Red / color2.Red,
        color1.Green / color2.Green,
        color1.Blue / color2.Blue);
    }

    /// Multiplies color by a coefficient.
    public static FloatColorRGB operator * (FloatColorRGB color, float theta)
    {
      return new FloatColorRGB(color.Red * theta, color.Green * theta, color.Blue * theta);
    }

    /// Divides color by a coefficient.
    public static FloatColorRGB operator / (FloatColorRGB color, float theta)
    {
      return new FloatColorRGB(color.Red / theta, color.Green / theta, color.Blue / theta);
    }

    /// Converts floating-point color to 32-bit integer RGB color (where A bits are set to zero).
    public readonly uint ToColor
    {
      get
      {
        return (uint)Math.Round(Red * 255.0) | (((uint)Math.Round(Green * 255.0)) << 8) |
          (((uint)Math.Round(Blue * 255.0)) << 16);
      }
    }

    /// Tests whether all values of the color are not NaNs or infinities.
    public readonly bool Defined
    {
      get
      {
        return !float.IsNaN(Red) && !float.IsInfinity(Red) && !float.IsNaN(Green) &&
          !float.IsInfinity(Green) && !float.IsNaN(Blue) && !float.IsInfinity(Blue);
      }
    }

    /// Converts floating-point color to 32-bit integer RGBA color (where A is 255).
    public readonly uint ToColorAlpha => ToColor | 0xFF000000u;

    /// Internal black color.
    private static FloatColorRGB _black = default;

    /// Internal white color.
    private static FloatColorRGB _white = new (1.0f, 1.0f, 1.0f);

    /// Returns a Black color.
    public static FloatColorRGB Black => _black;

    /// Returns a White color.
    public static FloatColorRGB White => _white;

    /// Red value ranging from 0.0 (no intensity) to 1.0 (fully intense).
    public float Red;

    /// Green value ranging from 0.0 (no intensity) to 1.0 (fully intense).
    public float Green;

    /// Blue value ranging from 0.0 (no intensity) to 1.0 (fully intense).
    public float Blue;
  }

  /// A special high-precision color value that has each individual component represented as 32-bit
  /// floating-point value in range of [0, 1]. Although components may have values outside of aforementioned
  /// range, such colors cannot be reliably displayed on the screen.
  public struct FloatColor
  {
    /// Creates new floating-color RGBA structure with the given values.
    public FloatColor(float red, float green, float blue, float alpha = 1.0f)
    {
      Red = red;
      Green = green;
      Blue = blue;
      Alpha = alpha;
    }

    /// Creates new floating-color RGBA structure from an unsigned 32-bit color value.
    public FloatColor(uint color)
    {
      Red = (color & 0xFFu) / 255.0f;
      Green = ((color >> 8) & 0xFFu) / 255.0f;
      Blue = ((color >> 16) & 0xFFu) / 255.0f;
      Alpha = ((color >> 24) & 0xFFu) / 255.0f;
    }

    /// Creates new floating-color RGBA structure from an unsigned 32-bit color value.
    public FloatColor(FloatColorRGB color, float alpha = 1.0f)
    {
      Red = color.Red;
      Green = color.Green;
      Blue = color.Blue;
      Alpha = alpha;
    }

    /// Returns a sum of two colors.
    public static FloatColor operator + (FloatColor color1, FloatColor color2)
    {
      return new FloatColor(
        color1.Red + color2.Red,
        color1.Green + color2.Green,
        color1.Blue + color2.Blue,
        color1.Alpha + color2.Alpha);
    }

    /// Subtracts one color from another.
    public static FloatColor operator - (FloatColor color1, FloatColor color2)
    {
      return new FloatColor(
        color1.Red - color2.Red,
        color1.Green - color2.Green,
        color1.Blue - color2.Blue,
        color1.Alpha - color2.Alpha);
    }

    /// Multiplies one color by another.
    public static FloatColor operator * (FloatColor color1, FloatColor color2)
    {
      return new FloatColor(
        color1.Red * color2.Red,
        color1.Green * color2.Green,
        color1.Blue * color2.Blue,
        color1.Alpha * color2.Alpha);
    }

    /// Divides one color by another.
    public static FloatColor operator / (FloatColor color1, FloatColor color2)
    {
      return new FloatColor(
        color1.Red / color2.Red,
        color1.Green / color2.Green,
        color1.Blue / color2.Blue,
        color1.Alpha / color2.Alpha);
    }

    /// Multiplies color by a coefficient.
    public static FloatColor operator * (FloatColor color, float theta)
    {
      return new FloatColor(
        color.Red * theta, color.Green * theta,
        color.Blue * theta, color.Alpha * theta);
    }

    /// Divides color by a coefficient.
    public static FloatColor operator / (FloatColor color, float theta)
    {
      return new FloatColor(
        color.Red / theta, color.Green / theta,
        color.Blue / theta, color.Alpha / theta);
    }

    /// Internal black color.
    private static FloatColor _black = new (0.0f, 0.0f, 0.0f);

    /// Internal white color.
    private static FloatColor _white = new (1.0f, 1.0f, 1.0f);

    /// Internal translucent black color.
    private static FloatColor _translucentBlack = default;

    /// Internal translucent white color.
    private static FloatColor _translucentWhite = new (1.0f, 1.0f, 1.0f, 0.0f);

    /// Returns a black color.
    public static FloatColor Black => _black;

    /// Returns a white color.
    public static FloatColor White => _white;

    /// Returns a translucent black color.
    public static FloatColor TranslucentBlack => _translucentBlack;

    /// Returns a translucent white color.
    public static FloatColor TranslucentWhite => _translucentWhite;

    /// Returns RGB portion of the color, discarding alpha-channel.
    public readonly FloatColorRGB RGB => new (Red, Green, Blue);

    /// Converts floating-point color to 32-bit integer RGBA color.
    public readonly uint ToColor
    {
      get
      {
        return (uint)MathF.Round(Red * 255.0f) | (((uint)MathF.Round(Green * 255.0f)) << 8) |
          (((uint)MathF.Round(Blue * 255.0f)) << 16) | (((uint)MathF.Round(Alpha * 255.0f)) << 24);
      }
    }

    /// Red value ranging from 0.0 (no intensity) to 1.0 (fully intense).
    public float Red;

    /// Green value ranging from 0.0 (no intensity) to 1.0 (fully intense).
    public float Green;

    /// Blue value ranging from 0.0 (no intensity) to 1.0 (fully intense).
    public float Blue;

    /// Alpha-channel value ranging from 0.0 (translucent) to 1.0 (opaque).
    public float Alpha;
  }

  /// 2D integer point.
  public struct Point
  {
    /// Creates 2D integer point with both coordinates set to the given value.
    public Point(int value) { X = value; Y = value; }

    /// Creates 2D integer point with the given values.
    public Point(int x, int y) { X = x; Y = y; }

    /// Creates 2D integer point with the given values.
    public Point(Vector2 vector) { X = (int)MathF.Round(vector.X); Y = (int)MathF.Round(vector.Y); }

    /// Adds two 2D integer vectors.
    public static Point operator + (Point point1, Point point2)
    {
      return new Point(point1.X + point2.X, point1.Y + point2.Y);
    }

    /// Subtracts one 2D integer vector from another.
    public static Point operator - (Point point1, Point point2)
    {
      return new Point(point1.X - point2.X, point1.Y - point2.Y);
    }

    /// Multiplies one 2D integer vector by another.
    public static Point operator * (Point point1, Point point2)
    {
      return new Point(point1.X * point2.X, point1.Y * point2.Y);
    }

    /// Divides one 2D integer vector by another.
    public static Point operator / (Point point1, Point point2)
    {
      return new Point(point1.X / point2.X, point1.Y / point2.Y);
    }

    /// Multiplies 2D integer vector by a coefficient.
    public static Point operator * (Point point, int theta)
    {
      return new Point(point.X * theta, point.Y * theta);
    }

    /// Divides 2D integer vector by a coefficient.
    public static Point operator / (Point point, int theta)
    {
      return new Point(point.X / theta, point.Y / theta);
    }

    /// Tests whether two points are equal.
    public static bool operator == (Point point1, Point point2)
    {
      return point1.X == point2.X && point1.Y == point2.Y;
    }

    /// Tests whether two points are not equal.
    public static bool operator != (Point point1, Point point2)
    {
      return point1.X != point2.X || point1.Y != point2.Y;
    }

    /// Tests whether current 2D integer vector is the same as a possibly another vector.
    public override readonly bool Equals(object obj)
    {
      if (obj == null || GetType() != obj.GetType())
        return false;

      Point other = (Point)obj;
      return X == other.X && Y == other.Y;
    }

    /// Returns hash code for the 2D integer vector.
    public override readonly int GetHashCode() => (X + Y.GetHashCode()).GetHashCode();

    /// Calculates dot-product between current and the given 2D integer vectors.
    /// The dot-product is an indirect measure of angle between two vectors.
    public readonly int Dot(Point point) => X * point.X + Y * point.Y;

    /// Calculates a so-called "cross-product" between current and the given 2D integer vectors, or
    /// a geometric analog of thereof.
    public readonly int Cross(Point point) => X * point.Y - Y * point.X;

    /// Calculates distance between current and given 2D integer vectors.
    public readonly float Distance(Point point) => (this - point).Length;

    /// Calculates average between current and given 2D integer vectors.
    public readonly Point Average(Point point) => (this + point) / 2;

    /// Returns 2D integer vector with X and Y swapped.
    public readonly Point Transpose => new (Y, X);

    /// Tests whether 2D integer vector has both X and Y equal to zero.
    public readonly bool Empty => X == 0 && Y == 0;

    /// Returns length of current 2D integer vector.
    public readonly float Length => (float)Math.Sqrt(X * X + Y * Y);

    /// Calculates angle (in radians) at which current vector is pointing at, in range of [-Pi, Pi].
    public readonly float Angle => (float)Math.Atan2(-Y, X);

    /// Returns a 2D integer vector, where both coordinates are zero.
    public static Point Zero => default;

    /// Returns a 2D integer vector, where both coordinates are one.
    public static Point One => new (1);

    /// Returns a 2D integer vector with values (1, 0).
    public static Point UnitX => new (1, 0);

    /// Returns a 2D integer vector with values (0, 1).
    public static Point UnitY => new (0, 1);

    /// Horizontal coordinate in 2D space.
    public int X;

    /// Vertical coordinate in 2D space.
    public int Y;
  }

  /// Rectangle defined by integer top and left margins, width and height.
  public struct Rect
  {
    /// Creates rectangle by specifying its individual boundaries.
    public Rect(int left, int top, int width, int height)
    {
      Left = left;
      Top = top;
      Width = width;
      Height = height;
    }

    /// Creates rectangle by specifying its individual boundaries.
    public static Rect Bounds(int left, int top, int right, int bottom)
    {
      return new Rect(left, top, right - left, bottom - top);
    }

    /// Tests whether the specified point is contained within current rectangle.
    public readonly bool Contains(int x, int y) => x >= Left && x < Right && y >= Top && y < Bottom;

    /// Tests whether a given rectangle is contained within current one.
    public readonly bool Contains(Rect rect)
    {
      return rect.Left >= Left && rect.Right <= Right && rect.Top >= Top && rect.Bottom <= Bottom;
    }

    /// Tests whether a given rectangle overlaps with the current one.
    public readonly bool Overlaps(Rect rect)
    {
      return rect.Left < Right && rect.Right > Left && rect.Top < Bottom && rect.Bottom > Top;
    }

    /// Calculates rectangle that results from intersection between current and the specified one.
    public readonly Rect Intersect(Rect rect)
    {
      if (Overlaps(rect))
      {
        return Bounds(
          Math.Max(Left, rect.Left),
          Math.Max(Top, rect.Top),
          Math.Min(Right, rect.Right),
          Math.Min(Bottom, rect.Bottom));
      }
      else
        return Zero;
    }

    /// Calculates rectangle that results from union between current and the specified one.
    public readonly Rect Join(Rect rect)
    {
      return Bounds(
        Math.Min(Left, rect.Left),
        Math.Min(Top, rect.Top),
        Math.Max(Right, rect.Right),
        Math.Max(Bottom, rect.Bottom));
    }

    /// Calculates displaced rectangle by certain offset.
    public readonly Rect Offset(int deltaX, int deltaY) => new (Left + deltaX, Top + deltaY, Width, Height);

    /// Returns rectangle with left and top decremented, while right and bottom incremented by a
    /// given offset.
    public readonly Rect Inflate(int deltaX, int deltaY) => new (Left - deltaX, Top - deltaY,
      Width + deltaX * 2, Height + deltaY * 2);

    /// Indicates whether the rectangle is empty, that is, having width or height of zero or less.
    public readonly bool Empty => Width <= 0 || Height <= 0;

    /// Tests whether two rectangles are equal.
    public static bool operator == (Rect rect1, Rect rect2)
    {
      return rect1.Left == rect2.Left && rect1.Top == rect2.Top &&
        rect1.Width == rect2.Width && rect1.Height == rect2.Height;
    }

    /// Tests whether two rectangles are not equal.
    public static bool operator != (Rect rect1, Rect rect2)
    {
      return rect1.Left != rect2.Left || rect1.Top != rect2.Top ||
        rect1.Width != rect2.Width || rect1.Height != rect2.Height;
    }

    /// Tests whether current rectangle is the same as another rectangle.
    public override readonly bool Equals(object obj)
    {
      if (obj == null || GetType() != obj.GetType())
        return false;

      Rect other = (Rect)obj;
      return Left == other.Left && Top == other.Top && Width == other.Width && Height == other.Height;
    }

    /// Returns hash code for the rectangle.
    public override readonly int GetHashCode() => (Left.GetHashCode() + Top.GetHashCode() +
      Width.GetHashCode() + Height.GetHashCode()).GetHashCode();

    /// Right edge of the rectangle.
    public int Right { readonly get { return Left + Width; } set { Width = value - Left; } }

    /// Bottom edge of the rectangle.
    public int Bottom { readonly get { return Top + Height; } set { Height = value - Top; } }

    /// Internal empty rectangle.
    private static Rect _zero = default;

    /// Returns an empty rectangle, where all elements are set to zero.
    public static Rect Zero => _zero;

    /// Left position of the rectangle.
    public int Left;

    /// Top position of the rectangle.
    public int Top;

    /// Width of the rectangle.
    public int Width;

    /// Height of the rectangle.
    public int Height;
  }

  /// Rectangle defined by floating-point top and left margins, width and height.
  public struct RectF
  {
    /// Creates rectangle by specifying its individual boundaries.
    public RectF(float left, float top, float width, float height)
    {
      Left = left;
      Top = top;
      Width = width;
      Height = height;
    }

    /// Creates rectangle by specifying its origin and size.
    public RectF(Vector2 origin, Vector2 size)
    {
      Left = origin.X;
      Top = origin.Y;
      Width = size.X;
      Height = size.Y;
    }

    /// Creates rectangle with floating-point coordinates from an integer one.
    public RectF(Rect rect)
    {
      Left = rect.Left;
      Top = rect.Top;
      Width = rect.Width;
      Height = rect.Height;
    }

    /// Creates rectangle by specifying its individual boundaries.
    public static RectF Bounds(float left, float top, float right, float bottom)
    {
      return new RectF(left, top, right - left, bottom - top);
    }

    /// Creates rectangle by specifying its top/left and bottom/right boundaries.
    public static RectF Bounds(Vector2 topLeft, Vector2 bottomRight)
    {
      return Bounds(topLeft.X, topLeft.Y, bottomRight.X, bottomRight.Y);
    }

    /// Tests whether the specified point is contained within current rectangle.
    public readonly bool Contains(float x, float y) => x >= Left && x < Right && y >= Top && y < Bottom;

    /// Tests whether the specified point is contained within current rectangle.
    public readonly bool Contains(Vector2 point) => Contains(point.X, point.Y);

    /// Tests whether a given rectangle is contained within current one.
    public readonly bool Contains(RectF rect)
    {
      return rect.Left >= Left && rect.Right <= Right && rect.Top >= Top && rect.Bottom <= Bottom;
    }

    /// Tests whether a given rectangle overlaps with the current one.
    public readonly bool Overlaps(RectF rect)
    {
      return rect.Left < Right && rect.Right > Left && rect.Top < Bottom && rect.Bottom > Top;
    }

    /// Calculates rectangle that results from intersection between current and the specified one.
    public readonly RectF Intersect(RectF rect)
    {
      if (Overlaps(rect))
      {
        return Bounds(
          Math.Max(Left, rect.Left),
          Math.Max(Top, rect.Top),
          Math.Min(Right, rect.Right),
          Math.Min(Bottom, rect.Bottom));
      }
      else
        return Zero;
    }

    /// Calculates rectangle that results from union between current and the specified one.
    public readonly RectF Join(RectF rect)
    {
      return Bounds(
        Math.Min(Left, rect.Left),
        Math.Min(Top, rect.Top),
        Math.Max(Right, rect.Right),
        Math.Max(Bottom, rect.Bottom));
    }

    /// Calculates displaced rectangle by certain offset.
    public readonly RectF Offset(float deltaX, float deltaY)
    {
      return new RectF(Left + deltaX, Top + deltaY, Width, Height);
    }

    /// Calculates displaced rectangle by certain offset.
    public readonly RectF Offset(Vector2 delta) => Offset(delta.X, delta.Y);

    /// Returns rectangle with left and top decremented, while right and bottom incremented by
    /// a given offset.
    public readonly RectF Inflate(float deltaX, float deltaY)
    {
      return new RectF(Left - deltaX, Top - deltaY, Width + deltaX * 2, Height + deltaY * 2);
    }

    /// Returns rectangle with left and top decremented, while right and bottom incremented by
    /// a given offset.
    public readonly RectF Inflate(Vector2 delta) => Inflate(delta.X, delta.Y);

    /// Indicates whether the rectangle is empty, that is, having width or height of zero or less.
    public readonly bool Empty => Width <= 0 || Height <= 0;

    /// Right edge of the rectangle.
    public float Right { readonly get { return Left + Width; } set { Width = value - Left; } }

    /// Bottom edge of the rectangle.
    public float Bottom { readonly get { return Top + Height; } set { Height = value - Top; } }

    /// Returns size of the rectangle.
    public readonly Vector2 Size => new (Width, Height);

    /// Top and left corner of the rectangle.
    public Vector2 TopLeft
    {
      readonly get { return new Vector2(Left, Top); }
      set { Left = value.X; Top = value.Y; }
    }

    /// Top and right corner of the rectangle.
    public Vector2 TopRight {
      readonly get { return new Vector2(Right, Top); }
      set { Right = value.X; Top = value.Y; } }

    /// Bottom and right corner of the rectangle.
    public Vector2 BottomRight
    {
      readonly get { return new Vector2(Right, Bottom); }
      set { Right = value.X; Bottom = value.Y; }
    }

    /// Bottom and left corner of the rectangle.
    public Vector2 BottomLeft
    {
      readonly get { return new Vector2(Left, Bottom); }
      set { Left = value.X; Bottom = value.Y; }
    }

    /// Internal empty rectangle.
    private static RectF _zero = default;

    /// Internal empty rectangle.
    private static RectF _unity = new (0.0f, 0.0f, 1.0f, 1.0f);

    /// Returns an empty rectangle, where all elements are set to zero.
    public static RectF Zero => _zero;

    /// Returns a rectangle positioned at zero origin with width and height set to one.
    public static RectF Unity => _unity;

    /// Left position of the rectangle.
    public float Left;

    /// Top position of the rectangle.
    public float Top;

    /// Width of the rectangle.
    public float Width;

    /// Height of the rectangle.
    public float Height;
  }

  /// Margins defined by top, left, right and bottom edge paddings.
  public struct Margins
  {
    /// Creates margins by specifying its paddings individually.
    public Margins(float left, float top, float right, float bottom)
    {
      Left = left;
      Top = top;
      Right = right;
      Bottom = bottom;
    }

    /// Creates margins by specifying its top/left and bottom/right corners.
    public Margins(Vector2 topLeft, Vector2 bottomRight)
    {
      Left = topLeft.X;
      Top = topLeft.Y;
      Right = bottomRight.X;
      Bottom = bottomRight.Y;
    }

    /// Creates margins by specifying horizontal and vertical paddings.
    public Margins(float horizontal, float vertical)
    {
      Left = horizontal;
      Top = vertical;
      Right = horizontal;
      Bottom = vertical;
    }

    /// Creates margins by specifying same padding for all edges.
    public Margins(float padding)
    {
      Left = padding;
      Top = padding;
      Right = padding;
      Bottom = padding;
    }

    /// Indicates whether all values are zero.
    public readonly bool Empty
    {
      get
      {
        return Math.Abs(Left) <= 1E-6 && Math.Abs(Top) <= 1E-6 &&
          Math.Abs(Right) <= 1E-6 && Math.Abs(Bottom) <= 1E-6;
      }
    }

    /// Returns a sum of left and right paddings.
    public readonly float Horizontal => Left + Right;

    /// Returns a sum of top and bottom paddings.
    public readonly float Vertical => Top + Bottom;

    /// Top and left edge.
    public Vector2 TopLeft
    {
      readonly get { return new Vector2(Left, Top); }
      set { Left = value.X; Top = value.Y; }
    }

    /// Top and right edge.
    public Vector2 TopRight
    {
      readonly get { return new Vector2(Right, Top); }
      set { Right = value.X; Top = value.Y; }
    }

    /// Bottom and right edge.
    public Vector2 BottomRight
    {
      readonly get { return new Vector2(Right, Bottom); }
      set { Right = value.X; Bottom = value.Y; }
    }

    /// Bottom and left edge.
    public Vector2 BottomLeft
    {
      readonly get { return new Vector2(Left, Bottom); }
      set { Left = value.X; Bottom = value.Y; }
    }

    /// Internal empty margins.
    private static Margins _zero = default;

    /// Returns an empty margins, where all elements are set to zero.
    public static Margins Zero => _zero;

    /// Left edge padding.
    public float Left;

    /// Top edge padding.
    public float Top;

    /// Right edge padding.
    public float Right;

    /// Bottom edge padding.
    public float Bottom;
  }

  /// Floating-point quadrilateral defined by four vertices in clockwise order starting from top/left.
  public struct Quad
  {
    /// Creates quadrilateral with individually specified vertices.
    public Quad(Vector2 topLeft, Vector2 topRight, Vector2 bottomRight, Vector2 bottomLeft)
    {
      TopLeft = topLeft;
      TopRight = topRight;
      BottomRight = bottomRight;
      BottomLeft = bottomLeft;
    }

    /// Creates quadrilateral with top/left position, width and height.
    public Quad(float left, float top, float width, float height)
    {
      TopLeft = new Vector2(left, top);
      TopRight = new Vector2(left + width, top);
      BottomRight = new Vector2(left + width, top + height);
      BottomLeft = new Vector2(left, top + height);
    }

    /// Creates quadrilateral from a given floating-point rectangle.
    public Quad(RectF rect)
    {
      TopLeft = rect.TopLeft;
      TopRight = rect.TopRight;
      BottomRight = rect.BottomRight;
      BottomLeft = rect.BottomLeft;
    }

    /// Creates quadrilateral from a given integer rectangle.
    public Quad(Rect rect)
    {
      TopLeft = new Vector2(rect.Left, rect.Top);
      TopRight = new Vector2(rect.Right, rect.Top);
      BottomRight = new Vector2(rect.Right, rect.Bottom);
      BottomLeft = new Vector2(rect.Left, rect.Bottom);
    }

    /// Creates quadrilateral with the specified top left corner and the given dimensions, which are scaled
    /// by the provided coefficient.
    public static Quad Scaled(float left, float top, float width, float height, float scale,
      bool centered = true)
    {
      if (Math.Abs(scale - 1.0f) < API.Epsilon)
          return new Quad(left, top, width, height);

      if (centered)
      {
        float newWidth = width * scale;
        float newHeight = height * scale;

        return new Quad(left + (width - newWidth) * 0.5f, top + (height - newHeight) * 0.5f,
          newWidth, newHeight);
      }
      else
        return new Quad(left, top, width * scale, height * scale);
    }

    /// Creates quadrilateral specified by its dimensions. The rectangle is then rotated and scaled around
    /// the specified middle point (assumed to be inside rectangle's dimensions) and placed in center of the
    /// specified origin.
    public static Quad Rotated(Vector2 origin, Vector2 size, Vector2 center, float angle,
      float scale = 1.0f)
    {
      bool scaled = Math.Abs(scale - 1.0f) > API.Epsilon;
      float sinAngle = (float)Math.Sin(angle);
      float cosAngle = (float)Math.Cos(angle);

      Vector2[] values = new Vector2[] {
        new(-center.X, -center.Y),
        new(size.X - center.X, -center.Y),
        new(size.X - center.X, size.Y - center.Y),
        new(-center.X, size.Y - center.Y)};

      for (int i = 0; i < values.Length; i++)
      {
        if (scaled)
          values[i] *= scale;

        Vector2 newValue = new (
          values[i].X * cosAngle - values[i].Y * sinAngle,
          values[i].X * sinAngle + values[i].Y * cosAngle);

        values[i] = newValue + origin;
      }
      return new Quad(values[0], values[1], values[2], values[3]);
    }

    /// Creates quadrilateral specified by its dimensions. The rectangle is then rotated and scaled around its
    /// center and placed at the specified origin.
    public static Quad Rotated(Vector2 origin, Vector2 size, float angle, float scale = 1.0f)
    {
      return Rotated(origin, size, size * 0.5f, angle, scale);
    }

    /// Creates quadrilateral specified by top-left corner and size. The rectangle is then rotated and scaled
    /// around the specified middle point (assumed to be inside rectangle's dimensions) and placed in the
    /// center of the specified origin. The difference between this method and Rotated() is that the
    /// rotation does not preserve centering of the rectangle in case where middle point is not actually
    /// located in the middle.
    public static Quad RotatedTopLeft(Vector2 topLeft, Vector2 size, Vector2 center, float angle,
      float scale = 1.0f)
    {
      return Rotated(topLeft, size, center, angle, scale).Offset(center);
    }

    /// Creates a horizontally skewed quadrilateral, oriented around its origin and with the given
    /// dimensions. A skew angle defines quadrilateral's top/left corner.
    public static Quad SkewedHoriz(Vector2 origin, Vector2 size, float angle)
    {
      float offset = (float)Math.Cos(angle) * size.Y * 0.5f;

      Quad quad = new (new RectF(origin - size * 0.5f, size));
      quad.TopLeft.X -= offset;
      quad.TopRight.X -= offset;
      quad.BottomRight.X += offset;
      quad.BottomLeft.X += offset;

      return quad;
    }

    /// Creates a vertically skewed quadrilateral, oriented around its origin and with the given
    /// dimensions. A skew angle defines quadrilateral's top/left corner.
    public static Quad SkewedVert(Vector2 origin, Vector2 size, float angle)
    {
      float offset = (float)Math.Cos(angle) * size.X * 0.5f;

      Quad quad = new (new RectF(origin - size * 0.5f, size));
      quad.TopLeft.Y -= offset;
      quad.TopRight.Y -= offset;
      quad.BottomRight.Y += offset;
      quad.BottomLeft.Y += offset;

      return quad;
    }

    /// Displaces vertices of current quadrilateral by the specified offset.
    public readonly Quad Offset(Vector2 delta) => new (TopLeft + delta, TopRight + delta,
      BottomRight + delta, BottomLeft + delta);

    /// Displaces vertices of current quadrilateral by the specified offset.
    public readonly Quad Offset(float deltaX, float deltaY) => Offset(new Vector2(deltaX, deltaY));

    /// Rescales vertices of current quadrilateral by the provided coefficient, optionally centering them
    /// around zero origin.
    public readonly Quad Scale(float scale, bool centered = true)
    {
      if (Math.Abs(scale - 1.0f) <= API.Epsilon)
        return this;

      if (centered)
      {
        Vector2 center = (TopLeft + TopRight + BottomRight + BottomLeft) * 0.25f;

        return new Quad(
          Vector2.Lerp(center, TopLeft, scale),
          Vector2.Lerp(center, TopRight, scale),
          Vector2.Lerp(center, BottomRight, scale),
          Vector2.Lerp(center, BottomLeft, scale));
      }
      else
        return new Quad(TopLeft * scale, TopRight * scale, BottomRight * scale, BottomLeft * scale);
    }

    /// Transforms (multiplies) vertices of current quadrilateral by the specified matrix.
    public readonly Quad Transform(Matrix3x2 matrix) => new (
      Vector2.Transform(TopLeft, matrix),
      Vector2.Transform(TopRight, matrix),
      Vector2.Transform(BottomRight, matrix),
      Vector2.Transform(BottomLeft, matrix));

    /// Creates quadrilateral from current one but having left vertices exchanged with the right ones,
    /// effectively mirroring it horizontally.
    public readonly Quad Mirror => new (TopRight, TopLeft, BottomLeft, BottomRight);

    /// Creates quadrilateral from current one but having top vertices exchanged with the bottom ones,
    /// effectively flipping it vertically.
    public readonly Quad Flip => new (BottomLeft, BottomRight, TopRight, TopLeft);

    /// Internal quadrilateral with all elements set to zero.
    private static Quad _zero = default;

    /// Internal quadrilateral with zero origin and size of one.
    private static Quad _unity = new (0.0f, 0.0f, 1.0f, 1.0f);

    /// Quadrilateral with all vertices set to zero.
    public static Quad Zero => _zero;

    /// Quadrilateral with vertices set at four corners set between (0, 0) and (1, 1).
    public static Quad Unity => _unity;

    /// Top/left vertex position.
    public Vector2 TopLeft;

    /// Top/right vertex position.
    public Vector2 TopRight;

    /// Bottom/right vertex position.
    public Vector2 BottomRight;

    /// Bottom/left vertex position.
    public Vector2 BottomLeft;
  }

  public partial struct Utility
  {
    /// Creates a left-handed perspective projection matrix based on a field of view, aspect ratio, and
    /// near and far view plane distances using reversed depth technique.
    public static Matrix4x4 MatrixPerspective4x4(float fieldOfView, float aspectRatio, float nearPlane,
      float farPlane)
    {
      float scaleY = 1.0f / MathF.Tan(fieldOfView * 0.5f);
      float scaleX = scaleY / aspectRatio;

      Matrix4x4 result = default;
      result.M11 = scaleX;
      result.M22 = scaleY;
      result.M34 = 1.0f;
      result.M33 = nearPlane / (nearPlane - farPlane);
      result.M43 = -farPlane * result.M33;
      return result;
    }

    /// Creates orthogonal projection matrix defined by the viewing volume in 3D space.
    public static Matrix4x4 MatrixOrthographic4x4(float width, float height, float rangeMin, float rangeMax)
    {
      Matrix4x4 result = default;
      result.M11 = 2.0f / width;
      result.M22 = 2.0f / height;
      result.M33 = 1.0f / (rangeMin - rangeMax);
      result.M43 = -rangeMax / (rangeMin - rangeMax);
      result.M44 = 1.0f;
      return result;
    }

    /// Creates a left-handed view matrix.
    public static Matrix4x4 MatrixLookAt4x4(Vector3 origin, Vector3 target, Vector3 ceiling)
    {
      Vector3 axisZ = Vector3.Normalize(target - origin);
      Vector3 axisX = Vector3.Normalize(Vector3.Cross(ceiling, axisZ));
      Vector3 axisY = Vector3.Cross(axisZ, axisX);

      Matrix4x4 result = Matrix4x4.Identity;

      result.M11 = axisX.X;
      result.M12 = axisY.X;
      result.M13 = axisZ.X;

      result.M21 = axisX.Y;
      result.M22 = axisY.Y;
      result.M23 = axisZ.Y;

      result.M31 = axisX.Z;
      result.M32 = axisY.Z;
      result.M33 = axisZ.Z;

      result.M41 = -Vector3.Dot(axisX, origin);
      result.M42 = -Vector3.Dot(axisY, origin);
      result.M43 = -Vector3.Dot(axisZ, origin);

      return result;
    }

  }
}