Input and Interaction 321190 2012 년봄학기 3/22/2012 박경신 Overview 입력장치 (Input device) 물리적입력장치 (Physical input devices) Mouse, Keyboard, Trackball 논리적장치 String, Locator, Pick, Choice, Valuators, Stroke device 입력모드 Request mode, Sample mode, Event mode GLUT Devices & Event-driven programming g 마우스, 키보드, 메뉴, 조이스틱, 테블렛,.. 디스플레이리스트 (Display lists) 유지모드그래픽스 (Retained mode graphics) 방식 지적 (Picking) 화면상의한객체를사용자가식별할수있도록하는입력연산 Interaction 컴퓨터기술의중요한발전가운데하나는사용자가컴퓨터화면을이용하여상호작용을할수있다는것이다. 상호작용 (Interaction) 사용자는마우스와같은대화식장치를통하여행동을취한다. 컴퓨터가사용자의입력을감지한다. 프로그램은이입력에반응하여상태를바꾼다. 프로그램은이새로운상태를디스플레이한다. 사용자는바뀐디스플레이를본다. 사용자가이변화에다시반응하는과정들이반복된다. Historical Highlights Vannevar Bush MEMEX J.C.R. Licklider Man-Computer Symbiosis Steve Russell Spacewar Ivan Sutherland Sketchpad Douglas Engelbart NLS (online System) Xerox PARC GUI (Graphical User Interface)
Graphical Input Physical Input Devices 입력장치를두가지다른방법으로생각할수있다 물리적장치 Mouse, Keyboard 논리적장치 물리적특성이아닌사용자프로그램과의상위인터페이스에의하여특징지어짐 입력모드 입력장치가응용프로그램에게입력을제공하는방식은측정과정 (Measure) 과장치트리거 (Trigger) 로설명될수있다 요구모드 (Request mode) 샘플모드 (Sample mode) 이벤트모드 (Event mode) mouse trackball light pen data tablet joy stick space ball Physical Input Devices 물리적입력장치 (Physical input devices) 지시장치 (Pointing devices) 사용자가화면상의한위치를지시할수있게함 대부분의경우사용자가컴퓨터에신호즉, 인터럽트를보내기위해 1 이상의버튼을가지고있다. Mouse, trackball, tablet, lightpen, joystick, spaceball 키보드장치 (Keyboard devices) 프로그램에문자코드를반환하는장치 Keyboard Relative Positioning Device 데이터테블렛 (data tablet) 같은장치는절대위치를제공한다. 마우스, 트랙볼, 조이스틱같은장치는변화하는속도를적분하여위치정보가계산된다. Rotation of cylinders in mouse Roll of trackball 정확한절대위치를구하기어려움 장치를가변-감도입력으로사용할수있음
Logical Input Devices 문자열장치 (String device) - keyboard 사용자프로그램에 ASCII문자열 (strings of characters) 을제공 위치장치 (Locator device) mouse, trackball 사용자프로그램에실세계좌표의위치 (position) 를제공 지적장치 (Pick device) mouse button, gun 사용자프로그램에객체의식별자 (ID) 를반환 선택장치 (Choice device) widgets, function keys, mouse button 사용자가선택사항들 (menu) 중하나를선택하도록함 벨류에이터장치 (Valuators) slide bars, joystick, dial 사용자프로그램에아날로그입력 (range of value) 을제공 획장치 (Stroke) mouse drag 위치들의배열 (array of positions) 을반환 X Window Input X Window System 모델은클라이언트와서버모델 (client-server model) 네트워크로구성. 그래픽스서버 (Graphics Server) 는래스터디스플레이, 키보드, 마우스를가진워크스테이션이다. 이서버는디스플레이에출력서비스를키보드와마우스를통한입력서비스를제공한다. 클라이언트 (Client) - OpenGL 프로그램은그래픽스서버를사용하는클라이언트이다. Input Modes 입력장치는 OS 에신호를보내는트리거 (trigger) 를가지고있다. 마우스 버튼 키보드에서 리턴 / 엔터 키 입력장치는트리거시컴퓨터에게측정치 (measure) 를넘겨준다. 신호를주는데사용할수있는장치의물리적입력이다. 마우스는 위치정보 를준다. 키보드는 ASCII code 를준다. Request Mode 요구모드 (Request mode) 에서는장치가트리거될때까지측정치가프로그램으로반환되지않는다. 문자입력을요구하는전형적인비그래픽스적인응용프로그램의표준 예를들어 C 프로그램의scanf 함수가사용될때프로그램이단말기에서문자를칠때까지기다리면서정지한다. 그리고엔터키 (trigger) 를누르기까지타이핑과교정이가능하다.
Sample Mode 샘플모드 (Sample mode) 에서는즉각적인입력을제공한다. 사용자프로그램에서함수의호출을만나는즉시측정치가반환된다. 따라서트리거가필요하지않다. 예 : C 프로그램의 getc Event Mode 대부분의시스템은여러개의입력장치가있으며각장치마다자신의트리거로측정과정을실행하는환경으로구성된다 입력장치가트리거 (trigger) 될때마다이벤트 (event) 가생성되고, 장치의측정치가장치식별자 (ID) 와더불어이벤트큐 (event queue) 에들어간다. 답신 (callback) 함수를특정이벤트와연결하여사용한다. Event Types Window 윈도우 resize, expose, iconify Keyboard 키를누름 (press) 와키에서뗌 (release) Mouse 마우스버튼을누름 Motion 마우스움직임 Idle 이벤트가없음 Programming Event-Driven Input 이벤트-구동 (Event-drive) 입력프로그래밍을위해이벤트에대응하는답신함수 (callback function) 을정의한다. 이벤트가발생시해당답신함수 (callback function) 이동작한다. 예를들어, GLUT 에서마우스이벤트의답신함수는 main 함수내에서 glutmousefunc(mouse) 를통해서지정한다. 그리고 mouse 답신함수의형태는다음과같다. void mouse(int button, int state, int x, int y)
GLUT Devices Keyboard normal keys special keys Mouse Position buttons Joystick Tablet Dial/button box Spaceball GLUT Keyboard Functions glutkeyboardfunc(func) ACII character 키가눌려졌을때불려짐 glutspecialfunc(func) 특수 special 키가눌려졌을때불려짐 glutkeyboardupfunc(func) ACII character 키가떼어졌을때불려짐 glutspecialupfunc(func) 특수 special 키가떼어졌을때불려짐 glutgetmodifiers() 이벤트발생시 Shift, Control, Alt keys 의상태를줌 glutignorekeyrepeat(val) GLUT 에게자동키보드반복을무시하라고알려줌 GLUT Keyboard Event Callback void keyboard(unsigned char key, int x, int y) 키보드인터랙션에대한처리를지정. key 인자는 ACII character code로지정 x, y 인자는키를눌렀을때의마우스의위치 GLUT Special Key GLUT 특수키 (special key) 지정 GLUT_KEY_F1,F2..,F12 GLUT_KEY_UP,DOWN,LEFT,RIGHT 방향키 GLUT_KEY_PAGE_UP,PAGE_DOWN,HOME,END,INSERT UP END void keyboard(unsigned char key, int x, int y) switch (key): /* q-key exits the program */ case q : exit(0); void specialkey(int key, int x, int y) void specialkey(int key, int x, int y) switch(key) GLUT KEY F1 case GLUT_KEY_F1: red = 1.0; green = 0.0; blue = 0.0; break; case GLUT_KEY_F2:
GLUT Modifier Key CTRL, ALT, SHIFT modifier key가눌려졌는지확인하려면 int glutgetmodifiers(void) id) 사용. GLUT_ACTIVE_SHIFT SHIFT 키 ( 혹은 Caps Lock인상태 ) GLUT_ACTIVE_CTRL CTRL GLUT_ACTIVE_ALT void keyboard(unsigned char key, int x, int y) if (key == 27) /* ESC-key exits the program */ exit(0); else if (key == r ) int mod = glutgetmodifier(); if (mod == GLUT_ACTIVE_CTRL) CTRL) red = 0.0; else red = 1.0; GLUT Mouse Functions glutmousefunc(void(*func)(int button, int state, int x, int y)) 마우스버튼이눌려졌을때불려짐 glutmotionfunc(void(*func)(int x, int y)) 마우스가버튼이눌려진상태에서움직일때불려짐 glutpassivemotionfunc(void (*func)(int x, int y)) 마우스버튼이눌려지지않은상태에서움직일때불려짐 GLUT Mouse Event Callback void mouse(int button, int state, int x, int y) button 인자에는 GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON state 인자에는 GLUT_DOWN ( 마우스버튼이눌려졌을때 ) GLUT_UP ( 마우스버튼이떼어졌을때 ) x, y 인자는마우스버튼이눌렸거나떼어졌을때마우스의위치 (in GLUT window coordinates) GLUT Motion Event Callback void motion(int x, int y) x, y 인자는마우스의새로운위치 (in GLUT window coordinates) id ti (i t i t ) void motion(int x, int y) void mouse(int button, int state, int x, int y)
GLUT Mouse Enter/Leave the Window void glutentryfunc(void(*func)(int state)); void entry(int state) state 인자는 GLUT_LEFT, GLUT_ENTERED X-window에서는정확히윈도우에마우스가들어오고나갈때의이벤트를발생시킴. Windows OS에서는마우스를현재윈도우에클릭해야 window focus 가바뀌게되므로이함수가정확히작동되지않음. void entry(int state) Mouse Positioning GLUT screen coordinate은원점을왼쪽위쪽 (top-left corner) 으로하고 x+ 는오른쪽, y+ 는아래쪽으로 1 pixel 단위로증가한다. OpenGL 은 2D drawing coordinate 은원점이왼쪽아래쪽 (bottom-left corner) 으로하고, x+ 는오른쪽, y+ 는위쪽으로증가한다. 따라서, 마우스로입력된 y 값을윈도우의높이 (height) 에서빼주어야 OpenGL 의화면에그림을그릴수있다. y = height y; h (0,0) w Drawing squares at cursor location void mouse(int button, int state, int x, int y) if(button==glut_right_button && state==glut_down) exit(0); if(button==glut_left_button && state==glut_down) drawsquare(x, y); void drawsquare(int x, int y) y = window_height - y; /* convert y position to screen drawing coordinates */ glcolor3ub( (char) rand()%256, (char) rand ()%256, (char) rand()%256); glbegin(gl_polygon); glvertex2f(x+size, y+size); glvertex2f(x-size, y+size); glvertex2f(x-size, y-size); glvertex2f(x+size, y-size); glend(); If both a mouse button and ALT key are pressed void mouse(int button, int state, int x, int y) specialkey = glutgetmodifiers(); if((state==glut_down)&&(specialkey == GLUT_ACTIVE_ALT)) if (button == GLUT_LEFT_BUTTON) red = 1.0; green = 0.0, blue = 0.0; else if (button = GLUT_MIDDLE_BUTTON) red = 0.0; green = 1.0, blue = 0.0;
GLUT Device Functions glutjoystickfunc(func) 조이스틱의상태를매 t milliseconds 단위로호출 gluttabletmotionfunc(func) 테블렛 puck 이움직였을때호출 gluttabletbuttonfunc(func) 테블렛버튼이눌렸거나떼어졌을때호출 glutdialsfunc(func) 다이얼이돌려졌을때호출 glutbuttonboxfunc(func) 다이얼 / 버튼박스의버튼이눌렸거나떼어졌을때호출 Widgets 대부분의윈도우시스템은그래픽사용자인터페이스 (Graphical User Interface) 위제트 (widgets) 을제공 그래픽디스플레이에입력기능을제공하는고수준인터페이스 (Higher-level interface) 물리적입력장치가제공하는대부분의기능을제공한다. 위제트의예 Menus Push Buttons Radio buttons Sliders Scroll bars Dials GLUT Menus Functions GLUT는간단한팝업메뉴 (pop-up menus) 기능을제공한다. 먼저메뉴안에항목들을정의한후, 이팝업메뉴를특정마우스버튼과연결해야한다 ( 이마우스버튼을눌렀을때나타날수있도록 ). 각메뉴항목에해당하는답신함수를정의해야함. 주 menus 아래 sub-menus를만들수있다. id = glutcreatemenu(func); /* starts defining a new menu */ glutaddmenuentry(label, value); /* adds an entry to the menu */ glutaddsubmenu(label, id); /* adds a submenu to the menu */ glutattachmenu(button); /* defines mouse buttons to pop-up the menu */ Menus는실행중에아래와같은함수를써서바꿀수도있다. glutsetmenu, glutremovemenuitem, glutchangetomenuentry, glutchangetosubmenu Menus는실행중에아래와같은함수를써서버튼에 attach 혹은 detach 가가능하다. glutdetachmenu Defining a simple menu int glutcreatemenu(void (*func)(int value)); void glutaddmenuentry(char *name, int value); name 인자는메뉴에나타나는이름 value인자는메뉴엔트리가선택됐을때답신함수에보내지는값 void glutattachmenu(int button); button인자에는 GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON menu_id = glutcreatemenu(menu); clear screen glutaddmenuentry( clear screen, 1); gluaddmenuentry( exit, exit 2); exit glutattachmenu(glut_right_button);
Menu actions Menu callback void menu(int id) if(id == 1) glclear(); if(id == 2) exit(0); 각각의메뉴는생성시 ID를갖는다. glutaddsubmenu(char *submenu_name, name, submenu id) 를사용하여 sub-menus 추가 Hierarchical Menus sub_menu = glutcreatemenu(size_menu); glutaddmenuentry( Increase t Size, 2); glutaddmenuentry( Decrease Size, 3); glutcreatemenu(top_menu); glutaddmenuentry( Quit, 1); glutaddsubmenu( Resize, sub_menu); glutattachmenu(glut_right_button); Quit Resize Increase Size Decrease Size Idle Callback The display callback glutidlefunc(void (*func)(void)) 의답신함수는다른이벤트가없을때실행됨. Idle은애니메이션움직임에사용함, e.g. rotating square void idle() /* change something */ t += dt glutpostredisplay(); tr l void display() glclear(); /* draw something that depends on t */ glutswapbuffers(); Idle 의 default 답신함수 (callback function) 는 NULL. 디스플레이답신함수는 GLUT에서윈도우가새로그리기 (window refresh) 를요할때불려진다. 윈도우가처음으로열렸을때 윈도우가재구성이필요할때 윈도우가 expose됐을때 사용자프로그램에서디스플레이가바뀌길원할때 glutdisplayfunc(display) l l 는모든 GLUT 프로그램에서반드시불리는 display callback이다.
glutpostredisplay void glutpostredisplay() 함수는윈도우가새로그려져야할필요가있는경우를표시하는일을한다. 일반적으로 display callback 함수를직접호출하는것보다, 이함수를사용하면디스플레이가다시그리기지시플래그를 GLUT 메인루프내에설치해서, 과다하거나불필요한화면그리기를방지한다. glutpostredisplay를사용하면이프로그램이이벤트루프를처리할때마다디스플레이가한번실행되도록한다. Animating a Display Display callback함수내에서디스플레이를새로그릴때 glclear() 를사용하여먼저윈도우를 clear 한다. 그러나, 프레임버퍼에서의그림정보는그림내용의디스플레이와분리되어있다. 따라서반쪽만그리게되는디스플레이를보게됨. single_double_buffer.cpp buffer.cpp 참고 rotating cube 예제 Double Buffering 2개의 color buffer를사용 Front Buffer 화면에출력 Back Buffer 그래픽스랜더링으로래스터이미지생성 Double Buffer 더블버퍼를초기화 glutinitdisplaymode(glut_double GLUT_RGB) display callback에서버퍼를지움 glclear(gl_color_buffer_bit ) display callback 에서마지막으로스왑버퍼를부름 glutswapbuffers() The Reshape callback glutreshapefunc(reshape) 는재구성이벤트답신함수를호출한다. void reshape(int w, int h) 윈도우의넓이 (width) 와높이 (height) 를반환한다. 이답신함수는자동적으로 redisplay를부른다. Reshape callback 함수는윈도우가처음열렸을때호출되므로관측함수를넣기에좋은곳이다.
Example Reshape void reshape(int w, int h) glviewport(0, 0, w, h); glmatrixmode(gl_projection); /* switch matrix mode */ glloadidentity(); if (w <= h) gluortho2d(-2 2.0, 2.0, 20-2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w); else gluortho2d(-2.0 guo * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0); glmatrixmode(gl_modelview); /* return to modelview mode */ Display Lists 그래픽스효율을증가시키기위해서네트워크상의클라이언트와서버구조를가진디스플레이프로세서라불리는특수목적컴퓨터를구성 초창기그래픽스시스템의구조 디지털아날로그변환기를통해 CRT에연결된 Host에기반을두고있음 디스플레이프로세서 (Display processor) 구조 래스터화 (Rasterization) 는디스플레이프로세서에서이루어짐. DPU(Display processor unit) 는제한된명령어집합 (instruction set) 을가지고있음. 대부분이 CRT에기본요소를그리기위한것. 사용자프로그램은호스트컴퓨터에서수행되어컴파일된명령리스트가되어디스플레이프로세서로보내지고, 그명령어들은디스플레이메모리 (display memory) 에디스플레이파일 (display file) 또는디스플레이리스트 (display list) 로저장됨 OpenGL Display List OpenGL에서디스플레이리스트는디스플레이할때사용하기위해저장된 OpenGL 명령어의집합. 자주실행될때유용 수행효율의향상을위해설계됨 디스플레이리스트정의 glnewlist(list, mode) list 는디스플레이리스트의식별자 (ID) mode 는 GL_COMPILE ( 서버에리스트를보내지만내용을디스플레이하지않도록지시 ), GL_COMPILE_AND_EXECUTE ( 즉시디스플레이 ) glendlist() 디스플레이리스트실행 glcalllist(list) 디스플레이리스트이름지정 glgenlists(range) OpenGL Display List /* init 함수내에서.. */ #define BOX 1 glnewlist(box, GL_COMPILE); glbegin(gl_polygon); glcolor3f(1.0, 0.0, 0.0); glvertex2f(-1.0, -1.0); glvertex2f(1.0, -1.0); glvertex2f(1.0, 1.0); glvertex2f(-1.0, 1.0); glend(); glendlist(); /* display 함수내에서.. */ p y glcalllist(box);
Display List Functions 디스플레이리스트생성 GLuint id; void init() id = glgenlists( 1 ); glnewlist( id, GL_COMPILE ); /* other OpenGL routines */ glendlist(); 생성된디스플레이리스트호출 void display() glcalllist( id ); Display List 여러개의디스플레이리스트를부르는함수 glcalllists(glsizei num, GLenum type, const GLvoid * lists_ptr) Type은 GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, SHORT GL_INT, GL_UNSIGNED_INT, INT GL_FLOAT, GL_2_BYTES, GL_3_BYTES, GL_4_BYTES 디스플레이리스트안에서다른디스플레이리스트도호출가능 디스플레이리스트생성은네스트 (nested) 하지못함 예를들어 glendlist() 전에 glnewlist() 가두번째로불리면 GL_INVALID_OPERATION라는에러 (error) 발생 glflush(), glget*(), glisenabled() 처럼즉시처리를요하는함수는디스플레이리스트안에불릴수없음 디스플레이리스트는한번생성되면 gldeletelists() 가불릴때까지내용을바꿀수없음. Display Lists and State 디스플레이리스트안에대부분의 OpenGL 함수들이들어갈수있음 디스플레이리스트안에서상태 (State) 를변화시킬수있고, 이런변경이디스플레이리스트가실행된후에도예측하지못한효과를줄수도있음. 예를들어, 빨간색네모를그리는디스플레이리스트가실행될때마다그림의색이적색으로설정되어프로그램에서이후에정의된기본요소들또한적색을가지게됨. 따라서, OpenGL 의행렬과속성스택의사용을권장함. 디스플레이리스트안에시작과끝에행렬과속성스택사용 glpushattrib(gl_all_attrib_bits); glpushmatrix(); glpopmatrix(); glpopattrib(); Display Lists and State 디스플레이리스트안에시작과끝에행렬과속성스택사용 #define RED_SQUARE 1 glnewlist(red_square, GL_COMPILE); glpushattrib(gl_current_bit); glcolor3f(1, 0, 0); glrectf(-1, -1, 1, 1); glpopattrib(); glendlist(); Stack: LIFO
Hierarchy and Display Lists 자동차모델예제 섀시 (chassis) 디스플레이리스트생성 바퀴 (wheel) 디스플레이리스트생성 glnewlist(car, GL_COMPILE); glcalllist(chassis); gltranslatef( ); glcalllist(wheel); gltranslatef( ); glcalllist(wheel); glendlist(); Picking 지적 (Picking) 은화면상의한객체를사용자가식별할수있도록하는입력연산 OpenGL에서지적연산을구현하기어려움. 객체 (object) 정의 디스플레이리스트사용 기본요소의그룹을표시하는태그시스템을생성 객체지적 (picking an object) 을정의 기본요소를마우스로클릭하나? 아니면가까이가는것으로하나? 여러객체가중첩 (overlap) 됐다면? 구현이슈 Picking Solutions 선택모드 (Selection mode) pick1.cpp 클리핑영역과시역을조절하여작은클리핑영역내의어떤기본요소 (primitive) 가커서 (cursor) 부근의영역으로렌더링되는지추적. 적중리스트 (hit list) 에기록되어후에사용자프로그램으로조사될수있음. 경계박스 (Bounding box) pick2.cpp 가장간단한방법 후면버퍼 (Back buffer) pick3.cpp color-coded objects 과 glreadpixel() 사용 Rendering Modes OpenGL의 glrendermode(mode) 에서선택된 3가지모드중하나로렌더링. 렌더모드 (GL_RENDER): 프레임버퍼에정상적인렌더링 (default) 피드백모드 (GL_FEEDBACK): 렌더링된기본요소의리스트를얻는데사용 선택모드 (GL_SELECT): 선택모드로전환하고장면을렌더링하면, 뷰볼륨안에있는각기본요소는적중레코드 (hit record) 를발생하여추후에사용하도록네임스택 (name stack) 이라고하는버퍼안에저장됨.
Selection Mode Functions void glselectbuffer(glsizei n, GLunint *buffer) 네임스택지정. 선택된데이터가배열안에있는지확인가능 선택데이터를넣을배열 buffer 의크기를 n 으로설정 void glinitnames() 네임스택을초기화 void glpushname(gluint name) name 을네임스택에넣는함수 void glpopname() 탑 (top) 에있는 name 을네임스택으로부터꺼내는함수 void glloadname(gluint name) 네임스택의탑을 name 으로대체하는함수 name 은객체를식별하기위해응용프로그램에서지정함 Using Selection Mode 1. 네임스택을초기화 2. 선택모드로전환 일반적으로선택모드에들어가기위해서는마우스답신을사용하고마우스답신이끝나기전에선택모드를떠남. 3. 사용자가정의한 ID로장면을렌더링 4. 다시정상적인렌더모드로전환 이과정에서다수의히트 (number of hits) 를넘겨받음. 5. 네임스택 (name buffer) 에히트레코드 (hit records) 조사 히트레코드는 ID 와깊이정보를포함 Selection Mode and Picking Selection Mode 사용자가정의한커서에중심을갖는조그만사각형안에렌더링된모든객체를지적한다고가정. 사각형의크기가지적감도의척도가됨. 투영행렬과지적행렬을곱하기위해서 glupickmatrix 를사용. void glupickmatrix(gldouble x, GLdouble y, GLdouble width, GLdouble height, GLint viewport[4])
Using Bounding Box Bounding Box 객체의범위 (the extent of an object) 을정의. 객체의범위는객체를포함하고있는좌표축에정렬된 (axisaligned) 가장작은사각형 세계좌표계안에어떤사각형이화면좌표계의특정점과대응하는지를결정하는것은비교적쉬운일. 객체들과경계사각형들을관련짓는간단한자료구조를응용프로그램이유지한다면근사한지적을구현가능. Using Back buffer Using Back buffer 객체들 (objects) 는각각다른색으로후면버퍼에렌더링. 응용프로그래머는새로운객체가프로그램으로정의될때마다단순히색을변화시켜객체의내용을결정 후면버퍼를사용한지적연산단계 : 1. 객체를지적색 (pick color) 로후면버퍼에그림 2. 마우스답신함수를이용하여마우스의위치값 (mouse position) 을얻음 3. glreadpixels() 함수를이용하여마우스위치에해당하는프레임버퍼안의위치를찾고이위치의색을구함 4. 읽혀진색에해당하는객체를색테이블을이용하여찾음
Dithering 일부그래픽스하드웨어에서표현가능한컬러의수를늘리기위해 Dithering 을사용함. 컬러를표현하기위해여러개의색을혼합하여사용함. 즉, 빨간색과흰색을번갈아바둑판모양으로칠해서눈에분홍색으로보이도록하는것. glenable(gl_dither) 와 gldisable(gl_dither) DITHER) 를사용하여활성화 / 비활성화를함. Default 로 Dithering 이활성화되어있음.