Graphics/DirectX

Direct X - 9. 텍스쳐 넣기 (그림넣기)

MOLOKINI 2014. 6. 8. 20:55

이번에는 다각형 안에 이미지를 넣어보자

3D에서는 이것을 바로 텍스쳐(Texture)라고 불러요, 이미지 파일을 읽어 작성한다.
 
게임에서는 필수적으로 사용되고, 보다 리얼한 모델을 구현하는데 초점을 맞춘다.

 

 
 
DirectX 3D의 텍스쳐에 대해서 간단하게 알아보자
이 텍스쳐를 다각형에 붙이려면 정점 데이터에 UV좌표를 주지 않으면 안됩니다.
UV좌표와는 정점의 어느 부분과 재질감의 어느 부분과 맞출까?를 나타내는 거다
 

UV좌표 - 모든 이미지에 동일!

 

 이번 실습에 쓰이는 다각형은 사각형이니까 이 UV좌표를 그대로 쓰면 되겠다!

 

그럼 소스를 보자

 

using System;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Windows.Forms;
using System.Drawing;

namespace MDXSample
{
    /// <summary>    /// 메인 샘플 클래스    /// </summary>
    public partial class MainSample : IDisposable
    {
        /// <summary>        /// 정점 버퍼        /// </summary>
        private VertexBuffer _vertexBuffer = null;
        private Texture _texture = null;           
         
        public bool InitializeApplication(MainForm topLevelForm)
        {
            // 폼의 참조를 보관 유지
            this._form = topLevelForm;
            PresentParameters pp = new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard;
            pp.EnableAutoDepthStencil = true;
            pp.AutoDepthStencilFormat = DepthFormat.D16;

            try
            {
                // Direct3D 디바이스 작성
                this.CreateDevice(topLevelForm, pp);
                // 폰트의 작성
                this.CreateFont();
            }
            catch (DirectXException ex)
            {
                // 예외 발생
                MessageBox.Show(ex.ToString(), "에러", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            this.SettingCamera();

           // 사각형 다각형을 표시하기 위한 정점 버퍼를 작성
           this._vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionTextured),                4, this._device, Usage.None, CustomVertex.PositionColored.Format, Pool.Managed);

            // 4점의 정보를 보관하기 위한 메모리를 확보
 CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[4];
            // 각 정점을 설정            vertices[0] = new CustomVertex.PositionTextured(-3.0f, 4.0f, 0.0f, 0.0f, 0.0f);            vertices[1] = new CustomVertex.PositionTextured(3.0f, 4.0f, 0.0f, 1.0f, 0.0f);            vertices[2] = new CustomVertex.PositionTextured(-3.0f, -4.0f, 0.0f, 0.0f, 1.0f);            vertices[3] = new CustomVertex.PositionTextured(3.0f, -4.0f, 0.0f, 1.0f, 1.0f);

          // 정점 버퍼를 잠근다
     using (GraphicsStream data = this._vertexBuffer.Lock(0, 0, LockFlags.None))            {                // 정점 데이터를 정점 버퍼에 씁니다                data.Write(vertices);
                // 정점 버퍼의 락을 해제합니다                this._vertexBuffer.Unlock();            }
            this._texture = TextureLoader.FromFile(this._device, "imymemine.jpg");
            this._device.RenderState.Lighting = false;

            return true;
        }

      /// <summary>        /// 메인 루프 처리        /// </summary>
        public void MainLoop()
        {
    // 화면을 단색(파랑색)으로 클리어
            this._device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0);

  // 「BeginScene」와「EndScene」의 사이에 화면에 출력할 내용을 코딩
            this._device.BeginScene();

            this._device.SetTexture(0, this._texture);
            // 정점 버퍼를 디바이스의 데이터 스트림에 바인드            this._device.SetStreamSource(0, this._vertexBuffer, 0);
            // 그릴려는 정점의 포맷을 세트            this._device.VertexFormat = CustomVertex.PositionTextured.Format;
            // 렌더링(그리기)            this._device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                        

    // 좌표 x=0 y=0 의 위치에 흰색으로 출력
            this._font.DrawText(null, "텍스쳐 입혀보기", 0, 0, Color.White);

      // 화면출력은 여기까지
            this._device.EndScene();
     
  // 실제의 디스플레이에 출력
            this._device.Present();
        }

        /// <summary>        /// 자원의 파기        /// </summary>
        public void Dispose()
        {
            if (this._texture != null)
            {
                this._texture.Dispose();
            }

            // 정점 버퍼를 해제
            if (this._vertexBuffer != null)
            {
                this._vertexBuffer.Dispose();
            }

            // 폰트 자원을 해제
            if (this._font != null)
            {
                this._font.Dispose();
            }

            // Direct3D 디바이스의 자원 해제
            if (this._device != null)
            {
                this._device.Dispose();
            }
        }
    }
}

 

        private Texture _texture = null;          
텍스쳐를 선언하자, 요게 있어야지 다각형에 텍스쳐를 붙일 수 있어
 
            this._vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionTextured),
                4, this._device, Usage.None, CustomVertex.PositionTextured.Format, Pool.Managed);

사각형이니까 4인데, 주목해야하는거는 구조체가 PositionTextured로 바뀌었다는것

텍스쳐쓸라면 이렇게해야한다, 위치와 UV좌표를 가질 수 있게 해준다

 전에는 PositionColored 였다

           

 CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[4];
            vertices[0] = new CustomVertex.PositionTextured(-3.0f, 4.0f, 0.0f, 0.0f, 0.0f);
            vertices[1] = new CustomVertex.PositionTextured(3.0f, 4.0f, 0.0f, 1.0f, 0.0f);
            vertices[2] = new CustomVertex.PositionTextured(-3.0f, -4.0f, 0.0f, 0.0f, 1.0f);
            vertices[3] = new CustomVertex.PositionTextured(3.0f, -4.0f, 0.0f, 1.0f, 1.0f);

정점을 담을 배열을 선언한다. 위와같이 PositionTextured로 구조체가 바뀌었다는점

CustomVertex.PositionTexturedX : 위치의 X좌표Y : 위치의 Y좌표Z : 위치의 Z좌표Tu : 텍스쳐 좌표의 U성분Tv : 텍스쳐 좌표의 V성분

 

구조체가 바뀌었으니까 파라미터도 바뀌겠지요

 

            this._texture = TextureLoader.FromFile(this._device, "imymemine.jpg");

텍스쳐를 로드하는 코드는 요 한줄로 끗

TextureLoader.FromFile 메서드로 Direct3D 디바이스와 이미지파일명만 지정하면 된다.

파일명으로는 "절대경로"와 "현재 디렉토리로부터 상대경로"를 지정해야해

bin -> Debug 에 넣으면된다

읽어들일 수 있는 형식은 

BMP, DDS, DIB, HDR, JPG, PFM, PNG, PPM, TGA

 

            this._device.SetTexture(0, this._texture);

그리기 메서드의 코드, SetTexture에 작성한 텍스쳐(_texture)을 적용하면 UV좌표가 설정되어있는 다각형에 텍스쳐가 적용되게 됩니다

Device.SetTexturestage : 디바이스 스테이지, 텍스쳐를 동시에 두개이상 사용하는게 아니라면 0texture : 사용하는 재질감

 

 

            this._device.SetStreamSource(0, this._vertexBuffer, 0);

            this._device.VertexFormat = CustomVertex.PositionTextured.Format;

            this._device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);

PositionColored에서 PositionTextured로 바뀐 점 말고는 다른건 없다!

 

 

 

저 이미지 2차원이 아니라 3차원이라는 것!