티스토리 뷰

[원글 - 2010년 이글루스]


XNA에서 2D그림을 그릴 때에는

SpriteBatch와 Texture2D 객체를 사용한다

외부 이미지의 경우 ContentManager 객체의 Load<>() method를 이용하거나,

Texture2D 객체의 FromFile() method가 제공되므로 이용하면 된다

하지만 bitmap 데이터를 직접 Texture2D에 옮기는 방법은 없을까?

또한, 실시간으로 Texture2D의 픽셀 값들을 갱신하는 방법은 없을까?

이는 매 프레임마다 변하는 카메라 입력 값을 XNA로 출력하거나 할 때 필요하게 된다

Texture2D객체에 보면 SetData<>() method가 존재한다

먼저, Texture2D객체를 생성하고 SetData<>()method로 데이터를 조작하면 된다.

가령, 640 by 480의 화면을 다루고 싶다면 다음 2가지를 준비하면된다.

1. 먼저 화면에 찍어줄 Color 버퍼이다

byte를 이용하여 나타내 주어도 되고, Color 객체로 직접 Array를 만들어도 된다

byte[] bytearray = new byte[640*480*4] 또는 Color[] colorarray = new Color[640*480]

2. 빈 Texture2D 객체

new를 이용해 빈 Texture2D객체를 만든다

Texture2D (GraphicsDevice, Int32, Int32, Int32, TextureUsage, SurfaceFormat)

사용법은 다음과 같다

Texture2D tex = new Texture2D(graphics.GraphicsDevice, 640, 480, 1, TextureUsage.None, SurfaceFormat.Color)

1번째 인자야 기본으로 주어진 GraphicDevice객체이고,

2번째, 3번째는 가로, 세로 길이이다.

4번째 인자는 밉뱁 레벨 pixel을 다룰 것이므로 1레벨만 필요하다

5번째는 Texture리소스의 옵션인데 필요없으므로 None이고

마지막 인자는 Textureformat인데, 다양한 옵션이 제공되지만

사용할 수 있는 것은 SurfaceFormat.Color (D3DFMT_A8R8G8B8 실제는 RGBA) 하나라고 봐도 무방하다

만든 이후에는 SetData<>()를 사용하면 된다

SetData(bytearray) 또는 SetData(colorarray)

==============================================================================================

다만, 사용함에 있어서 한가지 주의사항이 있는데

내용을 계속 갱신하기 위해서는 해당 Texture2D객체가 SpriteBatch를 통해서 마지막으로 그려지지 말아야 한다

다음 상황은 Exception을 유발하게 된다.

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit();

    texture.SetData<byte>(bytearray);

    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin();
    spriteBatch.Draw(texture, new Vector2(0, 0), Color.White);
    spriteBatch.End();

    base.Draw(gameTime);
}

그려줘야 할 Texture2D 객체가 많다면, 업데이트가 있는 Texture2D 객체를 우선 그리도록 하면 되지만

비디오 영상을 뿌려주는 역할로 이용하는 등의 단일 Texture2D객체를 사용하는 상황에서는 어떻게 해야 할까?

2가지 정도로 생각해 볼 수 있다



먼저, 단순히 생각해 볼 수 있는 방법은 dummy Texture2D객체를 생성하는 것이다

완전히 없을 수는 없으니까, 1 by 1 픽셀을 가진 Texture2D객체를 만든다

내용은 Alpha값이 0으로 투명 픽셀이며,

Draw할 때에도 -1, -1로 화면 바깥 쪽에 그려주는 방법이다

그렇게 되면 마지막으로 참조하는 Texture2D객체가 dummy이므로, 갱신이 가능하다



다른 방법으로는 Double buffering과 유사한 방법을 사용하는 것이다

홀수 프레임에서는 A라는 Texture2D객체에 Update & Draw를 수행하고

짝수 프레임에서는 B라는 Texture2D객체에 Update & Draw를 수행하는 방법이다

전자와 후자 모두 잘 동작함은 확인했다

전자의 경우에는 연산면에서 보면 한번에 2개의 Texture를 Draw하는 결과가 되고,

후자의 경우에는 한번에 1개의 Texture만을 그린다

물론, 내부적으로 후자가 전자의 경우보다 instruction을 (아주 조금이지만) 많이 사용한다

그렇지만 속도에는 영향을 주지 않는다고 봐도 무방할 것이다

메모리 측면에서는 전자의 경우는 메모리의 소비가 거의 없다고 봐도 무방한 반면

후자의 경우에는 버퍼를 2개 생성한 것과 같으므로 2배의 메모리를 사용한다고 볼 수 있다

현재 입장에서는 전자의 방법을 사용하는게 조금더 좋지 않나 생각하고 있다

댓글
최근에 올라온 글
Total
Today
Yesterday
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31