Super Kawaii Cute Cat Kaoani 컴퓨터 그래픽스 수업정리) 6_Viewing & Projection 2, Mesh

수업정리/컴퓨터 그래픽스

컴퓨터 그래픽스 수업정리) 6_Viewing & Projection 2, Mesh

치킨고양이짱아 2023. 1. 15. 16:53
728x90
728x90

Vertex Processing (Transformation Pipeline)

→ 오늘 배울거. projection transformation 의 또 다른 방법인 perspective projection과 viewport transformation

Perspective Effects(원근효과)

  • 멀리 있는건 작게 보이는 효과 → perspective projection에서는 렌더링도 이걸 반영해서 뒤에 있는걸 작게 보이도록 해야한다.
  • Vanishing point (소실점): 평행한 선들을 perspective drawing에서 연장에서 이으면 한점에서 만난다.

Perspective Projection

  • View volume: Frustum(절두체) → "Viewing frustum" 라고도 부른다.
  • Perspective projection: viewing frustum 을 canonical view volume으로 맵핑한다.

viewing frustums를 canonical view volume으로 맵핑하는게 왜 perspective effect를 내는가?

Let's first consider 3D View Frustum → 2D Projection Plane

(실제로는 View volume → Canonical View volume → 2D plane 과정을 거쳐야하지만,

헷갈리니까 View volume → 2D plane 과정을 바로 볼거다.)

Perspective projection

Homogeneous coordinates revisited

  • Homogeneous coordinate 개념이 또 사용된다.
  • 어떤 사람들은 projection이 homogeneous coordinate의 진짜 목표라고 말하기도 함

    (affine transformation 을 일관되게 처리하는게 진짜 목표가 아니라)

  • 근데 Perspective projection 에서는 division을 필요로 한다.

    → 이건 이제 affine transformation의 영역이 아니다.

    → affine transformation 에서는 평행은 평행으로 유지된다. 그래서

    소실점은 생기지 않음. (소실점은 평행한 선들이 만나는 점이니까)

  • Homogeneous coordinate 니까 점을 표현할 때 w = 1을 덧붙인다.
  • 그리고 arbitrary w에 대해서 다음 두 matrix가 같은 point를 의미한다고 약속하자.

    마지막 숫자가 1이 아니면 1이 되도록 전체를 나눠도 같은 Point를 의미한다.

Perspective projection

Perspective Projection Matrix

  • 우리지금까지 3D→ 2D example을 보고 perspective projection의 기초 아이디어를 살펴보았다.
  • 사실 3D → 2D로 바로 가는게 아니라 3D → 3D (View Frustum→ Canonical View volume) → 2D로 가야한다.

    하지만 헷갈리는 부분이 있어서 3D→ 2D의 예를 바로 보여줬음

  • 과정 일일히 따지면 projection matrix는 이렇게 표현된다.

glFrustum

  • glFrustum(left, right, bottom, top, near, far)

    : perspective projection matrix를 만들고 current matrix의 오른쪽에 곱하는 함수

    :마지막 인자 빼고는 모두 near plane 스펙을 명시하고 있음.

  • near과 far의 부호 → 무조건 양수여야한다!!!! (그럼 -붙어서 들어간다. 그리고 projection 했을때 양수쪽에 있는거임)
  • C ← CM_pers
  • 문제: 이 함수 직관적이지 않음. 조절하기가 쉽지가 않다.

gluPerspective()

  • gluPerspective(fovy, aspect, zNear, zFar)

    : perspective projection matrix를 만들고 current matrix의 오른쪽에 곱하는 함수

  • glFrustum()과 하는 일은 똑같음. 받는 인자만 다른거임

    근데 이 함수가 더 직관적이여서 많이 사용한다.

[Practice] glFrustum(), gluPerspective()

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE):

→ 그리는 도형의 앞면과 뒷면을 없애겠다는거. 그리고 테두리 선만 남기겠다는 의미임

Q. 코드에서 gluPerspective 가 gluLookAt 보다 먼저 오는 이유

→ 각 함수가 current Matrix의 오른쪽에 matrix를 곱하기 때문에 실제로 원하는 순서의 반대로 진행하는 거임

→ 그래서 순서가 glLoadIdentity() → glFrustm or gluPerspective → gluLookAt

(glLoadIdentity()는 먼저 꼭 해줘야한다. 이건 곱하는게 아니라 current matrix를 identity 로 만들어주는거니까)

Quiz #1

1) b, 2) a, 3) c

2번이 왜곡이 제일 작으니까 fovy 각도가 제일 작고

3번이 왜곡이 제일 크니까 fovy 각도가 제일 크다.

Viewport Transformation

Viewport Transformation Matrix

glViewport()

  • glViewport(xmin, ymin, width, height)

    xmin, ymin, width, height 값 모두 픽셀 단위로 명시된다.

🥵 주의해야할건 이 function은 viewport matrix를 만들어서 current matrix에 곱하지 않는다는거!

Viewport transformation은 OpenGL 에서 내부적으로 일워진다 우리가 transformation matrix를 곱해서 적용시킬 수 있는 건 canonical view volume 부터!

  • Default viewport setting for (xmin, ymin, width, height)는 (0, 0, window width, window height)임

    → 그래서 아무 설정안하고 띄웠을때 창 사이즈 전부를 활용하는거였다.

[Practice] glViewport()

glViewport는 매 랜더링마다 호출할 필요가 없다. 랜더링 하기 전에 한번만 호출하면 된다.

Mesh

→ 맞물리다 라는 뜻인듯

→ 물체 형태를 어떻게 표현할건지에 대한 이야기임/

Many ways to digitally encode geometry

  • geometry를 digitally하게 encode 하는 방법 크게 2가지로 분류할 수 있다.

    Explict: 명확하게 표현 → explit한 표현 중에서 무난하게 많이 사용되는 polygon mesh에 대해 배울거임

    Implict: 조금 간접적으로 표현

  • 각 choice에 잘맞는 작업들이 있음

The Most Popular One: Polygon Mesh

  • Polygon mesh: connect된 a bunch of polygon으로 3D space 상에 surface를 형성하는거

    → polygon: straight side로 된 closed shape

    → 많이 사용하는 polygon은 삼각형 또는 사각형(quads)

Triangle Mesh

  • Triangle Mesh를 많이 사용한다. 왜??

    → 다른 polygon을 사용하면 평면이 되지 않을 수 있다.

    하지만 삼각형은 항상 평면을 이룬다. (triangle always planar)

    → 다른 polygon은 볼록 다각형이 아닐 수 있음 (Non-convex)

    하지만 삼각형은 항상 볼록 다각형이다. (triangle always convex)

    → N-polygons은 항상 삼각형으로 나누어진다. (정삼각형은 아니더라도 삼각형으로 나누어짐)

  • 위의 이유로, modern GPU는 항상 모든 것을 set of triangles로 표현한다.

Representation for Triangle Mesh

Triangle Mesh를 하기 위해선

  • vertex position들
  • vertex들 사이의 관계 (to make triangles)

를 memory에 저장해야한다.


→ 이를 위한 두가지 방법이 존재한다. 이 두 방법을 모두 살펴볼거임

1) Separate triangles

2) Indexed triangle set

Vertex Winding Order (Vertex 명시하는 순서)

  • OpenGL에서 디폴트는

    → polygons의 vertices들을 counterclockwise로 명시하면 스크린에 front-facing이 나오는거

    바깥면이라고 생각되는 부분이 앞쪽으로 오도록 명시하면 된다.

Triangle Mesh - 1) Separate triangles

  • Triangle Mesh를 하는 방법 2개 배울건데 그 중 첫번째 방법
  • 방법

    → 삼각형 마다 vertex 3개의 coordinate value를 일일히 다 저장한다.

    → 삼각형 마다 coordinate value를 저장할때 겉이 앞면이라면

    겉을 정면에서 보고 있을 때를 기준으로 반시계 방향으로 저장

  • Various problems

    1) 공간을 낭비한다.

    2) crack due to roundoff

    같은 점이 여러 곳에 저장되다보니 같은 점인데도 다르게 저장될 수 있음. 그래서 그림의 육각형 같은 경우

    가운데 점이 다르게 저장되어서 틈이 생길수도 있다.

    3) Difficulty of finding neighbors

    이웃한 애를 찾는게 쉽지 않다. 첫번째 그림의 t2와 이웃한 삼각형을 찾기 위해선 다른 점들과의 거리를 일일히 구해서 거리 0인

    그 점이 어느 삼각형에 속한 애인지 확인해야함.

    근데 이마저도 실패할 수 있음. 2)에서 봤듯이 같은 점이 다르게 저장될 수 있기 때문에. 그럼 입실론 이하면 이웃이라고 정의해야하는데

    입실론을 어느 정도로 할지 이런거 정하기도 애매

Example: a cube of length 2

위의 정육면체는 면이 6개이기 때문에 triangle mesh로 표현하려면 삼각형 12개 필요

Drawing Separate Triangles using glVertex*()

삼각형 12개를 다음과 같이 glVertex로 그려서 cube 모양을 만들 수 있음

Vertex Array

  • polygon을 그리기 위해 더 발전된 방법을 방법을 써보자! Vertex Array!
  • Vertex array: vertex data를 한번에 넣어놓는거. (positions, normals, texture coordinates, color information)

    → 우리는 일단 position 만 고려할거다.

  • vertex array를 사용하면 전체 mesh를 OpenGL function을 한번 call 해서 다 그릴 수 있다!

    → glVertex*()를 엄청나게 call 할 필요가 없어진다.

    → rendering performance를 엄청나게 줄여준다!

  • 이거 쓰더라도 아직 Triangle Mesh의 첫번째 방법에 속하는거임! Separate Triangles 을 더 쉽게 하는 방법일 뿐

Drawing Separate Triangles using Vertex Array

  1. 너의 mesh를 위한 vertex array를 create 해라

    → dumpy.ndarray 또는 python list 를 사용해라

  1. Specify "pointer" to this vertex array

    → OpenGL에게 array pointer를 줘야한다.

    → 파이썬에선 포인터가 없으니까 어레이 이름 주면 된다.

    glVertexPointer() 함수를 사용하면 된다.

  1. 2)에서 명시된 "pointer"를 사용해서 너의 mesh를 Render 해라

    glDrawArrays() 함수를 사용하면 된다.

glVertexPointer() & glDrawArrays()

  • glVertexPointer(size, type, stride, pointer)

size: vertex 몇차원 점인지 물어보는거임.

type: array 안에 있는 각 coordinate value의 data type

GL_FLOAT, GL_SHORT, GL_INT, GL_DOUBLE 같은 것들이 들어간다.

stride: 다음 vertex로 가기 위한 byte offset

pointer: 어레이 주소를 주면 되는데 파이썬은 주소개념 없어서 어레이 이름 넣어준다.

  • glDrawArrays(mode, first, count)

mode: render할 primitive type

GL_POINTS, GL_TRIANGLES, ... (우리가 glBeign()안에 넣는거)

first: glVertexPointer에서 명시된 어레이에서 시작할 인덱스

count: render 되야할 vertex 개수 (그려야할 vertex 개수)

[Practice] Drawing Separate Triangles using Vertex Array

(밑에꺼 중복. 필기할 칸이 없어서...)

Quiz #2

Triangle Mesh - 2) Indexed triangle set

  • vertex들을 한번씩만 저장 (앞에서는 공유되는 점이라면 여러번 저장했었음)
  • 각 삼각형은 저장된 vertex 들 중 세개의 vertex를 point 하는거임
  • separate triangles 방법에서는 vertex array라는 이름으로 어레이 하나만 사용했음.
  • Indexed triangle set에서는 vertex array와 Index array라는 어레이 2개를 사용한다.

    vertex array에는 vertex들을 한번씩만! 쭉 저장하고 index array에서는 vertex array에서의 인덱스로 삼각형의 vertex 3개를 정해준다.

    (index array에서 숫자 적는 순서는 반시계 방향)

  • 장점

    1) Memory efficient : 각 vertex position 이 메모리에 한번씩만 저장되니까

    2) topology(위상배치)와 geometry(기하학)를 separately하게 표현할 수 있다.

    → 인덱스 어레이와 vertex 어레이를 따로 만드니까

    3) neighbors를 찾는게 적어도 잘 정의되어있음.

    → 같은 점은 하나로 저장되어 있으니까 적어도 seperate triangles 에서 처럼 같은 점이 다르게 저장될 일은 없음

    → 거리를 체크하는게 아니라 vertex index 가 같은게 있는 삼각형을 찾는다.

Drawing Indexed Triangles using Vertex & Indexed Array

  1. vertex array와 index array 생성하기

    → vertex array는 duplicate vertex data를 가지면 안된다.

    (한 vertex는 한번만 저장해야한다.)

  1. vertex array pointer를 명시하기

    → separate triangles 랑 똑같은 방법으로 glVertexPointer() 함수 써서 명시하면 된다.

  1. 2번에서 명시했던 vertex array pointerindices of vertices 를 사용해서 mesh를 render 하기

    → glDrawElements() 함수 사용하기

glDrawElements()

  • glDrawElement(mode, count, type, indices)

mode: render할 Primitive type

GL_POINTS, GL_TRIANTLES 같은게 들어간다.

count: render 될 index의 개수

삼각형 3개면: vertex 인덱스 3개 * 3 (삼각형개수) = 9

사각형 3개면: vertex 인덱스 4개 * 3 (사각형 개수) = 12

type: index array 안의 value들의 타입

GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT 같은게 들어간다.

indices: index array 의 포인터

파이썬이니까 그냥 어레이 이름 명시하면 된다.

[Practice] Drawing Indexed Triangles using Vertex & Index Array

🥵 어레이이름. itemsize → 이거 하면 한 element가 몇바이트인지 알 수 있음

😄 어레이이름. size → 이거 하면 인덱스가 몇개인지 알 수 있음. 2차원 어레이일 경우 (행 개수 * 열 개수)

Quiz #3

Do we need to hard-code all vertex positions and indices?

일일이 vertex 어레이를 만들고 index 어레이를 만들어서 하나 하나 입력해야할까?

→ Of course not!

  • 3D modeling tool을 이용해서 polygon mesh data를 storing 하는 object file(또는 model file)을 만든다.
  • 이걸 load 하면 파일로부터 읽어들인 데이터로 vertex 어레이 만들고 인덱스 어레이 만든다.

3D File Formats

object file 포멧이 많음. 이중에서 가장 쉽고 대중적으로 사용되는 포멧이 OBJ

  • OBJ

→ ASCII : human readable 하다는 말.

→ 읽기 쉽고 매우 간단하다.

→ 그래서 대부분의 게임 엔진 등에서 이 파일 포멧을 지원한다. (Widely supported)

OBJ File Token

obj 파일 문법같은거

An OBJ Example

object file 아래처럼 생겼다.

→ 큐브니까 vertex 8개 필요함

그래서 v ~~~ 이걸로 vertex 8개 등록

→ 큐브니까 face 6개 필요함.

그래서 f ~~~ 이걸로 face 6개 등록 (인덱스가 1부터 시작하기 때문에 그림 보면 0이 없음)

→ f 뒤에 숫자 4개. 즉, quad polygon

코드 분석하기(1)

코드 분석하기(2)

코드 분석하기(3)


Uploaded by N2T

728x90
728x90