Replacing gdiAlphaBlend with RC5/Cairo.
so, what the title says.
I need a replacement of gdiAlphaBlend, and I mean all the parameters, copy parts of the source to a destination source.
what I have found with RC5 I can only copy the whole picture and if the picture is bigger then the surface it will squeeze it inside, and its not what i need.
Re: Replacing gdiAlphaBlend with RC5/Cairo.
Hi baka, thanks for starting a new post, and for clarifying that you want all the parameters the same as the GDI+ AlphaBlend function.
I did spend a bit of time on this today, but I'm new to the RC5/Cairo stuff too, so I encountered some issues. First things first: the AlphaBlend API declaration at MSDN is declared as follows:
Code:
BOOL AlphaBlend(
_In_ HDC hdcDest,
_In_ int xoriginDest,
_In_ int yoriginDest,
_In_ int wDest,
_In_ int hDest,
_In_ HDC hdcSrc,
_In_ int xoriginSrc,
_In_ int yoriginSrc,
_In_ int wSrc,
_In_ int hSrc,
_In_ BLENDFUNCTION ftn
);
I'm assuming you want the output to go to an hDC (hdcDest), but do you require the source to be an hDC? Or can the source be a Cairo surface?
Re: Replacing gdiAlphaBlend with RC5/Cairo.
Re: Replacing gdiAlphaBlend with RC5/Cairo.
Gosh, wouldn't documentation be useful?
Re: Replacing gdiAlphaBlend with RC5/Cairo.
There will be no "squeeze", when you leave out the optional dx, dy Params in:
CC.RenderSurfaceContent SourceSrf_or_SrcImageKey, x, y, [dx], [dy]
I guess, what you really mean is, how to "Cut-Out" an area from a larger Source-Image - and render that
(as e.g. from a "Sprite-Panel" which contains a lot of Sprites, all sitting at different coordinates (maybe in different sizes as well).
The following code demonstrates such a "CutOut-Function" which returns such a SubArea as a separate CairoSurface.
Code:
Option Explicit
Private CC As cCairoContext, i As Long
Private Sub Form_Load()
Set CC = Cairo.CreateSurface(800, 600).CreateContext 'create our Main-DrawingContext
Dim SpritePanel As cCairoSurface 'load the SpritePanel from Disk
Set SpritePanel = Cairo.CreateSurface(0, 0, , "c:\temp\Ico_1to5.png")
'cut-out the Sprites from the Panel and store them separately (each with its own "nice StringKey") in the ImageList
For i = 0 To 4
Cairo.ImageList.AddSurface "Ico" & i + 1, CutFrom(SpritePanel, i * 50, 0, 50, 50)
Next
'rendering-time
CC.SetSourceColor vbWhite: CC.Paint 'ensure white BackGround
CC.RenderSurfaceContent "Ico2", 10, 10 'render our Sprite #2 (out of 5)
CC.RenderSurfaceContent "Ico3", 60, 60 'render our Sprite #3 (out of 5)
Set Me.Picture = CC.Surface.Picture 'flip the result to the Form-Picture
End Sub
Function CutFrom(Src As cCairoSurface, x, y, dx, dy) As cCairoSurface
Set CutFrom = Cairo.CreateSurface(dx, dy)
CutFrom.CreateContext.RenderSurfaceContent Src, -x, -y
End Function
The Image I was using within the code-snippet above (as the little "SpritePanel"), was that one here:
http://vbRichClient.com/Downloads/Ico_1to5.png
HTH
Olaf
Re: Replacing gdiAlphaBlend with RC5/Cairo.
so what I need to do is to create a "surface" for every "cut and paste" I need?
but Im doing numerous cut and paste every render! its a 2d multi-layer based game and everything is moving and changing.
this means i need to rethink a bit, maybe use different methods for different animations to lower the need to use the "cut and paste"
right now im cuttings a lot of pictures and also when they go outside the DC, this so that i dont render if i dont see it (im only rendering the visible area, even if the game area is a lot bigger)
I think you should add the next time you update RC5 a new function, maybe RenderSurfaceContentEx, where we can select the area that we want to copy, like gdiAlphaBlend. Im sure its possible using Cairo, that would make things easier. Usually we use a "bitmap collection", could be icons or different gui-art, its quite common and to be forced to cut it into a surface before we render its 1 step too much.
But I will try it out and see if its will work for my needs.
Re: Replacing gdiAlphaBlend with RC5/Cairo.
Quote:
Originally Posted by
dilettante
Gosh, wouldn't documentation be useful?
As so often lately - you talk about things you have no real clue about...
Cairo has no direct BitBlt-command because it is not needed (there's more powerful alternatives for such things in
most of the more advanced 2D- and 3D-graphics-APIs, which all use a bit of indirection in their Blitting-approaches).
And it is not that hard, to find these alternatives (by googling them).
- e.g. for OpenGL (which also does not have a direct "BitBlt") the way would be over glTexSubImage2D (in a separate step)
- with Direct2D (also not having a direct BitBlt-command) the solution would also be "indirect" (by using a separate IWICBitmapClipper-instance)
Same thing with Cairo basically - a little indirection is required.
But that's not a "documentation-problem" - it's a plain and simple "study the available APIs for the new Graphics-lib"-problem.
Besides - documentation for cairo is available in abundance:
- tons of examples here in the forum, which already covered what I've posted above (dreammanor posted a link already)
- because of the huge Cairo-tutorial that comes with the RC5 (which in that "completeness" doesn't exist - neither for GDI - nor for GDI+)
- and secondly, because the RC5-Classes wrap the original cairo-flat-API quite directly
So (with regards to the last point above) you can always look at the documentation or examples on the cairo-website:
https://cairographics.org/samples/
An alternative to what I posted as a demo, would be by a combination of the clip-image, imagepattern examples on the above linked site.
But you will of course not look at that - far from it - nor will you study the cairo-tutorial.
Uttering misleading, wrong comments about things you know nothing about, is all you do dile (when it comes to the Runtime-Classes of the VB6-successor).
Olaf
Re: Replacing gdiAlphaBlend with RC5/Cairo.
Quote:
Originally Posted by
baka
so what I need to do is to create a "surface" for every "cut and paste" I need?
No, you do the "CutOuts" only at "Resource-Loading-Time" (from your larger "Sprite-Panel-PNGs", which you can remove from memory,
after all "SubImage-Sprites" were transfered into the Cairo.ImageList under "nice describing Keys".
The rendering is only one line of code (no cutouts needed anymore) - instead you use the StringKey of the SubImage to render directly from the (smaller) Resource.
So there's two stages (which will also lead to cleaner code)
1) Resource-Loading of SubImages at Program-Startup (releasing the large Sprite-Panels memory after that)
2) Rendering-time (direct and fast Blending to any target-Coordinate on your Scene (using the smaller, memorywise better "CPU-cachable" SubSprites per StringKey).
Quote:
Originally Posted by
baka
... its a 2d multi-layer based game and everything is moving and changing.
When you talk about "Moving and changing", then you only talk about "Target-Coords" for your Sprites
(and "which Sprite you mean" wouldn't have to be described with "4 Source-Coords" anymore, but with a StringKey instead)
Quote:
Originally Posted by
baka
I think you should add the next time you update RC5 a new function, maybe RenderSurfaceContentEx...
Nope - as I tried to explain - it is not needed at all (and the needed code for the shown CutOut is just 2 lines - so - a function like that wouldn't save much)
Blending-Ops work faster, when the "contiguous amount of allocated memory" is "near together" (when we talk about Source-Images).
A BitBlt-Operation which reads the ScanLines (with appropriate Offsets from a larger "Sprite-Table" has to skip memory-addresses -
so the "cache-locality" is not as good as with those "pre-cutout" smaller Sprites.
Edit:
FWIW - below comes an additional alternative to the CutOut-approach (using a CairoPattern, which is a kind of "Description for a Brush")...
these patterns can act as a "thin meta-description-object" - "wrapped around" the Source-Surface, which still has the original Data -
though using the Pattern-Wrapping now allows to describe Offsets (or Rotations, whatever) in the Source-Surface.
But as said, I'd think that the BltTo-function below would be a bit slower than the Pre-CutOuts:
Code:
Option Explicit
Private CC As cCairoContext, SpritePanel As cCairoSurface, i As Long
Private Sub Form_Load()
Set CC = Cairo.CreateSurface(800, 600).CreateContext 'create our Main-DrawingContext
Set SpritePanel = Cairo.CreateSurface(0, 0, , "c:\temp\Ico_1to5.png")
'cut-out the Sprites from the Panel and store them separately (each with its own "nice StringKey") in the ImageList
For i = 0 To 4
Cairo.ImageList.AddSurface "Ico" & i + 1, CutFrom(SpritePanel, i * 50, 0, 50, 50)
Next
'rendering-time
CC.SetSourceColor vbWhite: CC.Paint 'ensure white BackGround
CC.RenderSurfaceContent "Ico2", 10, 10 'render our Sprite #2 (out of 5)
CC.RenderSurfaceContent "Ico3", 60, 60 'render our Sprite #3 (out of 5)
BltTo CC, 210, 10, 50, 50, SpritePanel.CreateSurfacePattern, 50, 0
BltTo CC, 260, 60, 50, 50, SpritePanel.CreateSurfacePattern, 100, 0
Set Me.Picture = CC.Surface.Picture
End Sub
Sub BltTo(CC As cCairoContext, x, y, dx, dy, SrcPat As cCairoPattern, xSrc, ySrc)
CC.Rectangle x, y, dx, dy 'define the target-region, using a normal rectangular path-definition
Set SrcPat.Matrix = SrcPat.Matrix.TranslateCoords(xSrc - x, ySrc - y) 'shift the Pattern
CC.Fill , SrcPat 'fill the Pattern into the above defined Rectangle-Coords
End Sub
Function CutFrom(Src As cCairoSurface, x, y, dx, dy) As cCairoSurface
Set CutFrom = Cairo.CreateSurface(dx, dy)
CutFrom.CreateContext.RenderSurfaceContent Src, -x, -y
End Function
Olaf
Re: Replacing gdiAlphaBlend with RC5/Cairo.
ic, thanks for all the samples and explanations. i will look into it and see what i can figure out and how to convert my code.
the idea to add a "alphablend" alternative is to make it easier when converting a vb6 gdi code to vb6 rc5 code, im sure im not alone using gdi/+ apis that way.
to cut it in pieces is not "bad", is just different and means i need to change a bit of code,
to explain what happens in the game, in "1" area
background layers: moving clouds + distant objects.
- a image 900x398 that moves slowly in parallax. (this would be easy to implement)
- a 899x127 image: horizontal moving + copy + parallax. (the cloud moves horizontally, and a new copy is rendered after it + parallax) in my gdi version i cut the part that disappears or before it enter the DC, this to speed up the rendering time. i could skip the cutting and see if it will maintain performance.)
- different objects here and there, they have fixed positions + parallax (they are located between clouds) no problems here, i skip the cutting (but in my gdi i do the same, if they go outside the boundaries, i cut out the part that is not visible)
- and more clouds, total of 7 clouds moving, and 8 different objects (in different size, some small some big)
middle layer: the "area", 2981x1970 big platform. we can only see 800x600 at a time, we can move around. the background follows you as well, but it using different parallax creating depth.
Front layer: the "area's" front part, with ropes and other objects that need to be "in front"
Front layer: Portals, to enter other areas. the portal is animated, the source is image 340x1166 that contains different effects, the portal itself is 7 different pictures
(theres no NPC/Enemies in this map, otherwise they will be on top of middle layer)
to show the "routine" Im using, that most other functions calls when ready:
Code:
Sub Render(ByVal Index&, ByVal x&, ByVal y&, ByVal sx&, ByVal sy&, ByVal sw&, ByVal sh&, Optional ByVal Fade&)
If x > 800 Or y > 600 Then Exit Sub
If x < 0 Then
sw = sw + x: If sw < 1 Then Exit Sub
sx = sx - x
x = 0
End If
If y < 0 Then
sh = sh + y: If sh < 1 Then Exit Sub
sy = sy - y
y = 0
End If
If x + sw > 800 Then sw = 800 - x: If sw < 1 Then Exit Sub
If y + sh > 600 Then sh = 600 - y: If sh < 1 Then Exit Sub
GdiAlphaBlend Image(0).hDC, x, y, sw, sh, Image(Index).hDC, sx, sy, sw, sh, Image(Index).Alpha - Fade
End Sub
Image(0) is the "empty" surface that later will be used to render to DC. Theres 11 other Images that the game uses all the time,
after that its dynamic, loading/unloading for each area. when all the rendering are done, we call:
Code:
Sub RenderDC()
If LTextCount > 0 Then DoText
StretchBlt desthDC, 0, 0, sys.Width, sys.Height, Image(0).hDC, 0, 0, 800, 600, vbSrcCopy
End Sub
theres no refresh or cls. theres 3 modes. 0=nothing. the new render will "paste" itself above image(0) and repaint it. 1=backcolor, using Gdi Brush FillRect, 2=a background picture using BitBlt