๋ฐ˜์‘ํ˜•

SharpDX vs GDI+

์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ DirectX์™€ GDI+์˜ ๊ธฐ๋ณธ์ ์ธ ์ฐจ์ด์ ๊ณผ SharpDX๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

[.Net] DirectX์™€ GDI+์˜ ์ฐจ์ด์ , ๊ทธ๋ฆฌ๊ณ  SharpDX ์ดํ•ดํ•˜๊ธฐ

 

[DirectX] DirectX์™€ GDI+์˜ ์ฐจ์ด์ , ๊ทธ๋ฆฌ๊ณ  SharpDX ์ดํ•ดํ•˜๊ธฐ

DirectX์™€ GDI์˜ ์ฐจ์ด์  SharpDX๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์ „์—, DirectX๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๊ทธ๋ฆฌ๊ณ  GDI์™€ ๋ฌด์Šจ ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€๋ถ€ํ„ฐ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ”ํžˆ ์•Œ๊ณ  ์žˆ๋Š” GDI(Graphics Device Interface)๋Š” ์œˆ๋„์šฐ ์šด์˜ ์ฒด์ œ์˜ ๊ทธ๋ž˜

luckygg.tistory.com

๊ฐ„๋‹จํ•˜๊ฒŒ ์š”์•ฝํ•˜์ž๋ฉด, 2D ์ด๋ฏธ์ง€ ๋ Œ๋”๋ง ๊ธฐ์ค€์œผ๋กœ ํ•˜๋“œ์›จ์–ด ๊ฐ€์†์„ ์ง€์›ํ•˜๋ƒ์˜ ์ฐจ์ด์ ์ด ์žˆ๋‹ค๊ณ  ๋ณด๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” WinForm ํ”„๋กœ์ ํŠธ์—์„œ SharpDX๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  GDI+ ๋Œ€๋น„ํ•˜์—ฌ ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ ํ•˜๊ธฐ

์˜ˆ์ œ ์ฝ”๋“œ๋Š” Visual Studio 2022 ํ™˜๊ฒฝ์œผ๋กœ ์ œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. WinForm์— Picture Box๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ณ , ์„ ํƒํ•œ ๋ฐฉ์‹(GDI+ ๋˜๋Š” DirectX)์— ๋”ฐ๋ผ Picture Box์— ์ด๋ฏธ์ง€๋ฅผ ์–ด๋–ป๊ฒŒ ๋ Œ๋”๋ง ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

WinForm ํ”„๋กœ์ ํŠธ ์ƒ์„ฑํ•˜๊ธฐ

ExamDirectX ์ด๋ฆ„์œผ๋กœ Windows Forms ์•ฑ(.NET Framework)๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

WinForm-ํ”„๋กœ์ ํŠธ-์ƒ์„ฑํ•˜๊ธฐ
WinForm ํ”„๋กœ์ ํŠธ ์ƒ์„ฑํ•˜๊ธฐ

UI Control ๋ฐฐ์น˜ํ•˜๊ธฐ

์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ, UI๋Š” Picture Box์™€ ๋ฒ„ํŠผ, ๋ผ๋””์˜ค ๋ฒ„ํŠผ์œผ๋กœ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

UI-๋ฐฐ์น˜
UI ๋ฐฐ์น˜

SharpDX NuGet ํŒจํ‚ค์ง€ ์„ค์น˜ํ•˜๊ธฐ

NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์—์„œ SharpDX๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์•„๋ž˜์˜ ํŒจํ‚ค์ง€๋“ค์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

NuGet-ํŒจํ‚ค์ง€-์„ค์น˜ํ•˜๊ธฐ
NuGet ํŒจํ‚ค์ง€ ์„ค์น˜ํ•˜๊ธฐ

SharpDX ๊ตฌํ˜„ํ•˜๊ธฐ

๋ณธ๋ฌธ ํ•˜๋‹จ์— ์ฒจ๋ถ€๋œ ์˜ˆ์ œ ์ฝ”๋“œ์—๋Š” MyDirectX.cs ํŒŒ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํŒŒ์ผ์— SharpDX ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ๋Œ€์ƒ ์ปจํŠธ๋กค์— ๋ Œ๋”๋ง ํ•˜๋Š”์ง€ ์ฝ”๋“œ๊ฐ€ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์—๋„ ์ฃผ์„์œผ๋กœ ์„ค๋ช…์„ ๋‚จ๊ฒจ ๋†“์•˜์ง€๋งŒ ๋ณธ๋ฌธ์—์„œ๋„ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐ ๊ฐ์ฒด ๋ณ„ ์šฉ๋„

Picture Box๋Š” GDI+ ๊ธฐ๋ฐ˜์˜ ์ปจํŠธ๋กค์ž…๋‹ˆ๋‹ค. DirectX ๊ฐ์ฒด๋กœ ํ•ด๋‹น ์ปจํŠธ๋กค์— ๋ Œ๋”๋ง ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์˜ ๊ธฐ๋ณธ ๊ฐ์ฒด๋“ค์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

//DirectX 2D ๊ทธ๋ž˜ํ”ฝ ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณต
SharpDX.Direct2D1.Factory2 _factory2D = null;

//GPU ํ•˜๋“œ์›จ์–ด์— ์ ‘๊ทผํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณต
SharpDX.Direct3D11.Device _device = null;

//๋ฐฑ ๋ฒ„ํผ์™€ ํ”„๋ก ํŠธ ๋ฒ„ํผ๋ฅผ ์Šค์™‘(ex: ๋”๋ธ” ๋ฒ„ํผ๋ง)ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ
SharpDX.DXGI.SwapChain _swapChain = null;

//๋ Œ๋”๋ง์ด ์ˆ˜ํ–‰๋˜๋Š” ํƒ€๊ฒŸ
SharpDX.Direct2D1.RenderTarget _renderTarget2D = null;

//DirectX 2D ๋น„ํŠธ๋งต
SharpDX.Direct2D1.Bitmap _bitmap = null;

PictureBox ์ปจํŠธ๋กค๊ณผ ์—ฐ๋™ํ•˜์—ฌ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ

์ผ๋ฐ˜์ ์œผ๋กœ ํ™”๋ฉด์— ์ด๋ฏธ์ง€๋ฅผ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋ Œ๋”๋ง ํ•˜๊ธฐ ์œ„ํ•ด ๋”๋ธ” ๋ฒ„ํผ๋ง์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ™”๋ฉด์— ๋ณด์ด๋Š” ๋ฒ„ํผ(ํ”„๋ŸฐํŠธ ๋ฒ„ํผ)์™€ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฒ„ํผ(๋ฐฑ ๋ฒ„ํผ) ๋‘ ๊ฐœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์Šค์™‘ ์ฒด์ธ(Swap Chain)์€ ์ด ๋ฐฑ ๋ฒ„ํผ์™€ ํ”„๋ก ํŠธ ๋ฒ„ํผ๋ฅผ ์Šค์™‘ ํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ถ€๋“œ๋Ÿฌ์šด ํ™”๋ฉด์„ ๋ณด์—ฌ์ฃผ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด _renderTarget2D๋Š” PictureBox์™€ ์—ฐ๋™๋ฉ๋‹ˆ๋‹ค.

public void InitializeControl(PictureBox control)
{
    //์Šค์™‘ ์ฒด์ธ์— ๋Œ€ํ•œ ์„ค์ •
    var desc = new SwapChainDescription()
    {
        BufferCount = 1, //์Šค์™‘ ์ฒด์ธ์— ์‚ฌ์šฉ๋  ๋ฒ„ํผ์˜ ์ˆ˜
        ModeDescription = new ModeDescription(control.Width, control.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm),
        //Rational: ํ™”๋ฉด ๊ฐฑ์‹  ์†๋„ 1/60
        IsWindowed = true, //์Šค์™‘ ์ฒด์ธ์ด ์ฐฝ ๋ชจ๋“œ์—์„œ ๋™์ž‘ํ•˜๋„๋ก ์„ค์ •
        OutputHandle = control.Handle, //์ถœ๋ ฅ์ด ์ด๋ฃจ์–ด์งˆ ์ฐฝ์˜ ํ•ธ๋“ค
        SampleDescription = new SampleDescription(1, 0), //๋ฉ€ํ‹ฐ์ƒ˜ํ”Œ๋ง์˜ ์ˆ˜์ค€
        SwapEffect = SwapEffect.Discard, //์Šค์™‘ ์ฒด์ธ์˜ ์Šค์™‘ ํšจ๊ณผ. Discard: ์Šค์™‘ ์ดํ›„ ๋ฐฑ ๋ฒ„ํผ ์‚ญ์ œ
        Usage = Usage.RenderTargetOutput //GPU๊ฐ€ ์ด ์ž์›์— ๊ทธ๋ž˜ํ”ฝ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์“ธ ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธ
    };

    _targetWindowSize.Left = 0;
    _targetWindowSize.Top = 0;
    _targetWindowSize.Right = control.Width;
    _targetWindowSize.Bottom = control.Height;

    SharpDX.Direct3D11.Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport, desc, out _device, out _swapChain);

    //DirectX 2D ๊ทธ๋ž˜ํ”ฝ ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณต
    _factory2D = new SharpDX.Direct2D1.Factory2();

    //Surface๋Š” ๊ทธ๋ž˜ํ”ฝ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ทธ๋ฆฌ๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค
    var backBuffer = Surface.FromSwapChain(_swapChain, 0);
    var properties = new RenderTargetProperties(new SharpDX.Direct2D1.PixelFormat(Format.Unknown, SharpDX.Direct2D1.AlphaMode.Premultiplied));

    _renderTarget2D = new RenderTarget(_factory2D, backBuffer, properties);
}

ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ SharpDX ๋น„ํŠธ๋งต ์ƒ์„ฑํ•˜๊ธฐ

WIC(windows Imaging Component)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜จ ํ›„ ๋ Œ๋”๋ง ํƒ€๊นƒ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Direct2D ๋น„ํŠธ๋งต์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

public void LoadBitmap(string filename)
{
    //Bitmap ๋””์ฝ”๋”/์ธ์ฝ”๋”, ํฌ๋งท ๋ณ€๊ฒฝ, ์Šค์ผ€์ผ๋Ÿฌ ๋“ฑ ์ง€์›
    var wicFactory = new SharpDX.WIC.ImagingFactory2();

    //ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
    var wicDecoder = new SharpDX.WIC.BitmapDecoder(wicFactory, filename, SharpDX.WIC.DecodeOptions.CacheOnDemand);

    //ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ๋ถˆ๋Ÿฌ์˜จ ๋””์ฝ”๋”์˜ ์ฒซ ํ”„๋ ˆ์ž„ ๊ฐ€์ ธ์˜ค๊ธฐ
    //์ด๋ฏธ์ง€ ํŒŒ์ผ์€ ํ•˜๋‚˜์˜ ํ”„๋ ˆ์ž„์ด์ง€๋งŒ, GIF์˜ ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ํ”„๋ ˆ์ž„
    var wicFrame = wicDecoder.GetFrame(0);

    //ํฌ๋งท ์ปจ๋ฒ„ํ„ฐ ์ƒ์„ฑ ๋ฐ ์ดˆ๊ธฐํ™”
    var converter = new SharpDX.WIC.FormatConverter(wicFactory);
    converter.Initialize(wicFrame, SharpDX.WIC.PixelFormat.Format32bppPRGBA);

    //๋ณ€ํ™˜๋œ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ Direct2D ๋น„ํŠธ๋งต์œผ๋กœ ๋ณ€ํ™˜
    _bitmap = SharpDX.Direct2D1.Bitmap.FromWicBitmap(_renderTarget2D, converter);

    //๊ฐ์ฒด ์†Œ๋ฉธ
    converter.Dispose();
    wicFrame.Dispose();
    wicDecoder.Dispose();
    wicFactory.Dispose();
}

ํ™”๋ฉด์— ๊ทธ๋ฆฌ๊ธฐ

ํ™”๋ฉด์— ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•ด ์•„๋ž˜์˜ ์ฝ”๋“œ๊ฐ€ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ๋งˆ์ง€๋ง‰ ๋ผ์ธ์˜ ์ฝ”๋“œ๊ฐ€ ์ค‘์š”ํ•œ๋ฐ์š”. Present ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ™”๋ฉด์— ๋ณด์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” ๋ชจ๋‹ˆํ„ฐ์˜ ๋ฆฌํ”„๋ ˆ์‹œ ์†๋„(VSync)์™€ ๋™๊ธฐํ™”ํ•˜๋Š” ์ธ์ž์ž…๋‹ˆ๋‹ค. 0์€ ์ฆ‰์‹œ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๊ณ , 1์€ ๋ชจ๋‹ˆํ„ฐ์˜ ๊ฐฑ์‹  ์†๋„์™€ ๋™๊ธฐ๋ฅผ ๋งž์ถฅ๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” VSync์™€ ๊ด€๋ จํ•˜์—ฌ ๋™์ž‘์„ ์„ค์ •ํ•˜๋Š” ํ”Œ๋ž˜๊ทธ์ž…๋‹ˆ๋‹ค. ํŠน์ • ํšจ๊ณผ๋ฅผ ์–ป๊ณ  ์‹ถ๋‹ค๋ฉด ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋˜์ง€๋งŒ ์„ฑ๋Šฅ ์ €ํ•˜๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ž˜ ์•Œ๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

public void Render()
{
    //๋ Œ๋”๋ง ์ž‘์—… ์‹œ์ž‘
    _renderTarget2D.BeginDraw();

    //๋ Œ๋”๋ง ํ™”๋ฉด ๋น„์šฐ๊ธฐ(ํŠน์ • ์ƒ‰์ƒ ์ฑ„์šฐ๊ธฐ ๊ฐ€๋Šฅ)
    _renderTarget2D.Clear(new SharpDX.Mathematics.Interop.RawColor4(1.0f, 1.0f, 1.0f, 1.0f));

    //1:1 ๋น„์œจ๋กœ ๊ทธ๋ฆฌ๊ธฐ
    //_renderTarget2D.DrawBitmap(_bitmap, 1.0f, SharpDX.Direct2D1.BitmapInterpolationMode.Linear);

    //๋ Œ๋”๋ง ํƒ€๊ฒŸ์— ์ฑ„์›Œ์„œ ๊ทธ๋ฆฌ๊ธฐ
    _renderTarget2D.DrawBitmap(_bitmap, _targetWindowSize, 1.0f, SharpDX.Direct2D1.BitmapInterpolationMode.Linear);

    //๋ Œ๋”๋ง ์ž‘์—… ์ข…๋ฃŒ
    _renderTarget2D.EndDraw();

    //์Šค์™‘ ์ฒด์ธ์˜ ๋ Œ๋”๋ง ์ด๋ฏธ์ง€๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋Š” ์—ญํ• 
    _swapChain.Present(1, PresentFlags.None);
}

๊ฐ์ฒด ์†Œ๋ฉธ

๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด๋Š” ์†Œ๋ฉธํ•ฉ๋‹ˆ๋‹ค.

public void Dispose()
{
    _renderTarget2D?.Dispose();
    _renderTarget2D = null;

    _swapChain?.Dispose();
    _swapChain = null;

    _device?.Dispose();
    _device = null;

    _factory2D?.Dispose();
    _factory2D = null;

    _bitmap?.Dispose();
    _bitmap = null;
}

๋ฒ„ํŠผ ๋™์ž‘

๋ผ๋””์˜ค ๋ฒ„ํŠผ์œผ๋กœ GDI+ ๋˜๋Š” DirectX๋ฅผ ์„ ํƒํ•œ ํ›„ ์‹คํ–‰ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๊ฐ ๋ฐฉ์‹ ๋ณ„ ๋ Œ๋”๋ง์„ ์œ„ํ•œ ์Šค๋ ˆ๋“œ ํ•จ์ˆ˜๊ฐ€ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. CPU ๋ฐ GPU ์‚ฌ์šฉ์œจ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด 500ํšŒ ๋ฐ˜๋ณตํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

private void btnLoad_Click(object sender, EventArgs e)
{
    try
    {
        OpenFileDialog dlg = new OpenFileDialog();
        if(dlg.ShowDialog() == DialogResult.OK)
        {
            Thread thread = null;
            if (rbtnDirectX.Checked == true)
            {
                _directX.LoadBitmap(dlg.FileName);
                thread = new Thread(threadFuncDirectX);
            }
            else
            {
                _bitmap = new Bitmap(dlg.FileName);
                //...

                thread = new Thread(threadFuncGDI);
            }
            thread.Start();
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}

private void threadFuncDirectX()
{
    for (int i = 0; i < 500; i++)
    {
        Thread.Sleep(30);
        _directX.Render();
    }
}

private void threadFuncGDI()
{
    for (int i = 0; i < 500; i++)
    {
        Thread.Sleep(30);
        _graphics.DrawImage(_bitmap, new Rectangle(0, 0, pbView.Width, pbView.Height));
    }
}

๋™์ž‘ ๊ฒฐ๊ณผ

์ธํ„ฐ๋„ท์—์„œ ๊ณ ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋ฐ›์Šต๋‹ˆ๋‹ค. ์ €๋Š” 24MB์˜ ๊ณ ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

GDI+๋กœ ๋™์ž‘ํ•˜๋ฉด CPU ๋ถ€ํ•˜๊ฐ€ ์•ฝ 10%๊นŒ์ง€ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. GPU๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋”ฐ๋กœ ์‚ฌ์šฉ๋Ÿ‰์ด ์—†์Šต๋‹ˆ๋‹ค.

GDI+-๋™์ž‘-์„ฑ๋Šฅ
GDI+ ๋™์ž‘ ์„ฑ๋Šฅ

๋ฐ˜๋ฉด, DirectX๋กœ ๋™์ž‘ํ•˜๋ฉด CPU ๋ถ€ํ•˜๊ฐ€ ๊ฑฐ์˜ ์—†์œผ๋ฉฐ GPU ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

DirectX-๋™์ž‘-์„ฑ๋Šฅ
DirectX ๋™์ž‘ ์„ฑ๋Šฅ

์ „์ฒด ์ฝ”๋“œ๋Š” ์•„๋ž˜ ์ฒจ๋ถ€๋œ ์˜ˆ์ œ ํŒŒ์ผ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

ExamDirectX.zip
12.28MB

๋ฐ˜์‘ํ˜•