본문 바로가기

Development/WPF

Create Pixel Shader Based CustomBrush

Introduction

WPF Application을 개발하다보면 기본적으로 제공하는 Brush이외 다른 형식의 Brush가 필요한 상황이 있습니다. 예를들어 지난 포스팅(http://whatisthat.co.kr/169)에서 다루었던 AngleGradient가 대표적인 예라고 할 수 있겠습니다. 지난 포스팅에서는 MarkupExtension을 이용해 내부적으로 ImageBrush를 생성하여 Brush로 사용하는 방법에 대해 소개 했지만, 매번 대상의 크기가 변경될 때마다 새로운 이미지를 생성해주어야 하는 문제점 때문에 퍼포먼스 상의 이슈가 발생할 수 있습니다.

이번시간에는 MarkupExtension과 PixelShader를 이용해 Brush를 제작하는 방법에 대해 소개합니다. PixelShader를 이용할 경우 Brush를 생성하는 과정에 대한 연산을 그래픽 카드에서 처리하기 때문에 기존 WriteableBitmap를 이용해 이미지를 생성하는 것보다 빠른 처리가 가능합니다.

WPF ShaderEffect에 대한 자세한 소개는 다음 URL을 참고하시기 바랍니다.
http://blog.wpfwonderland.com/2008/10/06/wpf-shader-effects-library-posted/

Create ShaderBrush Base Class

PixelShader를 기반으로한 Brush를 제작하기 위해서는 Texture를 Shader Effect에 연결하고, 결과를 Brush로 반환할 수 있는 MarkupExtension객체를 구현해야 합니다. WPF에서 Shader Effect를 이용하기 위해서는 대상이 반드시 UIElement를 상속받는 객체 여야 하는데, 이를 위해 Rectangle객체를 생성하고 이 객체를 Source로 사용하는 VisualBrush를 생성하고 리턴합니다.


대상 객체로 Rectangle를 사용하는 이유는 UIElement를 상속받는 객체중에서 가장 단순한 구조이면서 필요한 기능(Fill 속성)은 포함 하고 있기 때문입니다. 불필요한 연산에 소요되는 시간을 최소화 할 수 있기 때문입니다. (직접 FrameworkElement를 상속받아 더 적합한 형식을 제작할 수 도 있습니다.)

AngleGradientBrush

Pixel Shader를 이용한 Brush를 제작하기 위해서는 ShaderBrush를 상속받아 OnCreateEffect메서드를 Override 한 뒤 구현한 Effect를 리턴해야 합니다.


아래 코드는 위 코드에서 사용한 AngleGradientEffect 의 소스코드 입니다.


이상으로 이번 시간의 내용을 마치며, 이번시간에 사용된 전체 소스코드 입니다. 기타 질문이나 문의는 이메일이나 댓글로 남겨주시면 답변해 드리도록 하겠습니다.