Code/CCSJpeg.cs

A post-processing effect component that simulates JPEG compression artifacts. It exposes properties for quality, block size, chroma subsampling, and detail preservation, passes weighted values to shader attributes, and runs a blit using a postprocess shader.

Native Interop
using Sandbox;
using Sandbox.Rendering;

using Sandbox;
using Sandbox.Rendering;

/// <summary>
/// JPEG Compression effect. Simulates real JPEG artifacts using block-based
/// quantization in YCbCr color space with optional chroma subsampling.
/// </summary>
[Title( "JPEG Compression" )]
[Category( "Post Processing" )]
[Icon( "gradient" )]
public sealed class CCSJpeg : BasePostProcess<CCSJpeg>
{
    /// <summary>
    /// JPEG quality (1 = worst, 100 = best). Controls quantization levels.
    /// </summary>
    [Property, Title("Quality"), Range(1.0f, 100.0f)]
    public float quality { get; set; } = 50.0f;

    /// <summary>
    /// Block size in pixels. Standard JPEG uses 8x8 blocks.
    /// </summary>
    [Property, Title("Block Size"), Range(2, 32)]
    public int blockSize { get; set; } = 8;

    /// <summary>
    /// Chroma subsampling strength. 0 = 4:4:4, 1 = 4:2:2, 2 = 4:2:0 (standard JPEG).
    /// </summary>
    [Property, Title("Chroma Subsampling"), Range(0.0f, 2.0f)]
    public float chromaSubsampling { get; set; } = 1.0f;

    /// <summary>
    /// Preserves original pixel detail within blocks (0 = flat blocks, 1 = textured blocks).
    /// </summary>
    [Property, Title("Detail Preservation"), Range(0.0f, 1.0f)]
    public float detailPreservation { get; set; } = 0.0f;

    public override void Render()
    {
        float qualityW = GetWeighted(x => x.quality);
        int blockSizeW = GetWeighted(x => x.blockSize);
        float chromaSubsamplingW = GetWeighted(x => x.chromaSubsampling);
        float detailPreservationW = GetWeighted(x => x.detailPreservation);

        Attributes.Set("quality", qualityW);
        Attributes.Set("blockSize", blockSizeW);
        Attributes.Set("chromaSubsampling", chromaSubsamplingW);
        Attributes.Set("detailPreservation", detailPreservationW);

        var material = Material.FromShader("postprocess/ccs_jpeg.shader");
        if (material == null)
        {
            Log.Warning("CCSJpeg: Material 'materials/postprocess/ccs_jpeg.vmat' not found!");
            return;
        }

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