PDA

View Full Version : Slow when drawing the Map into another surface



nildo
28-11-2006, 12:39 PM
Hello!

I am having a problem with my game. When you press TAB, I draw into the DxDraw a new surface showing the map (just some squares in ISO format, showing the colision points). This new surface I draw using DrawAdd to add it to the main surface with alpha-blending of 100. But this slows down everything. I get something like 1 frame per second. Is there any workarround for this, or sugestions?

This new surface is the same width and height of the main DxDraw

Thank you!

WILL
28-11-2006, 01:56 PM
Hi nildo, welcome to PGD! :)

What version of UnDelphiX (or DelphiX) are you using?

HopeDagger
28-11-2006, 01:56 PM
I draw into the DxDraw a new surface showing the map (just some squares in ISO format, showing the colision points). This new surface I draw using DrawAdd to add it to the main surface with alpha-blending of 100. But this slows down everything. I get something like 1 frame per second. Is there any workarround for this, or sugestions?

DrawAdd draws an image with additive blending, which I thing you interpreted as being something else. To draw on the new surface normally, just use the regular Draw method. (Unless of course you want additive blending on the new surface?)

As a general note: The reason DrawAdd is so slow is because it has to do the blending manually (ie. software-based), since DelphiX uses (DirectDraw) software-rendering. Try to avoid blending routines in general with DelphiX unless you're using them with smaller images.

EDIT: Oh hey! Welcome to PGD, too. ;)

nildo
28-11-2006, 02:01 PM
DrawAdd draws an image with additive blending, which I thing you interpreted as being something else. To draw on the new surface normally, just use the regular Draw method. (Unless of course you want additive blending on the new surface?)

As a general note: The reason DrawAdd is so slow is because it has to do the blending manually (ie. software-based), since DelphiX uses (DirectDraw) software-rendering. Try to avoid blending routines in general with DelphiX unless you're using them with smaller images.

EDIT: Oh hey! Welcome to PGD, too. ;)

Thanx for the Welcome!! :)

What do you sugest for me to show de map of the area? I was pretending to draw it with alpha blending on the screen, with the colision blocks, NPCs and Players (isometric 2d mmorpg game).

Legolas
28-11-2006, 02:41 PM
You may switch to Jicro's UnDephiX (http://www.micrel.cz/Dx/), that should have a sort of hardware acceleration

nildo
28-11-2006, 02:56 PM
You may switch to Jicro's UnDephiX (http://www.micrel.cz/Dx/), that should have a sort of hardware acceleration

Is his units workarrounded with the latest unDelphiX units?

nildo
28-11-2006, 03:19 PM
You may switch to Jicro's UnDephiX (http://www.micrel.cz/Dx/), that should have a sort of hardware acceleration

Is his units workarrounded with the latest unDelphiX units?

I have changed to his units but it seems not to work propertly. My World editor stopped working like it needs to be.. (the Draw passing the Surface does not works correctly).

WILL
28-11-2006, 03:27 PM
Jicro has taken over UnDelphiX in all it's unofficial glory. :) It's the most current version and is considered to be the 'as official as we're gonna get' version of the old DelphiX. :)

nildo
28-11-2006, 03:30 PM
Jicro has taken over UnDelphiX in all it's unofficial glory. :) It's the most current version and is considered to be the 'as official as we're gonna get' version of the old DelphiX. :)

Strange... I could not get the DRAW to work correctly with his units... Perhaps you can help me?


procedure TDrawEngine.ApplyDraw(Sender: TObject; LagCount: Integer);
var
nAux: Integer;
begin
// Pinta o fundo
Surface.Fill(clBlack);

// Requisita pintura das layers
for nAux := 0 to High( FLayers ) do
begin
// Se a layer estiver vis??vel
if FLayers[ nAux ].Visible then
begin
// Requisita pintra
FLayers[ nAux ].RequestDraw;

// Desenha a layer
Surface.Draw( 0, 0, Surface.ClientRect, FLayers[ nAux ].Surface, False );
end;
end;

// Se tem que desenhar a grid, desenha
if FShowGrid then
DrawTheGrid;

// Se tem que desenhar os numeros, desenha
if FShowNumbers then
DrawTheNumbers;

// Desenha um ret?˘ngulo onde o mouse est?°, dependendo do tipo
case UsingTool of
utColision: DrawMouseSquare( clRed );
utTerrain : DrawMouseSquare( clYellow );
end;

// Desenha os Frames Por Segundo
DrawFPS;

// Applica as altera?ß?µes
Surface.Canvas.Release;
Flip;
end;


this line: Surface.Draw is not working. Or it's working, but the layer surface does not get's to the main surface

HopeDagger
28-11-2006, 03:32 PM
What do you sugest for me to show de map of the area? I was pretending to draw it with alpha blending on the screen, with the colision blocks, NPCs and Players (isometric 2d mmorpg game).

Blending is going to be slow with DelphiX; no real way around that. Others here are suggesting UnDelphiX, which I have no experience with, but if it can do the hardware blending you need, then it sounds like a good direction to head in. :)

(Omega (http://turbo.gamedev.net/omega.asp) is a fantastic hardware-accelerated Delphi game/graphics lib, too!)

WILL
28-11-2006, 03:58 PM
I unfortunately don't have a copy of Delphi here so I can't check this out right now, but your code looks ok to me.

It's likely a small change in the TCanvas.Release behavior. The function runs, but it does not show it being drawn, correct?

I should think that Jicro has put some kind of information about changes in versions. I recommend looking for new document/text files or checking the readme as blasphemous as that is. :)

It's likely to be something small, yet probably worth documenting. UnDelphiX is a good branch of DelphiX and with the hardware acceleration will do the job much nicer while keeping with the visual components you are used to.


Sorry I can't be of much more help, but I'm at work and unable to do much OP work at the moment. :P

savage
28-11-2006, 04:36 PM
If all you are displaying is an overlay type Map, you can fake dithered effect by making every 2nd pixel on your overlay Map transparent.

nildo
28-11-2006, 04:57 PM
If all you are displaying is an overlay type Map, you can fake dithered effect by making every 2nd pixel on your overlay Map transparent.

Hmmm I prefer using Hardware accelerating than this! Anyway, making this kind of transparency will get slow too.

I'll check his docs to see what has changed! I looked into the demos and they are pretty nice!

nildo
28-11-2006, 05:39 PM
Jicro has taken over UnDelphiX in all it's unofficial glory. :) It's the most current version and is considered to be the 'as official as we're gonna get' version of the old DelphiX. :)

It is showing the new layer!!!!! but... strange... the Polygon function does not takes visual effects :S

nildo
28-11-2006, 06:15 PM
Jicro has taken over UnDelphiX in all it's unofficial glory. :) It's the most current version and is considered to be the 'as official as we're gonna get' version of the old DelphiX. :)

It is showing the new layer!!!!! but... strange... the Polygon function does not takes visual effects :S

I know what's happening!!!!!!!

Can someone please help me with this? The DRAW of the new surface only takes effect when I resize my form ( :? )

EDIT: Using BltFast instead of DRAW works perfectly... But I need to use the DRAWADD instead of BltFast :(

WILL
28-11-2006, 07:07 PM
Patience my friend. ;) Web forums take a bit of time...

PGD can be both fast or slow at times.

nildo
29-11-2006, 10:18 AM
Patience my friend. ;) Web forums take a bit of time...

PGD can be both fast or slow at times.

Hehehe As I was trying to discover what was happening I was reporting here :wink:

jasonf
29-11-2006, 12:24 PM
You may switch to Jicro's UnDephiX (http://www.micrel.cz/Dx/), that should have a sort of hardware acceleration

Is his units workarrounded with the latest unDelphiX units?

I have changed to his units but it seems not to work propertly. My World editor stopped working like it needs to be.. (the Draw passing the Surface does not works correctly).

Hmmm.. I can't seem to access this site for the latest UnDelphiX.

I wanted to update my tutorials with a URL to it. But it doesn't appear to work. This worries me somewhat. If DelphiX isn't being maintained anymore (Where is Hori?) and UnDelphiX isn't being maintained by Turbo anymore but is being maintained by different people at different places which may be unreliable, then UnDelphiX will die. At the moment it lives because it has a large fan base and a good reputation for being easy and reliable. This is a reputation which is easily broken.

...or it could be a temporary glitch. Could someone confirm though. UnDelphiX needs its own URL and site. Perhaps a SourceForge Site. But it needs somewhere central to live where it can exist for many years.. I mean, even Hori's old site is still there, unchanged after all this time.

Legolas
29-11-2006, 12:31 PM
It works fine here

nildo
29-11-2006, 12:32 PM
It works fine here

The Website or the DRAW command?

Legolas
29-11-2006, 01:13 PM
It works fine here

The Website or the DRAW command?

The web site, sorry :)

nildo
29-11-2006, 01:18 PM
Aaaaaaaaaaaaaaaaaa :( I can't make this Damm DRAW to work.... :(

Traveler
29-11-2006, 01:46 PM
The undelphix site seems to work for me.

nildo, we understand you're having some difficulties, but unless you tell us exactly what is going wrong, we can't help you.

this line: Surface.Draw is not working. Or it's working, but the layer surface does not get's to the main surface
That doesn't make a lot of sense. From the looks of it your code looks okay, but then, we're missing a lot of the whole picture. Perhaps you can tell what kind of error you're getting.

jasonf
29-11-2006, 02:22 PM
I managed to get to the site. Interesting logo :wink: Looks incredibly similar to one which I drew a few years ago... http://www.cerebral-bicycle.co.uk/images/delphix.gif... tut tut..

nildo
29-11-2006, 02:31 PM
I'll describe exatly what's happening:

I am writting the World Editor for my MMORPG. I started it last week, and now I'm writting the layer wich you define the colision map. So, my engine so far has 2 layers.

The main layer is where I draw the isometric Grid.
The second layer is where I draw the colision points to show on the screen.

Here is the initial state of my world editor, right after I open it:

http://img153.imageshack.us/img153/9092/imagem01cp0.th.png (http://img153.imageshack.us/my.php?image=imagem01cp0.png)

The next step is to define the colision points. We will use the 12¬? button to define the points. Then my World Editor Engine draws the Surface of my Colision Points Layer to the main surface. Using this line to draw:


Surface.BltFast( 0, 0, Surface.ClientRect, 0, FLayers[ nAux ].Surface ); code1

the result will be this:

http://img398.imageshack.us/img398/2893/imagem02lf2.th.png (http://img398.imageshack.us/my.php?image=imagem02lf2.png)

Yesss... Since here everything is OK!! The colision points that where draw on a new surface is there! Wuhuuu!

But that is not enought.... I wan't to draw this colision surface using alpha channel. Then I'll change the BltFast method to DrawAlpha or just Draw. Then, changing that line quoted as code1 to this, and adding the colision points:


Surface.Draw( 0, 0, Surface.ClientRect, FLayers[ nAux ].Surface );

I get the following result:

http://img88.imageshack.us/img88/9577/imagem03fo0.th.png (http://img88.imageshack.us/my.php?image=imagem03fo0.png)

Look that the colision points.. Can't see them? Yes! You can't see because the DRAW method is not doing it's job... But wait, look what happen if I resize the window, manually:

http://img466.imageshack.us/img466/7862/imagem04gt7.th.png (http://img466.imageshack.us/my.php?image=imagem04gt7.png)

The Draw only applys when I resize my window.
That's the strange problem that is happening!

Really thaaaaaaank you!

savage
29-11-2006, 02:56 PM
Have you compared the internal workings of Surface.Draw and Surface.BltFast ( stepped through the code )?

It sounds like some kind of "repaint" message is not being fired when Surface.Draw is used, while it is being fired when Surface.BltFast is used. Compare the 2 lots of code and see if there is anything major that sticks out.

Same may be the case for DrawAlaha.

WILL
29-11-2006, 03:13 PM
For all your DelphiX, UnDelphiX concerns, I highly recommend this thread (http://www.pascalgamedevelopment.com/viewtopic.php?t=3861&highlight=). ;)

nildo
29-11-2006, 03:16 PM
Have you compared the internal workings of Surface.Draw and Surface.BltFast ( stepped through the code )?

It sounds like some kind of "repaint" message is not being fired when Surface.Draw is used, while it is being fired when Surface.BltFast is used. Compare the 2 lots of code and see if there is anything major that sticks out.

Same may be the case for DrawAlaha.

The difference is big. BltFast uses this:


ISurface.BltFast(X, Y, Source.IDDSurface, @SrcRect, DWORD(Flags));

while the Draw, DrawAlpha and the others use a set of calls totally different from BltFast starting from the function D2D.D2DRenderDrawDDSXY

Traveler
29-11-2006, 04:15 PM
I have to agree with savage about the paint message not doing his job. However my knowledge of (un)delphix doesn't go far enough to help you with a solution that does work.

Unless ijcro joins the discussion some time soon, I suggest sending him a pm describing your problem. He may be able to help you out.

nildo
29-11-2006, 04:24 PM
Sent!

ijcro
29-11-2006, 07:23 PM
OK I will see it.

nildo
29-11-2006, 07:27 PM
OK I will see it.

If you'd like I have written a simple example problem reproduction:


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DXClass, DXDraws, StdCtrls;

type
TForm1 = class(TForm)
dd1: TDXDraw;
DXTimer1: TDXTimer;
rb1: TRadioButton;
RadioButton1: TRadioButton;
procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
procedure dd1Initialize(Sender: TObject);
procedure PrepareNewSurface;
private
newsurface: TDirectDrawSurface;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

var
nWidth: Integer = 0;
bGoing: Boolean = true;

procedure TForm1.PrepareNewSurface;
begin
newsurface.Fill( 0 );
newsurface.Canvas.Rectangle( 10, 10, 10 + nWidth, 50 );

if bGoing then
begin
Inc( nWidth, 3 );

if nWidth = newsurface.Width - 10 then
bGoing := not bGoing;
end
else
begin
Dec( nWidth, 3 );

if nWidth <= 10 then
bGoing &#58;= not bGoing;
end;

newsurface.Canvas.Release;
end;

procedure TForm1.DXTimer1Timer&#40;Sender&#58; TObject; LagCount&#58; Integer&#41;;
begin
dd1.surface.fill&#40; 0 &#41;;
PrepareNewSurface;

if radiobutton1.Checked then
dd1.Surface.Draw&#40; 0, 0, newsurface &#41;
else
dd1.Surface.BltFast&#40; 0, 0, dd1.surface.ClientRect, 0, newsurface &#41;;

dd1.surface.canvas.release;
dd1.Flip;
end;

procedure TForm1.dd1Initialize&#40;Sender&#58; TObject&#41;;
begin
newsurface &#58;=TDirectDrawSurface.Create&#40; dd1.DDraw &#41;;
newsurface.SetSize&#40; dd1.Width, dd1.height &#41;;
end;


If I use Non-hardware acceleration (removing the [do3D] from options), it works but with software.

Thanx!

ijcro
01-12-2006, 08:00 AM
Hello!

I tried your example!

And there is my solution (you have to use version undelphi 1.07b):



unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, DXClass, DXDraws, StdCtrls;

type
TForm1 = class&#40;TForm&#41;
dd1&#58; TDXDraw;
DXTimer1&#58; TDXTimer;
doBltFast&#58; TRadioButton;
doDraw&#58; TRadioButton;
procedure DXTimer1Timer&#40;Sender&#58; TObject; LagCount&#58; Integer&#41;;
procedure dd1Initialize&#40;Sender&#58; TObject&#41;;
procedure PrepareNewSurface;
private
newsurface&#58; TDirectDrawSurface;
&#123; Private declarations &#125;
public
&#123; Public declarations &#125;
end;

var
Form1&#58; TForm1;

implementation

&#123;$R *.dfm&#125;

var
nWidth&#58; Integer = 0;
bGoing&#58; Boolean = true;

procedure TForm1.PrepareNewSurface;
begin
newsurface.Fill&#40; 0 &#41;;
newsurface.Canvas.Rectangle&#40; 10, 10, 10 + nWidth, 50 &#41;;

if bGoing then
begin
Inc&#40; nWidth, 3 &#41;;

if nWidth = newsurface.Width - 10 then
bGoing &#58;= not bGoing;
end
else
begin
Dec&#40; nWidth, 3 &#41;;

if nWidth <= 10 then
bGoing &#58;= not bGoing;
end;

newsurface.Canvas.Release;
end;

procedure TForm1.DXTimer1Timer&#40;Sender&#58; TObject; LagCount&#58; Integer&#41;;
begin
dd1.surface.fill&#40; 0 &#41;;
PrepareNewSurface;
dd1.ClearStack;
if doDraw.Checked then
dd1.Surface.Draw&#40; 0, 0, newsurface &#41;
else
dd1.Surface.BltFast&#40; 0, 0, dd1.surface.ClientRect, 0, newsurface &#41;;

dd1.surface.canvas.release;
dd1.Flip;
end;

procedure TForm1.dd1Initialize&#40;Sender&#58; TObject&#41;;
begin
newsurface &#58;=TDirectDrawSurface.Create&#40; dd1.DDraw &#41;;
newsurface.SetSize&#40; dd1.Width, dd1.height &#41;;
end;

end.



Shortly, use simple
dd1.ClearStack; for clear texture stack.

Regards

nildo
01-12-2006, 09:53 AM
First of all, thank you for the solution!
This works for Draw, but for DrawAlpha it does not work :cry:

ijcro
03-12-2006, 01:55 PM
Please, send me your demo (code) with DrawAlpha or DrawAdd, I see it!
Thanks

nildo
04-12-2006, 12:04 AM
Please, send me your demo (code) with DrawAlpha or DrawAdd, I see it!
Thanks

Just change the dd1.surface.Draw to dd1.Surface.DrawAlpha, in the same example, with an alpha of 100 for example.

Thanx

ijcro
04-12-2006, 10:00 AM
OK.

ijcro
05-12-2006, 08:12 AM
You can try this construction, but small problem with alpha is here still... :cry: sorry



procedure TForm1.DXTimer1Timer&#40;Sender&#58; TObject; LagCount&#58; Integer&#41;;
begin
dd1.surface.fill&#40;dd1.Surface.ColorMatch&#40;clBlack&#41;&#41;;
dl1.Items.Find&#40;'krecci'&#41;.StretchDraw&#40;dd1.Surface, dd1.Surface.ClientRect, 0&#41;;
PrepareNewSurface;
dd1.ClearStack;
if doDraw.Checked then
//dd1.Surface.Draw&#40; 0, 0, newsurface &#41;
dd1.Surface.Draw&#40;0, 0, newsurface.ClientRect, newsurface&#41;
else if doBlend.Checked then begin
if dd1.Surface.Lock then begin
dd1.Surface.DrawAlpha&#40;dd1.Surface.ClientRect, newSurface.ClientRect, newsurface, True, 128&#41;;
dd1.Surface.UnLock;
end;
end
else
dd1.Surface.BltFast&#40;0, 0, dd1.surface.ClientRect, 0, newsurface&#41;;

//dd1.surface.canvas.release;
dd1.Flip;
end;

ijcro
07-12-2006, 11:33 AM
I made little the analyse of problem.

Problem has two parts.
At first it is refresh of image surface.
It is not bug in unDelphiX. The concept no compute with change the picture in DDS, but prefer direct drawing. ClearStack dramatically suspend speed of drawing, I no advice it (so only for special purpose).

And second it is drawing...using DrawAlpha, DrawAdd and etc.
I think that it can be bug. I did track all the calls low level routines to DirectX and all returned with DD_OK flag (I am using last published version 1.07b). But pictures no show! This can be the same bug that picture is drawing on empty Surface. But I don't know best solution.

You can use ...

1/ technique of videotexture like Hori's sample

2/ predefined picture and draw it throught DXImageList (from one picture)

3/ directly drawing via DXDraw.Surface[.Canvas]

4/ own another technique for me unknown

Many clever and handy programmers are here.
Can anybody help us with this problem? For better unDelphiX? Thanks!