본문 바로가기
공허의 유산/표현의 자유

[opengl].[#2.GLSL] 04. gl_Color 끄적거리기

by 바른생활머시마 2023. 1. 7.
728x90
반응형

지난 글에서 Shader가 interpolation을 통해서 여러가지 벡터를 보간하고, 그것으로 멋진 효과를 만들어 낸다는, 지극히 주관적인 잔소리를 좀 했었어요.

https://learn-and-give.tistory.com/27

 

[opengl].[#2.GLSL] 03. Shader, 이걸 누가 설명 해 줬더라면...

나이가 들면서 점점 잔소리가 많아지는 것을 딸과의 대화에서 체감하고 있습니다. 예전에는 몰랐던 것을 이제 알게 되어, 똑같은 실수를 하지 않았으면 하는 바램이 크기 때문이죠. GLSL에서도

learn-and-give.tistory.com

 평가는 언제나 각자가 하는 것이니, 이를 위해 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를 수정한 색상 반전 구현

 이 예제에서 아래 내용을 꼭 염두에 두면 좋겠습니다.

  • 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

 

GitHub - red112/glsl: OpenGL Shading Language review

OpenGL Shading Language review. Contribute to red112/glsl development by creating an account on GitHub.

github.com

 

다음 시간에는 색상과 함께 전달되는 Vertex position을 조금 다뤄보겠습니다.

https://learn-and-give.tistory.com/29

 

[opengl].[#2.GLSL] 05. gl_Position 끄적거리기

앞에서 gl_Color의 특성에 대해서 알아보았습니다. https://learn-and-give.tistory.com/28 [opengl].[#2.GLSL] 04. gl_Color 끄적거리기 지난 글에서 Shader가 interpolation을 통해서 여러가지 벡터를 보간하고, 그것으로

learn-and-give.tistory.com

 

728x90
반응형

댓글