[3rd week] cg_practice_draw_the_basic_geometry_objects
Download
Report
Transcript [3rd week] cg_practice_draw_the_basic_geometry_objects
Draw the basic Geometry
Objects
Hanyang University
Jungsik Park
VERTEX ATTRIBUTE AND
GEOMETRIC PRIMITIVES
Division of Electrical and Computer Engineering, Hanyang University
Vertex
Vertex
3D 공간상의 점, 또는 기본 도형(삼각형, 폴리곤 등)의
꼭지점
Vertex attributes
Vertex coordinate
Composition of primitives
Vertex color
Normal vector
Texture coordinate
Division of Electrical and Computer Engineering, Hanyang University
Vertex coordinate
glVertex*()
vertex의 3D/2D 좌표를 지정.
vertex 속성 중 가장 중요한 속성으로 glBegin() ~
glEnd() 사이에 위치시킴으로써 frame buffer에 도형을
그리게 된다.
그 외의 속성은 지정하지 않아도 도형을 그릴 수
있으나 vertex 좌표를 지정하지 않으면 도형을 그릴 수
없다.
glFlush()를 호출함으로써 frame buffer의 내용을
화면에 출력한다.
Division of Electrical and Computer Engineering, Hanyang University
Vertex coordinate
OpenGL coordinate system
3D cartesian coordinate system
x, y, z 축 각각 [-1.0, 1.0]의 범위를 갖는 정규화된
직육면체의 view volume 내의 물체를 그린다.
일반적으로 더 큰 view volume, 혹은 원근감을 표현할
수 있는 frustum view volume 내의 물체를 그리기 위해
view volume 변환을 먼저 수행한다.
2D의 경우 z=0인 평면상의 물체를 그린다.
Division of Electrical and Computer Engineering, Hanyang University
Primitives
Geometric primitives
vertex들로 구성되며, vertex의 좌표는 glVertex*()로
지정
면을 가지는 도형의 경우 vertex들이 반시계 방향의
순서를 가지도록 지정되어야 한다.
Division of Electrical and Computer Engineering, Hanyang University
Polygon construction rules
폴리곤 구성의 규칙
폴리곤을 구성하는 모든 vertex는 한 평면상에 위치해야
한다.
폴리곤을 이루는 선들은 서로 교차해서는 안 되면,
폴리곤의 전체적인 모양은 볼록해야 한다.
위의 규칙을 항상 만족하는 삼각형을 많이 사용
Division of Electrical and Computer Engineering, Hanyang University
Polygon construction rules
다음 도형을 하나의 폴리곤으로 그리는 경우
glBegin(GL_QUADS);
glVertex2f(-0.5, -0.5);
glVertex2f(0.5, 0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
잘못된 결과가 나타난다.
Division of Electrical and Computer Engineering, Hanyang University
Example code
#include <GL/glut.h>
int primitive[] = {GL_POINTS, GL_LINES,
GL_LINE_STRIP, GL_LINE_LOOP
, GL_POLYGON, GL_QUADS,
GL_TRIANGLES};
int index;
void mydisplay(){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(primitive[index]);
glVertex2f(-0.5, 0.0);
glVertex2f(-0.3536, 0.3536);
glVertex2f(0.0, 0.5);
glVertex2f(0.3536, 0.3536);
glVertex2f(0.5, 0.0);
glVertex2f(0.3536, -0.3536);
glVertex2f(0.0, -0.5);
glVertex2f(-0.3536, -0.3536);
glEnd();
glFlush();
}
void mykeyboard(unsigned char key, int x,
int y)
{
if (key == 'n' || key == 'N')
index++;
else if (key == 'p' || key == 'P')
index--;
if (index < 0)
index = 6;
if (index > 6)
index = 0;
glutPostRedisplay();
}
int main(int argc, char** argv){
glutCreateWindow(“primitives");
glutDisplayFunc(mydisplay);
glutKeyboardFunc(mykeyboard);
glutMainLoop();
}
Division of Electrical and Computer Engineering, Hanyang University
Drawing with fewer vertices
GL_TRIANGLE_STRIP, GL_QUAD_STRIP
GL_TRIANGLE_FAN
P2
P3
P0
P1
P6
P4
P5
Advantages to using fewer vertices
메모리 공간 절약
연산수 감소 및 그래픽 카드로의 데이터 전송 대역폭
절약
Division of Electrical and Computer Engineering, Hanyang University
Example code - GL_TRIANGLE_STRIP
GL_TRIANGLES 사용
void mydisplay(){
glClear(GL_COLOR_BUFFER_BIT);
GL_TRIANGLE_STRIP 사용
void mydisplay(){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex2f(-0.6, -0.2);
glVertex2f(-0.5, 0.2);
glVertex2f(-0.3, -0.2);
// P0
// P1
// P2
glVertex2f(-0.3, -0.2);
glVertex2f(-0.5, 0.2);
glVertex2f(-0.2, 0.2);
// P2
// P1
// P3
glVertex2f(-0.3, -0.2);
glVertex2f(-0.2, 0.2);
glVertex2f(0.0, -0.2);
// P2
// P3
// P4
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(-0.6, -0.2);
glVertex2f(-0.5, 0.2);
glVertex2f(-0.3, -0.2);
glVertex2f(-0.2, 0.2);
glVertex2f(0.0, -0.2);
glVertex2f(0.1, 0.2);
glVertex2f(0.3, -0.2);
glVertex2f(0.4, 0.2);
glEnd();
// P0
// P1
// P2
// P3
// P4
// P5
// P6
// P7
glFlush();
}
glVertex2f(0.0, -0.2);
glVertex2f(-0.2, 0.2);
glVertex2f(0.1, 0.2);
// P4
// P3
// P5
glVertex2f(0.0, -0.2);
glVertex2f(0.1, 0.2);
glVertex2f(0.3, -0.2);
// P4
// P5
// P6
glVertex2f(0.3, -0.2);
glVertex2f(0.1, 0.2);
glVertex2f(0.4, 0.2);
// P6
// P5
// P7
glEnd();
glFlush();
}
Division of Electrical and Computer Engineering, Hanyang University
Example code – GL_TRIANGLE_FAN
#include <math.h>
#include <GL/glut.h>
#define PI
3.141592
void mydisplay(){
GLfloat x, y, angle;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0.0f, 0.0f);
for(angle = 0.0f; angle < (2.0f*PI); angle += (PI/8.0f))
{
x = 0.5f*sin(angle);
y = 0.5f*cos(angle);
glVertex2f(x, y);
}
glEnd();
glFlush();
}
int main(int argc, char** argv){
glutCreateWindow("simple");
glutDisplayFunc(mydisplay);
glutMainLoop();
}
Division of Electrical and Computer Engineering, Hanyang University
Draw 3D object
glVertex3*()로 3차원 좌표 지정(z축 추가)
아래 그림은 cube를 그린 예제
입체감을 표현하기 위해선 다음의 요소가 필요
perspective projection
lighting & shading
Division of Electrical and Computer Engineering, Hanyang University
Example code - Draw 3D object
void mydisplay(){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
void specialkeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
xRot-= 5.0f;
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
if(key == GLUT_KEY_DOWN)
xRot += 5.0f;
glBegin(GL_QUADS);
glVertex3f(0.3,0.3,0.3);
glVertex3f(0.3,-0.3,0.3);
glVertex3f(-0.3,-0.3,0.3);
glVertex3f(-0.3,0.3,0.3);
if(key == GLUT_KEY_LEFT)
yRot -= 5.0f;
if(key == GLUT_KEY_RIGHT)
yRot += 5.0f;
glVertex3f(0.3,0.3,-0.3);
glVertex3f(0.3,-0.3,-0.3);
glVertex3f(-0.3,-0.3,-0.3);
glVertex3f(-0.3,0.3,-0.3);
if(key > 356.0f)
xRot = 0.0f;
if(key < -1.0f)
xRot = 355.0f;
glVertex3f(0.3,0.3,-0.3);
glVertex3f(0.3,0.3,0.3);
glVertex3f(-0.3,0.3,0.3);
glVertex3f(-0.3,0.3,-0.3);
if(key > 356.0f)
yRot = 0.0f;
if(key < -1.0f)
glVertex3f(0.3,-0.3,-0.3);
glVertex3f(0.3,-0.3,0.3);
glVertex3f(-0.3,-0.3,0.3);
glVertex3f(-0.3,-0.3,-0.3);
yRot = 355.0f;
// Refresh the Window
glutPostRedisplay();
}
glVertex3f(0.3,0.3,0.3);
glVertex3f(0.3,0.3,-0.3);
glVertex3f(0.3,-0.3,-0.3);
glVertex3f(0.3,-0.3,0.3);
glVertex3f(-0.3,0.3,0.3);
glVertex3f(-0.3,0.3,-0.3);
glVertex3f(-0.3,-0.3,-0.3);
glVertex3f(-0.3,-0.3,0.3);
int main(int argc, char** argv){
glutCreateWindow("simple");
glutDisplayFunc(mydisplay);
glutSpecialFunc(specialkeys);
glutMainLoop();
}
glEnd();
glPopMatrix();
glFlush();
}
Division of Electrical and Computer Engineering, Hanyang University
Vertex color
OpenGL에서는 vertex 단위로 색상을 할당.
선, 면의 색상은 구성하는 vertex들의 색을
interpolation하여 결정
glColor*()
색상은 인자의 수에 따라 RGBA, RGB로 지정
void glColor4f (GLfloat red, GLfloat green, GLfloat
blue, GLfloat alpha);
void glColor3f (GLfloat red, GLfloat green, GLfloat
blue);
각 채널의 값의 범위
인자가 실수인 경우 [0.0, 1.0]
인자가 정수인 경우 [0, 255]
Division of Electrical and Computer Engineering, Hanyang University
Example code – vertex color
#include <GL/glut.h>
int primitive[] = {GL_POINTS, GL_LINES,
GL_LINE_STRIP, GL_LINE_LOOP
, GL_POLYGON, GL_QUADS, GL_TRIANGLES};
int index;
void mydisplay(){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(primitive[index]);
glColor3f(1.0, 0.0, 0.0);
// red
glVertex2f(-0.5, 0.0);
glColor3f(0.0, 1.0, 0.0);
// green
glVertex2f(-0.3536, 0.3536);
glColor3f(0.0, 0.0, 1.0);
// blue
glVertex2f(0.0, 0.5);
glColor3f(0.5, 0.5, 0.5);
// gray
glVertex2f(0.3536, 0.3536);
glColor3f(1.0, 1.0, 0.0);
// yellow
glVertex2f(0.5, 0.0);
glColor3f(1.0, 0.0, 1.0);
// magenta
glVertex2f(0.3536, -0.3536);
glColor3f(0.0, 1.0, 1.0);
// cyan
glVertex2f(0.0, -0.5);
glColor3f(1.0, 1.0, 1.0);
// white
glVertex2f(-0.3536, -0.3536);
glEnd();
void mykeyboard(unsigned char key, int x,
int y)
{
if (key == 'n' || key == 'N')
index++;
else if (key == 'p' || key == 'P')
index--;
if (index < 0)
index = 6;
if (index > 6)
index = 0;
glutPostRedisplay();
}
int main(int argc, char** argv){
glutCreateWindow(“primitives");
glutDisplayFunc(mydisplay);
glutKeyboardFunc(mykeyboard);
glutMainLoop();
}
glFlush();
}
Division of Electrical and Computer Engineering, Hanyang University
Other attributes
Normal vector
폴리곤 앞면의 법선 벡터. 폴리곤 단위가 아닌 vertex
단위로 지정.
glNormal*()
lighting, backface culling 등에 사용됨
Texture coordinate
폴리곤에 텍스쳐를 매핑할 때 폴리곤의 각 지점과
영상의 픽셀을 대응시키기 위한 좌표
glTexcoord*()
Division of Electrical and Computer Engineering, Hanyang University
MANIPULATION OF THE
OPENGL STATES
Division of Electrical and Computer Engineering, Hanyang University
States
Point size & line width
Winding
Backface culling
Depth test
Polygon mode
Fill face
Wireframe
Point
Shade model
Division of Electrical and Computer Engineering, Hanyang University
States
State를 변화시키는 방법
on/off 로 사용되는 state variable
glEnable() / glDisable()
depth test, lighting, texture mapping 등
그 외의 값을 가지는 state variable을 변화시키는 경우
glFrontFace(), glLineWidth() 등 해당 state variable
전용 함수
Division of Electrical and Computer Engineering, Hanyang University
Point size & line width
Point size
점의 크기를 지정
void glPointSize(GLfloat size);
기본값은 1이고, 사용할 수 있는 값의 범위는 플랫폼에 따라 다르다.
Point size로 사용할 수 있는 값의 범위를 알아내는 법
GLfloat sizes[2];
GLfloat step;
glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step);
Line width
선의 두께를 지정
void glLineWidth (GLfloat width);
기본값은 1이고, 사용할 수 있는 값의 범위는 플랫폼에 따라 다르다.
Line width로 사용할 수 있는 값의 범위를 알아내는 법
GLfloat sizes[2];
GLfloat step;
glGetFloatv(GL_LINE_WIDTH_RANGE,sizes);
glGetFloatv(GL_LINE_WIDTH_GRANULARITY,&step);
Division of Electrical and Computer Engineering, Hanyang University
Example – line width
void mydisplay(){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
GLfloat y;
GLfloat fSizes[2];
GLfloat fCurrSize;
glGetFloatv(GL_LINE_WIDTH_RANGE,fSizes);
fCurrSize = fSizes[0];
for(y = -0.9f; y < 0.9f; y += 0.2f)
{
glLineWidth(fCurrSize);
glBegin(GL_LINES);
glVertex2f(-0.8f, y);
glVertex2f(0.8f, y);
glEnd();
fCurrSize += 1.0f;
}
glFlush();
}
Division of Electrical and Computer Engineering, Hanyang University
Winding
폴리곤을 구성하는 vertex들의 순서를 지정
폴리곤의 앞면과 뒷면을 결정하기 위한 방법
glFrontFace(GL_CCW);
반시계 방향으로 vertex 지정(디폴트)
glFrontFace(GL_CW);
시계 방향으로 vertex 지정
앞면과 뒷면을 결정함으로써 보이지 않는 부분을 그리지
않거나, 앞면과 뒷면에 각각 다른 색상,재질을 지정할 수
있다.
Division of Electrical and Computer Engineering, Hanyang University
Backface culling
폴리곤의 보이지 않는 면(뒷면)을 제거하는 옵션
glEnable(GL_CULL_FACE);
glDisable(GL_CULL_FACE);
불필요한 면을 그리지 않음으로써 성능상의 이득을
얻을 수 있다.
종이 같은 얇은 평면, 유리와 같은 투명한 물체는
뒷면도 그려져야 하므로 backface culling을 사용하지
않는다.
Division of Electrical and Computer Engineering, Hanyang University
Depth test
어떤 물체가 다른 물체의 앞에 있는 경우, 뒤의 물체가
그려지지 않도록 한다.
glEnable(GL_DEPTH_TEST);
depth buffer를 이용하여 픽셀을 그릴 때마다 z값을
비교하여 높은 z값을 갖는 픽셀로 갱신함으로써 뒤의
물체가 보이지 않도록 한다.
glDisable(GL_DEPTH_TEST);
z값과 관계없이 나중에 그려지는 물체를 그린다.
backface culling과 달리 z값을 비교하여 그려지는지
여부를 결정하기 때문에 depth test로 인한 성능
이득은 없지만 사실적인 표현을 위해 필요한 요소.
backface culling : 아예 그리지 않음
depth test : 그렸지만 보이지 않음
Division of Electrical and Computer Engineering, Hanyang University
Polygon mode
폴리곤을 색칠된 면으로 그리거나, wireframe으로
그리는 옵션
void glPolygonMode (GLenum face, GLenum mode);
face : GL_FRONT, GL_BACK,
GL_FRONT_AND_BACK
mode : GL_FILL, GL_LINE, GL_POINT
예 : 물체의 앞면을 wireframe으로 그릴 경우
glPolygonMode(GL_FRONT, GL_LINE);
Division of Electrical and Computer Engineering, Hanyang University
Shade model
폴리곤의 면을 색칠하는 방법 지정
glShadeModel(GL_SMOOTH);
vertex 색상을 interpolation하여 면의 각 부분을 색칠
glShadeModel(GL_FLAT);
폴리곤을 구성하는 vertex 중 마지막 vertex의 색상으로
면을 색칠
Division of Electrical and Computer Engineering, Hanyang University
Example code
#include <stdio.h>
#include <GL/glut.h>
bool bBackfaceCull = false;
bool bDepthTest = false;
bool bShadeSmooth = false;
bool bWireFrame = false;
bool bWindCCW = false;
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
void mydisplay(){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
if (bBackfaceCull) glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
if (bDepthTest)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
if (bWindCCW)
glFrontFace(GL_CCW);
else
glFrontFace(GL_CW);
if (bShadeSmooth) glShadeModel(GL_SMOOTH);
else
glShadeModel(GL_FLAT);
if (bWireFrame)
glPolygonMode(GL_FRONT, GL_LINE);
else
glPolygonMode(GL_FRONT, GL_FILL);
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
Division of Electrical and Computer Engineering, Hanyang University
Example code(cont’d)
glBegin(GL_QUADS);
// Front Face
glColor3f(1.0f, 1.0f, 1.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(0.3,0.3,0.3);
glVertex3f(0.3,-0.3,0.3);
glVertex3f(-0.3,-0.3,0.3);
glVertex3f(-0.3,0.3,0.3);
// White
// Yellow
// Red
// Magenta
// Back Face
glColor3f(0.0f, 1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.3,0.3,-0.3);
glVertex3f(0.3,-0.3,-0.3);
glVertex3f(-0.3,-0.3,-0.3);
glVertex3f(-0.3,0.3,-0.3);
// Cyan
// Green
// Black
// Blue
// Top Face
glColor3f(0.0f, 1.0f, 1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glColor3f(1.0f, 0.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.3,0.3,-0.3);
glVertex3f(0.3,0.3,0.3);
glVertex3f(-0.3,0.3,0.3);
glVertex3f(-0.3,0.3,-0.3);
// Cyan
// White
// Magenta
// Blue
// Bottom Face
glColor3f(0.0f, 1.0f, 0.0f);
glColor3f(1.0f, 1.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glColor3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.3,-0.3,-0.3);
glVertex3f(0.3,-0.3,0.3);
glVertex3f(-0.3,-0.3,0.3);
glVertex3f(-0.3,-0.3,-0.3);
// Green
// Yellow
// Red
// Black
Division of Electrical and Computer Engineering, Hanyang University
Example code(cont’d)
// Left face
glColor3f(1.0f, 1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glColor3f(1.0f, 1.0f, 0.0f);
// Right face
glColor3f(1.0f, 0.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glColor3f(0.0f, 0.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f);
glEnd();
glPopMatrix();
glVertex3f(0.3,0.3,0.3);
glVertex3f(0.3,0.3,-0.3);
glVertex3f(0.3,-0.3,-0.3);
glVertex3f(0.3,-0.3,0.3);
// White
// Cyan
// Green
// Yellow
glVertex3f(-0.3,0.3,0.3);
glVertex3f(-0.3,0.3,-0.3);
glVertex3f(-0.3,-0.3,-0.3);
glVertex3f(-0.3,-0.3,0.3);
// Magenta
// Blue
// Black
// Red
// Show the graphics
glFlush();
}
void specialkeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
if(key == GLUT_KEY_DOWN)
if(key == GLUT_KEY_LEFT)
if(key == GLUT_KEY_RIGHT)
if(key > 356.0f)
if(key < -1.0f)
if(key > 356.0f)
if(key < -1.0f)
xRot-= 5.0f;
xRot += 5.0f;
yRot -= 5.0f;
yRot += 5.0f;
xRot = 0.0f;
xRot = 355.0f;
yRot = 0.0f;
yRot = 355.0f;
glutPostRedisplay();
}
Division of Electrical and Computer Engineering, Hanyang University
Example code(cont’d)
void mykeyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'b': case 'B':
bBackfaceCull = !bBackfaceCull;
if (bBackfaceCull) printf("backface culling : on\n");
else printf("backface culling : off\n");
break;
case 'd': case 'D':
bDepthTest = !bDepthTest;
if (bDepthTest) printf("depth test : on\n");
else printf("depth test : off\n");
break;
case 'w': case 'W':
bWireFrame = !bWireFrame;
if (bWireFrame) printf("draw wireframe\n");
else printf("fill face\n");
break;
case 's': case 'S':
bShadeSmooth = !bShadeSmooth;
if (bShadeSmooth) printf("smooth shading\n");
else printf("flat shading\n");
break;
case 'c': case 'C':
bWindCCW = !bWindCCW;
if (bWindCCW) printf("wind counter-clockwise\n");
else printf("wind clockwise\n");
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv){
glutCreateWindow("simple");
glutDisplayFunc(mydisplay);
glutKeyboardFunc(mykeyboard);
glutSpecialFunc(specialkeys);
glutMainLoop();
}
Division of Electrical and Computer Engineering, Hanyang University