지난 글에서 Shader가 interpolation을 통해서 여러가지 벡터를 보간하고, 그것으로 멋진 효과를 만들어 낸다는, 지극히 주관적인 잔소리를 좀 했었어요.
https://learn-and-give.tistory.com/27
평가는 언제나 각자가 하는 것이니, 이를 위해 Shader에 대해서 설명을 해 보도록 할께요.
이전 글의 마지막에, 이러니 저러니 다 하더라도, Fragment shader에서 색상을 특정값으로 지정하면 단색으로 칠해지는 것을 보았는데요, 그럼 주어지는 색상과 출력되는 색상이 어떤 관계인지 살펴보겠습니다.
우선 RGB 색상을 가지는 Vertex로 만들어지는 삼각형을 하나 그려보겠습니다. Vertex Shader나 Fragment Shader 모두 별다른 처리를 하지 않고 주어지는 값을 그대로 사용합니다. 즉, Shader 코드를 쓰기는 하지만 결과적으로는 Shader를 쓰지 않은 상태(Fixed Rendering pipeline)와 같은 결과가 나옵니다.
먼저 OpenGL 코드는 아래와 같습니다.
//Rendering function
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.f,0.f,0.f);
glVertex3f(-0.5,-0.5,0.0);
glColor3f(0.f,1.f,0.f);
glVertex3f(0.5,0.0,0.0);
glColor3f(0.f,0.f,1.f);
glVertex3f(0.0,0.5,0.0);
glEnd();
glFlush();
}
Vertex Shader는 아래와 같습니다.
전달 받은 값을 그대로 전달합니다. ftransform은 modelview를 곱해주는 함수 정도로 생각해주세요. 여기서 눈여겨 볼 것은, Front color에 gl_Color를 입력하는 부분입니다. 전달 받은 값이 gl_Color이고, 그 결과 색이 gl_FrontColor입니다.
void main()
{
// the following three lines provide the same result
gl_FrontColor = gl_Color;
gl_Position = ftransform();
}
Fragment Shader는 아래와 같습니다.
여기도 마찬가지로 전달 받은 색상값(gl_Color)을 출력값(gl_FragColor)에 넣어줍니다.
void main()
{
// gl_FragColor = vec4(0.4,0.4,0.8,1.0);
gl_FragColor = gl_Color;
}
실행하면, 당연히 원래 색상이 그대로 나옵니다.
자, 그럼 여기에 조금 변화를 주겠습니다.
Vertex Shader에서 각 Vertex의 색상을 반전 시켜보겠습니다. 색상값이 0~1로 주어지기 때문에 전달 받은 값을 1에서 빼주면 됩니다.
void main()
{
vec4 invColor;
invColor[0]=1.f-gl_Color[0];
invColor[1]=1.f-gl_Color[1];
invColor[2]=1.f-gl_Color[2];
invColor[3]=1.f-gl_Color[3];
gl_FrontColor = invColor;
gl_Position = ftransform();
}
결과는 아래와 같습니다.
이 예제에서 아래 내용을 꼭 염두에 두면 좋겠습니다.
- Vertex Shader의 gl_FrontColor에 값을 할당하여 그려지는 색을 변경 할 수 있다.
- Vertex에 할당 된 색상은 gl_Color로 Vertex Shader에 전달 된다.
- 배경 색상은 아무런 변화가 없다.
이 내용이 Vertex Shader의 입출력과 적용 범위를 이해하는데 큰 도움이 될 것 입니다.
Vertex에 할당 된 색상만 반전시키고 나면, 그 이후에 이를 보간하여 그려주는 과정은 기존 과정이 그대로 적용되었습니다.
여기서, 한번 생각 해 볼 퀴즈~
Vertex Shader는 그대로 유지하고 색상을 반전하는 방법은 무엇일까요?
바로 Fragment Shader에서 똑같은 처리를 해주는 것이죠. 반전을 하고 보간을 하는 것이나, 보간을 하고 반전을 하는 것이나 같기 때문이죠. Vertex Shader를 원래 코드로 수정한 후, Fragment Shader의 코드를 아래와 같이 수정하면 같은 결과를 얻게 됩니다. (Vertex Shader도 반전 상태에서 아래 코드를 적용하면 반전에 반전이니 원래 색상이 나오죠.)
void main()
{
vec4 invColor;
invColor[0]=1.f-gl_Color[0];
invColor[1]=1.f-gl_Color[1];
invColor[2]=1.f-gl_Color[2];
invColor[3]=1.f-gl_Color[3];
//gl_FragColor = gl_Color;
gl_FragColor = invColor;
}
그럼, 반전을 하고 싶다면 어떤 방법이 좋을까요?
이 예만 놓고 본다면, Vertex Shader에서 수정하는 것이 더 좋을 것 같아요.(개인적인 생각) 왜냐하면 Fragment Shader는 Pixel 단위로 수행되는 연산이고, Vertex Shader는 Vertex마다 수행되니, Fragment Shader가 훨씬 많은 연산을 할 것 같은데, 사용자가 작성한 코드가 더 많이 적용되면 아무래도 최적화에 좀 덜 유리할 것 같네요.
코드는 github에 올려두었습니다. history에서 chapter 제목을 선택하면 각 챕터별 코드를 볼 수 있을 것입니다.
https://github.com/red112/glsl
다음 시간에는 색상과 함께 전달되는 Vertex position을 조금 다뤄보겠습니다.
https://learn-and-give.tistory.com/29
'공허의 유산 > 표현의 자유' 카테고리의 다른 글
[opengl].[#2.GLSL] 06. gl_Position 끄적거리기(2) (0) | 2023.01.09 |
---|---|
[opengl].[#2.GLSL] 05. gl_Position 끄적거리기 (0) | 2023.01.08 |
[opengl].[#2.GLSL] 03. Shader, 이걸 누가 설명 해 줬더라면... (0) | 2023.01.05 |
[아빠의 Roblox 숙제]#2. 물체를 밀어서 이동시키기(1) (0) | 2021.01.30 |
[아빠의 Roblox 숙제]#1. 와리가리 물체를 이용해서 건너가기 (0) | 2021.01.29 |
댓글