1.10 트라이앵글 스트립

지금까지 우리는 정점 토폴로지로 트라이앵글 리스트만을 사용해왔습니다. 그러나 트라이앵글 리스트가 정점을 구성하는 유일한 방법은 아닙니다. GPU 파이프라인은 데이터 크기 효율성 측면에서 유리한 다른 옵션들을 제공합니다. GPU 메모리는 소중하며, CPU와 GPU 메모리 간의 데이터 전송은 느릴 수 있으므로 전송하는 데이터 양을 최적화하는 것이 중요합니다.

플레이그라운드 실행 - 1_10_triangle_strips

트라이앵글 리스트는 직관적이지만, 중복된 정점 문제가 있습니다. 공유되는 정점들이 여러 번 전송되어 데이터 크기를 불필요하게 늘립니다. 하지만 더 효율적인 방법이 있습니다. 바로 트라이앵글 스트립(triangle strip)입니다.

triangle-strip 토폴로지를 사용하면 반복적인 정점을 GPU로 보내는 것을 피하여 대역폭과 연산 자원을 절약할 수 있습니다.

샘플에 사용된 트라이앵글 스트립 토폴로지
샘플에 사용된 트라이앵글 스트립 토폴로지

토폴로지를 전환해도 셰이더 코드를 변경할 필요는 없습니다. 셰이더 수준에서는 개별 정점을 다루며, 이 정점들이 어떻게 구성되거나 삼각형으로 연결되는지에 대해서는 알지 못합니다.

const positions = new Float32Array([
    100.0, -100.0, 0.0,
    100.0, 100.0, 0.0,
    -100.0, -100.0, 0.0,
    -100.0, 100.0, 0.0
]);

let positionBuffer = createGPUBuffer(device, positions, GPUBufferUsage.VERTEX);

const texCoords = new Float32Array([
    1.0,
    0.0,
    // 🔴

    1.0,
    1.0,

    0.0,
    0.0,

    0.0,
    1.0
]);

let texCoordsBuffer = createGPUBuffer(device, texCoords, GPUBufferUsage.VERTEX);

전환을 위해 정점 데이터가 생성되는 JavaScript 코드를 업데이트해야 합니다. 이전에는 직사각형을 형성하기 위해 6개의 정점이 필요했습니다. 이는 직사각형이 두 개의 삼각형으로 나눌 수 있으며, 각 삼각형은 3개의 정점으로 구성되고 그중 두 개는 공유되기 때문입니다. 이제 triangle-strip을 사용하면 공유 정점을 중복하지 않으므로 네 개의 점만 있으면 됩니다. 이 정점들은 지그재그 또는 triangle-strip 패턴으로 정렬되어야 합니다. 유사한 조정이 텍스처 좌표에도 적용되어 두 개의 좌표를 절약할 수 있습니다.

primitive: {
    topology: 'triangle-strip',
    frontFace: 'ccw',
    cullMode: 'none'
}

파이프라인 디스크립터를 정의할 때, 프리미티브 섹션에서 triangle-strip을 토폴로지로 지정합니다.

passEncoder = commandEncoder.beginRenderPass(renderPassDesc);
passEncoder.setViewport(0, 0, canvas.width, canvas.height, 0, 1);
passEncoder.setPipeline(pipeline);
passEncoder.setBindGroup(0, uniformBindGroup);
passEncoder.setVertexBuffer(0, positionBuffer);
passEncoder.setVertexBuffer(1, texCoordsBuffer);
passEncoder.draw(4, 1);
passEncoder.end();

마지막으로, 커맨드 버퍼를 생성할 때 그릴 정점의 수를 업데이트합니다. 이번에는 네 개의 정점만 그리지만, 최종 결과는 여전히 직사각형입니다.

이것으로 프리미티브 토폴로지를 전환하는 데 필요한 변경 사항을 마쳤습니다. triangle-strip은 데이터 크기 최적화를 제공하지만, 특정 메시 패턴을 따라야 합니다. 복잡한 메시를 여러 triangle-strip으로 분할하는 것이 항상 쉽지 않기 때문에 triangle-list는 여전히 가장 일반적인 옵션입니다. 다음 섹션에서는 인덱스 버퍼를 사용하여 데이터 최적화를 위한 보다 보편적인 접근 방식을 살펴보고, 토폴로지 패턴에 맞춰야 하는 필요성을 줄일 것입니다.

WebGPU는 아직 다루지 않은 세 가지 추가 토폴로지인 point-list, line-list, line-strip을 제공합니다. 이 토폴로지들은 삼각형이 아닌 개별 점과 선을 렌더링하는 데 특별히 사용됩니다. 이전에 언급된 삼각형 기반 토폴로지들과 달리, 이들은 정점들 사이에 어떠한 삼각형 연결성도 정의하지 않습니다.

GitHub에 의견 남기기