
Direct2D Include [Windows]
Re: Direct2D Include [Windows]
Sound really nice!! Thanks for share! 

If translation=Error: reply="Sorry, Im Spanish": Endif
Re: Direct2D Include [Windows]
I did an animation test, i expected it to be a bit smoother on 4k resolution, i did not use a timer, maybe someone can improve it.
Simply save the code in the PBDirect2D folder an run it.
Simply save the code in the PBDirect2D folder an run it.

Code: Select all
;DemoAnim.pb
IncludeFile "PBDirect2D.pb"
EnableExplicit
#ANIM_DOTS_COUNT = 3
Enumeration
#MENU_ID_START_STOP
EndEnumeration
;- _ANIM
Structure _ANIM
lastTime.q
active.b
counter.f
EndStructure
;- _APP
Structure _APP
win.i
menu.i
oldProc.i
anim._ANIM
;Device independent resources
d2dFactory.ID2D1Factory
dWriteFactory.IDWriteFactory
txtFormat.IDWriteTextFormat
;Device dependent resources
renderTarget.ID2D1HwndRenderTarget
dotBrush.ID2D1SolidColorBrush
rectBrush.ID2D1SolidColorBrush
EndStructure
Global._APP app
Procedure app_createDeviceIndependentResources()
Protected.l hr
Protected.D2D1_FACTORY_OPTIONS fOpts
Protected.D2D1_STROKE_STYLE_PROPERTIES props
fOpts\DebugLevel = #D2D1_DEBUG_LEVEL_NONE
hr = D2D1CreateFactory_(#D2D1_FACTORY_TYPE_SINGLE_THREADED, ?IID_ID2D1Factory, @fOpts, @app\d2dFactory)
hr = DWriteCreateFactory_(#DWRITE_FACTORY_TYPE_SHARED, ?IID_IDWriteFactory, @app\dWriteFactory)
If hr = #S_OK
;Text format
hr = app\dWriteFactory\CreateTextFormat("Segoe UI", #Null, #DWRITE_FONT_WEIGHT_REGULAR,
#DWRITE_FONT_STYLE_NORMAL, #DWRITE_FONT_STRETCH_NORMAL, 18.0,
"en-us", @app\txtFormat)
If hr = #S_OK
app\txtFormat\SetTextAlignment(#DWRITE_TEXT_ALIGNMENT_LEADING)
EndIf
EndIf
ProcedureReturn hr
EndProcedure
Procedure app_discardDeviceIndependentResources()
If app\d2dFactory
app\d2dFactory\Release() : app\d2dFactory = 0
EndIf
If app\dWriteFactory
app\dWriteFactory\Release() : app\dWriteFactory = 0
EndIf
If app\txtFormat
app\txtFormat\Release() : app\txtFormat = 0
EndIf
EndProcedure
Procedure app_createDeviceResources()
Protected.l hr
Protected.RECT rc
Protected.i hwnd
Protected.D2D1_SIZE_U sz
Protected.D2D1_RENDER_TARGET_PROPERTIES rtProps
Protected.D2D1_HWND_RENDER_TARGET_PROPERTIES hwndProps
Protected.D2D1_COLOR_F color
Protected.D2D1_BRUSH_PROPERTIES bProp
hr = #S_OK
If app\renderTarget = 0
hwnd = WindowID(app\win)
GetClientRect_(hwnd, @rc)
sz\width = rc\right - rc\left
sz\height = rc\bottom - rc\top
;Create a Direct2D render target.
rtProps\type = #D2D1_RENDER_TARGET_TYPE_DEFAULT
rtProps\pixelFormat\format = #DXGI_FORMAT_UNKNOWN
rtProps\pixelFormat\alphaMode = #D2D1_ALPHA_MODE_UNKNOWN
rtProps\dpiX = 0.0
rtProps\dpiY = 0.0
rtProps\usage = #D2D1_RENDER_TARGET_USAGE_NONE
rtProps\minLevel = #D2D1_FEATURE_LEVEL_DEFAULT
hwndProps\hwnd = hwnd
hwndProps\pixelSize\height = sz\height
hwndProps\pixelSize\width = sz\width
hwndProps\presentOptions = #D2D1_PRESENT_OPTIONS_NONE
hr = app\d2dFactory\CreateHwndRenderTarget(@rtProps, @hwndProps, @app\renderTarget)
If hr = #S_OK
;Brushes
bProp\opacity = 1.0
color\r = 0 : color\g = 162/255 : color\b = 232/255 : color\a = 1.0
app\renderTarget\CreateSolidColorBrush(@color, @bProp, @app\rectBrush)
color\r = 0.0 : color\g = 1.0 : color\b = 0.0 : color\a = 1.0
app\renderTarget\CreateSolidColorBrush(@color, @bProp, @app\dotBrush)
EndIf
EndIf
ProcedureReturn hr
EndProcedure
Procedure app_discardDeviceResources()
If app\renderTarget
app\renderTarget\Release() : app\renderTarget = 0
EndIf
If app\dotBrush
app\dotBrush\Release() : app\dotBrush = 0
EndIf
If app\rectBrush
app\rectBrush\Release() : app\rectBrush = 0
EndIf
EndProcedure
Procedure app_init()
InitializeStructure(@app, _APP)
EndProcedure
Procedure app_release()
app_discardDeviceResources()
app_discardDeviceIndependentResources()
EndProcedure
Procedure app_onSize(width.w, height.w)
Protected.D2D1_SIZE_U sz
If app\renderTarget
sz\width = width
sz\height = height
app\renderTarget\Resize(@sz)
EndIf
EndProcedure
Procedure app_onRender()
Protected.l hr, i
Protected.q tag1, tag2
Protected.D2D1_COLOR_F color
Protected.D2D1_ROUNDED_RECT dotsRect
Protected.D2D1_RECT_F rtRect
Protected.D2D1_SIZE_F rtSize
Protected.D2D1_ELLIPSE dot
Protected.f dotRectSize, t, vel
Protected.q currentTime, deltaTime, timeDelay, t2
Protected.s text
hr = #S_OK
hr = app_createDeviceResources()
If hr = #S_OK
app\renderTarget\BeginDraw()
currentTime = ElapsedMilliseconds()
deltaTime = currentTime - app\anim\lastTime
app\anim\lastTime = currentTime
timeDelay = 16 - deltaTime
color\r = 1.0 : color\g = 1.0 : color\b = 1.0 : color\a = 1.0
app\renderTarget\Clear(@color)
app\renderTarget\GetSize(@rtSize)
rtRect\right = rtSize\width
rtRect\bottom = rtSize\height
;Round Rectangle
dotRectSize = 200.0
dotsRect\rect\left = (rtSize\width / 2) - dotRectSize / 2
dotsRect\rect\top = (rtSize\height / 2) - dotRectSize / 2
dotsRect\rect\right = (rtSize\width / 2) + dotRectSize / 2
dotsRect\rect\bottom = dotsRect\rect\top + dotRectSize ;(rtSize\height / 2) + dotRectSize / 2
dotsRect\radiusX = 20.0
dotsRect\radiusY = 20.0
app\renderTarget\FillRoundedRectangle(@dotsRect, app\rectBrush)
t = app\anim\counter
dot\point\x = (rtSize\width / 2) - 40
dot\point\y = (rtSize\height / 2)
dot\radiusX = 10.0
dot\radiusY = 10.0
For i = 0 To #ANIM_DOTS_COUNT - 1
If app\anim\active
dot\point\y = (rtSize\height / 2) + (Sin(t) * ((dotRectSize / 2) - 40 ))
EndIf
app\renderTarget\FillEllipse(@dot, app\dotBrush)
dot\point\x + 40
t - 0.5
Next
;Text
text = "Press F1 to Start / Stop"
app\renderTarget\DrawText(text, Len(text), app\txtFormat, @rtRect, app\rectBrush, #D2D1_DRAW_TEXT_OPTIONS_NONE, #DWRITE_MEASURING_MODE_NATURAL)
hr = app\renderTarget\EndDraw(@tag1, @tag2)
app\anim\counter + 0.090
EndIf
If (hr = #D2DERR_RECREATE_TARGET)
hr = #S_OK
app_discardDeviceResources()
EndIf
If timeDelay > 0
Delay(timeDelay)
EndIf
EndProcedure
Procedure.i win_proc(hwnd.i, msg.l, wparam.i, lparam.i)
Select msg
Case #WM_SIZE
app_onSize(PeekW(@lparam), PeekW(@lparam + SizeOf(Word)))
Case #WM_DISPLAYCHANGE
InvalidateRect_(hwnd, #Null, #False)
Case #WM_ERASEBKGND
Protected.RECT rc
If Not app\anim\active
GetClientRect_(hwnd, @rc)
app_onSize(rc\right, rc\bottom)
app_onRender()
ProcedureReturn 1
EndIf
Case #WM_PAINT
If Not app\anim\active
app_onRender()
ValidateRect_(hwnd, #Null)
ProcedureReturn 0
EndIf
EndSelect
ProcedureReturn CallWindowProc_(app\oldProc, hwnd, msg, wparam, lparam)
EndProcedure
Procedure app_processEvent(ev.l)
Select ev
Case #PB_Event_Menu
Select EventMenu()
Case #MENU_ID_START_STOP
app\anim\active = Bool(Not app\anim\active)
If Not app\anim\active
app\anim\counter = 0
EndIf
InvalidateRect_(WindowID(app\win), 0, #False)
EndSelect
EndSelect
EndProcedure
Procedure main()
Protected.l ev
app_init()
If app_createDeviceIndependentResources() <> #S_OK
MessageRequester("Error" , "Failed to initialize Direct2D")
End
EndIf
app\anim\active = #True
app\win = OpenWindow(#PB_Any, 10, 10, 600, 400, "DemoAnim", #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget)
app\menu = CreateMenu(#PB_Any, WindowID(app\win))
AddKeyboardShortcut(app\win, #PB_Shortcut_F1, #MENU_ID_START_STOP)
app\oldProc = SetWindowLongPtr_(WindowID(app\win), #GWLP_WNDPROC, @win_proc())
Repeat
If app\anim\active
ev = WindowEvent()
If ev = 0
app_onRender()
Else
app_processEvent(ev)
EndIf
Else
ev = WaitWindowEvent()
app_processEvent(ev)
EndIf
Until ev = #PB_Event_CloseWindow
EndProcedure
main()
Re: Direct2D Include [Windows]
I'm running an Intel iGPU here and it takes < 1ms rendering (at 2560x1440 though, not 4k), so it's nice and fast here Justin (it should be to be fair, for such a simple scene).
I did disable vSync (hwndProps\presentOptions = #D2D1_PRESENT_OPTIONS_IMMEDIATELY), removed the Delay() & adjusted animation speed to tie-in with elapsed milliseconds to get the measurements.
Cool project & very powerful for 2d rendering, thanks for sharing.
I did disable vSync (hwndProps\presentOptions = #D2D1_PRESENT_OPTIONS_IMMEDIATELY), removed the Delay() & adjusted animation speed to tie-in with elapsed milliseconds to get the measurements.
Cool project & very powerful for 2d rendering, thanks for sharing.

Re: Direct2D Include [Windows]
Added Windows Animation Manager component:
https://learn.microsoft.com/en-us/windo ... ain-portal
It handles animations and transitions, it runs better.
Example in DemoWAM.pb in the repo.
Hi pjay,
the #D2D1_PRESENT_OPTIONS_IMMEDIATELY flag makes a big difference thanks for the tip, but the cpu usage is also high, about 10-15% could you reduce it?
Anyways, using the WAM runs pretty smooth, enough for UI animations.
Now i think the code is ready to attemp a DirectX animated canvas gadget, i will try it in a few days.
https://learn.microsoft.com/en-us/windo ... ain-portal
It handles animations and transitions, it runs better.
Example in DemoWAM.pb in the repo.
Hi pjay,
the #D2D1_PRESENT_OPTIONS_IMMEDIATELY flag makes a big difference thanks for the tip, but the cpu usage is also high, about 10-15% could you reduce it?
Anyways, using the WAM runs pretty smooth, enough for UI animations.
Now i think the code is ready to attemp a DirectX animated canvas gadget, i will try it in a few days.
Re: Direct2D Include [Windows]
Just noticed that with the current settings the alpha channel was not supported, you have to use a pixelformat with #DXGI_FORMAT_B8G8R8A8_UNORM and #D2D1_ALPHA_MODE_PREMULTIPLIED flags.
Updated and opacity animation test in DemoWAM.pb.

Updated and opacity animation test in DemoWAM.pb.

Re: Direct2D Include [Windows]
This is most excellent.
Could you provide an example of how to use CreateBitmap and DrawBitmap?
Could you provide an example of how to use CreateBitmap and DrawBitmap?
Re: Direct2D Include [Windows]
link no longer existing:
Justin wrote: Thu Aug 29, 2024 12:31 pm The files are at github:
https://github.com/omegakode/PBDirect2D
Belive! C++ version of Puzzle of Mystralia
Bug Planet
<Wrapper>4PB, PB<game>, =QONK=, PetriDish, Movie2Image, PictureManager,...
Bug Planet
<Wrapper>4PB, PB<game>, =QONK=, PetriDish, Movie2Image, PictureManager,...
Re: Direct2D Include [Windows]
I have downloaded the files as a ZIP archive (149 KiB):IceSoft wrote: Mon Nov 25, 2024 1:52 pm link no longer existing:Justin wrote: Thu Aug 29, 2024 12:31 pm The files are at github:
https://github.com/omegakode/PBDirect2D
https://www.dreisiebner.at/temp/PBDirec ... -09-12.zip
Peter
Re: Direct2D Include [Windows]
Hi,
the files are up again, i needed to make it private for some time, now is public again.
This code creates a bitmap in memory, draws it to the window and you can save it as a jpg using File->Save.
For loading and drawing an image from a file is in DemoApp.pb.
the files are up again, i needed to make it private for some time, now is public again.
This code creates a bitmap in memory, draws it to the window and you can save it as a jpg using File->Save.
For loading and drawing an image from a file is in DemoApp.pb.
Code: Select all
IncludeFile "PBDirect2D.pb"
;https://www.codeproject.com/Articles/5269188/Direct2D-Tutorial-Part-1-RenderTarget#bitmap
EnableExplicit
;- Enum MENU_ID
Enumeration
#MENU_ID_SAVE
EndEnumeration
;- _APP
Structure _APP
win.i
menu.i
d2dFactory.ID2D1Factory
imgFactory.IWICImagingFactory
renderTarget.ID2D1HwndRenderTarget
brush1.ID2D1SolidColorBrush
d2dBmp.ID2D1Bitmap
wicBmp.IWICBitmap
oldProc.i
EndStructure
Global._APP app
Procedure app_discardDeviceDependentResources()
If app\renderTarget
app\renderTarget\Release() : app\renderTarget = 0
EndIf
If app\brush1
app\brush1\Release() : app\brush1 = 0
EndIf
If app\d2dBmp
app\d2dBmp\Release() : app\d2dBmp = 0
EndIf
EndProcedure
Procedure app_release()
If app\d2dFactory
app\d2dFactory\Release() : app\d2dFactory = 0
EndIf
If app\imgFactory
app\imgFactory\Release() : app\imgFactory = 0
EndIf
app_discardDeviceDependentResources()
EndProcedure
;Creates a WIC Bitmap
Procedure.i app_createImage(imgFactory.IWICImagingFactory)
Protected.IWICBitmap wicBmp
Protected.D2D1_BRUSH_PROPERTIES bProp
Protected.D2D1_RENDER_TARGET_PROPERTIES rtProps
Protected.ID2D1SolidColorBrush brush1
Protected.D2D1_COLOR_F color
Protected.ID2D1RenderTarget bmpRt
Protected.D2D1_ROUNDED_RECT rc
Protected.q tag1, tag2
imgFactory\CreateBitmap(200, 200, ?GUID_WICPixelFormat32bppPBGRA, #WICBitmapCacheOnLoad, @wicBmp)
;Create bitmap render target
rtProps\type = #D2D1_RENDER_TARGET_TYPE_DEFAULT
;Enable alpha channel
rtProps\pixelFormat\format = #DXGI_FORMAT_B8G8R8A8_UNORM
rtProps\pixelFormat\alphaMode = #D2D1_ALPHA_MODE_PREMULTIPLIED
rtProps\dpiX = 0.0
rtProps\dpiY = 0.0
rtProps\usage = #D2D1_RENDER_TARGET_USAGE_NONE
rtProps\minLevel = #D2D1_FEATURE_LEVEL_DEFAULT
app\d2dFactory\CreateWicBitmapRenderTarget(wicBmp, @rtProps, @bmpRt)
;Brush
bProp\opacity = 1.0
color\r = 0 : color\g = 162/255 : color\b = 232/255 : color\a = 1.0
bmpRt\CreateSolidColorBrush(@color, @bProp, @brush1)
;Draw bitmap
bmpRt\BeginDraw()
color\r = 1 : color\g = 0 : color\b = 0 : color\a = 1
bmpRt\Clear(@color)
rc\rect\left = 10
rc\rect\top = 10
rc\rect\right = 100
rc\rect\bottom = 100
rc\radiusX = 20
rc\radiusY = 20
bmpRt\FillRoundedRectangle(@rc, brush1)
bmpRt\EndDraw(@tag1, @tag2)
bmpRt\Release()
ProcedureReturn wicBmp
EndProcedure
Procedure app_saveImage()
Protected.IStream stm
Protected.IWICBitmapEncoder encoder
Protected.IWICBitmapFrameEncode frame
Protected.IPropertyBag2 props
Protected.D2D1_SIZE_F bmpSize
Protected.l bmpWidth, bmpHeight, hr
Protected.GUID pixelFormat
Protected.s file
file = SaveFileRequester("Save", "test.jpg", "JPG file|*.jpg|All files|*.*", 0)
If file = "" : ProcedureReturn : EndIf
hr = SHCreateStreamOnFileEx_(file, #STGM_CREATE | #STGM_WRITE | #STGM_SHARE_EXCLUSIVE,
#FILE_ATTRIBUTE_NORMAL, #True, #Null, @stm)
If hr <> #S_OK : ProcedureReturn : EndIf
hr = app\imgFactory\CreateEncoder(?GUID_ContainerFormatJpeg, #Null, @encoder)
If hr <> #S_OK : ProcedureReturn : EndIf
encoder\Initialize(stm, #WICBitmapEncoderNoCache)
encoder\CreateNewFrame(@frame, @props)
frame\Initialize(props)
app\wicBmp\GetSize(@bmpWidth, @bmpHeight)
app\wicBmp\GetPixelFormat(@pixelFormat)
frame\SetPixelFormat(@pixelFormat)
frame\WriteSource(app\wicBmp, #Null)
frame\Commit()
encoder\Commit()
frame\Release()
encoder\Release()
stm\Release()
EndProcedure
Procedure app_createDeviceIndependentResources()
Protected.D2D1_FACTORY_OPTIONS fOpts
Protected.l hr
;Create D2D1Factory
fOpts\DebugLevel = #D2D1_DEBUG_LEVEL_NONE
hr = D2D1CreateFactory_(#D2D1_FACTORY_TYPE_SINGLE_THREADED, ?IID_ID2D1Factory, @fOpts, @app\d2dFactory)
;Create WICImagingFactory
hr = CoCreateInstance_(?CLSID_WICImagingFactory, #Null, #CLSCTX_INPROC_SERVER, ?IID_IWICImagingFactory, @app\imgFactory)
app\wicBmp = app_createImage(app\imgFactory)
ProcedureReturn hr
EndProcedure
Procedure app_createDeviceDependentResources()
Protected.RECT rc
Protected.l hr
Protected.i hwnd
Protected.D2D1_SIZE_U sz
Protected.D2D1_RENDER_TARGET_PROPERTIES props
Protected.D2D1_HWND_RENDER_TARGET_PROPERTIES hwndProps
hr = #S_OK
If app\renderTarget = 0
hwnd = WindowID(app\win)
GetClientRect_(hwnd, @rc)
sz\width = rc\right - rc\left
sz\height = rc\bottom - rc\top
;Create a Direct2D render target.
props\type = #D2D1_RENDER_TARGET_TYPE_DEFAULT
;Enable alpha channel
props\pixelFormat\format = #DXGI_FORMAT_B8G8R8A8_UNORM
props\pixelFormat\alphaMode = #D2D1_ALPHA_MODE_PREMULTIPLIED
props\dpiX = 0.0
props\dpiY = 0.0
props\usage = #D2D1_RENDER_TARGET_USAGE_NONE
props\minLevel = #D2D1_FEATURE_LEVEL_DEFAULT
hwndProps\hwnd = hwnd
hwndProps\pixelSize\height = sz\height
hwndProps\pixelSize\width = sz\width
hwndProps\presentOptions = #D2D1_PRESENT_OPTIONS_NONE
hr = app\d2dFactory\CreateHwndRenderTarget(@props, @hwndProps, @app\renderTarget)
If hr = #S_OK
;Create D2DBitmap from WICBitmap
app\renderTarget\CreateBitmapFromWicBitmap(app\wicBmp, #Null, @app\d2dBmp)
EndIf
EndIf
ProcedureReturn hr
EndProcedure
Procedure app_onSize(width.w, height.w)
Protected.D2D1_SIZE_U sz
If app\renderTarget
sz\width = width
sz\height = height
app\renderTarget\Resize(@sz)
EndIf
EndProcedure
Procedure app_onRender()
Protected.l hr, x, y, width, height, txtOpts
Protected.D2D1_COLOR_F color
Protected.q tag1, tag2
Protected.D2D1_SIZE_F rectSize, rtSize, bmpSize, scaledBmpSize
Protected.D2D1_RECT_F rcF2, rcBmpDest, rcBmpSrc
Protected.D2D1_POINT_2F bmpPos, pt
Protected.s txt
hr = #S_OK
hr = app_createDeviceDependentResources()
If hr = #S_OK
rectSize\width = 200.0
rectSize\height = 200.0
app\renderTarget\BeginDraw()
color\r = 1.0 : color\g = 1.0 : color\b = 1.0 : color\a = 1.0
app\renderTarget\Clear(@color)
app\renderTarget\GetSize(@rtSize)
app\d2dBmp\GetSize(@bmpSize)
rcBmpSrc\left = 0
rcBmpSrc\top = 0
rcBmpSrc\right = bmpSize\width
rcBmpSrc\bottom = bmpSize\height
rcBmpDest\left = 10
rcBmpDest\top = 10
rcBmpDest\right = rcBmpDest\left + bmpSize\width
rcBmpDest\bottom = rcBmpDest\top + bmpSize\height
app\renderTarget\DrawBitmap(app\d2dBmp, @rcBmpDest, 1, #D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, @rcBmpSrc)
hr = app\renderTarget\EndDraw(@tag1, @tag2)
EndIf
If (hr = #D2DERR_RECREATE_TARGET)
hr = #S_OK
app_discardDeviceDependentResources()
EndIf
ProcedureReturn hr
EndProcedure
Procedure win_proc(hwnd.i, msg.l, wparam.i, lparam.i)
Select msg
Case #WM_SIZE
app_onSize(PeekW(@lparam), PeekW(@lparam + SizeOf(Word)))
Case #WM_DISPLAYCHANGE
InvalidateRect_(hwnd, #Null, #False)
Case #WM_ERASEBKGND
Protected.RECT rc
GetClientRect_(hwnd, @rc)
app_onSize(rc\right, rc\bottom)
app_onRender()
ProcedureReturn 1
Case #WM_PAINT
app_onRender()
ValidateRect_(hwnd, #Null)
ProcedureReturn 0
EndSelect
ProcedureReturn CallWindowProc_(app\oldProc, hwnd, msg, wparam, lparam)
EndProcedure
Procedure main()
Protected.l ev
If app_createDeviceIndependentResources() <> #S_OK
MessageRequester("Error" , "Failed to initialize Direct2D")
End
EndIf
app\win = OpenWindow(#PB_Any, 10, 10, 600, 400, "Demo Bitmap", #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget |
#PB_Window_SizeGadget)
app\oldProc = SetWindowLongPtr_(WindowID(app\win), #GWLP_WNDPROC, @win_proc())
app\menu = CreateMenu(#PB_Any, WindowID(app\win))
MenuTitle("File")
MenuItem(#MENU_ID_SAVE, "Save")
BindMenuEvent(app\menu, #MENU_ID_SAVE, @app_saveImage())
Repeat
ev = WaitWindowEvent()
Until ev = #PB_Event_CloseWindow
app_release()
EndProcedure
main()