이전 글에서 이미지, 캔버스, 비디오를 텍스처로 로딩하는 방법을 알아봤습니다.
이 글에서는 WebGPU에서 비디오를 사용하는 보다 효율적인 방법을 설명합니다.
이전 글에서 비디오를 WEbGPU 텍스처로 로딩할 때 copyExternalImageToTexture를 호출하였습니다.
이 함수는 비디오의 현재 프레임을 우리가 만들어둔, 이미 존재하는 텍스처에 복사하였습니다.
WebGPU에는 비디오를 사용하는 또다른 방법이 있습니다.
importExternalTexture인데 이름에서 알 수 있듯이 이 함수는 GPUExternalTexture를 반환해줍니다.
이 외부(external) 텍스처는 비디오데이터를 직접 표현합니다. 복사가 필요하지 않습니다. [1]importExternalTexture에 비디오를 넣어주면 텍스처가 반환되고, 바로 사용할 수 있습니다.
importExternalTexture의 텍스처를 사용할 때는 몇 가지 큰 유의사항이 있습니다.
텍스처는 현재 자바스크립트 작업이 종료될 때까지만 유효합니다.
대부분의 WebGPU 앱의 경우 위 말은 텍스처가 requestAnimationCallback 함수가 끝날때까지만 존재한다는 뜻입니다.
또는 requestVideoFrameCallback, setTimeout, mouseMove 와 같은 다른 렌더링을 수행하는 이벤트일 수도 있습니다.
함수가 종료되면 텍스처가 만료(expired)됩니다.
비디오를 다시 사용하려면 importExternalTexture를 다시 호출해야만 합니다.
이 말인즉, importExternalTexture를 호출할 때마다 새로운 바인드그룹을 만들어서[2] 새로운 텍스처를 셰이더에 전달할 수 있어야 한다는 뜻입니다.
const newTexture = device.importExternalTexture(...); const same = oldTexture === newTexture;
같은 텍스처라면 이미 존재하는 바인드그룹과 참조된 oldTexture를 사용 가능합니다.
셰이더에서 texture_external 를 사용해야만 합니다.
이전 텍스처 예제에서는 모두 texture_2d<f32>를 사용했지만 importExternalTexture에서 만들어진 텍스처는 texture_external를 사용한 바인딩 포인트에만 바인딩 될 수 있습니다.
셰이더에서 textureSampleBaseClampToEdge 를 사용해야만 합니다.
이전 텍스처 예제에서는 모두 textureSample를 사용했지만 importExternalTexture에서 만들어진 텍스처는 textureSampleBaseClampToEdge만 사용할 수 있습니다. [3]
이름 그대로, textureSampleBaseClampToEdge는 기본 텍스터 밉 레벨 (레벨 0)만 샘플링합니다.
다시 말해, 외부 텍스처는 밉맵을 사용할 수 없습니다.
게다가, edge clamping을 하기 때문에 addressModeU: 'repeat'는 무시됩니다.
fract를 아래와 같이 사용하면 직접 반복(repeat)을 할 수 있습니다.
let color = textureSAmpleBaseClampToEdge(
someExternalTexture,
someSampler,
fract(texcoord)
);`
이러한 제약들이 문제가 있다면 이전 글에서와 같이 copyExternalImageToTexture를 사용해야만 합니다.
importExternalTexture를 사용한 예제를 만들어 봅시다.
비디오는 아래와 같습니다.