CCSLensFlares.cs

Post-processing component that implements screen space lens flares. It exposes texture and scalar properties, sets shader attributes (including optional color/opacity maps), and blits using a postprocess shader.

Native Interop
using Sandbox;
using System;


using Sandbox;
using Sandbox.Rendering;

/// <summary>
/// Screen Space Lens Flares (Single Pass)
/// </summary>
[Title( "Lens Flares" )]
[Category( "Post Processing" )]
[Icon( "auto_awesome" )]
public sealed class CCSLensFlares : BasePostProcess<CCSLensFlares>
{
    /// <summary>
    /// Color gradient texture for chromatic aberration effect (optional).
    /// </summary>
    [Property, Title("Color Map (Optional)")]
    public Texture color_map { get; set; }

    /// <summary>
    /// Lens dirt texture for dust/scratches effect (optional).
    /// </summary>
    [Property, Title("Opacity Map (Optional)")]
    public Texture opacity_map { get; set; }

    [Property, Title("Cutoff"), Range(0.0f, 1.0f)]
    public float fCutoff { get; set; } = 0.7f;

    [Property, Title("Flare Spacing"), Range(0.01f, 1.0f)]
    public float fStretch { get; set; } = 0.3f;

    [Property, Title("Flare Count"), Range(1.0f, 20.0f)]
    public float fShape { get; set; } = 8.0f;

    [Property, Title("Gain"), Range(0.0f, 5.0f)]
    public float fGain { get; set; } = 1.0f;

    [Property, Title("Tint")]
    public Color fColor { get; set; } = new Color(1.0f, 1.0f, 1.0f, 1.0f);

    [Property, Title("Dirt Enhancer")]
    public bool fDoubleAdd { get; set; }

    [Property, Title("Bypass (Debug)")]
    public bool fBypass { get; set; }

    public override void Render()
    {
        // ИСПРАВЛЕНО: Убрана строгая проверка на null
        // Текстуры теперь опциональны — эффект работает и без них

        float fCutoffW = GetWeighted(x => x.fCutoff);
        float fStretchW = GetWeighted(x => x.fStretch);
        float fShapeW = GetWeighted(x => x.fShape);
        float fGainW = GetWeighted(x => x.fGain);

        Color fColorW = fColor;
        bool fDoubleAddW = fDoubleAdd;
        bool fBypassW = fBypass;

        Attributes.Set("fCutoff", fCutoffW);
        Attributes.Set("fStretch", fStretchW);
        Attributes.Set("fShape", fShapeW);
        Attributes.Set("fGain", fGainW);
        Attributes.Set("fColor", new Vector4(fColorW.r, fColorW.g, fColorW.b, fColorW.a));
        Attributes.Set("fDoubleAdd", fDoubleAddW ? 1 : 0);
        Attributes.Set("fBypass", fBypassW ? 1 : 0);
        
        // Передаем текстуры (могут быть null)
        Attributes.Set("color_map", color_map);
        Attributes.Set("opacity_map", opacity_map);
        
        // Булевые флаги для шейдера — применять ли текстуры
        Attributes.Set("useColorMap", color_map != null ? 1 : 0);
        Attributes.Set("useOpacityMap", opacity_map != null ? 1 : 0);

        var material = Material.FromShader("postprocess/ccs_flare_prepass.shader");
        if (material == null)
        {
            Log.Warning("CCSLensFlares: Shader not found!");
            return;
        }

        var blit = BlitMode.WithBackbuffer(material, Stage.AfterPostProcess, 4000, true);
        Blit(blit, "CCSLensFlares");
    }
}