PDA

View Full Version : Shading problem - faster getpixel needed



blackvoid
19-07-2004, 02:48 PM
We are developing a historical strategy game and want to use some shading on some part of the map to write text on it (general names, messages, etc). You can check it at: http://www.48.hu (it is in Hungarian, but you can have a look at the screens - Letoltes section). - We are not yet ready financially to employ someone with DirectX experience to do the engine, so we are trying to build it ourselves (us means a Delphi programmer plus me, we are fine with Delphi but very little experience in DirectX).

We use Delphix and Delphi 5.0. We also use TurboPixels from turbo.gamedev.net

Our shading routine (darkens a rectangular area) looks like this:

procedure TGamesForm.Arnyek(kx, ky, vx, vy: integer);
var i,j:integer;
color:cardinal;
begin
turbolock(DXDraw.Surface);
for i:=kx to kx+vx do begin
for j:=ky to ky+vy do begin
color:=turbogetpixel16(i,j);
turboSetPixel16rgb(i,j, r16(color) div 2, g16(color) div 2, b16(color) div 2);
end;
end;
end;
turbounlock;
end;

R16, G16 and B16 calculate the RGB colors individually.
It looks very nice, but unfortunately it also results a BIG framerate hit. We tried to replace the content of the inner loop with this:

if (i+j) mod 2 =0 then begin
turboSetPixel16RGB(i,j, R_ARNYEK, G_ARNYEK, B_ARNYEK);

This also achieves shading without a significant framerate hit by drawing the color ARNYEK on every other pixel. However this is MUCH uglier.

It seems that what slows us down is turbogetpixel16:

function turboGetPixel16(const x, y: Integer): cardinal;
begin
result := 0;
if (X < 0) or (X > xmax) or // Clip to DelphiX Surface
(Y < 0) or (Y > ymax) then Exit;
result := pword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
y * LockedSurfaceDesc.lpitch + x * 2)^;
end;

Is there any way to speed this up?

I read a lot of threads on this forum, but did not get much closer. I tried to change our DxDraw surface to system memory, but that resulted in an even worse framerate hit.

And some other questions:
1. How easy would it be to transfer our project to PowerDraw and what would be the benefits?
2. We use the procedure textout for the text functions (seems good enough so far). Would it be much faster to use a bitmap font and TurboPixel (or some other tool)?


Thanks,

BlackVoid (Bulcsu Varhegyi)
Designer/Developer
HydroGame

Harry Hunt
19-07-2004, 05:53 PM
One thing you should definitely try is to embed any code that accesses the surface memory into your code. The big problem with the GetPixel function is that you can pass any X and Y coordinates to it but your routine will only work on a small part of the surface. The GetPixel routine therefore performs multiplications that wouldn't be necessary if you'd embed the code into your own routine. (You only need to do multiplications after each line. To move from pixel to pixel, all you need to do is add 2 to your pointer).
What I believe is more costly than GetPixel is the calculations you make to shade the pixels. You might be able to optimize that a bit by using shifts instead of divisions or by using assembler.
Another idea would be to use a 32 bit color mode instead of a 16 bit color mode because if you modify color values in 16 bit mode, that will generally require some sort of processing whereas in 32 bit mode, this wouldn't be necessary.

As far as I know, PowerDraw uses Direct3D for drawing graphics. This will make many things faster but in general, surface pixel access does not benefit from 3D acceleration.

blackvoid
19-07-2004, 09:18 PM
Thanks for the quick reply!

We will try the embedding plus do the calculation only per line.

I have tested only the getpixel part without any calculation and shading and that was also slow. This leads me that this slows us down.

Also TurboPixel only works on 24 bit, how can I get pixel color on 32 bit? (is there a function for this in Delphi that works on DD surface?)

Harry Hunt
20-07-2004, 06:30 AM
You should use 32 bit color mode because many modern graphics cards don't support 24 bit color modes anymore. Both 24 bit color mode and 32 bit color mode use one byte per color component. 32 bit color mode uses an extra byte for alpha blending which however is not directly supported by DirectDraw.
Modifying the TurboPixel code to work with 32 bits shouldn't be a big deal.


result := pword(integer(LockedSurfaceDesc.lpsurface) + // surface pointer
y * LockedSurfaceDesc.lpitch + x * 4)^;

I believe adding 4 to the surface pointer instead of 3 will do the trick. I'm quite sure you won't have to change the way you compose your color values, so simply try the above.

Harry Hunt
22-07-2004, 01:45 PM
If you post in multiple forums it's a good idea to post links. That way, nobody will post something that has already been posted by someone else before...


http://www.gamedev.net/community/forums/topic.asp?topic_id=257872

blackvoid
17-09-2004, 07:45 AM
Guys, thanks for all the answers.

In the end we went with a colored grid for shading effect. It looks quite good and does not affect framerate.