무언가를 그릴 때마다 glEnable과 glDisable을 호출해야 합니까?

StackOverflow https://stackoverflow.com/questions/802079

  •  03-07-2019
  •  | 
  •  

문제

다음과 같은 OpenGL 함수를 얼마나 자주 호출해야 합니까? glEnable() 또는 glEnableClientState() 그리고 그에 상응하는 glDisable 상대방?응용 프로그램 시작 시 한 번 호출되도록 되어 있습니까? 아니면 비활성화된 상태로 두고 무언가를 그리는 데 즉시 필요한 기능만 활성화해야 합니까?성능차이가 있나요?

도움이 되었습니까?

해결책

"조건에 따라서".

전체 앱이 하나의 enable/disable 상태 조합 만 사용하는 경우, 처음에는 처음으로 설정하고 이동합니다.

대부분의 실제 앱은 혼합해야하며 전화해야합니다. glEnable() 특정 상태를 활성화하려면 뽑기를 한 다음 glDisable() "무대를 지우기 위해"완료되면 다시.

상태 스위치가 때로는 비싸기 때문에 상태를 정리, 상태 추적 및 많은 최적화 체계가 발생합니다.

다른 팁

상태 변수의 값을 자주 확인하고 이후에 glEnable/glDisable을 호출하는 경우 속성 스택(glPushAttrib / glPopAttrib)을 사용하여 상황을 약간 정리할 수 있습니다.

속성 스택을 사용하면 코드 영역을 격리할 수 있으므로 한 섹션의 속성 변경이 다른 섹션의 속성 상태에 영향을 주지 않습니다.

void drawObject1(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);    

  /* Isolated Region 1 */

  glPopAttrib();
}        

void drawObject2(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_FOG);
  glEnable(GL_GL_POINT_SMOOTH);    

   /* Isolated Region 2 */

  glPopAttrib();
}    

void drawScene(){
  drawObject1();
  drawObject2();
}

하지만 GL_LIGHTING 그리고 GL_DEPTH_TEST drawObject1에 설정되어 있으면 상태가 drawObject2에 유지되지 않습니다.glPushAttrib가 없으면 그렇지 않습니다.또한 함수 호출이 끝날 때 glDisable을 호출할 필요가 없으며 glPopAttrib가 작업을 수행합니다.

성능 측면에서는 glEnable/glDisable에 대한 개별 함수 호출로 인한 오버헤드가 최소화됩니다.많은 상태를 처리해야 하는 경우 자체 상태 관리자를 만들거나 glGetInteger를 여러 번 호출해야 할 것입니다...그런 다음 그에 따라 행동하십시오.추가된 기계 및 제어 흐름으로 인해 코드의 투명성이 떨어지고 디버깅이 더 어려워지며 유지 관리가 더 어려워질 수 있습니다.이러한 문제로 인해 더 유익한 다른 최적화가 더 어려워질 수 있습니다.

속성 스택은 추상화 계층을 유지하고 격리 영역을 생성하는 데 도움이 될 수 있습니다.

glPushAttrib 맨페이지

우선, 어떤 OpenGL 버전을 사용하십니까? 그리고 대상 그룹의 어떤 생성 그래픽 하드웨어가 있습니까? 이것을 아는 것은보다 정당한 대답을 더 쉽게 만들 수 있습니다. 내 대답은 OpenGL 2.1을 가정합니다.

OpenGL은 상태가 변경 될 때마다 새로운 OpenGL API 호출을 통해 프로그래머가 다시 명시 적으로 변경 될 때까지 해당 상태가 "전류"로 만들어집니다. 클라이언트 상태 배열 호출이 현재 정점 색상을 정의하지 않은 것처럼이 규칙에 대한 예외가 존재합니다. 그러나 규칙을 정의하는 예외입니다.

"응용 프로그램의 시작 부분에 한 번"응용 프로그램이 여전히 실행중인 동안 OpenGL 컨텍스트를 파괴 해야하는 시간이 있기 때문에 그다지 의미가 없습니다. 모든 윈도우 생성 직후에 의미가 있다고 가정합니다. 상태에 맞는 것이 나중에 변경 될 필요가 없습니다. : 모든 드로우 호출이 동일한 Vertex 어레이 데이터를 사용하는 경우 나중에 GldisableClientState로 비활성화 할 필요가 없습니다.

이전 고정 기능 파이프 라인과 관련된 많은 활성화/비활성 상태가 있습니다. 이것에 대한 쉬운 구속은 다음과 같습니다. 셰이더를 사용하십시오! 최대 5 년에 카드 세대를 목표로한다면 어쨌든 고정 기능 파이프 라인을 모방 할 것입니다. 셰이더를 사용하면 변환 및 래스터 화 단계에서 발생하는 일을 다소 완전히 제어 할 수 있으며 변경/업데이트가 매우 저렴한 유니폼으로 자신의 "상태"를 만들 수 있습니다.

OpenGL이 위에서 언급 한 것처럼 State Machine이라는 것을 아는 것은 가능한 한 상태 변경을 최소로 유지하기 위해 노력해야한다는 것을 분명히해야합니다. 그러나 상태 호출을 활성화/비활성화하는 것보다 성능에 훨씬 더 많은 영향을 미치는 다른 것들이있을 것입니다. 그들에 대해 알고 싶다면 읽으십시오.


상태의 비용 ~ 아니다 기존 고정 기능 상태 호출과 관련이 있으며 간단하지 않은 상태가 아닌 상태는 비용이 크게 다를 수 있습니다. 특히 셰이더를 연결하고 바인딩 이름, (텍스처, 프로그램, 버퍼 객체의 "이름")는 일반적으로 상당히 비쌉니다. 그렇기 때문에 텍스처에 따라 메시의 드로우 순서를 정렬하는 데 사용되는 많은 게임과 응용 프로그램이 이유입니다. 그런 식으로 그들은 같은 질감을 두 번 묶을 필요가 없었습니다. 그러나 요즘에는 셰이더 프로그램에도 동일하게 적용됩니다. 필요하지 않으면 동일한 셰이더 프로그램을 두 번 묶고 싶지 않습니다. 또한 특정 OpenGL 버전의 모든 기능이 해당 카드의 공급 업체가 OpenGL을 준수한다고 주장하더라도 모든 카드에 하드웨어 가속되는 것은 아닙니다. 준수한다는 것은 그들이 사양을 따른다는 것을 의미합니다. gl__ arb __imaging의 glhistogram 및 glminmax와 같은 일부 기능은 이와 관련하여 기억되어야합니다.


결론 : 명백한 이유가 없다면 셰이더를 사용하십시오! 유니폼을 대신 사용할 수 있기 때문에 많은 비정상적인 상태 호출에서 당신을 절약 할 수 있습니다. OpenGL 셰이더는 방금 약 6 년 동안 알고있었습니다. 또한 상태 변경을 활성화/비활성화하는 오버 헤드 ~할 수 있다 문제가되지만 일반적으로 Gluseprogram, Glcompileshader, Gllinkprogram, Glbindbuffer 및 Glbindtexture와 같은 다른 비싼 상태 변경을 최적화함으로써 더 많은 것이 더 많습니다.

추신 : OpenGL 3.0 클라이언트 상태를 제거/비활성화 한 통화를 제거했습니다. 드로우 어레이 가이 버전에서 그리는 유일한 방법이므로 암시 적으로 활성화됩니다. 즉각적인 모드가 제거되었습니다. GL.. 포인터 호출도 제거되었습니다.

내가 가르친 경험의 규칙은 현재 상태를 확인하고 필요한 경우에만 변경하기보다는 거의 항상 활성화/비활성화하는 것이 거의 항상 더 저렴하다고 말했습니다.

즉, Marc의 대답은 확실히 작동 해야하는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top