Dip2K’s WPF 3D 입문 (1/3)

.NET 3.0의 기초화장(파운데이션) 중에 하나인 WPF에 대한 자료를 찾아 살펴보았다. 2D에 앞서 바로 3D를 살펴보았는데.. 이를 정리해 보고자한다.

먼저 개발을 위한 요구사항은 먼저 .NET 3.0 Framework를 설치해야 한다. 그리고 2개를 더 설치해줘야 하는데..  Microsoft Windows SDK for .NET Framework 3.0와  Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF)를 순서대로 설치해야 한다. 물론 이 모두에 앞서 OS(Win2000, XP, Vista)와 Visual Studio 2005가 설치되어져 있어야 한다. 참고로 필자의 OS는 .NET 3.0이 이미 설치된 윈도우즈 비스타이다.

일단 필요한것을 모두 실치했다면 VS2005를 실행해보라. 그리고 새로운 프로젝트 생성을 실행시키면 다음과 같은 WPF와 WCF 관련 프로젝트 생성을 위한 템플릿이 추가된다. (아래 이미지 캡춰는 비스타의 기본 프로그램인 “캡처도구”를 사용하였다) 참고로 WWF, 즉 지금의 WF는 또 다른 Extensions를 설치해줘야 한다.

여기서 Windows Application (WPF)를 선택하자. WPF에서 2D와 3D가 따로 있는것이 아니라 2D든 3D든 똑같이 WPF인데, 새로운 프로젝트를 생성하게 되면 자동으로 솔루션 탐색기에 아래와 같은 파일들이 자동으로 구성된다.

여기서 실제 우리가 관심을 집중시켜 코딩할 소스 파일은 Window1.xaml과 Windows1.xaml.cs이다. 확장자 XAML은 eXtansible Application Markup Language로써 개발단계에서 UI와 Data 부분을 정의할 수 있는 XML 포멧이다. UI와 Data가 아닌 실행에 관련된 로직은 확장자가 CS인 XAML 까지 포함한 동일한 파일명이다. 여기서 한가지 더 언급하면 Data의 경우 XAML 에도 넣을 수 있지만 CS 에서도 정의할 수 있다는 점이다. 여하튼 바로 이러한 UI와 Logic의 분리.. 즉, UI는 XAML 에 작성하고 로직은 CS 에 작성한다는 것이 디자이너와 개발자간의 분리된 효율적인 협업이 손쉬워졌다는 것이다. 아직 이러한 방식으로 프로젝트에서 디자이너와 협업을 해보지 않아서 모르겠지만, 적용했을시에 개발자는 편해지겠지만 디자이너는 머리가 좀 아플것같다. 디자이너가 XAML 에 익숙해져야 하는데, 이 XAML 이 꽤나 많은 내용을 담고 있기 때문인데… 이러한 문제점에 대해서 MS에서는 디자이너가 코딩보다는 미적인 감각을 더욱 잘살리길 바라는 바, XAML을 좀더 쉽게 만들 수 있는 툴을 MS에서 제공하고 있다. (참고로 XAML은 발음은 “제믈” 이다)

이제 UI를 작성해보자. 즉, 아래와 같은 폼을 구성할 것이다.

도구모음을 통해 해당 컨트롤을 가져다 디자인을 하든, 아니면 필자처럼 직접 xaml을 막코딩하든…. 위의 폼 구성에 대한 xaml의 내용은 다음과 같다. 참고로 여전이 WPF를 위한 VS2005의 개발환경의 지원은 완벽하지 않다.


  
    
      
        
        
        
        
      
      
      
        
          
        
        
          
            
          
        
      
    
  

청색 코드가 실제로 새롭게 추가된 코드이다. 먼저 폼에 DockPanel 컨트롤을 올려 놓았고 그 DockPanel의 좌측에 StackPanel와 우측에 Viewport3D 컨트롤을 올려놓았다. StackPanel에는 Cube, RotateX, RotateY, RotateZ 버튼이 놓여있다. 위의 코드를 보면 각 버튼을 클릭했을때 수행해야할 이벤트 매서드가 Click이라는 속성의 값으로 지정 되어져 있다. 이 이벤트 지정에 관련된 부분만 뽑아내 보면 아래와 같다.


    
    
    
    

이제 Viewport3D를 살펴보자. OpenGL이나 DirectX와 같은 3D 그래픽 개발을 해본 사람이라면 알겠지만 이 XAML 의 Viewport3D 요소 안에 카메라의 설정과 빛이 정의되어져 있다. 마찬가지로 3D Model에 대한 좌표데이터와 같은 Data 부분도 이 XAML 에 정의할 수 있다는 것은 앞서 언급을 했다. Viewport3D를 로직 구현부분(CS 파일)에서 접근하기 위해 Viewport3D의 Name 속성의 값으로 “mainViewport”로 지정해 놓았다. 그리고 카메라와 빛에 대한 정의가 되어 있다. 3D 개발을 해본 사람이라면 이 부분(카메라와 빛의 속성)은 직관적으로 알 수 있기에 자세히 설명하지 않겠다. (궁금하면 방명록에 질문을 하시길..) Viewport3D에 대한 부분만을 다시 나타내보면 아래와 같다.


    
        
    
    
        
            
        
    

여기까지가 UI에대한 XAML 부분이고 UI의 이벤트 등과 같은 로직에 대한 부분은 다음에 살펴보기로 하겠다.

Shape에 Effect 넣기

예전에 PowerPoint 2007을 설치하고 글자와 도형에 멋진 효과를 넣을 수 있는 것을 보고 직접 구현해 보았다. GDI+을 이용하였으며 Native C++로 구현하였다. 필요한 자료를 찾던 중에 윈도우즈 개발 환경은 이제 C#으로 넘어가야하나라는 생각이 강하게 들었다. 같은 GDI+라도 .NET과 Native Win32에서 제공되는 클래스가 차별화되어있고 많은 GDI+ 관련 자료가 C#으로 되어 있는 이유이다.

위의 실행 결과를 보면 Shape에 입체효과(베벨 또는 엠보싱)와 그림자를 넣어주었다. 이미지 처리에서 사용되는 Convolution Filter로써 Blur Filter와 Emboss Filter를 사용하여 효과를 주었다.

간단이 과정을 살명하면 먼저 도형을 GraphicsPath를 통해 만들고 이 Path를 임시 버퍼에 검정색으로 그린뒤, 이 버퍼에 Blur 효과를 주고 화면상에 그리면 그림자가 그려지게 된다. 여기에 사용한 Convolution Filter는 다음과 같다.

const int filterHalfSize = 4;
int convolutionFilter[(filterHalfSize*2+1)*(filterHalfSize*2+1)] = { 
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1,
};

Divider 값은 필터의 크기가 9이므로 그 두배인 81로 했다. 이렇게 그림자를 그린후에 이 위에 그대로 Path를 그린다. 이제 다시 Emboss 효과를 줘서 만든 이미지를 생성하는데 여기에 사용한 Filter는 다음과 같다.

const int filterHalfSize2 = 1;
int convolutionFilter2[
	(filterHalfSize2*2+1)*(filterHalfSize2*2+1)] = { 
	1, 0, 0,
	0, 0, 0,
	0, 0, -1,
};

Divider 값은 1로 했으며(즉, 평균을 내기 위해 나누지 않았으며) 결과값에 32를 더했다. Emboss 효과를 적용해서 만들어진 이미지는 다음과 같다.


이것을 그대로 사용하면 않되고 원래 도형의 모양으로 Clipping 해야한다. GDI+의 grfx의 SetClip 함수를 이용해 Clipping해서 그려주게 되면 완료된다.

과거에는 이러한 효과를 실시간으로 적용하기에는 연산 속도가 느려 전문분야에나 활용되다가 이제는 윈도우즈 비스타의 UI에 기본적으로 사용되고 있다. 갑작이 드는 생각은 OS에서 버전업이라는 개념은 그 속내의 변화보다는 겉모양의 변화가 발생했을때 이루어지고 있다는 것이다. 속내의 변화는 서비스팩이나 업데이트를 통해 이루어지고 있고 새로운 제품으로써 버전업은 일반 사용자에게 가장 강하게 어필할 수 있는 UI 부분의 진보이다. 이러한 UI의 중요성을 절대 무시해서는 않될 것 같다.