Graphics/OpenGL

OpenGL 기초 - 블렌딩

MOLOKINI 2014. 5. 17. 18:58

화면에 그려진 그림은 색상버퍼라는 메모리에 저장됩니다.

그림이 이미 그려진 상태에서 같은 위치에 다른 그림을 그리면 새 그림을 새 메모리에 기록하기 때문에, 이전에 있던 그림에 덮어져서 그려지게 됩니다.
 
이런 당연한 현상도 블렌딩 모드를 변경하면 달라질 수 있습니다.
블렌딩은 색상버퍼에 이미 기록되어있는 값과 새로 그려지는 값의 논리연산방법을 지정해 줍니다.

 
블렌딩 기능을 사용하려면 다음 명령으로 요고를 적용시켜야 합니다.
 
glEnable(GL_BLEND);
 
블렌딩은 색상버퍼에 이미 기록된 값 D와 새로 기록되는 값 S와의 연산을 정의합니다.
연산방법은 다음 두 함수로 정의됩니다.
 
void glBlendFunc(GLenum sfactor, GLenum dfactor);
void glBlendEquation(GLenum mode);
 
sfactor와 dfactor는 S색상과 D색상에 각각 적용할 연산식을 정의하며, mode는 두 연산결과를 합칠 방법을 정의합니다.
모드에 따른 연산식은 아래와 같습니다, 디폴트는 GL_FUNC_ADD
SF, DF는 sfactor, dfactor
 
모드                                               연산식
GL_FUNC_ADD                                S*SF + D*DF
GL_FUNC_SUBTRACT                      S*SF - D*DF
GL_FUNC_REVERSE_SUBTRACT       D*DF - S*SF
GL_MIN                                          S*SF, D*DF중 작은 값
GL_MAX                                         S*SF, D*DF중 큰 값
 
사실 뭔소린지 잘 모르겠어요, 예제를 해봅시다.
S와 D에 적용되는 연산식의 종류는 아래와 같습니다, 잘 안쓰는 항은 생략한거니까 자세한건 레퍼런스를 참고하세염
 
연산식                                                색상(FR, FG, FB, FA)
GL_ZERO                                           (0,0,0,0)
GL_ONE                                             (1,1,1,1)
GL_SRC_COLOR                                 (RS, GS, BS, AS)
GL_ONE_MINUS_SRC_COLOR              (1-RS, 1-GS, 1-BS, 1-AS)
GL_DST_COLOR                                  (RD, GD, BD, AD)
GL_ONE_MINUS_DST_COLOR               (1-RD, 1-GD, 1-BD, 1-AD)
GL_SRC_ALPHA                                  (AS, AS, AS, AS)
GL_ONE_MINUS_SRC_COLOR               (1-AS, 1-AS, 1-AS, 1-AS)
GL_DST_ALPHA                                   (AD, AD, AD, AD)
GL_ONE_MINUS_DST_COLOR                (1-AD, 1-AD, 1-AD, 1-AD)
GL_CONSTANT_COLOR                        (RC, GC, BC, AC)
GL_ONE_MINUS_CONSTANT_COLOR     (1-RC, 1-GC, 1-BC, 1-AC)
GL_CONSTANT_ALPHA                         (AC, AC, AC, AC)
GL_ONE_MINUS_CONSTANT_ALPHA      (1-AC, 1-AC, 1-AC, 1-AC)
GL_SRC_ALPHA_SATURATE                  (i,i,i,1) i = min(AS, 1-AD)
 
연산식에 의해 R, G, B, A 색상 요소에 곱해지는 FR, FG, FB, FA 함수가 정의되고 이 함수가 각 색상요소에 적용됨으로써, 중간식이 생성되며 두 중간식을 연산하여 최종 색상을 도출합니다.
 
색상이 아닌 상수와도 연산이 가능한데 그 때는 아래의 함수로 지정합니다.
 
void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
디폴트는 (0,0,0,0) 검정색이다.
다음 함수는 좀 더 상세한 연산식을 정의한다.
 
void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
 
지정 가능한 연산식의 종류는 동일하다.
계산식이 좀 더 복잡한 대신 다양한 기교를 부릴 수 있다.
 
#include <gl/glut.h>
 
void DoDisplay();
void KeyDown(unsigned char key, int x, int y);
void DoMenu(int value);
 
GLfloat Alpha = 0.5f;
GLenum Src = GL_SRC_ALPHA;
GLenum Dest = GL_ONE_MINUS_SRC_ALPHA;
 
int main()
{
     glutCreateWindow("OpenGL"); // 윈도우 만들기.
     glutDisplayFunc(DoDisplay); // 화면표시함수.
     glutKeyboardFunc(KeyDown); // 키보드 입력 함수.
     glutCreateMenu(DoMenu); // 메뉴 생성 함수
     glutAddMenuEntry("Opaque",1); // 메뉴 엔트리 1
     glutAddMenuEntry("Traslucent",2); // 메뉴 엔트리 2
     glutAttachMenu(GLUT_RIGHT_BUTTON); // 오른쪽 버튼을 누르면 메뉴생성
     glutMainLoop(); // 메인루프
     return 0;
}
 
void KeyDown(unsigned char key, int x, int y) // q, a를 눌렀을 때 알파값 변경
{
     switch(key) {
     case 'q':
          Alpha += 0.1;
          break;
     case 'a':
          Alpha -= 0.1;
          break;
     }
     glutPostRedisplay(); // 화면 재생성
}
 
void DoMenu(int value)
{
     switch(value) {
     case 1:
          Src = GL_ONE;
          Dest = GL_ZERO;
          break;
     case 2:
          Src = GL_SRC_ALPHA;
          Dest = GL_ONE_MINUS_SRC_ALPHA;
          break;
     }
     glutPostRedisplay();
}
 
void DoDisplay()
{
     glClearColor(1,1,1,1);
     glClear(GL_COLOR_BUFFER_BIT);
 
     glEnable(GL_BLEND);
     glBlendFunc(Src, Dest);
 
     glColor3f(0, 0, 1);
     glRectf(-0.5, 0.8, 0.5, 0.0);
 
     glColor4f(1, 0, 0, Alpha);
     glBegin(GL_TRIANGLES);
     glVertex2f(0.0, 0.5);
     glVertex2f(-0.5, -0.5);
     glVertex2f(0.5, -0.5);
     glEnd();
     glFlush();
}
 

 

삼각형이 q를 누르면 진해지고 a를 누르면 연해집니다

오른쪽 버튼을 눌러 메뉴를 호출하고 Opaque를 누르면 알파값 1, Traslucent를 누르면 알파값이 적용됩니다.

 

 

이 예제에서의 반투명 출력에 사용한 블렌드 연산식은 다음과 같습니다.

 

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

 

삼각형의 알파값이 0.4라고 했을 때, GL_SRC_ALPHA의 블렌딩 함수는 (AS, AS, AS, AS)이다. 그래서 S의 각 색상요소에 0.4가 곱해집니다. 

GL_ONE_MINUS_SRC_ALPHA의 블렌딩 함수는 모두 1-AS이므로, D의 각 색상요소에 0,6이 곱해진다. 두 연산결과를 연산하는 모드는 디폴트인 GL_FUNC_ADD이므로, 두 값을 더해 최종 색상을 결정합니다.

 

(

0.4 * 1 + 0.6 * 0

0.4 * 0 + 0.6 * 0

,

 0.4 * 0 + 0.6 * 0

0.4 * 0.4 + 0.6 * 0.6

// RGBA

(0.4 * (1, 0, 0, 0.4) + 0.6 * (0, 0, 1, 0.6)) 

 // 빨간색삼각형 + 파란색삼각형

0.4 * 빨간색 + 0.6 * 파란색

 

빨간거 40%(S색), 파란거 60%(D색) 섞어서 기록하는겁니다.

 

불투명 모드일 때는

glBlendFunc(GL_ONE, GL_ZERO);

 

앞이 S고 뒤가 D입니다.

S의 색상은 그대로고, D의 색상은 없애니까 불투명해지는거겠지요?

'Graphics > OpenGL' 카테고리의 다른 글

OpenGL 기초 - GLUT  (0) 2014.05.19
OpenGL 기초 - 안티앨리어싱  (0) 2014.05.17
OpenGL 기초 - 점, 선, 삼각, 사각, 다각형  (0) 2014.05.17
OpenGL 기초 - 상태머신, 버전조사  (0) 2014.05.16
OpenGL 기초 - 색상변경  (0) 2014.05.16