1. مهمان گرامی، جهت ارسال پست، دانلود و سایر امکانات ویژه کاربران عضو، ثبت نام کنید.
    بستن اطلاعیه

برنامه نویسی Direct3D در ویژوال بیسیک

شروع موضوع توسط minaaa ‏24/10/11 در انجمن Visual Basic

  1. کاربر پیشرفته

    تاریخ عضویت:
    ‏9/12/10
    ارسال ها:
    19,773
    تشکر شده:
    6,457
    امتیاز دستاورد:
    113
    [h=2][/h][h=2]برنامه نویسی Direct3D در ویژوال بیسیک[/h] [h=2](قسمت اول)[/h]
    DirectX8 ابزاری برای ساخت تصاویر ثابت و متحرک دو بعدی و سه بعدی می باشد. برای کار با DirectX8 ابتدا بایستی آنرا روی سیستم خود نصب کنید. سپس در محیط VB از منوی Project گزینه References را انتخاب کنید. در فرمی که ظاهر میشود اطمینان حاصل کنید که گزینه DirectX8 for VB type library فعال باشد.

    برای کار با DirectX8 بایستی از تعریف نمودن شی پایه DirectX8 شروع نمود:
    کد:
    کد:

    Dim Dx As DirectX8
    شی Direct3D8 برای کنترل اشیا سه بعدی بکار می رود:
    کد:
    کد:

    Dim D3D As Direct3D8
    شی Direct3DDevice8، سخت افزار مربوط به رندر تصاویر را مشخص می کند:
    کد:
    کد:

    Dim D3DDevice As Direct3DDevice8
    حال برای شروع کار با Direct3D ، تابع ( )initialise را تعریف می کنیم. اگر اینکار درست انجام شود تابع، مقدار True را برمی گرداند:
    کد:
    کد:

    Public Function initialise() As Boolean Dim DispMode As D3DISPLAYMODE
    شی D3DISPLAYMODE حالت نمایش را مشخص می نماید.
    کد:
    کد:

    Dim D3DWindow As D3DPRESENT_PARAMETERS
    شی فوق مشخص می کند که Viewport شما چگونه باشد. حال شی اصلی DirectX8 را می سازیم:
    کد:
    کد:

    Set Dx = New DirectX8
    سپس شی اصلی ساخت واسط سه بعدی را می سازیم:
    کد:
    کد:

    Set D3D = Dx.Direct3DCreate()
    سپس حالت فعلی نمایش را با دستور زیر استخراج می کنیم:
    کد:
    کد:

    D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, DispMode
    حال دو حالت برای کار با DirectX داریم:
    1. Windowed Mode
    2. Fullscreen Mode

    1. برای کار با حالت پنجره ای ابتدا این موضوع را به DirectX اطلاع می دهیم :
    کد:
    کد:

    D3DWindow.Windowed = 1
    سپس نوع Referesh تصویر را مشخص می کنیم:
    کد:
    کد:

    D3DWindow.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC
    سپس بایستی فرمت بافر نگهدارنده تصاویر را مشخص کنیم:
    کد:
    کد:

    D3DWindow.BackBufferFormat = DispMode.Format
    2. برای کار با حالت تمام صفحه، ابتدا نوع Refresh را مشخص کرده سپس تعداد بافرهای تصویر و سرانجام نوع و سایز بافر را مشخص می نمائیم:
    کد:
    کد:

    D3DWindow.SwapEffect = D3DSWAPEFFECT_DISCARD D3DWindow.BackBufferCount = 1 D3DWindow.BackBufferFormat = DispMode.Format D3DWindow.BackBufferHeight = DispMode.Height D3DWindow.BackBufferWidth = DispMode.Width
    سپس پنجره نمایش مشخص می گردد:
    کد:
    کد:

    D3DWindow.hDeviceWindow = frmMain.hWnd
    حال بایستی یک Device ساخته شود که یا از طریق سخت‌افزار و یا نرم‌افزار تصاویر را رندر نماید:
    کد:
    کد:

    Set D3DDevice = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, frmMain.hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DWindow) End Sub
    درصورتی که کارت گرافیک شما امکانات رندر سخت‌افزاری تصاویر را ندارد از D3DDEVTYPE_REF بجای D3DDEVTYPE_HAL استفاده کنید. حال بایستی روتین Render را بنویسیم. البته در این درس تصویری برای رندر نداریم و تنها چگونگی نوشتن این روتین را بیان خواهم کرد:

    ابتدا بایستی Device مربوط به رندر، قبل از کشیدن تصویر در آن پاک شود:
    کد:
    کد:

    D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, &H0, 1#, 0
    عدد hex ای که در دستور فوق آمده رنگ زمینه صفحه را مشخص می کند. سپس بایستی تصاویر مورد نظر را رندر کنیم. اینکار توسط دستورات زیر انجام می شود:
    کد:
    D3DDevice.BeginScene
    کد:

    'All rendering calls go between these two lines
    D3DDEvice.EndScene
    در پایان بایستی صفحه را Update کنید:
    کد:
    کد:

    D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
     
  2. کاربر پیشرفته

    تاریخ عضویت:
    ‏9/12/10
    ارسال ها:
    19,773
    تشکر شده:
    6,457
    امتیاز دستاورد:
    113
    پاسخ : برنامه نویسی Direct3D در ویژوال بیسیک

    [h=2]برنامه نویسی Direct3D در ویژوال بیسیک (قسمت دوم)[/h]
    برنامه نویسی Direct3D در ویژوال بیسیک (قسمت دوم)
    1. شمارش تعداد آداپتورهای گرافیکی یک سیستم
    فرض کنید متغیر nAdapters متغیری از نوع Long باشد. همچنین شی D3DADAPTER_IDENTIFIER8 یک ساختار است که اطلاعات مربوط به آداپتور را نگه می دارد. در اینصورت روتین EnumerateAdapters بصورت زیر خواهد بود:
    کد:
    کد:

    Dim AdapterInfo As D3DADAPTER_IDENTIFIER8 Private Sub EnumerateAdapters Dim i As Integer nAdapters = D3D.GetAdapterCount
    برای بدست آوردن جزئیات آداپتورها بصورت زیر عمل می کنیم:
    کد:
    کد:

    For i = 0 To nAdapters - 1 D3D.GetAdapterIdentifier i, 0, AdapterInfo
    نام آداپتور بصورت لیستی از کدهای اسکی است که بایستی آنها را درون یک String قرار دهیم:
    کد:
    کد:

    Name = "" For J = 0 To 511 Name = Name & Chr$(AdapterInfo.Description(J)) Next J Name = Replace(sTemp, Chr$(0), " ") Next i End Sub
    بنابراین در متغیر Name نام آداپتور قرار خواهد گرفت.


    2. مشخص کردن نوع Rendering
    فرض کنید شی D3DCAPS8 توانایی Rendering آداپتور را نشان دهد. در اینصورت روتین EnumerateDevices بصورت زیر خواهد بود:
    کد:
    کد:

    Private Sub EnumerateDevices() On Local Error Resume Next Dim Caps As D3DCAPS8 Dim deviceindex As Long deviceindex = 0 'For Example D3D.GetDeviceCaps deviceindex, D3DDEVTYPE_HAL, Caps If Err.Number = D3DERR_NOTAVAILABLE Then MsgBox("Reference Rasterizer (REF)")
    اگر آداپتور امکان رندر سخت افزاری نداشته باشد در اینصورت:
    کد:
    کد:

    Else MsgBox("Hardware Acceleration (HAL) + Reference Rasterizer (REF)") End If End Sub
    3. شمارش تعداد Mode نمایشی آداپتور
    فرض کنید در صورت REF بودن امکان رندر، متغیر r=2 و در غیراینصورت r=1 باشد . همچنین شی D3DDISPLAYMODE اطلاعات مدهای نمایشی را در خود داشته باشد و متغیر nModes از نوع Long باشد. در اینصورت روتین EnumerateDispModes بصورت زیر خواهد بود:
    کد:
    کد:

    Private Sub EnumerateDispModes(r As Long) Dim i As Integer Dim mode_tmp As D3DDISPLAYMODE Dim deviceindex As Long deviceindex=0 'For Example nModes = D3D.GetAdapterModeCount(deviceindex) For i = 0 to nModes - 1 D3D.EnumAdapterModes(deviceindex, i, mode_tmp)
    ابتدا Modeها را به دو گروه ۱۶ بیتی و ۳۲ بیتی تقسیم می کنیم:
    کد:
    کد:

    If mode_tmp.Format = D3DFMT_R8G8B8 Or mode_tmp.Format = D3DFMT_X8R8G8B8 Or mode_tmp.Format = D3DFMT_A8R8G8B8 Then
    حال چک می کنیم که Device قابل پذیرش و معتبر است یا نه:
    کد:
    کد:

    If D3D.CheckDeviceType(deviceindex, r, mode_tmp.Format, mode_tmp.Format, Flase) >= 0 Then MsgBox(mode_tmp.Width & "X" & mode_tmp.Height & "32 Bit [FMT:" & mode_tmp.Format & "]" End If Else If D3D.CheckDeviceType(deviceindex, r, mode_tmp.Format, mode_tmp.Format, Flase) >=0 Then MsgBox(mode_tmp.Width & "X" & mode_tmp.Height & "16 Bit [FMT:" & mode_tmp.Format & "]" End If End If Next i End Sub
    4. مشخص کردن توانایی های آداپتور گرافیکی
    فرض کنید در صورت REF بودن امکان رندر، متغیر r=2 و در غیراینصورت r=1 باشد:
    کد:
    کد:

    Private Sub EnumerateHardware(r as long) Dim caps As D3DCAPS8 Dim deviceindex As Long deviceindex=0 'For Example D3D.Getdevicecaps deviceindex, r, caps If Caps.MaxActiveLights = -1 Then MsgBox "Maximum Active Lights: Unlimited" Else MsgBox "Maximum Active Lights: " & Caps.MaxActiveLights End If MsgBox "Maximum Point Vertex size: " & Caps.MaxPointSize MsgBox "Maximum Texture Size: " & Caps.MaxTextureWidth & "X" & Caps.MaxTextureHeight MsgBox "Maximum Primatives in one call: " & Caps.MaxPrimitiveCount If Caps.TextureCaps And D3DPTEXTURECAPS_SQUAREONLY Then MsgBox "Textures must always be square" End If If Caps.TextureCaps And D3DPTEXTURECAPS_CUBEMAP Then MsgBox "Device Supports Cube Mapping" End If If Caps.TextureCaps And D3DPTEXTURECAPS_VOLUMEMAP Then MsgBox "Device Supports Volume Mapping" End If If Caps.DevCaps And D3DDEVCAPS_PUREDEVICE Then MsgBox "Device supports the Pure Device Option" End If If Caps.DevCaps And D3DDEVCAPS_HWTRANSFORMANDLIGHT Then MsgBox "Device supports hardware transform and lighting" End If If Caps.DevCaps And D3DDEVCAPS_HWRASTERIZATION Then MsgBox "Device can use Hardware Rasterization" End If If Caps.Caps2 And D3DCAPS2_CANCALIBRATEGAMMA Then MsgBox "Device can Calibrate Gamma" End If If Caps.Caps2 And D3DCAPS2_CANRENDERWINDOWED Then MsgBox "Device can Render in Windowed Mode" End If If Caps.Caps2 And D3DCAPS2_FULLSCREENGAMMA Then MsgBox "Device can calibrate gamma in fullscreen mode" End If If Caps.RasterCaps And D3DPRASTERCAPS_FOGRANGE Then MsgBox "Device supports range based fog calculations" End If If Caps.RasterCaps And D3DPRASTERCAPS_ANISOTROPY Then MsgBox "Device supports Anisotropic Filtering" End If If Caps.RasterCaps And D3DPRASTERCAPS_ZBUFFERLESSHSR Then MsgBox "Device does not require a Z-Buffer/Depth Buffer" End If End Sub
     
  3. کاربر پیشرفته

    تاریخ عضویت:
    ‏9/12/10
    ارسال ها:
    19,773
    تشکر شده:
    6,457
    امتیاز دستاورد:
    113
    پاسخ : برنامه نویسی Direct3D در ویژوال بیسیک

    [h=2]برنامه نویسی Direct3D در ویژوال بیسیک (قسمت سوم)[/h]
    برنامه نویسی Direct3D در ویژوال بیسیک (قسمت سوم)
    شروع کار برای رسم اشیا دوبعدی
    ابتدا ثابت FVF را تعریف می کنیم. این ثابت توصیف "فرمت قابل انعطاف نقطه flexible-vertex-format" برای یک Vertex دو بعدی انتقال یافته و ساده شده می باشد. سپس بایستی یک ساختار برای توصیف این Vertex معرفی کنیم:
    کد:
    کد:

    Const FVF = D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE Or D3DFVF_SPECULAR
    کد:
    کد:

    Private Type TLVERTEX X As Single Y As Single Z As Single rhw As Single color As Long specular As Long tu As Single tv As Single End Type
    فرض کنید بخواهیم یک مربع را در صفحه رسم کنیم. برای رسم آن نیاز به 4 عدد Vertex داریم. بنابراین آرایه TriStrip را از نوع TLVERTEX تعریف میکنیم:
    کد:
    کد:

    Dim TriStrip (0 To 3) As TLVERTEX
    حال به سراغ تابع Initialise که در درس 1 با آن آشنا شدید می رویم و دستورات زیر را به آن اضافه می کنیم:

    ابتدا سیستم سایه زنی Vertex را طوری تنظیم می کنیم که از FVF استفاده کند:
    کد:
    کد:

    D3DDevice.SetVertexShader FVF
    حال سیستم Lighting را برای Vertex های دو بعدی غیر فعال می کنیم زیرا نیازی به آن نداریم:
    کد:
    کد:

    D3DDevice.SetRenderState D3DRS_LIGHTING, False
    حال بایستی تابع InitializeGeometry را اجرا کنیم. این تابع را در ادامه توضیح خواهم داد. اگر نتیجه این تابع True باشد دراینصورت Initialise به درستی انجام شده است:
    کد:
    کد:

    If InitialiseGeometry() = True Then Initialise = True Exit Function End If
    تابع InitialiseGeometry در این درس، تابعی ساده است که تنها آرایه Vertex ها را مقدار دهی می کند. برای رسم یک مربع نیاز به مقداردهی ۴ Vertex در جهت عقربه های ساعت داریم. ( این مربع شامل ۲ مثلث است)

    [​IMG]
    کد:
    کد:

    Private Function InitialiseGeometry() As Boolean On Error GoTo BailOut: TriStrip(0) = CreateTLVertex(100, 100, 0, 1, RGB(255, 255, 255), 0, 0, 0) TriStrip(1) = CreateTLVertex(300, 100, 0, 1, RGB(255, 0, 0), 0, 0, 0) TriStrip(2) = CreateTLVertex(100, 300, 0, 1, RGB(0, 255, 0), 0, 0, 0) TriStrip(3) = CreateTLVertex(300, 300, 0, 1, RGB(0, 0, 255), 0, 0, 0) InitialiseGeometry = True Exit Function BailOut: InitialiseGeometry = False End Function
    همانطور که مشاهده می کنید برای تعریف Vertex از تابع CreateTLVertex استفاده شده است. این تابع صرفاً مقادیر ساختار TLVERTEX را مقداردهی می کند:
    کد:
    کد:

    Private Function CreateTLVertex(X As Single, Y As Single, Z As Single, rhw As Single, color As Long, specular As Long, tu As Single, tv As Single) As TLVERTEX CreateTLVertex.X = X CreateTLVertex.Y = Y CreateTLVertex.Z = Z CreateTLVertex.rhw = rhw CreateTLVertex.color = color CreateTLVertex.specular = specular CreateTLVertex.tu = tu CreateTLVertex.tv = tv End Function
    نکته: شما می توانید مقادیر اعشاری Floating Point را برای مختصاتهای x و y و z بکار ببرید، اما Direct3D مختصاتها را با گردکردن آنها تخمین می زند و بنابراین ممکن است باعث ایجاد نتایج ناخواسته شود.

    حال بایستی تابع Render را بنویسیم:
    کد:
    کد:

    Public Sub Render() D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0 D3DDevice.BeginScene D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TriStrip(0), Len(TriStrip(0)) D3DDevice.EndScene D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 End Sub
    ساختار اصلی برای اجرای توابع فوق بصورت زیر است:
    کد:
    کد:

    Initialize Do While YourEvent = True Render DoEvents Loop
     
  4. کاربر پیشرفته

    تاریخ عضویت:
    ‏9/12/10
    ارسال ها:
    19,773
    تشکر شده:
    6,457
    امتیاز دستاورد:
    113
    پاسخ : برنامه نویسی Direct3D در ویژوال بیسیک

    [h=2]برنامه نویسی Direct3D در ویژوال بیسیک (قسمت چهارم)[/h]
    برنامه نویسی Direct3D در ویژوال بیسیک (قسمت چهارم)
    Vertex:
    یک نقطه در فضای سه بعدی که برای دادن موقعیت، Scale و زاویه یک Face استفاده می شود.

    Face:
    یک چند ضلعی که توسط مجموعه‌ای از نقاط به نام Vertex ساخته می شود.

    Mesh:
    مش، مجموعه‌ای از Faceها است که یک شی سه بعدی را روی صفحه تشکیل می دهند.

    Direct3D از ساختاری بنام D3DVERTEX برای نمایش یک Vertex استفاده می کند. برای ساخت Face نیز از آرایه‌ای از Vertexها استفاده می شود. آرایه همیشه بایستی قابل تقسیم به سه باشد زیرا اشکال از Faceهای مثلثی ساخته می شوند. هنگامیکه این مثلثها کنار هم گذاشته شوند، شی سه بعدی را می سازند. Direct3D از بافری با نام Index Buffer استفاده می کند که به Direct3D می گوید با چه ترتیبی Vertexها را رسم نماید. Indexها بایستی همیشه در جهت عقربه‌های ساعت مشخص شوند.

    [​IMG]
     
  5. کاربر پیشرفته

    تاریخ عضویت:
    ‏9/12/10
    ارسال ها:
    19,773
    تشکر شده:
    6,457
    امتیاز دستاورد:
    113
    پاسخ : برنامه نویسی Direct3D در ویژوال بیسیک

    [h=2]برنامه نویسی Direct3D در ویژوال بیسیک (قسمت پنجم)[/h]
    برنامه نویسی Direct3D در ویژوال بیسیک (قسمت پنجم)
    در این درس می خواهیم یک مربع که دارای بافت می باشد، رسم کنیم. برای اینکار از کتابخانه کمکی D3DX8 و همچنین شی Direct3DTexture8 استفاده می نمائیم.
    کد:
    کد:

    Dim D3DX As D3DX8 Dim Texture As Direct3DTexture8
    حال بایستی در تابع Initialize بافت مربوطه را از روی یک فایل تصویری Load کنیم:
    کد:
    کد:

    Private Function Initialize() As Boolean . . . Set Texture = D3DX8.CreateTextureFromFile(D3DDevice, App.Path & yourfilename) End Function
    تابع Render نیز بصورت زیر خواهد بود:
    کد:
    کد:

    Private Sub Render() D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0 D3DDevice.BeginScence D3DDevice.SetTexture 0, Texture D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TripStrip(0), Len(TriStrip(0)) . . . End Function