I'm developing a reliable 2D drawing framework, that can be used with : games (fullscreen/window), SDI and MDI applications. And no, it's not just another engine for hobby - it's a really serious project to be used in commercial software. It'll be opensource, absolutely free for any usage (commercial too), no credits needed at all. It is (and will continue to be) reliable and easy to use.
Its main purpose is to provide hardware-accelerated drawing, so that your app can do a lot more with the CPU, and to have more options than GDI has.

Right now, though, I have one problem - alphablending. I must have this one in hardware too, so I need someone to show me how to do this in D3D, while the DDraw code isn't rendered absolutely useless. I need this to do exactly what Blt does, but with alpha.

Since I have enough experience in developing commercial games and applications (and the design and music for them), I constantly control my code to be: reliable, exactly-what-you-need (complete, but expandable too) , flexible, readable, debuggable, optimized. I know it is going to be useful - it's my job to write complete code that will be the backbone of many other pieces of software to come from the companies I work for.


I'm asking here first, before googling enough, because I respect much more the opinion and knowledge of assembler fellows, than those of C++ dreamers.

Thanks in advance for any help you provide.
Posted on 2005-01-26 12:33:40 by Ultrano
Hello Ultrano

The blits can be performed using alpha information.

IDirectDrawSurface::Blt

Syntax

HRESULT Blt(
LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwFlags,
LPDDBLTFX lpDDBltFX
);


ALPHA Parameters dwFlags:

Value Description
DDBLT_ALPHADEST Use the alpha information in the pixel format or the alpha channel surface attached to the destination surface as the alpha channel for this blit.
DDBLT_ALPHADESTCONSTOVERRIDE Use the dwConstAlphaDest member in the DDBLTFX structure as the alpha channel for the destination surface for this blit.
DDBLT_ALPHADESTNEG The NEG suffix indicates that the destination surface becomes more transparent as the alpha value increases. (0 is opaque)
DDBLT_ALPHADESTSURFACEOVERRIDE Use the lpDDSAlphaDest member in the DDBLTFX structure as the alpha channel for the destination for this blit.
DDBLT_ALPHAEDGEBLEND Use the dwAlphaEdgeBlend member in the DDBLTFX structure as the alpha channel for the edges of the image that border the color key colors.
DDBLT_ALPHASRC Use the alpha information in the pixel format or the alpha channel surface attached to the source surface as the alpha channel for this blit.
DDBLT_ALPHASRCCONSTOVERRIDE Use the dwConstAlphaSrc member in the DDBLTFX structure as the alpha channel for the source for this blit.
DDBLT_ALPHASRCNEG The NEG suffix indicates that the source surface becomes more transparent as the alpha value increases. (0 is opaque)
DDBLT_ALPHASRCSURFACEOVERRIDE Use the lpDDSAlphaSrc member in the DDBLTFX structure as the alpha channel for the source for this blit.
Posted on 2005-01-27 02:09:22 by Siekmanski
could be done in direct3d too, by drawing quads, with additional advantages like texture filtering and easy rotating (and alpha blending). to answer your question here is quite much work; but if you want i can give you some links to similar stuff.
Posted on 2005-01-27 03:45:00 by lifewire
Hello Ultrano

Here's an Alpha Blending example I've done in D3D9

http://members.home.nl/siekmanski/d3d9_alpha.zip
Posted on 2005-01-27 07:11:44 by Siekmanski
Thanks, guys - but still I can't implement it the way I want. The Blt with xxALPHAxx values - everybody swears those flags are unused. So, I made tests of blitting with these flags, one of which is:


IlixBlt_WithFinalAlpha proc pSprite,pRect,pRect2,Alpha
local fx:DDBLTFX
ZeroMemory &fx,sizeof fx
mov fx.dwSize,sizeof fx
mov fx.dwAlphaSrcConst,40

mov edx,pSprite
pcall lpBackBuffer.Blt,pRect,[edx].iSprite.lpSurface,pRect2,DDBLT_WAIT or DDBLT_ALPHASRCCONSTOVERRIDE,addr fx
.if eax
PrintHex eax ; this is never called
.endif

_ret: ret
IlixBlt_WithFinalAlpha endp

I came to the conclusion that the second flag is obviously ignored :( . I have DX9c runtime. Ok, so with DirectDraw it won't work. Then I looked at your(Siekmanski's) and Homer's examples on using DX9 to draw 2D. I see they don't fit with DirectDraw code at all - ok, I'll remove(or make optional) all DDraw references. I'll make it all D3D. Everybody states D3D will run faster, but in my framework it won't just for one interesting reason.
Now, like I said - this framework (called "Ilix") supports MDI/SDI windowing - which actually is my primary goal. More specifically, MDI applications with fast and regular (50fps) updates on all their children windows. Something like my software "Dreamer".
In DirectDraw I actually clip both the backbuffer and frontbuffer with the currently drawn window, and when blitting to some hidden area, I get to wait just a few hundred cycles (no blitting is actually done). In Direct3D so far I see I can't do the same speedup trick. Since a picture is worth a thousand words, :



This clipping is done by DDraw. And is not present in D3D.
I came up with a (not so easy) solution for this one - I create a DirectDrawClipper, when starting drawing a window, I get the visible rectangles with it, and then on each Blt I do clipping manually.
But then I kind of wonder whether there's an easy way to update the screen, but just the dirty rectangles of the current hWnd, that are visible??


Otherwise, I finally kind of love the idea of using D3D for effects. :-D
Posted on 2005-01-27 11:43:03 by Ultrano
Have a look at:

IDirect3DDevice9::Present Method

Syntax

HRESULT Present( CONST RECT *pSourceRect,
CONST RECT *pDestRect,
HWND hDestWindowOverride,
CONST RGNDATA *pDirtyRegion )

It's a combination of the Flip and Blt methods like in directdraw7

presentation by copying only the pixels within the region, or some suitably expanded set of rectangles.
This can be an aid to optimization.
Posted on 2005-01-27 22:25:47 by Siekmanski
I can confirm that the alpha blending parameters are simply ignored in DirectDraw even if the video baord reports it as available in hardware.

I think Ultrano refers to his own drawing of the GUI windows BEFORE he uses PRESENT or FLIP to put the backbuffer on the screen.

But IF you want to use alpha blending then if the window beneeath the alpha blended one must be drawn also... if you want dynamical content.

You must be able to see the chenges in the window that is under the foreground alpha blended one?

Otherwise the solution should be a simple Z buffer.

Although i have always condsidered kind of pathetically to have to use 3D for 2D things... it must be a twisted world to ever consider such ideea in the first place :D. Since of course hardware accelerated 2D should always bee much faster than hardware accelerated 3D for 2D stuff.... but doh

I must say thay draing hardware accelerated 3D rectangles should be fast enough today. So not the window drawing speed is my concern but the drawing or things that are 2D inside the windows ... Like a huge word or text document made of thousands of letters ;) or other 2D like stuff...

This will impact severely on a 3D drawn GUI.
In a game you use only little text or 2D elements on top od 3D renders and usually one can store those into textures that rarely change... but in a general purpose GUI this in not always the case.

That is why 3D powered general purpose GUIs are not used today -- at least not widely used :P
Posted on 2005-01-27 23:28:23 by BogdanOntanu
Thanks, Siekmanski - that was just the method I needed! :) . I just finished downloading the DX9 SDK.

Now, redrawing a window is like this:


invoke StartDrawingWindow,hWnd1
; the above proc gets the RGNDATA for the hWnd1 (using an IDirectDrawClipper)
;------[ do some clipping if you want ]---\
;IlixSetBounds proto x:DWORD,y:DWORD,wid:DWORD,hei:DWORD
;IlixGetBounds proto ; !!WARNING - returns values in EAX,EBX,ECX and EDX
;IlixRestoreBounds proto
;IlixPushBounds proto
;IlixPopBounds proto
;iSetDrawOffset proto x:DWORD,y:DWORD
;---------------------------------------------/

;------[ mark dirty regions ]-----------\
; only if we shouldn't redraw it ALL
; later we'll Blt onscreen only these rectangles

;iSetWholeWindowDirty proto
invoke iAddDirtyRectangle,x,y,wid,hei
;------------------------------------------/

;------[draw with iBlt ]---------\
; iBlt automatically trims/splits rectangles to actually draw with
; a final, Blt3D()-like proc

invoke iBlt,10,10,254,354,0,0,Sprite1 ;x,y,wid,hei,srcx,srcy,pSprite
;---------------------------------/

; finalize. If all should be redrawn, this uses IDirect3DDevice9::Present
; just once, otherwise it calls the Present once for each dirty rectangle
invoke EndDrawingWindow



When drawing alpha-sprites, there can be an automated or manual preloading of background- the automation is not yet complete ^^"

Using 3D to do the 2D work - yes, it's kind of funny.. and also hard in my case (because of these speedup tricks). Anyway, I'll benchmark several ideas and decide which is best to use :). Making a game with graphics like FF6's will be possible, at least :).

Thanks, again :)
Posted on 2005-01-28 13:11:49 by Ultrano
IDirect3DDevice9::Present , about the "pDirtyRegion" argument:
"The implementation can choose to copy the whole source rectangle."

...

ouch

So, I can't just trim and update onscreen only the rectangles that have been changed - sometimes Present will show ugly monsters onscreen :roll:

Well, that can also be some good news - it saves me the iAddDirtyRectangle usage at thousands of places (though it's kind of automated with macros). (I'll just hope my customers have good videocards in the PCs they create music on. ) This also saves me from making an auto-fix of the alpha-problem that Bogdan mentioned :-D


I'll just manually do the split/trim in iBlt, to match the visible areas only. This speedup is necessary for MDI apps with dozens of windows :) .

No z-buffer, no texture/final filtering, just 16-bit color - I think several pre-GeForce cards will handle 45million texels/s :-D

And also, there was a problem with DDraw being updated at 50fps in SDI - when I move WinAmp ModernSkin in alpha-mode over my SDI window, WinAmp starts to flicker a lot - in DX9 this flicker is missing ^^ .

Some time will pass before I post the actual package , since I have some work to do beforehand - job, uni, life :)
Posted on 2005-01-29 22:59:23 by Ultrano
Afternoon, Ultrano.

You may be looking for using SetViewport to only render where you wish.

Depending upon what you're actually wanting to render, it might be an idea to have a look at SwapChains.

Cheers,
Scronty
Posted on 2005-01-30 04:05:34 by Scronty
I managed to make the DX9 Blt function, and initially thought it was running perfectly - with one Blt. But then I tried increasing the number of Blts, and ouch - my PC started crawling at more than 200 Blts ! I'm sure it's because I'm using DrawPrimitiveUP. I tried locking vertex buffers, then using DrawPrimitive - but it's absolutely the same result :( . And when drawing just with one Blt, my test program takes up 4 to 8% of the cpu . All tests are being done at 33fps .

I am yet to try using matrices.

I've uploaded the source and binaries here:
http://www.ultrano.com/chaos/IlixHuh.zip
Posted on 2005-02-01 17:35:42 by Ultrano
:-D
A preview demo - I'm a bit happy now it works perfectly for my purposes.
Description of the demo is included, as well as its srccode.
And soon you'll be able to make such MDI interfaces easily, too :alright:


http://www.ultrano.com/chaos/IlixPreview.zip
Posted on 2005-02-02 16:22:02 by Ultrano
You should absolutely never use DrawPrimitiveUP. Copy the data to your vbuffer and use index buffers where possible.
Posted on 2005-02-04 10:03:33 by defbase
The Microsoft D3D team says otherwise here.
But yes - you are right - they missed to say this "mem copy" is not RAM-RAM but RAM- VGA lock+command.

Anyway, I am totally disgusted by D3D's performance in window-mode! I reverted the project to DDraw, and I feel very fine now - Ilix now has full support for the three modes (SDI/MDI, windowgame and fullscreengame). It runs very well, when not using alphablend it takes 0.5% cpu to redraw 50 times per second 10 windows in an MDI app, 1024x768 !!! When using alphablend , it takes 1% (in 16bpp screen) up to 47% (5 large bitmaps in 32bpp screen). And there are many other plusses for using DDraw - overall, I achieve the performance I demand :-D

I'm writing the documentation to Ilix now, and meanwhile adding more, game-oriented features. Also, some tutorials for beginners in gamedev are already ready :alright: . Well, with Ilix I'm taking people away from DDraw programming - but that's only for good.
Posted on 2005-02-05 04:18:19 by Ultrano
Ultrano, since Phil left, the D3D team have been... questionable on some respects ;) Anyway it's easy to prove UP is slow - just try and render 100 simple D3DXSprites then do the same with 100 textured quads. Massive speed difference.

I am totally disgusted by D3D's performance in window-mode


In what way? Windowed mode, you're constrained to Windows desktop resolution and bitdepth, as well as refresh rate, which affects your page flipping on Present(). I recommend you stay away from DDraw and stick to D3D - even for 2D, there are major advantages. Plus when DX10 comes along, upgrading will be a nightmare.

Interested in seeing your product when it's ready.
Posted on 2005-02-05 09:00:09 by defbase
So far I haven't tried D3DXSprites :oops: . But I'll consider taking them on a testdrive when I complete the documentation . I see I can let the developer choose whether to use D3D (he'll be just specifying the flag ILIX_MODE_D3D) in StartupIlix() - all else will be done transparently and efficiently. But I'm still tempted by the speedup lpBackBuffer->SetClipper() provides :-D

Right now I am also thinking about including DSound and DInput wrappers in Ilix :) . But that'll be done after the first public release of Ilix.
DSound - for sounds (.wav) and playback of music (.mp3, .wma and .ogg - internally decompressed through ACM, I can add effects too) . DInput - for analog controllers and force-feedback (the latter only if I fix the wiring of my DualShock :( )

I'm having a lot of fun on this project :-D .
Posted on 2005-02-05 10:35:57 by Ultrano
DSound - for sounds (.wav) and playback of music (.mp3, .wma and .ogg - internally decompressed through ACM, I can add effects too)


Interesting. I can understand you wanting to do this as an all-DX exercise, but why not wrap BASS or FMOD? They are far simpler and more capable than DSound for what your target audience will probably do.
Posted on 2005-02-07 14:18:49 by defbase
I uploaded Ilix at
http://www.ultrano.com/ilix/
The documentation is not complete yet, but the demos should make clear what is what and how to use Ilix :alright:

defbase: yes, you're right, bass or fmod will be good - it's just that I haven't worked with them yet - but I know ACM well, and DirectSound - perfectly. In one of the demos I actually was too lazy to use anything ... but MCI :oops:
Ilix now supports a gamepad - but just with the joyGetxxx API :)
Anyway, I consider the code worth for showing, so go to the url above and get it ;)


btw, I found a nice link-page for 2D game developers:
http://www.ambrosine.com/resource.html
Posted on 2005-02-09 13:21:56 by Ultrano
Just a note on the development:
The following one or two weeks I will be extremely busy with my job - I have to do a lot of work , and the sooner I finish it - the higher my promotion will be. Thus, I won't be able to make the documentation in this time - and I won't be able to review any deep feedback.
Wish me luck not to experience any bugs :alright:
(oh and since I'm also a 2D/3D designer, wish me some inspiration :-D )
When I'm finally free, I'll work hard on making Ilix useful for many of the developers here ;)
Posted on 2005-02-10 13:30:43 by Ultrano
Sounding a lot like my old DX engine project, except its all 2D.
You are offering an interface to DirectX which includes a bunch of non DX yet gamedev related code (I'm guessing) - right?
Is this DLL based?
Posted on 2005-02-23 07:23:01 by Homer