skyLibrary_inclue

1. <대단원 1>. openGL기본 학습

Intro
이 페이지는 위키를 연습?할겸 제가 현제 공부중인 openGL내용을 정리하기 위한 페이지입니다. 혹시 openGL을 공부하시는 분들은 참고하셔서 도움이 되면 좋겠습니다.
공부하는 도서는 openGL superbible 3판 번역서 + openGL Game programming 두권으로 하고 있습니다. 아마 openGL superbible은 이번달에 5판 원서가 해외에서 나오는 걸로 알고 있는데, 이걸 보시는 분은 참고해서 원서를 보는것도
나쁘지 않겟네요.

1.1. Chapter 1.OpenGL에서 3D그래픽 기본지식

  • openGL을 공부하기전에 이에 필요한 간단한? 용어와 개념을 간단히 정리하고 들어갑시다.

1.1.1. 팝핑(popping)현상

  • 핵심 정리 : 2차원 상에서 3차원 물체를 표현할때 앞면과 뒷면이 바뀌어서 보이는 현상을 팝핑 현상이라고 부른다.

: example : 정육각형을 그릴때 모든 변을 그린다면 우리는 뒷면과 앞면을 착각해서 볼 수 있다. 왜냐하면 뒷면에 해당하는 선들이 앞쪽에 위치한 선으로 착각할 수 있기 때문이다. 

이런 팝핑현상은 3차원적인 표현을 방해한다. 고로 보통 이를 제거하기위해서 뒷면을 그리는 선을 제거하여 3차원적인 표현을 더 생생하게 한다. 이렇게 뒷면의 선을 제거하는 방식을 은면제거 혹은 숨겨진 표면 제거라고 한다.


팝핑 현상의 예시
popping1.png
[PNG image (11.89 KB)]


은면제거 예시
poping3.png
[PNG image (10.91 KB)]


1.1.2. 랜더링 & 랜더(render)

  • 핵심정리 : 3차원 사물에 대한 정보를 가지고 화면(2차원)에 표시하는 것을 랜더(render)한다라고 말하고 랜더링이라고 한마디로 말한다.

1.1.3. 원근법

컴퓨터화면은 2차원이다. 하지만 우리가 3D게임을 할때 보면 그 내용물은 마치 3차원의 물체처럼 보인다. 하지만 실제로는 내용물은 2차원적인 것을 3차원처럼 보이게 만든것뿐이다. 그렇다면 어떻게 2차원적인것을 3차원적인것처럼 보이게 만들 수 있을까? 여러가지 방법이 잇지만 그중에 하나는 원근법을 사용한다는 것이다. 원근법이란 가까히 있는 것은 크게 멀리있는것은 조그마하게 표현하는것을 말한다. 더 정확히 말하자면 선사이의 각도를 조절하여 3차원효과를 내는 기법을 말한다.
원근법의 대표적인 예로는 우리가 수학을 배울때 쉽게 보는 정육각형 그림이다.

1.1.4. 색상과 조명 ,그림자 그리고 쉐이딩

3차원적인 요소를 더 두드러지게 표현하기 위해서는 쉐이딩을 사용하면 된다. 쉐이딩이란 입체적인 물체에 음영이나 색상 밝기 등을 잘 조절하여 표면에 입히는 기법을 말한다. 이런 기법을 통해서 정육각형같은 경우는 각 면을 도드라지게 표현할 수 있고, 더욱 실감나는 3차원적인 표현을 가능케 한다.

texture.png
[PNG image (12.08 KB)]

1.1.5. 텍스쳐 맵핑

지오메트리(도형)이 증가하면 증가할 수 록 그래픽하드웨어에서 처리해야할 일들은 많아진다. 만약 이렇게 많은 지오메트리(도형)을 일일히 쉐이딩 작업을 한다면 실시간 작업이
필요한 경우에는 속도저하에 대한 문제가 발생할 수가 있다. 이런점에서 텍스쳐 맵핑은 훌륭한 대안책이 될 수 있다. '''텍스쳐 맵핑이란 각 입체 표면에 미리준비해둔 이미지를
입히는 것을 이야기한다. 여기서 준비해둔 이미지를 텍스쳐라고 부르며, 텍스쳐의 각 요소를 텍셀 , 이런 텍셀을 물체의 표면에 맞춰 입히는 작업을 필터링'''
이라고 부른다.


1.1.6. 블랜딩

블랜딩(blending)이란 화면상에 색상과 물체를 혼합하는 효과를 이야기한다. 이를 사용하는 곳은 주로 두 이미지가 겹쳐있는 효과를 내기위해서 사용한다. 예를 들어
거울에 비치는 내모습을 표현할때를 생각해보면 거울이라는 이미지와 내 얼굴이 비치는 이미지를 합치는 효과를 생각하면 된다(반사효과).

1.1.7. 안티 알리어싱

컴퓨터는 기계어라는 언어라는 이진적인 표현(이진법적인 표현)을 사용한다. 한마디로 1011001과 같은 표현을 예시로 들 수 있는데, 이 때문에 연속적인 표현을 실질적으로 표현
하는것이 불가능하다. 선을 그린다고 보면 이는 점들의 집합에 해당할 뿐이고, 보이기에 선일 뿐이지 점들의 조밀한 집합에 불가하다. 그리고 컴퓨터에서의 점의
표현은 사각형의 점으로 표현이되는데 그 이유는 연속적인 표현이 불가한 컴퓨터로서는 완전히 동그랗게 이어진 원을 그리기에는 실수표현에 한계가 있기 때문이다.(무한 소수의
표현이 불가하다고 하는게 더 옳을 수도 있겟다.) 그래서 사각형으로 표현되어지는 점으로 원을 그리게되면 계단현상이 일어난 원을 보게 될것이다. 안티 알리어싱은 이러
란 계단현상을 부드럽게 표현해주는 방법을 말한다.



계단 현상 그림
antialiasing.png
[PNG image (13.94 KB)]




1.1.8. 실시간 3D & 비실시간 3D

  • 실시간 3D는 말그대로 사용자가 화면 구성에 필요한 데이터를 입력 즉시 화면에 반영하는 방식을 이야기한다. 예를 들어 비행기 시뮬레이션 프로그램이라던가, 게임을 예시로 들 수 있다.
  • 비실시간 3D는 반대로 미리 구성해둔 3D이미지를 화면에 보여주는 방식을 이야기한다. 예시로는 애니매이션이나 영화를 들 수 있겠다. 고품질 3D이미지같은 경우는 이를 랜더링하고 구성하는데에만 해도 몇시간이 걸릴 정도로 많은 시간이 소요되는데, 이를 위한게 미리 3D이미지를 구성해두고 화면에 띄워주면 즉시 화면에 보여줄 수 있어서 마치 실시간 랜더링한 것 처럼 보여줄 수 있다.

1.1.9. 즉시모드와 보류모드(씬그래프)

실시간 3D 그래픽을 위한 API 프로그래밍 방식에는 즉시모드와 보류모드 두가지 방법이 있다.
  • 보류모드란, api상에서 미리 어떤 기본적인 도형의 구성방식이나 처리방식이 내부적으로 정해져있는 상태에서 도형을 구성하는 데이터를 API 또는 툴킷에 제공함으로써 도형을 구성(이미지 구성)하는 방식을 이야기한다. 장면내의 모든 물체들과 그 사이의 관계를 미리 만들어진 데이터 구조로 만들어두는것을 씬그래프(scene graph)라 한다.
  • 즉시모드란, 그래픽 프로세서에 직접적인 명령을 전달해서 상태를 변경시켜 이어지는 모든 명령에 그 상태를 반영하는 방식을 이야기한다. 이 방식은 위에서 언급한 씬그래프에 API의 내부적인 동작에도 이 방식이 쓰인다. 즉시모드에서 이미 실행된 명령은 그 다음 명령에 영향을 받지 않는데 예를 들자면 화면에 하늘에 대한 폴리곤을 텍스쳐를 입힌뒤 이 텍스쳐 상태를 해제하고, 땅에 조명효과에를 주기 위해 조명효과 상태를 변경시킨다면, 화면에는 하늘에 미리 구성된 텍스쳐에는 변함이 없으며 하늘에 조명효과가 반영이 되고 땅은 텍스쳐 상태가 반영이 안되고 조명효과에 대한 것만 반영이 될 것이다.

1.1.10. 좌표체계

  • 화면을 구성하는 좌표방식은 우리가 보통사용하는 직교좌표계(데카르트 좌표계)말고도 여러가지가 있다. 이 좌표체계에 따라서 이미지 구성하는 방식도 완전히 달라질 수 있어서 이를 잘 고려해서 선택해야한다. 하지만 지금 우리는 일단 직교좌표계를 가지고 논해볼 것이다.

1.1.11. 뷰포트(viewport)와 클리핑(clipping)

  • 클리핑이란, 우리가 화면에 이미지를 그리기 위해서는 openGL에게 화면의 좌표 기준을 알려줄 필요가 있는데, openGL에게 화면 좌표계 영역을 정해주는 것을 클리핑이라고 한다.

:
example) 직사각형 좌측하단 (0.0) ~ 직사각형 우측 상단(100,100) 좌표로 구성되는 직사각형모양의 좌표계를 클리핑한다라고 보면 이 좌표계 영역은 중심이 (50,50)인 클리핑
영역이라고 한다. 만약 좌표중심을 (0,0)으로 만들고 싶다면 x축과 y축의 +영역좌표와 -영역좌표를 대칭형으로 만들어야한다. 
  • 뷰포트란, 화면의 좌측 하단이 0,0으로 기준을 두고 우리가 눈으로 보는 윈도우 창에서 임의의 크기를 할당해서 이미지 작업을 할 수 있는 화면에서의 실질적인 이미지 작업 영역를 이야기한다. 클리핑과 연관지어 이야기하면, 클리핑을 화면에 적용시키는 영역으로 말할 수 있겟다. 이 뷰포트는 보통 창 전체를 설정해두고 작업하지만, 특수한 경우 화면의 구성을 서로 다른 이미지로 구성해야한다면, 뷰포트를 나누어서 작업할 수 있다.

1.1.12. 직교 투영과 원근 투영

  • 고등학교 기하와 백터단원을 배울 때 projection(투영)을 배웠을 것이다. 이때 배운 투영이란, 직교 투영으로 2차원으로 구성된 면에 수직한 축을 기준으로 도형을 구성하는 점들을 면으로 수직하게 내리는 것을 말한다. 직교투영의 특징은 물체가 멀리있는가 없는가에 상관없이 같은 크기 비율로 표현이 된다는 점이다.
  • 원근 투영은 가까이 있는가 멀리있는가에 대한 표현을 가능케하는 비율을 적용한 투영으로 한점에서 퍼지는 빛을 생각하면 쉽게 알 수 있다.



원근투영 그림 예시
farprojection.png
[PNG image (14.54 KB)]


1.2. Chapter 2. openGL의 사용


  • 들어가기전에 openGL은 프로그래밍 언어가 아닌 그래픽 하드웨어 제어를 위한 소프트웨어 인터페이스이다. 그리고 높은 이식성을 지닌 그래픽&모델링 라이브러리이다. 다시말해, OpenGL은 언어가 아닌 API이다.

1.2.1. OpenGL의 작동방식



  • openGL의 내부는 상태들의 변화를 통해서 작동하는 기계상태로 동작한다.


  • openGL에는 창관리, 상호 작용 인터페이스에 대한 어떤 함수도 없다. 이는 일반적인 임플리먼테이션(지정된 규약을 구현한 구현체)에 적용하기 위해서이다. Mac이나 리눅스 윈도우 각각 환경에 대해서 모두 접근이 가능케 하기위함이라고 간단히 말할 수 있다.


  • 일반 적인 임플리먼테이션이라는 용어를 약간 자세히 설명하자면 이 말은 그래픽 이미지를 출력할 수 있는 시스템이라면 어디든지 이 openGL을 적용할 수 있어야한다는 걸 함축하는 용어라고 할 수 있다.

더 자세한 용어 설명 : 어떤 목적에 맞추어 프로그램을 작성하는 것(목적을 만족시키는 것)을 ‘임플리먼트한다’고 한다. - from <네이버 지식백과>


참고로 일반적인 임플리먼테이션은 소프트웨어 임플리먼테이션이다.



  • 그렇다면 이 openGL은 구체적으로 어떤식으로 작용하는가? 윈도우를 예시로 들어보자. 윈도우 같은 경우 어떤 화면에 이미지를 출력하려면 GDI(graphic Device Interface)라는 그래픽 장치 인터페이스를 통해서 출력장치로 출력데이터를 보내 출력한다.



  • openGL은 어플리케이션으로부터 구성하려는 이미지에 대한 정보를 받아 이미지를 구성후 이 GDI에게 구성한 이미지를 보내 출력장치가 이를 출력하게끔한다. 다른 운영체제도 마찬가지로 윈도우에서 GDI에 해당하는 부분만 다를뿐 과정은 같다.


1.2.2. openGL의 하드웨어 임플리먼테이션



  • openGL은 하드웨적으로 처리되는 부분도 있고 소프트웨어적으로 처리되는 부분이있다. 여기에서 말하고자 하는것은 하드웨어적인 것이다.



  • openGL의 하드웨어 임플리먼테이션은 그래픽 개발사에서 그래픽 카드 드라이버 형태로 개발되고 사용된다. openGL이 특정 플랫폼에서 시작하여 일반적인 플랫폼으로 전향하고 개방화를 실시했을때 각 그래픽 드라이버에 대한 openGL의 개발은 하드웨어 제작사에서 이루어져야 한다고 생각하고 그리 시행했는데, 이는 매우 적합한 선택이 되었고 이로 인해 하드웨어 임플리먼테이션은 그래픽 개발사에서 맡게되었다.



  • 하드웨어적인 내용을 설명하려면 우선 openGL의파이프라인에 대해서 설명해야한다. 고로 그 파이프라인에 대해서 살펴보자.

1.2.3. 파이프라인


  • 이는 그림부터 보여주고 설명하겟다.

pipeLine2.png
[PNG image (16.11 KB)]


  • 1. 우선 명령 버퍼에 openGL명령이 쌓인다.(vertex데이터와 텍스쳐 데이터가 쌓인다.)



  • 2. 그 다음, vertex데이터와 텍스쳐 데이터에 대해서 조명, 변환과정이 일어난다. 자세히 설명하자면, 물체를 구성하는 점들에 대해서 좌표변환, 방향변환을 수행하고 텍스쳐(이미지)에 대해서 조명이나 색상을 변화시키는 과정이라고 할 수 있다.



  • 3. 그 후 변환데이터를 레스터라이즈(화면에 나타날 화상을 구성하는 단계)부분으로 보낸후, 외관과 색상 텍스쳐, 지오메트리를 명령대로 구성하여 프레임 버퍼로 보낸다.



  • 4. 프레임 버퍼는 그래픽 출력장치의 메모리를 이야기하며, 여기에 올라간다는 이야기는 화면에 보여진다는 이야기와 같다.

1.2.4. 데이터 타입


  • openGL은 데이터타입을 내부적으로 정의 하고 내부에서 쓰고 있다. 이는 역시 일반적인 임플리먼테이션을 고수하기 위해서임은 당연한 사실이다.(각 환경마다 데이터 형식이 다르기 때문에 이를 모두수용하기 위해서는 자체적으로 정의한 데이터형식을 쓸 수 밖에 없다.)


  • 그리고 이 데이터타입은 openGL에 naming convention(이름 규칙)에 따라 정해져있는데 직관적이라 은근히 외우기 쉽다. 아래의 표를 살펴보자.


<openGL데이터 타입> <설명> <대응 c언어 데이터 타입> <변수 접두어 규칙>
GLbyte 8비트 정수 signed char b
GLshort 16비트 정수 short s
GLint, GLsizei 32비트 정수 long l
GLfloat, GLclampf 32비트 실수 float f
GLdouble, GLclampd 64비트 실수 double d
GLubyte, GLboolean 부호없는 8비트 정수 unsigned char ub
GLushort 부호없는 16비트 정수 unsigned short us
GLuint, GLenum, GLbitfield 부호없는 32비트 정수 unsigned long ui


  • openGL을 상징하는 GL을 앞에 붙히는건 이뿐만아니라 함수에도 적용된다는 사실을 하나 알아두자.

  • size 라는 단어가 들어간 타입은 길이나 깊이와 같은 값을 담는데 쓰이는 타입이라는 것을 나타낸다.

  • clamp라는 단어가 붙은 타입은 크기가 0.0에서 1.0사이로 범위가 제한되는 타입이라는 의미를 가진다.

  • enum은 열거형 boolean은 트루 폴스.

  • bitfield는 눈치 채셧듯이 바이너리 비트필드 값에 대한 타입이다. 앞서 말한 openGL의 내부는 상태에 대한 기계상태의 변화로 이루어 진다고 했는데 이게 나중에 상태에 대한 묶음을 표현하고 상태묶음을 그때그때 편리하게 변화할때 쓰인다.

1.2.5. 함수 이름 규칙


  • 규칙 : <라이브러리 이름><루트 명령어><(선택적) 인자의 수><(선택적)인자 타입>

  • 위와 같은 방식으로 함수 이름이 정해져있는데 예를 들어보자면 다음과 같다.

  • glColor3f(GLfloat a, GLfloat b, GLfloat c); ---->이와 같은 함수를 분석해보면, gl이라는 라이브러리에 Color라는 명령을 담당하는 float인자가 3개있는 함수이다.라고 해석할 수 있다.

  • 위의 규칙에서 (선택적)이라고 되어있는 것은 없을수도 있고 있을수도 잇다는 이야기이다. 위를 예를 이용해서 설명하자면, glColor()가 있 을 수 있다는 이야기이다.

  • 참고사항 : openGl의 내부적인 데이터타입은 float을 사용하고 있기 때문에 왠만해서는 이 데이터 타입에 맞게 데이터를 전달해주는게 정확도 측면이나 전체적인 성능 향상의 측면에서 더 좋다.
Retrieved from http://wiki.zeropage.org/wiki.php/OpenGL스터디
last modified 2021-02-07 05:23:55