← 목록으로
창의개인연구

창의개인연구 ④ Three.js DragControls로 3D 공간 음향 인터페이스 만들기

3

창의개인연구 시리즈. 2D 데모를 거쳐 본격적으로 3D 공간 위에서 청감 실험을 하기 위한 인터페이스를 만든다.

다시 3D로

③ 글에서 2D 캔버스로 후퇴해 거리 모델과 팝 노이즈 같은 디테일을 정리했다. 이제 음원이 머리 위/아래에 있는 경우, 그리고 사용자가 자유롭게 회전시키며 음원을 둘러보는 경우를 실험하려면 다시 3D가 필요하다.

이번에는 Three.js 임포트 문제를 먼저 해결하고 들어갔다. 핵심 변화는 두 컨트롤러를 동시에 쓰는 구조다.

  • OrbitControls — 마우스 좌클릭으로 시점을 회전, 휠로 줌 인·아웃. 카메라를 움직인다.
  • DragControls — 씬 안의 오브젝트를 직접 잡아 끌 수 있게 해 준다. 음원을 움직인다.

이 두 컨트롤러가 같은 마우스 입력을 두고 충돌하지 않도록 우선순위를 잡는 게 첫 과제였다. 결국 "DragControls가 오브젝트 위에서 드래그를 잡을 때만 OrbitControls를 임시로 비활성화"하는 식으로 정리했다.

씬 구성

  • 청자 — 노란 구. 원점(0, 0, 0)에 고정.
  • 음원 — 푸른 구. 사용자가 자유롭게 끌고 다닌다.
  • 유효 범위 — 가상 5m 정육면체. (m는 가상 단위. 실제 미터와는 무관하지만 직관적인 수치로 정함)

음원의 위치는 매 프레임마다 Three.js의 Vector3에서 Web Audio의 panner.positionX/Y/Z로 그대로 흘려보낸다. 이 한 줄짜리 동기화가 이번 데모의 본체이고, 나머지 코드는 전부 그것을 도와주는 보조 장치다.

function syncPanner(mesh, panner, t) {
  panner.positionX.setValueAtTime(mesh.position.x, t);
  panner.positionY.setValueAtTime(mesh.position.y, t);
  panner.positionZ.setValueAtTime(mesh.position.z, t);
}

positionX.value = ...로 한 번에 대입하면 AudioContext의 다음 처리 블록까지 보간 없이 점프해 가끔 클릭음이 들렸다. 짧은 시간을 주는 setValueAtTime / setTargetAtTime이 더 안정적이었다.

두 가지 음원 모드

모드 구현 특징
합성 톤 OscillatorNode 사인·삼각·사각·톱니파 + 주파수 슬라이더
파일 재생 AudioBufferSourceNode 사용자가 직접 올린 WAV/MP3

파일 재생 모드는 청감 실험을 훨씬 다양하게 만들었다. 짧은 효과음뿐 아니라 노래 파일을 넣어도 위치 이동에 따라 공간감이 자연스럽게 바뀌었다. 다만 큰 파일은 decodeAudioData 단계에서 약간의 지연이 있었다.

슬라이더로 노출한 파라미터

  • 볼륨GainNode.gain 직결.
  • 높이(Y) — 마우스로 잡는 게 어색해서, 별도 슬라이더로 위/아래만 따로 컨트롤.
  • 거리 모델inverse로 고정(③에서 검증).
  • 팬닝 모델HRTF로 고정.
  • 감쇠 파라미터refDistance, rolloffFactor는 기본값 유지.

높이를 별도 슬라이더로 분리한 이유는, 화면 평면 위에서 드래그하는 동작이 Z축 변화에 가깝게 인식되기 때문이다. 마우스 드래그로 위·아래 이동을 시도하면 의도와 어긋난다. UI를 의도와 일치시키는 것만으로도 청감 검증이 훨씬 명확해졌다.

청감으로 얻은 인상

헤드폰 기준으로,

  • 슬라이더보다 직접 잡아서 움직였을 때 위치 인지 속도가 확실히 빨라졌다. "방금 음원이 내 머리 옆을 스쳐 지나갔다"는 감각이 또렷이 들어왔다.
  • Y축 변화는 의외로 인지되었다. 머리 위쪽에서 들리는 듯한 인상이 약하지만 분명히 생긴다.
  • **Z축(앞뒤)**은 여전히 약하다. 정면과 배면의 차이는 방향보다는 거리감의 변화로 해석되는 경향이 강했다. 일반화된 HRTF의 한계와 스테레오 출력의 한계가 겹친 결과로 보인다.

한계

이 데모는 "한 개의 음원을 직관적으로 옮긴다"는 단순한 형태였다. 실제 보조 장치는 한 개의 장애물만 다루지 않는다. 보행자, 차량, 벽처럼 동시다발적으로 발생하는 다수의 음원을 어떻게 분리해서 인지시키느냐가 진짜 문제다.