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

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

by 바른생활머시마 2023. 1. 5.
728x90

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

 "초보"에게 도움이 될 것 같은 잔소리 중, 하나를 이야기 해 볼께요. 

 

 랜더링 파이프 라인 알고 있나요?

 

 누군가 예전에 저에게 물어봤다면, 아주 자신있게 잘 알고 있다고 답했을 것입니다. 지금은 그런 대답 섣불리 못하게 되었죠.  예전에 자료를 정리하면서 어디선가 퍼왔던 그림인데, 랜더링 파이프라인을 순서대로 보여줍니다.

 

랜더링 파이프 라인

 Graphics 관련 된 공부를 좀 해보신 분들은 아마도 한두번 본 적은 있을 것입니다. 

 

 잠시 주제를 바꿔서,  Polygon In/Out Test 알고리즘 요즘도 공부하는지 모르겠네요. 

윤곽선이 만들어지고 안을 채우려면 폴리곤 안과 밖을 구분 할 수 있어야 하죠. 이 알고리즘이 꼭 Graphics만을 위해서 쓰이는 것은 아니랍니다. Picking을 할 때 Ray와 삼각형의 교점을 구하거나, 어떤 좌표가 어떤 구역에 포함되어 있는지, 충돌 검사를 한다거나 기하 구조를 이용한 판정에 사용되기도 합니다.  적어도 랜더링을 위해 이 알고리즘을 공부하는 사람들은 많이 줄어들었을 것입니다. 왜냐하면, 다 알아서 해주기 때문에 몰라도 별 문제가 없는 세상이 되었기 때문이죠. 

 

 랜더링 파이프라인도 마찬가지였습니다.

 랜더링 파이프 라인을 잘 몰라도 원하는 그림을 그려낼 수 있었기 때문이죠. 지나고보면 원하는 그림을 다 그릴 수 있었던 것이 아니라, 미리 제한 된 범위를 알고서 그 범위가 전부라고 생각했기 때문에 불편함이 없었던 것이죠. (쉐이더 없이 랜더링하는)고정 파이프라인을 통해서 그려지는 결과만으로도 충분히 가슴벅차고 화려한 그래픽을 느낄 수 있었죠. (그때는!)

 

 그러나, 저처럼 만족하고 사는 사람들이 있는가 하면 더 멋진 것을 원했던 사람들도 많았나 봅니다.그래서, 고정 파이프라인이 아니라 저 랜더링 파이프라인도 프로그래밍 할 수 있으면 좋겠다는 필요로부터 쉐이더가 나왔습니다.(맞...겠죠??ㅋㅋ)  GLSL 강좌를 보고 따라하면서 멋진 그래픽을 보고 감동한 적이 많은데, 정작 중요한 것은 모르고 있었습니다. 쉐이더의 진정한 가치를 몰랐던 것 같아요.

 

 개인적인 의견입니다만, Shader의 꽃은(위 파이프라인으로 이야기를 하자면), Fragments로부터 Colored Fragments로 넘어가는 과정에 있다고 생각합니다. 그 과정을 위해서 여러가지 데이터를 준비해서 넣으면 멋진 결과가 짠! 나오는 것이죠. 위 그림에서 이 단계에 interpolation이라고 되어 있습니다. 이 interpolation이 그렇게 중요한 것인지 몰랐었죠.

 

빨강, 파랑, 초록이 보간 된 삼각형

 

 

 

 

 

 Graud(Smooth) shading을 하면, 각 vertex에 할당 된 색상이 부드럽게 섞여지는거? 멋지긴한데 그게 그렇게 놀랄 일이야?

 

 제가 저렇게 생각했었는데, 맞는 말이기도 하고, 또 한편 경솔한 말이기도 합니다.

 

 이제 핵심 주제를 조금 이야기 해볼께요.

 위 그림에는 각 Vertex에 Color가 할당되어 있고, 그것을 interpolation하여, fragments의 색상을 결정하는 과정이 표현되어 있습니다. 그런데, 이 과정은 비단 "색상"에만 적용되는 것이 아니라, Vertex에 할당 된 어떤 벡터에 대해서 적용되는 것이죠. "색상"은 RGB(A)로 만들어진 벡터이고, interpolation 된 벡터값이 각 fragment에 할당되는 것입니다. 

 

이 주제로 적어 갈 글의 거의 마지막에 조명에 대한 이야기를 하면서 다시 이야기 할 내용인데, 지금 먼저 한번 생각 해 보면 좋겠습니다.

 

어떤 정사각형의 푸르스름한 책상이 있고, 책상 가운데 위에 조명이 있다고 가정 해 보겠습니다. 이 책상을 조명이 있는 위쪽에서 보면 아래와 같이 보일 것입니다. OpenGL로 이 책상의 윗면을 그려본다고 가정 해 보겠습니다. 아래 그림처럼 그려질까요??

 

 

 

파란 정사각형 책상 한가운데 있는 조명

정사각형이고 조명이 각 꼭지점과의 거리나 각도가 똑같기 때문에, 각 꼭지점은 똑같은 색상이 될 것 입니다. 위 랜더링 파이프 라인의 interpolation 단계를 생각해보면 어떻게 그려질지 상상 해 볼 수 있습니다. 상상 해 보셨나요? 실망스럽게도 결과는 아래와 같이 단색 사각형이 나오게 됩니다. 왜 그런지 이해가 되시면 당신은 멋쟁이!!!

interpolation 된 결과

고정 파이프라인에서 보간은 색상에 대해서 되기 때문에, 같은색 꼭지점으로 된 도형은 내부도 같은 색이 되는 것입니다.

만약, 가운데 Vertex가 하나 추가된다면 어떨까요?? 가운데가 가장 밝은 색이 될테니까 적어도 같은 색은 아닐 것입니다. 4각형을 어느 방향의 삼각형으로 나누었느냐에 따라 결과가 달라지겠지만, 적어도 가운데와 꼭지점은 색이 다를 것입니다. Vertex를 가운데 뿐만 아니라 더 많이 추가한다면??? 아주 촘촘하게 추가한다면???

 

 Vertex를 추가해서 좀 더 좋은 결과를 낼 수 있다고 생각해 내셨다면 훌륭한 입문자!!!!

 

 Vertex를 추가하면 왜 품질이 좋아질까요???

 바로 Vertex의 위치에서 계산되는 색이 위치에 따라 다르기 때문이죠. 같은 색의 책상인데 위치에 따라 색상이 다른 이유는? 바로 그 위치에서 조명에 대한 상대적인 방향, 즉 조명과 면의 각도가 다르기 때문이죠.

대표적인 조명에 따른 밝기 계산 모델

 

 결과적으로는, 가장 작은 단위인 픽셀 단위로 조명에 따른 색상을 계산하는 것이 최선이죠.

  하지만, 조명에 따른 색상을 계산하기 위해서는 법선벡터(normal vector) 정보가 필요한데, 픽셀에 법선 벡터는 어떻게 넣죠??? 법선벡터는 vertex에 할당을 하긴하는데....

 

 이 부분이 바로 Shader의 꽃!!! 입니다.

 Shader는 Vertex에 할당 된 다양한 vector(attributes)를 Fragment 단위로 보간해 줍니다.

 또한, 이 값들을 이용하여 Fragment 단위로 임의의 계산식을 만들어 색상값을 정할 수 있습니다.  

 

즉, 계산에 필요한 값은 충분히 가져가고, 원하는 수식을 적용해서 색상을 결정 할 수 있죠. 아래는 이런 과저을 통해 그려진 이미지 입니다.가운데가 가장 밝고, 주변으로 갈수록 원형으로 부드럽게 어두워집니다. 

 

쉐이더를 이용한 랜더링

변화를 좀 더 잘 구별 할 수 있도록 조정을 좀 해 보면 더 잘 나타납니다.

이렇게 만들어진 조명 랜더링 모델이 바로 퐁쉐이딩이고, Shader 없이 고정 파이프라인으로 계산하려면 vertex를 아주 많이 할당해야 합니다. 그러나, Shader를 쓰면 적용하고자 하는 수식 모델을 적용하고 필요한 값을 Vertex의 attribute로 전달함으로써 매우 현실적이거나 매우 비현실적이면서도 독특한 효과를 낼 수 있죠. 즉, 표현의 자유도가 고정 파이프라인에 비해 비교 할 수 없을 정도로 높아지죠.

 

 꼭 더욱 현실에 가깝게 표현하는 것만이 가치있는 것은 아닙니다. 매우 사실적인 표현을 하고 싶은 경우에는 현실과 구별할 수 없을 만큼 세밀하게 표현하기 위한 모델과 데이터로 표현 할 수 있고, 경우에 따라서는 다 무시하고 매우 단순하게 표현 할 수도 있습니다. 예를 들어, vertex에 아주 많은 정보를 넘겨주더라도, Fragment shade가 아래 코드로 되어 있다면...

void main()
{
	gl_FragColor = vec4(0.4,0.4,0.8,1.0);
}

난 나의 길을 가련다!

 

 이런 자유도가 바로, 쉐이더의 가장 중요한 핵심 가치입니다.(개인적인 생각)

 이런 쉐이더에 대해서 천천히 조금씩 소개 해 보도록 하겠습니다.

 

728x90
반응형

댓글