glDrawArrays와 glDrawElements의 차이점


12

는 OpenGL ES에 내 마음을 상쾌하게하는 동안, 나는 우연히 glDrawArrays하고 glDrawElements.

나는 그것들이 어떻게 사용되는지 이해하고 왜 그들이 다른지 이해합니다.

내가 이해하지 못하는 것은 glDrawElements무승부 전화를 저장 하는 방법을 알 수 없다는 것입니다 ( 무승부 전화 저장 은 내가 읽은 대부분의 책에서 언급 한 설명이므로 여기에 언급합니다).

두 개의 삼각형을 사용하여 정사각형을 그리는 간단한 시나리오를 상상해보십시오.

을 사용 glDrawArrays하는 동안 사용 하는 6 개의 정점 세트 glDrawElements가 필요하며 6 개의 요소가있는 인덱스 배열 외에 4 개만 필요합니다.

위의 내용을 감안할 때, 내가 이해하지 못하는 것이 있습니다.

  1. glDrawElements4 개의 요소 (6 번)가있는 정점 배열로 인덱스하기 위해 인덱스 배열 (정사각형 인 경우 6 개의 인덱스)을 사용해야하는 경우 그리기 호출을 어떻게 저장할 수 있습니까? 다시 말해, glDrawElements여전히 총 ​​6 개의 드로우 콜이 필요 하다는 의미 glDrawArrays입니까?
  2. glDrawElements정점과 인덱스에 각각 하나씩 2 개의 배열이 필요한 경우 공간 절약 을 사용하는 방법은 무엇입니까?
  3. 간단하게하기 위해 2 개의 삼각형에서 정사각형을 그리는 경우, 얼마나 많은 그리기 호출 glDrawElements(정점 배열의 4 개 항목과 색인 배열의 glDrawArrays6 개 항목 ) 및 (정점 배열의 6 개 항목)이 개별적으로 필요합니까?

감사.

답변:


16

각 glDraw *는 그리기 호출입니다.

1 glDrawArrays는 1 그리기 호출입니다.
1 glDrawElements는 1 그리기 호출입니다.

사용하는 정점 또는 인덱스의 수는 중요하지 않습니다 (드로우 콜 수에 관한 한). 1 glDraw *는 1 드로우 콜입니다.

쿼드를 그리는 간단한 사례 (사용하는 GL 버전이 쿼드를 제거하지 않았다고 가정) 또는 삼각형은 이들을 비교하기에 좋은 예가 아닙니다. 쿼드 목록 또는 삼각형 목록은 glDrawArrays는 인덱싱에 대한 추가 오버 헤드가 없기 때문에 더 효율적으로 나타납니다.

좀 더 복잡한 경우를 보자. 그러나보다 실제적인 시나리오를 나타내는 사례를 보자. 여러 개의 삼각형 스트립과 팬으로 구성된 모델이 있다고 상상해보십시오.

glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);

이 예제에서 glDrawArrays를 사용하면 모델에 대해 총 6 개의 그리기 호출이 제공됩니다. 그러나 스트립과 팬 모두 인덱스 된 삼각형으로 쉽게 변환 할 수 있으므로 인덱스를 추가하면 다음과 같이됩니다.

glDrawElements (GL_TRIANGLES, .....);

그것은 전체 모델에 대한 하나의 끌기 호출입니다.


glDrawArray에 비해 glDrawElements의 장점은 단순한 메모리 절약 이상의 것입니다. 이는 메모리를 측정하는 순진한 방법입니다. 인덱스가 일반적으로 정점보다 작기 때문에 정점을 재사용 할 수있는 메모리를 절약 할 수있는 가능성 이 있습니다 (따라서 균형에 대한 인덱스가 많더라도 더 작을 수 있음).

  • 드로우 콜 횟수 감소 각 드로우 콜은 유효성 검사 상태, 설정 등으로 인해 약간의 오버 헤드가 발생 하며이 오버 헤드의 대부분은 CPU 측에서 발생합니다. 드로우 콜 수를 줄임으로써 이러한 오버 헤드를 크게 피할 수 있습니다.

  • 정점 재사용. 이것은 단순한 메모리 절약 이상의 것입니다. GPU에는 하드웨어 정점 캐시가있을 수 있으며, 최근에 변환 된 정점을 저장할 수 있습니다. 동일한 꼭짓점이 다시 들어오고 캐시에 있으면 다시 변환하지 않고 캐시에서 재사용 할 수 있습니다. 하드웨어는 인덱스를 비교하여 캐시를 확인하므로 OpenGL 용어로 캐시를 사용하는 유일한 방법은 glDrawElements를 사용하는 것입니다.


구체적인 질문에 대답하려면 다음을 수행하십시오.

  1. glDrawElements가 그리기 호출을 어떻게 저장할 수 있습니까? 사용하는 예제에서는 그렇지 않습니다. 각각 하나의 드로우 콜이 있습니다. 위에서 논의했듯이이 예제는 두 가지를 비교하기에는 매우 나쁜 예입니다.

  2. glDrawElements를 사용하면 공간이 어떻게 절약됩니까? 인덱스가 꼭짓점보다 작기 때문입니다. 16 비트 인덱스는 2 바이트이고 위치 / 컬러 / 텍스처 정점은 24 바이트입니다. 6 개의 정점은 144 바이트, 4 개의 정점에 6 개의 색인은 108 바이트입니다.

  3. 2 개의 삼각형에서 정사각형을 그리는 경우 ...? 하나와 하나. glDraw * 호출은 하나의 드로우 호출이며, 사용 된 정점 또는 인덱스의 수는이 측정과 관련이 없습니다. 그러나 나는 다시 강조해야합니다.이 둘을 비교하기에는 매우 나쁜 예입니다.


마지막으로 문제를 조금 복잡하게 만드는 것은 삼각형이있는 glDrawElements가 데스크탑 GPU에서 최적의 경로이며, 모바일에서는 매우 다를 수 있습니다. 일부 모바일 GPU는 GL_TRIANGLE_STRIP (이 경우 기본 요소를 연결하기 위해 축퇴 삼각형을 추가 할 것)이있는 glDrawArrays를 선호 할 수 있으며 기본 다시 시작 또는 다중 그리기와 같은 고급 주제는 다루지 않았습니다.


의견을 보내 주셔서 감사합니다. 공유 한 내용을 읽는 데 시간이 조금 걸립니다. 귀하의 답변을 인정한다는 사실을 알려 드리고자합니다. 다시 감사합니다.
Unheilig

6 개의 DrawTriangleFans 및 DrawTriangleStrips 호출을 1 개의 단일 DrawTriangles 호출로 변환하는 예제에서. 이것이 실제로 성능을 향상 시킵니까? 100 개의 삼각형으로 구성된 삼각형 스트립을 그리는 것이 100 개의 삼각형을 개별적으로 그리는 것보다 훨씬 효율적이라는 점을 이해하면 1이 아닌 6 개의 함수 호출을 사용하여 발생하는 페널티를 쉽게 상쇄 할 수 있습니다.
Samuel Li

@SamuelLi 6 대 1은 크게 개선되지는 않으며 단순히 원리를 설명하기위한 것입니다. 또한 앞서 언급했듯이 스트립은 일반적으로 1998 년 이후의 데스크톱 하드웨어에서 인덱싱 된 목록보다 성능이 우수하지 않습니다. 스트립 사용을 알리는 문서의 날짜를 확인하십시오.
Maximus Minimus

설명해 주셔서 감사합니다. @MaximusMinimus
사무엘 리
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.