■ OpenGL: Geometric and Vertex
지오메트릭은 머 도형이라고 이해하면 좋다. 그리고 버텍스는 꼭지점이다. 즉 꼭지점을 알고 있으면 선으로 연결하여 도형을 만들 수 있는 관계가 성립된다.
OpenGL에서 도형을 만들기 위한 방법으로
- 지원되는 함수 사용
- glBegin - glEnd를 통해 그리기
가 있는 것 같다. 하지만 이 함수보다 효율적으로 빠르게 도형을 만들기 위해서 버텍스 배열을 사용한다고 한다. 한번 알아 보자 어떻게 하는지
1. OpenGL에서 Vertex 사용 방법
step 1: 디스크 파일 또는 알고리즘을 통해 지오메트리 데이터를 읽어 배열에 저장
- 위치 또는 도형에 대한 vertex 정보를 담은 vertex 배열을 선언한다.
step 2: Vertex 배열 사용 설정
- OpenGL은 클라이언트(CPU)와 서버(그래픽 하드웨어)등 두가지 방법으로 동작함.
- 클라이언드 모드에서 Vertex 배열 사용 설정 함수
- glEnableClientState(GL_VERTEX_ARRAY) / glDisableClientState(GL_VERTEX_ARRAY) : 활성함수와 비활설 함수 짝을 이룬다.
void glEnableClientState(GLenum cap);
Specifies the capability to enable. Symbolic constants GL_COLOR_ARRAY, GL_EDGE_FLAG_ARRAY, GL_FOG_COORD_ARRAY, GL_INDEX_ARRAY, GL_NORMAL_ARRAY, GL_SECONDARY_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY, and GL_VERTEX_ARRAY are accepted.
http://www.opengl.org/sdk/docs/man2/xhtml/glEnableClientState.xml
step 3: 배열의 형태 지정(vertex, color, normal vector, etc.)
vertex 배열을 선언하고 사용하겠다라고 예기했으니 데이터를 얻을라면 어디 버텍스 정보를 가져다 써라라고 해줘야 함. 아래와 같은 여러 함수가 있는데 입맛에 따라서 골라서 써야 함. 복잡하지만 정리하면 다음과 같음
================================================================================================
- GLint size: 좌표 타입을 구성하는 요소(두개 -x,y 세개-x,y,z 내게-x,y,z,w)
- CLenum Type: 실수 인지 정수인지 데이터 포멧(GLfloat)
- GLsizei stride: stride is the byte offset between consecutive vertexes. If stride is 0, the vertices are understood to be tightly packed in the array.(배열에서 가져올때 간격을 말하는듯, 0이면 배열 0,1,2..,N 이렇게 순차적으로 가져오고 만약 1이면 0, 2, 4, ...,N 요렇게? 가져 올듯)
- GLvoid *pointer: 데이터를 가져올 Vertex 배열
================================================================================================
void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void glEdgeFlagPointer(GLsizei stride, const GLvoid *pointer);
void glVertexPointer(GLint size, GLenumtype, GLsizei stride, const GLvoid *pointer); //버텍스 위치 정보
Command | Sizes | Values for type Argument |
glVertexPointer | 2, 3, 4 | GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE |
glNormalPointer | 3 | GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE |
glColorPointer | 3, 4 | GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_DOUBLE |
glIndexPointer | 1 | GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE |
glTexCoordPointer | 1, 2, 3, 4 | GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE |
glEdgeFlagPointer | 1 | no type argument (type of data must be GLboolean) |
http://www.felixgers.de/teaching/jogl/vertexArrayData.html
glVertexPointer(2, GL_FLOAT, 0, Vertex);//좌표 타입 x,y로 구성, 데이터 포멧은 GLfloat, 데이터 간격은 0으로 Vertex 배열에 위치 지정
step 4: 배열 정보 랜더링
이제 마지막으로 꼭지점들의 정보를 받았으니 이 정보들을 랜덩링해서 보여주면 된다.
glDrawArrays(GL_POINTS, 0, 10); // POINT 형식으로 처음 0 번째 부터 10개를 그려라
glDrawArrays(CLenum 모드, GLint 처음, GLint 개수);
GLenum 모드: OpenGL 의 Basic Model 중 하나가 되고
GLint 처음: 이전 지정한 vertex 배열에서 시작 주소
GLint 개수: 시작 지점으로 부터 읽을 vertex 의 개수가 됨
2. 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | void C3DScatterPlot::RenderScene(void) { // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glTranslatef(0.0f, 0.0f, -350.0f); //원근 투영을 사용하고 있으므로 z좌표를 뒤로 350 이동하여 보기 GLfloat Vertex[10][2]; //꼭지점 정보 저장을 위한 2차원 배열 설정 for(int i=0; i<10; i++){ //10개의 x, y 좌표를 랜덤하게 Vertex 배열에 저장 Vertex[i][0]=(GLfloat)(rand()%50); // y Vertex[i][1]=(GLfloat)(rand()%50); // x } //Vertex 배열 사용 활성화- 클라이언트 모드 glEnableClientState(GL_VERTEX_ARRAY); //포인트를 그릴때 크기 지정 glPointSize(10.0f); //색상 지정 glColor3f(0.0f, 1.0f, 0.0f); //Vertex 배열 위치 지정 glVertexPointer(2, GL_FLOAT, 0, Vertex); //드로잉 glDrawArrays(GL_POINTS, 0, 10); } |
void glDrawArrays(
GLenum mode,
GLint first,
GLsizei count
);
mode
Specifies what kind of primitives to render. Symbolic constants GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY, GL_LINES_ADJACENCY, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_TRIANGLE_STRIP_ADJACENCY and GL_TRIANGLES_ADJACENCY are accepted.
first
Specifies the starting index in the enabled arrays.
count
Specifies the number of indices to be rendered.
위에 보면 랜덤으로 x,y 를 저장하고 있는 꼭지점 배열의 정보를 가져와 10의 사이즈를 갖는 Point들이 드로잉 된것을 볼 수 있다.
http://www.felixgers.de/teaching/jogl/vertexArrayData.html
'OpenGL' 카테고리의 다른 글
OpenGL: Normal Vector (0) | 2014.05.04 |
---|---|
OpenGL: Index of Vertex Array (0) | 2014.05.04 |
OpenGL: gluPerspective, glFrustum (0) | 2014.04.20 |
OpenGL: Setting Viewport (0) | 2014.04.19 |
OpenGL: Setting Clipping region (0) | 2014.04.19 |
◆ OpenGL: gluPerspective
원근 투영 방법
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
- 멀고 가까움을 표현함
- gluPerspective(시야각, 종횡비, 전방전달면, 후방절단면)
ex) gluPerspective(45.0, width/height, 1.0, 400.0);
http://warmz.tistory.com/440
시야(FOV: Field of View):상하 y축 방향의 시야각(0 -180도)
X축 방향의 시야는 종횡비(Aspect Ratio)에 의해 결정됨(폭 / 높이)
'OpenGL' 카테고리의 다른 글
OpenGL: Index of Vertex Array (0) | 2014.05.04 |
---|---|
OpenGL: Geometric and Vertex (0) | 2014.05.04 |
OpenGL: Setting Viewport (0) | 2014.04.19 |
OpenGL: Setting Clipping region (0) | 2014.04.19 |
OpenGL: Basic knowledge for 3D programing (0) | 2014.04.19 |
◆ OPENGL - 뷰포트 설정
뷰포트를 설정하는 함수는 다음과 같다.
1 | void glViewport(GLint xTopLeft, GLint yTopLeft, GLsizei width, GLsizei height) |
xTopLeft, yTopLeft: 창 내에 위치한 뷰포트의 좌측 하단 좌표를 의미
width, height: 뷰포트의 너비와 높이
'OpenGL' 카테고리의 다른 글
OpenGL: Geometric and Vertex (0) | 2014.05.04 |
---|---|
OpenGL: gluPerspective, glFrustum (0) | 2014.04.20 |
OpenGL: Setting Clipping region (0) | 2014.04.19 |
OpenGL: Basic knowledge for 3D programing (0) | 2014.04.19 |
Windows OpenGL: Making Window Application with OpenGL (0) | 2014.04.19 |
◆ OPENGL - 클리핑 영역 설정
클리핑 영역을 조정하여 종횡비가 맞는 정사작형으로 만드는 일
aspect rate(종횡비): 아래 viewport에 보면 종횡비 aspect ratio = w/h 로 계산된다.
http://www3.ntu.edu.sg/home/ehchua/programming/opengl/CG_Introduction.html
종횡비가 1일 경우 정사각형이며, 0.5일 경우 가로 2 세로가 1이기 때문에 가로가 늘려진 사각형임을 알 수 있음
뷰포트가 정사각형이 아닌 상태에서 정사각형 클리핑 영역을 매핑하게 되면 찌그러지게 되므로 적절한 클리핑 영역 설정을 통해 종횡비를 맞춰야 함
직교 투영 방식에서의 클리핑 영역 설정 방법
1 | void glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal); |
3D 좌표계에서
left와 right는 x축의 최솟값과 최댓값
bottom, top는 y축의 최솟값과 최댓값
near, far: z축의 최솟값과 최댓값
z 축의 경우 값이 작아질수록 관측자로 부터 멀어짐을 의미
http://warmz.tistory.com/440
두 그림을 비교해 보면 x 축의 최댓값과 최솟값이 변화여 viewport에 보이는 사각형이 비율에 따라 줄어든것을 확인할 수 있다. 아래 그림 두번째 보면 glOrtho에서 사용되는 변수들의 위치를 확인할 수 있다.
즉, Viewport를 설정해 그릴 화면 영역을 잡고 x,y,z 종횡비를 설정하여 어떻게 투영해서 보여 줄것인가를 결정하면 된다.
http://potatoland.org/glart/week3/
http://www.pling.org.uk/cs/cgv.html
투영함수 이전에 다음 두 함수 사용
1 2 3 | // Reset coordinate system glMatrixMode(GL_PROJECTION); glLoadIdentity(); |
glMatrixMode 함수는 투영을 위한 행렬 변환을 하는 부분
glLoadIdentity 함수는 행렬 처리가 이루어지기 전에 좌표계를 초기화 하는 역할을 함
- glOrtho의 작동 방식이 새로운 클리핑 영역을 만는 것이 아니라 기존의 클리핑 영역과 행렬을 곱한 값을 새로운 클리핑 영역으로 지정하기 때문임
glOrtho 호출 전에 좌표를 초기화 하는 과정이 필요함을 알아 두자.
glOrtho를 호출 후 다음 두 함수 사용됨
1 2 | glMatrixMode(GL_MODELVIEW); glLoadIdentity(); |
------------
정사각형 유지를 위한 클리핑 영역 설정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /////////////////////////////////////////////////////////// // Called by GLUT library when the window has chanaged size void ChangeSize(int w, int h) { GLfloat aspectRatio; // Prevent a divide by zero if(h == 0) h = 1; // Set Viewport to window dimensions glViewport(0, 0, w, h); // Reset coordinate system glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Establish clipping volume (left, right, bottom, top, near, far) aspectRatio = (GLfloat)w / (GLfloat)h; if (w <= h) glOrtho (-100.0, 100.0, -100 / aspectRatio, 100.0 / aspectRatio, 1.0, -1.0); else glOrtho (-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } |
'OpenGL' 카테고리의 다른 글
OpenGL: gluPerspective, glFrustum (0) | 2014.04.20 |
---|---|
OpenGL: Setting Viewport (0) | 2014.04.19 |
OpenGL: Basic knowledge for 3D programing (0) | 2014.04.19 |
Windows OpenGL: Making Window Application with OpenGL (0) | 2014.04.19 |
Windows OpenGL: Rendering Context (0) | 2014.04.19 |
◆ OPENGL - 3D 프로그래밍을 위한 기본적인 지식들
실시간 3D 그래픽을 위한 API 프로그래밍 방식은 크게 두 가지로 나뉨
1. 보류 모드(Retained Mode)
- 물체나 장면에 대한 정보를 API 또는 툴킷에 제공
- API 또는 툴킷은 내부적인 처리를 거쳐 화면에 출력할 이미지를 만들어 내는 방식
- 사용자는 카메라의 위치나 방향을 조정하거나 장면 내의 다른 ㅁㄹ체에 대한 약간의 정보 정도만 다루면 됨
적용 예: 광선 추적기, 비행 시뮬레이션, 이미지 생성기
- 장면 내의 모드 물체들과 그 사이의 관계를 미리 만들어진 데이터 구조로 만들어 두고, 이 구조에 축적인 약간의 정보들만 제공하여 완성된 이미지 만들어 냄
- 렌더링에 대한 세부적인 부분까지 신경 쓸 필요가 없다는 장점. 사용이 편함
- 최종 이미지 생산을 위해 중간 단계 구조(Scene graph)를 가지는 특징이 있음
2. 즉시 모드(Immediate Mode)
- 이미 실행된 명령에 대해서는 그 후에 내려진 명령이 아무런 영향을 주지 못함
▶ 좌표체계
OpenGL을 포함한 대부분의 3D API에서는 화면 내에 무언가를 그리고자 할 때 어떤 좌표계(Coordinate System)을 사용할 것인지, 그리고 그 좌표가 물리적인 화면의 픽셀과 어떻게 대응될 것인지 함께 지정해야 함
2D, 3D
즉
좌표계 설정 - OpenGL 은 오른손 좌표계를 사용함
픽셀 설정이 필요함
http://www.hyperzoid.com/csc492/rendering.html
▶ 좌표의 클리핑(Clipping: 자르기)
클리핑 영역을 설정할때 참고 해야 함
http://lueseypid.tistory.com/37
▶ 뷰포트: 드로잉 좌표와 창 좌표의 매핑
클리핑 영역과 창의 픽셀 수가 정확히 맞아떨어지는 경우는 드물다. 따라서 논리적 직교 좌표를 물리적ㅇ니 화면 픽셀 좌료로 전화하는 과정이 필요한데, 이때 사용되는 것이 뷰포트(Viewport)라는 개념이다.
클리핑 영역에 두배 크기로 설정된 뷰포트
클리핑 영역과 같은 크기로 설정된 뷰포트
▶ 투영: 3D를 2D로 설정
우리가 보는 영상이 3D라도 실제 화면에 나타나는 것은 2D이다. 따라서 3D 이미지들이 2D로 투영되여 화면에 나타나는데 두가지 방법이 사용된다.
1. 직교 투영(Orthographic Projection)
- 모든 물체들이 거리에 관계없이 동일한 크기 비율로 투영됨
- 주로 건축물의 설계도나 디자인 문서 등에 주로 사용됨
2. 원근 투영(Perspective Projection)
- 물체가 얼마나 가까이 또는 멀리 있는가에 따라 거리를 고려하여 투영
http://www3.ntu.edu.sg/home/ehchua/programming/opengl/CG_Introduction.html
'OpenGL' 카테고리의 다른 글
OpenGL: Setting Viewport (0) | 2014.04.19 |
---|---|
OpenGL: Setting Clipping region (0) | 2014.04.19 |
Windows OpenGL: Making Window Application with OpenGL (0) | 2014.04.19 |
Windows OpenGL: Rendering Context (0) | 2014.04.19 |
Windows OpenGL: Setting and selecting Pixel format (0) | 2014.04.19 |