화면에 그려진 그림은 색상버퍼라는 메모리에 저장됩니다.
그림이 이미 그려진 상태에서 같은 위치에 다른 그림을 그리면 새 그림을 새 메모리에 기록하기 때문에, 이전에 있던 그림에 덮어져서 그려지게 됩니다.
이런 당연한 현상도 블렌딩 모드를 변경하면 달라질 수 있습니다.
블렌딩은 색상버퍼에 이미 기록되어있는 값과 새로 그려지는 값의 논리연산방법을 지정해 줍니다.
블렌딩 기능을 사용하려면 다음 명령으로 요고를 적용시켜야 합니다.
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 |