렌더링 파이프라인 완벽 이해 – Pixel Shader 단계는 왜 필요할까?

이전 글에서는 Rasterizer 단계가 왜 필요한지를 정리했습니다.

Vertex Shader 단계에서 공간 변환이 끝난 삼각형은 아직 실제 화면 이미지 형태가 아닙니다.

GPU는 여전히 삼각형이 화면 위의 어떤 픽셀을 차지하는지를 계산해야 합니다.

그리고 바로 이 작업을 Rasterizer 단계가 담당하게 됩니다.

Rasterizer 단계에서는 삼각형 내부에 포함되는 픽셀 후보(Fragment)를 생성하고,
각 픽셀의 깊이값(Z값)과 보간(Interpolation) 데이터도 함께 계산하게 됩니다.

예를 들어 Vertex마다 서로 다른 UV 좌표나 Normal 값이 존재하더라도,
Rasterizer 단계에서는 삼각형 내부 위치에 따라 이 값들을 부드럽게 확장해서 Pixel Shader 단계로 전달하게 됩니다.

즉, Rasterizer 단계는 단순히 픽셀을 판별하는 과정이 아니라,
삼각형 기반 Primitive를 실제 픽셀 계산이 가능한 형태로 변환하는 단계라고 볼 수 있습니다.

이번 글에서는 렌더링 파이프라인의 다음 단계인 Pixel Shader 단계에 대해 정리해보려고 합니다.

Pixel Shader 단계는 GPU가 실제 화면 색상을 계산하기 시작하는 단계입니다.

지금까지는 삼각형을 구성하고,
공간 변환을 수행하며,
픽셀 후보를 생성하는 과정이었다면,
이제부터는 실제 화면에 어떤 색상이 출력되어야 하는지를 계산하기 시작합니다.

그리고 바로 이 단계에서 Texture, Lighting, Material, Reflection 같은 그래픽 표현들이 본격적으로 등장하게 됩니다.

즉, 현대 게임 그래픽의 시각적 품질 상당수는 결국 Pixel Shader 단계에서 결정된다고 볼 수도 있습니다.

이 단계를 이해하면 왜 Shader가 현대 GPU 구조의 핵심이 되었는지,
왜 최근 게임 그래픽이 점점 더 복잡한 계산을 수행하기 시작했는지도 함께 보이기 시작합니다.


Pixel Shader는 화면의 색상을 결정하는 단계

Rasterizer 단계가 끝나면 GPU는 픽셀의 후보라고 할 수 있는 Fragment를 가지게 됩니다.

이 시점에서는 어떤 픽셀이 삼각형 내부에 포함되는지까지는 계산이 끝난 상태입니다.

하지만 아직 실제 화면 이미지는 완성되지 않았습니다.

왜냐하면 GPU는 여전히 이 픽셀이 어떤 색상을 가져야 하는지를 계산해야 하기 때문입니다.

예를 들어 같은 삼각형이라도 금속 재질인지 나무 재질인지에 따라 표면의 느낌 자체가 달라질 수 있습니다.

또한 빛을 얼마나 받고 있는지,
그림자 안에 포함되어 있는지,
반사가 얼마나 강하게 발생하는지에 따라서도 픽셀의 최종 색상은 계속 달라질 수 있습니다.

즉, Rasterizer 단계는 픽셀 후보를 생성하는 과정이고,
실제 화면에 출력될 최종 색상을 계산하는 작업은 아직 끝나지 않은 상태라고 할 수 있습니다.

그리고 바로 이 작업을 Pixel Shader 단계가 담당하게 됩니다.

Pixel Shader 단계에서는 Fragment마다 최종 색상을 계산하게 됩니다.

이 과정에서 Texture Sampling, Lighting 계산, Material 표현 같은 다양한 작업들이 수행될 수 있습니다.

그래서 현대 게임 그래픽의 시각적 품질 상당수는 결국 Pixel Shader 단계에서 결정된다고 볼 수도 있습니다.


왜 이름이 “Pixel Shader”일까?

Shader라는 이름은 원래 빛과 음영(Shade)을 계산하는 과정에서 등장했습니다.

초기의 GPU에서는 주로 조명 계산과 표면의 음영 표현을 처리하는 역할로 사용되었고,
이 때문에 Shader라는 이름이 붙기 시작했습니다.

하지만 최근의 GPU 구조에서는 이 역할이 훨씬 더 확장되었습니다.

최근의 Pixel Shader는 단순히 밝기나 음영만 계산하는 단계가 아닙니다.

Texture 색상을 읽어오거나, 빛 반사 계산을 수행하고, 그림자 표현이나 후처리(Post Process) 효과까지 처리하게 됩니다.

즉, Pixel Shader는 화면 픽셀의 최종 색상을 계산하는 프로그램이라고 할 수 있습니다.

최근 게임 그래픽에서 등장하는 다양한 시각 효과들도 상당수가 Pixel Shader 단계에서 처리됩니다.

예를 들어 금속 재질 특유의 반사 표현이나,
빛이 표면에 닿는 방식,
물체 표면의 질감 표현 같은 것들도 결국 Pixel Shader 계산 흐름 안에서 처리되는 경우가 많습니다.

그래서 Pixel Shader는 단순히 색상을 출력 단계가 아니라,
실제 화면의 시각적 품질을 결정하는 핵심 단계 중 하나라고 볼 수 있습니다.


Pixel Shader는 Fragment마다 실행된다

Vertex Shader가 Vertex 단위로 실행되었던 것처럼, Pixel Shader는 Fragment 단위로 실행됩니다.

즉, Rasterizer 단계에서 생성된 픽셀 후보(Fragment)마다 Pixel Shader가 각각 실행된다고 볼 수 있습니다.

예를 들어 화면 위에 매우 큰 삼각형 하나가 출력된다고 가정해보겠습니다.

삼각형 자체는 하나지만, 실제 화면에서는 수많은 픽셀 영역을 차지하게 됩니다.

그리고 Rasterizer 단계에서는 이 삼각형 내부를 구성하는 Fragment들이 대량으로 생성됩니다.

Pixel Shader는 바로 이 Fragment들 각각에 대해 최종 색상 계산을 수행합니다.

따라서 화면 위에 출력되는 픽셀 수가 많아질수록 Pixel Shader가 수행해야 하는 계산량 역시 크게 증가할 수 있습니다.

해상도가 높아질수록 GPU 부하가 증가하는 이유도 바로 여기에 있습니다.

4K 해상도에서는 Full HD보다 훨씬 더 많은 픽셀을 처리해야 합니다.

그리고 Pixel Shader는 이 픽셀들 각각에 대해 Texture Sampling, 조명 계산, Material 표현 같은 작업들을 계속 수행하게 됩니다.

최근 게임 그래픽에서 Pixel Shader 부하가 매우 중요해진 이유 역시
결국 처리해야 하는 픽셀 수 자체가 계속 증가하고 있기 때문이라고 볼 수 있습니다.


Texture는 왜 필요할까?

실제 게임 화면은 단순한 삼각형의 색상만으로 구성되지 않습니다.

예를 들어 벽 하나를 생각해보겠습니다.

단순 회색 삼각형만 사용하면 벽돌 무늬나 표면의 스크래치, 거친 재질 느낌 같은 세부 표현들을 만들 수 없습니다.

결국 화면에는 단순 도형만 출력될 뿐, 실제 물체 같은 느낌은 거의 전달되지 않게 됩니다.

그래서 Texture를 사용하기 시작했습니다. Texture는 이미지 데이터입니다.

예를 들어 벽돌 패턴이 그려진 이미지를 준비해두고, 삼각형 표면 위에 그 이미지를 붙이는 방식입니다.

그리고 이 과정에서 UV 좌표라는 개념이 등장하게 됩니다.

UV 매핑 표현
정육면체의 UV 매핑 표현.

Vertex에는 보통 Position만 저장되는 것이 아니라,
Texture 이미지의 어느 위치를 사용할 것인지에 대한 UV 좌표도 함께 저장됩니다.

3D 모델과 UV좌표의 관계 표현
3차원 효과와 관련한 UV 공간의 텍스처 응용.

 

Rasterizer 단계에서는 이 UV 좌표 역시 보간(Interpolation) 과정을 거쳐 Fragment 단위로 확장됩니다.

그리고 Pixel Shader 단계에서는 Fragment가 가지고 있는 UV 좌표를 이용해서 Texture 이미지 안의 색상 데이터를 읽어오게 됩니다.

이 과정을 Texture Sampling이라고 부릅니다.

따라서 Pixel Shader는 단순히 색상을 계산하는 단계가 아니라,
이미지 데이터를 기반으로 실제 표면의 질감과 디테일을 표현하는 단계이기도 합니다.

최근 게임 그래픽에서 보이는 대부분의 표면 디테일 역시 결국 Texture와 Pixel Shader의 계산을 기반으로 만들어진다고 볼 수 있습니다.


조명(Lighting)은 왜 Pixel Shader에서 처리될까?

게임 그래픽에서 가장 중요한 요소 중 하나가 바로 조명(Lighting)입니다.

실제 물체의 입체감이나 재질 느낌 상당수는 결국 빛 계산 결과에 의해 결정되기 때문입니다.

예를 들어 같은 표면이라도 빛을 정면으로 받고 있는지,
비스듬하게 받고 있는지,
혹은 그림자 안에 포함되어 있는지에 따라 전혀 다른 모습으로 보이게 됩니다.

금속 표면이 강하게 반짝이거나, 거친 표면이 빛을 퍼뜨리는 느낌 역시 대부분 조명 계산 결과에 의해 만들어집니다.

따라서 실제 게임 화면에서는 단순 Texture 색상만으로는 충분한 시각 표현을 만들기 어렵습니다.

빛이 표면과 어떻게 상호작용하는지까지 함께 계산해야 훨씬 자연스러운 결과를 만들 수 있게 됩니다.

그리고 이런 계산은 보통 Pixel Shader 단계에서 수행됩니다.

그 이유는 조명 계산이 최종 픽셀 단위로 이루어져야 훨씬 자연스러운 결과를 만들 수 있기 때문입니다.

예를 들어 같은 삼각형 내부라도 픽셀 위치에 따라 빛의 방향과 카메라 방향, 그리고 Normal 벡터 값이 계속 달라질 수 있습니다.

따라서 Pixel Shader 단계에서는 Fragment마다 서로 다른 조명 결과가 계산될 수 있습니다.

이 과정 덕분에 표면이 훨씬 부드럽고 자연스럽게 표현될 수 있게 됩니다.

최근 게임 그래픽에서 사용되는 PBR(Material) 같은 기술들도 결국 Pixel Shader에서 다양한 기법을 적용해 조명을 계산한 결과입니다.

따라서 Pixel Shader 단계는 단순 색상 출력 단계가 아니라,
실제 표면의 재질감과 시각적 분위기를 결정하는 핵심 단계라고 볼 수 있습니다.


왜 최근 게임 그래픽은 점점 복잡해질까?

Pixel Shader 단계를 이해하면 최근 게임 그래픽이 왜 점점 더 복잡한 계산을 수행하게 되었는지도 함께 보이기 시작합니다.

초기의 게임 그래픽은 비교적 단순한 색상 계산만으로도 화면을 구성했습니다.

하지만 최근 게임들은 훨씬 더 사실적인 재질 표현과 조명 효과를 요구합니다.

예를 들어 최근 게임에서는 금속 표면의 반사 표현,
간접광(Indirect Lighting),
미세한 그림자 표현,
거친 재질의 표면 느낌 같은 요소들도 매우 중요하게 다뤄집니다.

그리고 이런 표현들을 만들기 위해서는 단순 Texture 색상만으로는 부족합니다.

실제로는 빛이 표면과 어떻게 상호작용하는지,
카메라 방향에 따라 반사가 어떻게 달라지는지,
주변 환경의 빛이 얼마나 영향을 주는지까지 함께 계산해야 합니다.

최근 게임에서 사용되는 PBR(Material),
Screen Space Reflection,
Ambient Occlusion,
Global Illumination 같은 기술들도 결국 이런 과정에서 등장하게 되었습니다.

그리고 이러한 계산들의 상당수는 Pixel Shader 단계에서 수행됩니다.

즉, 최근 게임 그래픽은 점점 더 많은 픽셀 단위 계산을 요구한다고 볼 수 있습니다.

또한, 해상도가 높아질수록 처리해야 하는 Fragment 수 자체도 크게 증가하게 됩니다.

결국 GPU는 엄청난 수의 픽셀에 대해 Texture Sampling,
조명 계산, 반사 계산 같은 작업들을 계속 수행해야 합니다.

따라서 최근 게임 그래픽에서 GPU 성능이 점점 더 중요해지고 있는 이유 역시 결국 Pixel Shader 단계의 계산량 증가와 연관되어 있습니다.


왜 Pixel Shader 부하가 GPU 성능과 연결될까?

게임 성능을 이야기하다 보면 “GPU 사용량이 높다”라는 표현을 자주 보게 됩니다.

그리고 실제로 최근 게임 그래픽에서 GPU 부하와 가장 깊게 연결되는 단계 중 하나가 바로 Pixel Shader 단계입니다.

그 이유는 Pixel Shader가 Fragment마다 실행되기 때문입니다.

예를 들어 화면 해상도가 높아질수록 GPU가 처리해야 하는 픽셀 수 자체가 크게 증가하게 됩니다.

Full HD보다 4K 해상도에서 GPU 부하가 훨씬 커지는 이유 역시 결국 더 많은 픽셀을 계산해야 하기 때문입니다.

그리고 최근 게임들은 단순 색상 계산만 수행하지 않습니다.

Texture Sampling,
복잡한 조명 계산,
반사 표현,
그림자 처리,
후처리 효과 같은 다양한 작업들이 Pixel Shader 단계에서 계속 수행됩니다.

특히 최근 게임 그래픽에서는 Screen Space Reflection,
Ambient Occlusion,
Bloom,
Depth of Field 같은 후처리 효과들도 적극적으로 사용됩니다.

이런 효과들 역시 결국 화면 픽셀 단위 계산을 기반으로 동작하게 됩니다.

따라서 해상도가 높아지거나,
후처리 효과가 많아지거나,
조명 계산이 복잡해질수록 Pixel Shader 단계의 계산량 역시 크게 증가하게 됩니다.

최근 게임 그래픽에서 GPU 부하가 점점 증가하는 이유 역시 결국 처리해야 하는 픽셀 수와 Pixel Shader 계산량 자체가 계속 증가하고 있기 때문이라고 볼 수 있습니다.


보간(Interpolation) 데이터는 Pixel Shader에서 사용된다

이전 Rasterizer 글에서는 보간(Interpolation)에 대해 설명했습니다.

Rasterizer 단계에서는 Vertex 단위 데이터를 Fragment 단위로 부드럽게 확장하게 됩니다.

예를 들어 삼각형의 각 Vertex마다 서로 다른 UV 좌표나 Normal 값, Vertex Color 값이 존재할 수 있습니다.

그리고 Rasterizer 단계에서는 삼각형 내부 위치에 따라 이 값들을 자연스럽게 섞어서 Fragment마다 새로운 값을 만들어내게 됩니다.

이렇게 생성된 보간 데이터는 이후 Pixel Shader 단계로 전달됩니다.

Pixel Shader는 이 데이터를 이용해서 실제 화면 색상을 계산하게 됩니다.

예를 들어 UV 좌표는 Texture Sampling에 사용되고, Normal 데이터는 조명 계산에 사용될 수 있습니다.

또한 Vertex Color 같은 데이터 역시 최종 색상 계산 과정에 함께 활용될 수 있습니다.

즉, Pixel Shader는 단순히 하나의 고정된 색상을 출력하는 단계가 아니라,
Rasterizer 단계에서 전달된 다양한 보간 데이터를 기반으로 최종 화면 결과를 계산하는 단계라고 볼 수 있습니다.

이렇게 계산 과정이 연결되기 때문에 Rasterizer와 Pixel Shader는 서로 굉장히 밀접하게 연관되어 있습니다.

Rasterizer 단계가 Fragment와 보간 데이터를 생성하면,
Pixel Shader는 그 데이터를 이용해서 실제 화면의 시각적 표현을 만들어내게 됩니다.


Pixel Shader는 현대 그래픽 표현의 핵심이다

초기의 GPU는 비교적 단순한 색상 계산만 수행했습니다.

하지만 최근 GPU는 점점 더 복잡한 Pixel Shader 계산을 수행하기 시작했습니다.

왜냐하면 최근 게임들은 더 사실적인 재질,
더 복잡한 조명,
더 다양한 후처리 효과를 요구하기 때문입니다.

현대 게임 그래픽의 시각적 품질 상당수는 결국 Pixel Shader 단계에서 결정된다고 볼 수 있습니다.


Pixel Shader는 “최종 화면 색상을 계산하는 단계”

Pixel Shader 단계에서 단순히 색상을 출력하는 것 이상으로 훨씬 더 많은 작업들이 처리된다는 것을 살펴봤습니다.

예를 들어 Texture를 이용한 표면 표현,
조명 계산,
반사 표현,
재질(Material) 계산 같은 다양한 그래픽 처리들이 대부분 Pixel Shader 단계에서 이루어지게 됩니다.

최근 게임 그래픽에서 보이는 금속 특유의 반사 느낌이나,
거친 표면의 질감 표현,
빛에 따라 달라지는 재질의 분위기 같은 것들도 결국 Pixel Shader 계산 결과라고 볼 수 있습니다.

또한 최근 그래픽 기술들은 점점 더 복잡한 화면 표현을 요구합니다.

사실적인 조명, 정교한 그림자, 후처리 효과, 반사 표현 같은 기술들도 대부분 Pixel Shader 단계에서 처리됩니다.

따라서 Pixel Shader 단계는 단순 색상 출력 단계라기보다,
실제 화면의 시각적 품질을 결정하는 핵심 단계에 가깝다고 할 수 있습니다.

그리고 Pixel Shader에서 다양한 효과가 처리된다는 사실을 알게되면
왜 최신 그래픽스 프로그래밍의 많은 기법들이 Shader 중심으로 발전하게 되었는지도 함께 보이기 시작합니다.

최근 GPU가 강력한 병렬 Shader 연산 구조를 가지게 된 이유 역시 엄청난 수의 픽셀 계산을 빠르게 처리하기 위해서라고 볼 수 있습니다.


마무리

Pixel Shader 단계는 GPU가 실제 화면 색상을 계산하는 핵심 단계라고 볼 수 있습니다.

이 단계에서는 Texture Sampling,
조명 계산,
Material 표현,
후처리 효과 같은 다양한 그래픽 계산들이 수행됩니다.

그리고 최근 게임 그래픽이 점점 더 사실적으로 발전하고 있는 이유 역시
Pixel Shader 단계에서 처리되는 더 사실적이고 복잡한 기법들이 더 많아졌기 때문이라고 할 수 있습니다.

최근 게임들은 단순히 물체를 화면에 출력하는 수준을 넘어,
빛 반사와 재질 표현,
간접광,
후처리 효과까지 함께 계산하기 시작했습니다.

그리고 이런 표현들의 상당수는 결국 Pixel Shader 단계에서 처리됩니다.

Pixel Shader는 단순 색상 출력 단계가 아니라, 실제 화면의 시각적 품질을 결정하는 핵심 계산 단계라고 할 수 있습니다.

다음 글에서는 렌더링 파이프라인의 마지막 단계 중 하나인 Output Merger 단계에 대해 이어서 정리해보려고 합니다.

그리고 GPU가 왜 최종 픽셀을 Frame Buffer에 기록하기 시작했는지,
깊이 테스트(Depth Test)와 블렌딩(Blending) 같은 개념들은 왜 등장하게 되었는지도 함께 살펴보려고 합니다.


👉 게임 엔진 구조를 더 깊이 이해하고 싶다면

아래 강의를 통해 직접 구현해보는 것을 추천드립니다.

C++로 만드는 게임 엔진 프레임워크 강의

👉 C++로 만드는 게임 엔진 프레임워크 강의 바로가기

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다