2013-08-07 3 views
4

OpenGL에서 2D 배치 렌더러를 XNA/MonoGame 인터페이스에서 영감을 얻었지만 작은 디자인 문제로 인해 입력을 찾고 있습니다. 현재는 네 일반적인 방법으로 정점 데이터를 제출할 수 있습니다 : 다른 세 임의의 수를 (스프라이트와 모양이 독특한 변환을)를 포함 할 수있는 반면OpenGL 일괄 렌더러에서 임의의 버텍스 데이터 일괄 처리

void Render(const Sprite& sprite); 
void Render(const Shape& shape); 
void Render(const Vertex* vertices, unsigned int length); 
void Render(const Vertex* vertices, unsigned int length, const Texture* texture); 

스프라이트는 네 개의 정점, 색상 및 질감 좌표를 포함하고 있습니다. 모든 것은 질감 또는 비 질감 일 수 있습니다. 상태 변경 횟수와 OpenGL 그리기 호출 수를 줄이기 위해 모든 것을 배치하고 싶습니다. 대부분의 제출물이 꼭지점을 공유하여 glDrawArrays 대신 glDrawElements를 사용할 수 있다고 가정하는 것이 합리적이라고 생각하지만 위에서 설명한 내용을 적절하게 일괄 처리하는 방법을 파악하는 데 어려움이 있습니다.

XNA/MonoGame 스프라이트 정육점은 질감이있는 사각형/삼각형 및 임의의 모양이 아닌 모든 도구로만 작동하기 때문에 작동합니다. 또는 SFML 렌더러와 같이 할 수 있고 드로어 블 객체 각각에 대해 드로 콜을 발행 할 수 있지만 일괄 렌더링의 목적에 어긋납니다.

내 렌더러가 "모든 것을 해보려는 것"은 내가 피하고 싶은 느낌인데, 보통 내 경험으로 보면 너무 복잡해지기 때문에 기분이 좋습니다.

내가 묻는 것은 렌더러를 어떻게 다시 디자인 할 수 있습니까? 여러 제출물에 대해 개별 배치 목록을 보관할 수 있습니까? 렌더러를 어떻게 든 모듈화 할 수 있을까요? XNA/MonoGame 에서처럼 질감이있는 객체 만 허용해야합니까?

답변

6

좋아, 그래서 우리는 상태 변화와 전화를 최소화해야합니다. Vertex Buffer Objects 및 셰이더를 포함하여 최신 OpenGL을 사용하고 있다고 가정합니다.

하나의 접근법은 모든 정점 데이터가 동일한 형식을 갖도록하는 것입니다. 예를 들어, 각 정점에는 위치, 색상 및 텍스처 좌표 (xyz, rgba, uv)가 있습니다. VBO에서 정점 데이터를 인터리브하는 경우 렌더링 전에 glVertexAttribPointerglEnableVertexAttribArray에 대한 단일 호출 만 필요합니다.

이것은 텍스쳐링되지 않은 객체에 대한 일부 중복 데이터를 의미하지만, 모든 것을 단일 배치로 밀어 넣는 것이 좋습니다.

질감이없는 개체를 처리하려면 빈 흰색 텍스처를 바인딩하고 질감이있는 개체로 처리하십시오. 또는 조각 쉐이더에서 균일 변수 (0에서 1 사이의 부동 소수점)를 사용하고 mix 함수를 사용하여 텍스처 색상과 정점 색상을 혼합 할 수 있습니다. 배치 스프라이트 우리는 항상 GPU에 "세계"-coordinates을 업로드 할 수 있도록 우리가 먼저 CPU의 변환을 처리해야 모양으로

. 이렇게하면 각 스프라이트마다 변형 유니폼을 설정하지 않아도됩니다. 각 스프라이트마다 개별 그리기 호출이 필요합니다.

또한 가능한 한 텍스처별로 정렬해야합니다. 텍스처 바인딩은 수행 할 수있는 비싼 작업 중 하나입니다.

  • 하나의 형식으로 모든 정점 데이터를 보관 데이터를 저장하는 하나의 Vertex- 및 색인 버퍼 개체를 유지하고 VBO의 데이터를 인터리브 :

    우리의 접근 방식은 기본적으로 다음 아래로 비등

  • 세척 질감으로
  • 정렬 (우리가 그 옵션을 갈 경우 텍스처 혼합 균일 또는 설정) 우리는 텍스처를 변경할 때마다 버퍼
01의 데이터 (요소/배열을 그릴)

CPU에서 GPU 메모리로 데이터를 가져 오는 것은 다른 방법으로 수행 할 수 있습니다. 예를 들어 GPU에 충분히 큰 빈 메모리 버퍼를 먼저 할당하고 렌더 호출 중 하나를 수행 할 때마다 glBufferSubData을 사용하여 정점/인덱스 데이터의 하위 집합을 업로드합니다.

프로필 기억하십시오!

이런 종류의 작업을 수행 할 때 프로파일 링을하는 것이 매우 중요합니다. 예를 들어 배치 및 개별 그리기 호출 간의 성능을 비교하거나 glDrawArrays와 glDrawElements의 성능을 비교할 수 있습니다. 무료이고 아주 좋은 OpenGL 프로파일 러인 gDebugger을 사용하는 것이 좋습니다.

너무 큰 VBO는 hurt your performance 일 수 있습니다. 합리적인 크기로 유지하고 채울 때마다 드로우 콜을 사용하여 플러시하십시오.

+0

매우 견고한 정보입니다. 감사합니다. 실제로 총 3 개의 렌더러를 만들었지 만 (교육용으로 여러 버전 지원) 통찰력은 내가 볼 수있는 한 잘 번역됩니다. 내 버텍스는 같은 형식을 가지고 있습니다. 믹스 기능을 사용할 때 0과 1의 값, 전체 텍스처 색상 또는 전체 정점 색상 만 보간 할 것입니다. 맞습니까? 변환은 사용자가 제안한 것과 똑같이 처리됩니다. 또한 배치 렌더링 전에 언 텍스쳐 된 오브젝트를 배치에 복사하는 것을 고려했습니다. 나는 gDebugger에 대해 몰랐다. 링크를 가져 주셔서 감사합니다! – NordCoder