Newer
Older
rpg / v2 / packages / engine / src / render / __tests__ / postShader.test.ts
/**
 * Тесты сборщика пост-прохода: эффекты включаются точно по опциям,
 * юниформы соответствуют включённому коду (GLSL не прощает лишнего).
 */
import { describe, expect, it } from 'vitest';
import { postPass } from '../postShader';

describe('postPass — сборка фрагмента', () => {
    it('пустые опции — прямой сэмпл без юниформ эффекта', () => {
        const s = postPass();
        expect(s.fragment).toContain('texture2D(tDiffuse, uv)');
        expect(s.fragment).not.toContain('uVignette');
        expect(s.fragment).not.toContain('uGrain');
        expect(s.fragment).not.toContain('uWobble');
        expect(Object.keys(s.uniforms)).toEqual([]);
    });

    it('виньетка и зерно — код и стартовые значения', () => {
        const s = postPass({ vignette: 0.35, grain: 0.03 });
        expect(s.fragment).toContain('uVignette * dot(d, d)');
        expect(s.fragment).toContain('n * uGrain');
        expect(s.fragment).not.toContain('uWobble');
        expect(s.uniforms.uVignette).toEqual({ value: 0.35 });
        expect(s.uniforms.uGrain).toEqual({ value: 0.03 });
    });

    it('дисторсия — сдвиг uv до сэмпла, сэмпл идёт после', () => {
        const s = postPass({ wobble: 0.002 });
        expect(s.fragment.indexOf('uWobble')).toBeLessThan(s.fragment.indexOf('texture2D'));
        expect(s.uniforms.uWobble).toEqual({ value: 0.002 });
    });

    it('полный набор — все юниформы объявлены и использованы', () => {
        const s = postPass({ vignette: 0.4, grain: 0.02, wobble: 0.002 });
        for (const u of ['uVignette', 'uGrain', 'uWobble', 'uTime', 'tDiffuse']) {
            expect(s.fragment).toContain(u);
        }
        // каждая использованная юниформа — объявлена (GLSL 1)
        expect(s.fragment).toContain('uniform float uVignette;');
        expect(s.fragment).toContain('uniform float uGrain;');
        expect(s.fragment).toContain('uniform float uTime;');
    });

    it('сэмпл конвертируется linear→sRGB ДО эффектов (RT хранит linear)', () => {
        const s = postPass({ vignette: 0.4, grain: 0.02 });
        // конверсия сразу после сэмпла...
        expect(s.fragment.indexOf('linearToOutputTexel')).toBeLessThan(s.fragment.indexOf('uVignette * dot(d, d)'));
        // ...и единственная (в конце второй конверсии нет — кадр дважды посветлел бы)
        expect(s.fragment.split('linearToOutputTexel').length - 1).toBe(1);
        expect(s.fragment).toContain('texture2D(tDiffuse, uv).rgb, 1.0');
    });
});