Dagon 0.32.0

Очередной релиз Dagon содержит значительное изменение — переход на OpenGL 4.3. Это не должно сильно ударить по поддержке видеокарт (движок работает на всех десктопных видеокартах, выпущенных за последние лет 10), но дает много новых возможностей, в особенности — доступ к вычислительным шейдерам. Соответственно, появился новый класс ComputeShader, о работе с которым я писал ранее. Добавлен один встроенный вычислительный шейдер — dagon.compute.resample, реализация ресэмплинга текстур. Еще одна фича OpenGL 4.3 — кэширование шейдерных бинарников. В теории это должно ускорять их загрузку, хотя в Dagon встроенных шейдеров не так уж и много, и кэширование пока большого значения не имеет. По умолчанию оно отключено — можно включить свойством Application.shaderCache.enabled, либо опцией enableShaderCache в settings.conf. Бинарники сохраняются в папку data/__internal/shader_cache.

Добавлен арена-аллокатор (dagon.core.arena) — я о нем тоже писал отдельный пост. Пока он, впрочем, не используется встроенными классами движка, но пригодится в будущем для интеграции GScript.

Новый модуль dagon.core.dialogs — минимальное кроссплатформенное решение для открытия системного диалога открытия/сохранения файла. Поддерживает Windows и Linux, зависимости при линковке не тянет. Под GNOME работает на основе Zenity, под KDE — на основе kdialog.

Добавлена поддержка так называемого «оконного полноэкранного режима»: если в конфиге заданы нулевые windowWidth и windowHeight, то движок создает безрамочное окно размером с весь экран. Этот режим удобен для мультимониторных конфигураций.

Наконец, добавлено новое расширение dagon:audio для воспроизведения звука через библиотеку SoLoud. Сама библиотека, как обычно, предоставляется в готовом виде при компиляции под 64-битные Windows и Linux. Под Windows также предоставляется libopenmpt для поддержки трекерной музыки.

dagon:audio

В новой версии Dagon будет встроенный звуковой движок на основе SoLoud — расширение dagon:audio. Поясню для тех, кто не знает: SoLoud — это библиотека-микшер с поддержкой 3D-звука и базовых потоковых форматов (WAV, MP3, OGG, FLAC), а также трекерных форматов через OpenMPT. Есть частотные фильтры и встроенные синтезаторы — в частности, текстово-речевой преобразователь, SFXR, эмулятор VIC-20 и генератор разных видов шума. SoLoud поддерживает множество бэкендов, и по дефолту работает на основе SDL2, как и сам Dagon (пользователь, однако, может выбрать конкретный бэкенд через опцию audio.backend в settings.conf). Короче говоря, это своего рода «FMOD от мира OpenSource». Особо отмечу удобный API и, более того, прямо из коробки — обертка для D, позволяющая писать в объектно-ориентированном стиле.

SoLoud можно было и раньше использовать в приложениях Dagon с использованием BindBC-SoLoud, но dagon:audio упрощает работу со звуком в играх еще больше, предоставляя удобный механизм привязки 3D-слушателя и пространственных звуков SoLoud к объектам движка. Для этого я ввел менеджер AudioManager и компонент SoundComponent:

class MyGame: Game
{
    AudioManager audioManager;

    this(uint windowWidth, uint windowHeight, bool fullscreen, 
        string title, string[] args)
    {
        super(windowWidth, windowHeight, fullscreen, title, args);
        audioManager = New!AudioManager(this);
        currentScene = New!TestScene(this);
    }
}

class TestScene: Scene
{
    AudioManager audio;
    SoundComponent cubeSpeaker;
    WavStream music;

    this(MyGame game)
    {
        super(game);
        this.audio = game.audioManager;
    }

    override void afterLoad()
    {
        Camera camera = addCamera();
        camera.position = Vector3f(0.0f, 1.8f, 5.0f);
        game.renderer.activeCamera = camera;

        audio.listener = camera;

        auto eCube = addEntity();
        eCube.position = Vector3f(0, 1, 0);

        cubeSpeaker = audio.addSoundTo(eCube);
        music = audio.loadMusic("data/music/song.mp3");
        cubeSpeaker.play(music);
    }

    override void onUpdate(Time t)
    {
        audio.update(t);
    }
}

Позиция и ориентация слушателя и позиция источника звука обновляются автоматически в update.

Есть также класс PlaylistPlayer для управления плейлистами. Он упрощает загрузку множества аудиофайлов из папки и переключение между ними — полезно для автоматического воспроизведения фоновых мелодий одну за другой.

PlaylistPlayer pl = audio.addPlaylistPlayer();
pl.addTracksFromDirectory("data/music");
pl.play(0);

SoundComponent и PlaylistPlayer совместимы между собой:

cubeSpeaker.playlistPlayer = pl;
cubeSpeaker.play(0);

О звуковых движках

Что происходит со свободными звуковыми движками? Возвращаюсь к этой теме раз в несколько лет, и каждый раз ситуация все печальнее. Использовал когда-то Squall в эпоху Game Maker, он оказался заброшен с 2009 года. Потом долгое время сидел на OpenAL-soft, но у него тоже много лет не было обновлений (хотя в последние годы какое-то шевеление вроде началось). Ушел я с него по той причине, что захотелось движок с блэкджеком и шлюхами — то есть, со встроенной поддержкой всех аудиоформатов. Уже работая над Dagon, выбрал SoLoud, который активно разрабатывался до 2020 года, и с тех пор ни одного релиза.

Есть, конечно, движки для C++, в том числе довольно крутые — но, ребят, неужели делать API для C вышло из моды? В мое время это само собой разумелось. Не знаю теперь, что делать — не на закрытый FMOD же переходить. Возможно, форкну SoLoud, если так и не найду ему замены.