XNA for C#
DirectX 9 for C#
DirectX 9 for C++
DirectX 9 for VB
Forum
   
My XNA Book
      
       Go to section on this site

Additional info


Latest Forum posts

 Account settings
  Posted by: Anonymous
  When: 07/05/2014 at 09:48:39

 forced subtitle
  Posted by: Applefly
  When: 07/05/2014 at 06:00:48

 convert DVD into PMS
  Posted by: Applefly
  When: 07/05/2014 at 05:55:25

 DVD to Digital Copy easily
  Posted by: VIKIVannessa
  When: 05/05/2014 at 06:52:29

 DVD on Xbox 360/Xbox One Console
  Posted by: VIKIVannessa
  When: 05/05/2014 at 06:51:47

 Extract .Srt Subtitles
  Posted by: Applefly
  When: 04/05/2014 at 03:54:38

 Encode Movie collection
  Posted by: Applefly
  When: 04/05/2014 at 03:52:41

 Convert DVD to WMV
  Posted by: Applefly
  When: 29/04/2014 at 05:53:50

 rip DVDs into digital files
  Posted by: Applefly
  When: 29/04/2014 at 05:51:20

 iTunes movies/music to Kindle Fire
  Posted by: ciciyu80
  When: 29/04/2014 at 05:10:20


Ads

지형의 Normal에 대한 직관적인 접근

이제 우리의 지형의 모든 vertex들에 Normal vector를 적용하여 그래픽 카드가 조명을 계산할 수 있도록 해 보겠습니다. 이번 tutorial을 통해 조명 설정에 대해 쉽게 이해하고 쉽게 구현하는 방법을 찾을 수 있을 것 입니다. 사실, 수학적으로 100% 완벽하지는 않지만 비교적 적은 계산으로 비교적 그럴듯한 조명이 표현할 수 있다는 데 만족하도록 합시다. 좀 더 수학적인 내용은 다음 기회에 살펴보도록 하겠습니다.

여기에 기초적인 설명을 위해 Reimer씨가 만든 그림이 있습니다. 2개의 파란색 선은 우리의 지형 안에 존재하는 임의의 경계선(Grid) 입니다. 우리가 찾고자 하는 것은 붉은색 선으로 표현된 두 파란색 선들이 공유하는 점(Point)의 Normal vector입니다. 그리고 하단에 보이는 검은 선은 점들(Points)사이의 단위 거리 입니다.

이렇게 생각해 봅시다. 어차피 2개의 파란색 선은 X좌표와 Y좌표로써 존재하기 때문에 언제나 직각입니다. Z축 좌표값이 없는 상태라면 이 경계선(Grid)는 평평하게 누워있는 것처럼 보일 것이고, Normal vector는 수직으로 위쪽을 향해 있겠지요. 만약 그림과 같이 초록색 선의 길이만큼 Z축 좌표값(높이값)이 주어진다면 당연히 경계선(Grid)는 그만큼 기울어지게 될 것입니다. 기울어지는 정도는 왼쪽 점(Point)에 주어진 높이와 오른쪽 점(Point)에 주어진 높이의 차이의 절반입니다.

따라서, 두 경계선(Grid)가 공유하는 점(Point)에서 초록색 선의 길이의 절반과 수직하는 검은색 선 - 점들(Points)의 단위 길이를 내적이 바로 우리에게 필요한 Normal vector가 됩니다. Reimer씨가 만든 그림과 비교해 봅시다.



설명이 길어 졌지만, 코드로 구현하기가 어려운 내용은 아닙니다. 이제 새 Windows Game 프로젝트를 생성하고 Adding Color 프로젝트에서 우리의 지형을 가져옵시다.

가장 먼저 Lighting Basic에서 사용했던 VertexPositionNormalColored 구조체를 선언해 주어야 하겠지요

 public struct VertexPositionNormalColored
 {
     public Vector3 Position;
     public Color Color;
     public Vector3 Normal;
 
     public static int SizeInBytes = 7 * 4;
     public static VertexElement[] VertexElements = new VertexElement[]
     {
         new VertexElement( 0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0 ),
         new VertexElement( 0, sizeof(float) * 3, VertexElementFormat.Color, VertexElementMethod.Default, VertexElementUsage.Color, 0 ),
         new VertexElement( 0, sizeof(float) * 4, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0 ),
     };
 }

전역 변수 vertices도 재정의 해줍시다.

 VertexPositionNormalColored[] vertices;

이제 새로 정의된 vertex들은 Normal vector를 가질 수 있으므로 SetupVertices함수에 다음과 같이 Normal vector를 설정하는 코드를 추가해 줍시다.

 for (int x = 1; x < WIDTH-1; x++)
 {
     for (int y = 1; y < HEIGHT-1; y++)
     {
         Vector3 normX = new Vector3((vertices[x - 1 + y * WIDTH].Position.Z - vertices[x + 1 + y * WIDTH].Position.Z) / 2, 0, 1);
         Vector3 normY = new Vector3(0, (vertices[x + (y - 1) * WIDTH].Position.Z - vertices[x + (y + 1) * WIDTH].Position.Z) / 2, 1);
         vertices[x + y * WIDTH].Normal = normX + normY;
         vertices[x + y * WIDTH].Normal.Normalize();
     }
 }

지형의 외곽선을 제외하고 먼저 X축 방향의 Normal을 계산하고 Y축 방향을 Normal을 계산하여 이 두 Normal vector를 합쳐 지형의 vertex가 가지는 Normal vector를 구합니다.

또한 외곽선 부분의 vertex들의 Normal vector 또한 필요하므로 지형의 각 vertex의 값을 지정하는 Loop에서 모든 vertex들의 Normal vector을 초기화 시켜주도록 합시다.

 vertices[x + y * WIDTH].Position = new Vector3(x, y, heightData[x, y]);
 vertices[x + y * WIDTH].Normal = new Vector3(0, 0, 1);

이제 Normal vector의 설정은 모두 끝났습니다. 하지만 아직 할 일이 약간 더 남아있네요. 이전 tutorial과는 다르게 우리의 지형에서는 Indexbuffer를 사용하고 있기 때문에 더 많은 vertex들을 담을 수 있도록 Vertexbuffer의 크기를 크게 잡아주어야 합니다.

SetupVertices함수에서 Vertexbuffer를 생성하는 코드를 다음과 같이 수정합시다.

 vb = new VertexBuffer(device, VertexPositionNormalColored.SizeInBytes * WIDTH*HEIGHT, ResourceUsage.WriteOnly, ResourceManagementMode.Automatic);
 vb.SetData(vertices);

그리고 Draw함수에 이전 tutorial과 같이 조명을 설정해 줍시다.

 effect.Parameters["xEnableLighting"].SetValue(true);
 effect.Parameters["xLightDirection"].SetValue(new Vector3(0.5f, 0.5f, -1));

마지막으로 디바이스에게 우리가 사용하는 vertex들의 형식이 VertexPositionNormalColored임을 알려줍시다.

 device.Vertices[0].SetSource(vb, 0, VertexPositionNormalColored.SizeInBytes);
 device.Indices = ib;
 device.VertexDeclaration = new VertexDeclaration(device, VertexPositionNormalColored.VertexElements);
 device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, WIDTH*HEIGHT, 0, (WIDTH-1)*(HEIGHT-1)*2);

이제 F5(디버그)키를 눌러 실행하면 조명이 설정된 우리의 지형을 확인할 수 있습니다.






Google
 
Webwww.riemers.net


If you appreciate the amount of time I spend creating and updating
these pages, feel free to donate -- any amount is welcome !



- Website design & XNA + DirectX code : Riemer Grootjans -
©2003 - 2011 Riemer Grootjans
Translations

This site in English
This site in Korean
This site in Czech

Microsoft MVP Award



2007 - 2011 MVP Award
DirectX - XNA

Contents

[Tutorials]
[XNA in C#]
Series 1: 지형
XNA의 시작
이펙트 파일
첫 번째 삼각형
월드 좌표계
회전, 위치 변환
인덱스
지형 생성의 기본
파일로부터 지형 생성
키보드 입력
[tut10]
[tut11]
[tut12]
[tut13]
-- Expand all --


Thank you!

Support this site --
any amount is welcome !

Stay up-to-date

I don't have the time to keep a News section, so stay informed about the updates by clicking on this RSS file!