Code/CCSVhsDistort.cs

A post-process effect component that simulates VHS-style vertical scrolling and horizontal tracking distortion. It exposes tunable properties (warp size, speed, distortion, chromatic aberration, static, deinterlace skew), reads blended values via GetWeighted, sets shader attributes, loads a postprocess shader material and issues a Blit to apply the effect.

File Access
using Sandbox;
using System;


using Sandbox;
using Sandbox.Rendering;

/// <summary>
/// Simulation of the vertical scrolling - horizontal "tracking" effect on old VHS tapes.
/// </summary>
[Title( "VHS Distortion" )]
[Category( "Post Processing" )]
[Icon( "dehaze" )]
public sealed class CCSVHSD : BasePostProcess<CCSVHSD>
{
    /// <summary>
    /// How big are the distortion lines.
    /// </summary>
    [Property, Title("Warp Size"), Range(0f, 20.0f)]
    public float warp_size { get; set; } = 12.0f;

    /// <summary>
    /// Enhance the distorted areas.
    /// </summary>
    [Property, Title("Warp Distortion Multiplier"), Range(-0.5f, 0.5f)]
    public float warp_distort { get; set; } = 0.05f;

    /// <summary>
    /// How fast the distorted areas scroll.
    /// </summary>
    [Property, Title("Warp Speed"), Range(-30.0f, 30.0f)]
    public float warp_speed { get; set; } = 6.0f;

    /// <summary>
    /// number of smaller lines to chop the main warp lines into.
    /// </summary>
    [Property, Title("Warp Variation"), Range(-30.0f, 30.0f)]
    public float warp_random { get; set; } = 1.5f;

    /// <summary>
    /// How fast the distorted areas scroll.
    /// </summary>
    [Property, Title("Chromatic Abberation"), Range(-0.25f, 0.25f)]
    public float ca { get; set; } = 0.02f;

    /// <summary>
    /// Amount of static that each warp line has
    /// </summary>
    [Property, Title("Static Amount"), Range(0.0f, 1.0f)]
    public float Static { get; set; } = 0.5f;

    /// <summary>
    /// high frequency horizontal ripple distortion effect on the entire image.
    /// </summary>
    [Property, Title("DeInterlace Skew"), Range(0.0f, 20.0f)]
    public float dSkew { get; set; } = 0.5f;

    public override void Render()
    {
        // Числовые значения через GetWeighted — поддерживает блендинг в PostProcess Volume
        float warpSizeW = GetWeighted(x => x.warp_size);
        float warpDistortW = GetWeighted(x => x.warp_distort);
        float warpSpeedW = GetWeighted(x => x.warp_speed);
        float warpRandomW = GetWeighted(x => x.warp_random);
        float caW = GetWeighted(x => x.ca);
        float staticW = GetWeighted(x => x.Static);
        float dSkewW = GetWeighted(x => x.dSkew);

        // Передаем значения в шейдер
        Attributes.Set("warp_size", warpSizeW);
        Attributes.Set("warp_speed", warpSpeedW);
        Attributes.Set("warp_random", warpRandomW);
        Attributes.Set("warp_distort", warpDistortW);
        Attributes.Set("ca", caW);
        Attributes.Set("Static", staticW);
        Attributes.Set("dSkew", dSkewW);

        // Загружаем материал с проверкой на null
        var material = Material.FromShader("postprocess/ccs_vhs_distort.shader");
        if (material == null)
        {
            Log.Warning("CCSVHSD: Material 'materials/postprocess/ccs_vhsd.vmat' not found!");
            return;
        }

        // Применяем эффект через современный Blit API
        // Приоритет 9000 перенесен из оригинального кода
        var blit = BlitMode.WithBackbuffer(material, Stage.AfterPostProcess, 9000, true);
        Blit(blit, "CCSVHSD");
    }
}