[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