Web Audio Spatialization на основе направления просмотра - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь модулировать громкость звука, основываясь на направлении обзора между камерой и звуком. Так что, если вы полностью смотрите на источник звука, громкость равна 100%, если вы отворачиваетесь, он выключается.

Установка встроенной directionalCone , которая ссылается на Panner Audio API , не то, что я хочу. Это определяет, включен ли звук, когда проигрыватель находится внутри конуса, я хотел бы работать в зависимости от направления просмотра.

У меня есть кое-что, работающее в Aframe, путем создания точки между направлением обзора камеры и направление между плеером и аудиоклипом. Однако это (по какой-то причине) довольно дорого, мне интересно, есть ли какая-то встроенная функциональность, которую я пропускаю.

tick: function() {
        if(!this.sound.isPlaying) return; //todo: this is true even outside the spatial distance!

        var camFwd = this.camFwd;
        this.camera.object3D.getWorldPosition(camFwd);

        var dir = this.dir;     
        this.el.object3D.getWorldPosition(dir);

        dir.subVectors(
            camFwd, //camera pos
            dir     //element pos
            ).normalize();

        this.camera.object3D.getWorldDirection(camFwd);

        var dot = THREE.Math.clamp(camFwd.dot(dir), 0, 1);

//float dot = Mathf.dot(transform.forward, (camTrans.position-transform.position).normalized);

        this.setVolume(THREE.Math.lerp(
            this.data.minVolume, 
            this.data.maxVolume, 
            dot));
    }, 

Это дает ожидаемый эффект, но в профилировщике производительности это выглядит довольно дорого. В частности, getWorldDirection по какой-то причине является дорогостоящим, хотя сама иерархия проста.

1 Ответ

1 голос
/ 23 апреля 2020

В частности, getWorldDirection по некоторым причинам стоит дорого

Object3D.getWorldPosition() и Object3D.getWorldDirection() всегда вынуждают пересчитывать матрицу мира объекта. В зависимости от времени выполнения tick этого достаточно:

camFwd.setFromMatrixPosition( this.camera.object3D.matrixWorld );
dir.setFromMatrixPosition( this.el.object3D.matrixWorld );

Код просто извлекает позицию из мировой матрицы, не обновляя ее. Вы можете использовать аналогичный подход для вектора направления, хотя код немного сложнее:

var e = this.camera.object3D.matrixWorld.elements;
camFwd.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
...