객체 지향 OpenGL


12

한동안 OpenGL을 사용하고 있으며 많은 자습서를 읽었습니다. 많은 사람들이 여전히 고정 파이프 라인을 사용한다는 사실 외에도 일반적으로 모든 초기화, 상태 변경 및 드로잉을 하나의 소스 파일에 넣습니다. 튜토리얼의 제한된 범위에는 문제가 없지만 전체 게임으로 확장하는 방법을 연구하는 데 어려움을 겪고 있습니다.

OpenGL 사용법을 파일간에 어떻게 분할합니까? 개념적으로, 순수한 화면에 물건을 렌더링하는 렌더링 클래스의 이점을 볼 수 있지만 쉐이더 및 조명과 같은 물건은 어떻게 작동합니까? 조명 및 쉐이더와 같은 별도의 클래스가 있어야합니까?


1
더 많은 코드를 가진 더 큰 튜토리얼뿐만 아니라 오픈 소스 게임도 있습니다. 그중 일부를 확인하고 코드가 어떻게 구성되어 있는지 확인하십시오.
MichaelHouse

렌더링 엔진과 관련하여 초보자입니까?
Samaursa

이 질문은 범위를 좁히지 않으면 합리적으로 대답 할 수 없습니다. 무엇을 만들려고합니까? 어떤 종류의 게임, 어떤 종류의 그래픽 등이 있습니까?
Nicol Bolas

1
@Sullivan : "이러한 개념은 거의 모든 게임에 적용될 것이라고 생각했습니다." 그들은하지 않습니다. Tetris를 만들도록 요청하면 OpenGL을 중심으로 큰 래퍼 레이어 또는 무언가를 만드는 것을 귀찮게하지 않을 것입니다. 직접 사용하십시오. Mass Effect와 같은 것을 만들려면 렌더링 시스템 주위에 여러 계층의 추상화가 필요합니다. 테트리스에서 언리얼 엔진을 던지는 것은 샷건을 사용하여 파리를 사냥하고 있습니다. 직접 코딩하는 것보다 훨씬 어렵습니다. 당신은 큰 당신이 같은 시스템의 복잡 구축해야 필요 하고, 크지.
Nicol Bolas

1
@ 설리번 (Sullivan) : 귀하의 질문이 암시하는 유일한 복잡성은 여러 파일로 나누는 것에 대해 이야기하는 것입니다. 테트리스에서도 할 수있는 일입니다. 그리고 테트리스와 언리얼 엔진 사이에는 많은 수준의 복잡성이 있습니다. 또 다시 : 당신은 어느 것을 요구하고 있습니까?
Nicol Bolas

답변:


6

나는 OO OpenGL이 필요하지 않다고 생각합니다. 셰이더, 모델 등 클래스에 대해 이야기 할 때 다릅니다.

기본적으로 게임 / 엔진 초기화를 먼저 수행합니다. 그런 다음 텍스처, 모델 및 셰이더를 RAM (필요한 경우) 및 버퍼 객체에로드하고 셰이더를 업로드 / 컴파일합니다. 그런 다음 데이터 구조 또는 셰이더 클래스에서 모델 에는 셰이더, 모델 및 텍스처 버퍼 객체의 ID 가 int 입니다.

대부분의 엔진에는 엔진 구성 요소가 있으며 모든 엔진에는 특정 인터페이스가 있다고 생각합니다. 내가 본 모든 엔진에는 Renderer 또는 SceneManager 또는 둘 다 와 같은 구성 요소가 있습니다 (게임 / 엔진의 복잡성에 따라 다름). 당신은 할 수있는 것보다 OpenGLRenderer의 렌더러 인터페이스를 구현하는 클래스 및 / 또는 DXRenderer합니다. 그런 다음 SceneManagerRenderer 가있는 경우 다음 작업 중 일부를 수행 할 수 있습니다.

  • 렌더링을 위해 SceneManager를 트래버스 하고 각 객체를 렌더러 로 전송
  • 일부 SceneManager 방법 에서 대문자 캡슐화
  • 처리하도록 SceneManager렌더러로 보냅니다.

렌더러는 아마도 구성된 각 메시의 드로우 함수를 호출하는 오브젝트의 드로우 함수를 호출하고 메시는 텍스처 오브젝트를 바인딩하고 셰이더를 바인딩하며 OpenGL 드로우 함수를 호출 한 다음 셰이더, 텍스처 및 오브젝트 데이터 버퍼 오브젝트를 사용하지 않습니다.

참고 : 이것은 단지 예일뿐입니다. SceneManager 를 더 자세히 연구 하고 사용 사례를 분석하여 최상의 구현 옵션이 무엇인지 확인해야합니다.

물론 비디오 및 RAM 메모리 사용을 모두 처리하는 MemoryManager , ResourceLoader 등과 같은 엔진의 다른 구성 요소가 있으므로 필요에 따라 특정 모델 / 셰이더 / 텍스처를로드 / 언로드 할 수 있습니다. 여기에는 메모리 캐싱, 메모리 매핑 등이 포함됩니다. 각 구성 요소에 대한 자세한 내용과 개념이 있습니다.

다른 게임 엔진에 대한 자세한 설명을 살펴보십시오. 많은 게임 엔진이 있으며 설명서가 거의 있습니다.

그러나 그렇습니다. 수업은 인생을 더 쉽게 만듭니다. 당신은 그것들을 완전히 사용하고 캡슐화, 상속, 인터페이스 및 더 멋진 것들에 대해 기억해야합니다.


이것은 내가 찾고있는 대답입니다. 그러나 "... 텍스처, 모델 및 셰이더를 RAM (필요한 경우) 및 버퍼 객체에로드하고 셰이더 업로드 / 컴파일 ..."이라고하면 원래의 질문으로 되돌아갑니다. 모델과 셰이더와 같은 것을 캡슐화하기 위해 객체를 사용해야합니까?
설리번

객체는 클래스의 인스턴스이며 '전적으로 사용해야합니다'.
edin-m

죄송합니다. '어떻게 객체를 사용해야합니까?' 내 잘못이야.
설리번

글쎄, 그것은 당신의 수업 디자인에 달려 있습니다. 기본적인 예는 다음과 같이 직관적입니다. object3d (class)에는 메쉬 (class)가 있습니다. 각 메시에는 재질 (클래스)이 있습니다. 각 재질에는 텍스처 (클래스 또는 ID 일 수 있음)와 셰이더 (클래스)가 있습니다. 그러나 각 구성 요소에 대해 읽으면서 SceneManager, Renderer, MemoryManager를 만드는 데는 다르지만 동등한 접근 방식이 있음을 알 수 있습니다 (이들 모두 단일 클래스 또는 다중 클래스, 상속 등일 수 있음). 이 주제 (게임 엔진 아키텍처)에 대해 수십 권의 책이 쓰여졌으며, 질문에 대한 자세한 답변을 위해 책을 쓸 수 있습니다.
edin-m

이것이 내가 얻는 가장 좋은 대답이라고 생각합니다. 도와 주셔서 감사합니다 :)
Sullivan

2

OpenGL에는 이미 '개체'개념이 있습니다.

예를 들어, ID가있는 것은 객체로 통할 수 있습니다 (특별히 'Objects'라고 불리는 것들도 있습니다). 버퍼, 텍스처, 정점 버퍼 오브젝트, 정점 배열 오브젝트, 프레임 버퍼 오브젝트 등. 약간의 작업으로 수업을 둘러 쌀 수 있습니다. 또한 컨텍스트가 확장을 지원하지 않는 경우 사용되지 않는 이전 OpenGL 함수로 쉽게 넘어갈 수있는 방법을 제공합니다. 예를 들어 VertexBufferObject는 glBegin (), glVertex3f () 등을 사용하여 대체 될 수 있습니다.

기존 OpenGL 개념에서 벗어나야하는 몇 가지 방법이 있습니다. 예를 들어 버퍼에 메타 데이터를 버퍼 객체에 저장하려고합니다. 예를 들어 버퍼가 꼭짓점을 저장하는 경우입니다. 꼭짓점의 형식은 무엇입니까 (예 : 위치, 법선, 텍스 코드 등). 사용하는 기본 요소 (GL_TRIANGLES, GL_TRIANGLESTRIP 등), 크기 정보 (저장된 부동 수, 삼각형 수 등). 그것들을 draw arrays 명령에 쉽게 꽂기 위해.

나는 당신이 보는 것이 좋습니다 OGLplus . OpenGL에 대한 C ++ 바인딩입니다.

또한 glxx 는 확장 로딩에만 해당됩니다.

OpenGL API를 래핑하는 것 외에도 약간 더 높은 수준의 빌드를 만들어야합니다.

예를 들어 모든 셰이더를로드하고 사용하는 모든 셰이더를 담당하는 머티리얼 매니저 클래스가 있습니다. 또한 속성을 그들에게 전송하는 책임이 있습니다. 그렇게하면 다음과 같이 전화 할 수 있습니다 : materials.usePhong (); material.setTexture (sometexture); material.setColor (). 공유 균일 버퍼 객체와 같은 최신 기능을 사용하여 쉐이더가 1 블록에서 사용하는 모든 속성을 포함하는 하나의 큰 버퍼를 가질 수 있기 때문에 유연성이 향상됩니다. 지원되는 경우 균일 한 루틴을 사용하여 1 개의 큰 모 놀리 식 셰이더를 사용하고 서로 다른 셰이더 모델간에 교체하거나 여러 개의 작은 셰이더를 사용할 수 있습니다.

또한 셰이더 코드 작성을 위해 GLSL 사양에서 소비되는 것을 볼 수 있습니다. 예를 들어 #include는 셰이더 로딩 코드에서 매우 유용하고 구현하기가 매우 쉽습니다 ( ARB 확장 기능 도 있음). 또한 지원되는 확장명에 따라 코드를 즉시 생성 할 수 있습니다 (예 : 공유 유니폼 객체 사용 또는 일반 유니폼 사용으로 대체).

마지막으로 장면 그래프, 특수 효과 (흐림, 광선), 그림자, 조명 등과 같은 여러 렌더링 패스가 필요한 작업을 수행하는 고급 렌더링 파이프 라인 API가 필요합니다. 그리고 그 위에 그래픽 API와는 관련이 없지만 세계의 객체 만 다루는 게임 API가 있습니다.


2
"OGLplus를 살펴 보는 것이 좋습니다. OpenGL에 대한 C ++ 바인딩입니다." 나는 그것을 반대 하는 것이 좋습니다 . RAII를 좋아하지만 대부분의 OpenGL 객체에는 전적으로 부적절합니다. OpenGL 객체는 전역 구성과 관련이 있습니다 : OpenGL 컨텍스트. 따라서 컨텍스트가있을 때까지 이러한 C ++ 오브젝트를 작성할 수 없으며 컨텍스트가 이미 손상된 경우 이러한 오브젝트를 삭제할 수 없습니다. 또한 전역 상태를 변경하지 않고 객체를 수정할 수 있다는 환상 을 줍니다 . 이것은 EXT_DSA를 사용하지 않는 한 거짓말 입니다.
Nicol Bolas

@NicolBolas : 컨텍스트가 있는지 확인한 다음 초기화해야합니까? 아니면 관리자 만 OpenGL 컨텍스트가 필요한 객체를 만들 수 있습니까? --- btw, 훌륭한 튜토리얼 세트 (프로필의 링크)! 어떻게 든 OpenGL / Graphics를 검색 할 때 결코 그들을 보지 못했습니다.
Samaursa

@Samaursa : 끝까지? OpenGL 객체 관리자가 있다면 ... 객체를 스스로 관리 할 필요는 없습니다. 관리자가 그들을 위해 할 수 있습니다. 컨텍스트가 존재할 때만 초기화하면 제대로 초기화되지 않은 객체를 사용하려고하면 어떻게됩니까? 코드베이스에 연약함이 생깁니다. 전역 상태를 건드리지 않고 이러한 객체를 수정하는 기능에 대해 말한 내용도 변경하지 않습니다.
Nicol Bolas

@NicolBolas : "컨텍스트가 생길 때까지 이러한 C ++ 객체를 생성 할 수 없습니다"... 베어 OpenGL 구문을 사용하는 것과 다른 점이 있습니까? 내 눈에 oglplus::Context클래스는 이러한 의존성을 눈에 띄게 만듭니다. 문제가 될까요? 새로운 OpenGL 사용자가 많은 문제를 피하는 데 도움이 될 것이라고 생각합니다.
xtofl

1

현대 OpenGL에서는 서로 다른 vaos 및 shader 프로그램을 사용하여 렌더링 된 객체를 서로 완전히 분리 할 수 ​​있습니다. 그리고 하나의 객체의 구현조차도 많은 추상화 계층으로 분리 될 수 있습니다.

예를 들어, 터 레인을 구현하려면 생성자가 터 레인에 대한 정점과 인덱스를 생성하고 배열 버퍼로 설정하고 속성 위치를 지정하면 데이터를 음영 처리하는 TerrainMesh를 정의 할 수 있습니다. 또한 렌더링 방법을 알고 있어야하며 렌더링을 설정하기 위해 수행 한 모든 컨텍스트 변경 사항을 되돌려 야합니다. 이 클래스 자체는 렌더링 할 셰이더 프로그램에 대해 아무 것도 알 수 없으며 장면의 다른 객체에 대해서도 아무것도 알지 않아야합니다. 이 클래스 위에서 셰이더 코드를 인식하는 Terrain을 정의 할 수 있으며 그 역할은 셰이더와 TerrainMesh 사이의 연결을 만드는 것입니다. 이것은 속성과 균일 한 위치를 가져오고 텍스처에로드하는 것을 의미합니다. 이 클래스는 지형이 어떻게 구현되는지, 어떤 LoD 알고리즘을 사용하는지, 지형을 음영 처리하는 것에 대한 책임은 없습니다. 위에서, 동작 및 충돌 감지 등과 같은 OpenGL 이외의 기능을 정의 할 수 있습니다.

결론적으로 OpenGL은 저수준으로 사용되도록 설계되었지만 독립적 인 추상화 계층을 계속 만들 수 있으므로 언리얼 게임 크기로 확대 할 수 있습니다. 그러나 원하는 레이어 수는 실제로 원하는 응용 프로그램의 크기에 따라 다릅니다.

그러나이 크기에 대해 스스로 거짓말하지 말고 10k 라인 애플리케이션에서 Unity의 객체 모델을 모방하려고 시도하지 마십시오. 결과적으로 완전한 재앙이 될 것입니다. 계층을 점차적으로 빌드하고 필요할 때 추상화 계층의 수만 늘리십시오.


0

ioDoom3은 아마도 훌륭한 코딩 연습을 따르기 위해 Carmack에 의존 할 수 있기 때문에 아마도 훌륭한 출발점이 될 것입니다. 또한 그가 Doom3에서 메가 텍스쳐링을 사용하지 않는다고 믿기 때문에 렌더 파이프로 비교적 간단합니다.


6
"당신은 훌륭한 코딩 관습을 따르기 위해 Carmack에 의지 할 수 있듯이"오 이런, 좋은 일입니다. Carmack은 훌륭한 C ++ 코딩 방법을 따릅니다. 그것은 폭동입니다! 아 ... 농담이 아니었다. 음 ... 혹시 실제로 한 보고 자신의 코드를? 그는 C 프로그래머이고 그렇게 생각합니다. C에는 문제가 없지만 C ++ 에 대한 질문입니다 .
Nicol Bolas

나는 C 배경에서 왔으므로 그의 코드는 나에게 많은 의미가 있습니다 .P와 그렇습니다. 지진 기반 게임에서 약간의 시간을 보냈습니다.
chrisvarnz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.