Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: WILL's Custom sdlutils.pas Modification

  1. #1
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    WILL's Custom sdlutils.pas Modification

    Savage requested that I post this so here is the entire sdlutils.pas file. It's based off the 1.0 Beta release of JEDI-SDL.

    New things added:

    - Precalculated Commonly used trig values
    - Precalculated Trig Tables [size=9px](negative and possitive values)[/size]
    - New Draw Functions [size=9px](SDL_RotateDeg_Alpha, SDL_DrawCircle, SDL_DrawLine_Alpha, SDL_PutPixel_Alpha, SDL_DrawRect, SDL_DrawRect_Alpha, SDL_DrawFillRect_Alpha)[/size]
    - A few minor optimizations, tweeks & enhancements

    sdlutils_will01.zip (18 KB)
    Jason McMillen
    Pascal Game Development
    Co-Founder





  2. #2

    WILL's Custom sdlutils.pas Modification

    Neat, thanks WILL
    It would be nice if it was Ellipse and not Circle, and even harder add thickens to the Lines/Circle/Etc.
    I wrote it a while back but I was very disappointed with it.. (there were gaps)
    [size=9px]BEGIN GEEK CODE BLOCK
    <br />d s-- : a24 GB GCS GTW GE C++ P L+ W++ N+ K- w++++ M- PS+ PE+ Y- t+ 5+++ X+ R*
    <br />tv b+ DI++ D+ e++ h+ G-
    <br />END GEEK CODE BLOCK[/size]
    <br />Create your own GeekCode block at: <a href="">...</a>

  3. #3
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    WILL's Custom sdlutils.pas Modification

    All my modifications are shown within "{Added/Modified by WILL}" comments. I believe all the "Jason" stuff is added by the other guy.

    Ah... well the circle is obviously a much easier to draw in a speedy way. (I'm not sure if I'm using the best method here though.)

    Why not contribute your own Ellipse function? I'm sure that there is a ton of docs out there on how to do it.
    Jason McMillen
    Pascal Game Development
    Co-Founder





  4. #4

    WILL's Custom sdlutils.pas Modification

    I tried to make a set with line “thickens”, I wasn’t able to make it satisfactory
    The make it look full/good I overdrawn, making it slow and without it there were pixels missing.
    [size=9px]BEGIN GEEK CODE BLOCK
    <br />d s-- : a24 GB GCS GTW GE C++ P L+ W++ N+ K- w++++ M- PS+ PE+ Y- t+ 5+++ X+ R*
    <br />tv b+ DI++ D+ e++ h+ G-
    <br />END GEEK CODE BLOCK[/size]
    <br />Create your own GeekCode block at: <a href="">...</a>

  5. #5
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    SDL_RotateDeg_AddAlpha

    I figured that this would be the best place to post this as it relates to my own sdlutils.pas added draw functions.

    In my Cyber-Crisis post I was trying to do an explosion effect and needed a function that would allow me to take a texture and rotate, ADD, scale and fade all at once. It seems that even with my added functions, JEDI-SDL just doesn't cut the mustard. :?

    So I went looking for the best way I could at least work my way to such a function. I came to my own [size=9px](as yet un-added)[/size] SDL_RotateDeg_Alpha() function. It was the only one to allow mor than one effect at once. Rotate and Alpha. I figured I'd start with changing simple Alpha to Add with the ability to adjust the level for fading.

    This is the result:
    [pascal]procedure SDL_RotateDeg_AddAlpha(DstSurface, SrcSurface: PSDL_Surface; SrcRect: PSDL_Rect;
    DestX, DestY, OffsetX, OffsetY: Integer; Angle: Integer;
    Alpha: UInt;
    var
    aSin, aCos: Single;
    MX, MY, DX, DY, NX, NY, SX, SY, OX, OY, Width, Height, TX, TY, RX, RY, ROX, ROY: Integer;
    SrcColor, DstColor: UInt32;
    srcRR, srcGG, srcBB, dstRR, dstGG, dstBB: UInt8;
    TempTransparentColour: UInt32;
    MAXX, MAXY: Integer;
    begin
    // Rotate the surface to the target surface.
    TempTransparentColour := SrcSurface.format.colorkey;

    maxx := DstSurface.w;
    maxy := DstSurface.h;
    aCos := degCOS[Angle];
    aSin := degSIN[Angle];

    Width := round(abs(srcrect.h * acos) + abs(srcrect.w * asin));
    Height := round(abs(srcrect.h * asin) + abs(srcrect.w * acos));

    OX := Width shr 1;
    OY := Height shr 1;
    MX := (srcRect.x + (srcRect.x + srcRect.w)) shr 1;
    MY := (srcRect.y + (srcRect.y + srcRect.h)) shr 1;
    ROX := (-(srcRect.w shr 1)) + Offsetx;
    ROY := (-(srcRect.h shr 1)) + OffsetY;
    Tx := ox + round(ROX * aSin - ROY * aCos);
    Ty := oy + round(ROY * aSin + ROX * aCos);
    SX := 0;
    for DX := DestX - TX to DestX - TX + (width) do
    begin
    inc(SX);
    SY := 0;
    for DY := DestY - TY to DestY - TY + (Height) do
    begin
    if ((DX > 0) and (DX < MAXX)) and
    ((DY > 0) and (DY < MAXY)) then
    begin
    RX := SX - OX;
    RY := SY - OY;
    NX := mx + Round(RX * aSin + RY * aCos); //
    NY := my + Round(RY * aSin - RX * aCos); //

    if (NX >= srcRect.x) and (NX <= srcRect.x + srcRect.w) then
    begin
    if (NY >= srcRect.y) and (NY <= srcRect.y + srcRect.h) then
    begin
    SrcColor := SDL_GetPixel(SrcSurface, NX, NY);
    if (SrcColor <> TempTransparentColour) then
    begin
    SDL_GetRGB(SrcColor, SrcSurface.format, @srcRR, @srcGG, @srcBB);


    SDL_AddPixel(DstSurface, DX, DY,
    SDL_MapRGB(DstSurface.format,
    (Alpha * srcRR) shr 8,
    (Alpha * srcGG) shr 8,
    (Alpha * srcBB) shr );
    end;
    end;
    end;
    end;
    inc(SY);
    end;
    end;
    end;[/pascal]

    Works fairly well and the effect looks nice too. But there are two things that really bother me about both of these functions still.

    1) It's slow! Stick try to use this function in your game loop and you'll notice the FPS drop.

    2) That darn border around where the texture's edge is.


    I'd like to find a way to improve (1) and remove (2) for both these functions. Anyone capable willing to lend some time to this?
    Jason McMillen
    Pascal Game Development
    Co-Founder





  6. #6

    WILL's Custom sdlutils.pas Modification

    If the games is 2D you may want to pre-render the rotations ( maybe 8 or 12 frames ) and maybe even the scaling as well. Then at run-time all you would need to do is ADD and FADE the textures.

    Doing 2 for loops and some SDL_AddPixel or any other Pixel level operation will get slower the bigger the texture gets.

    Pre-rendering may take up more memory, but should give you a few extra clock cycles, I think. Or you could switch to using OpenGL for your 2D game where Rotating, Adding, Fading and Scaling are almost free.
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  7. #7
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    WILL's Custom sdlutils.pas Modification

    You know whats funny though? The function that uses Add instead of Alpha is actually a bit quicker. I believe that has a great deal to do with the fact that there is less calculations and only 1 GetPixel command called.

    We'll I'd be glad to toss in some OpenGL stuff to do all of the messy stuff in hardware, but I'd probably need a few pointers on how I'd go about that.

    Also, I think I can take off a bit more wasted ticks off of this function. At least enough to make this function a bit more manageable for use in the library it's self.
    Jason McMillen
    Pascal Game Development
    Co-Founder





  8. #8

    WILL's Custom sdlutils.pas Modification

    Hi!

    I've only had a look at SDL, and I've never really used it, but here are few ideas how could speed-up your function:


    1) If SDL had someting like SDL_GetPixels(source_surface, source_rect, memory_buffer_1), then you could do all transformations in memory and after that you call SDL_AddPixels(dest_surface, dest_rect, memory_buffer_2).


    2) Try avoiding floating operations. For example, you can do something like:

    aSin, aCos: Longint

    aCos := Round (degCOS[Angle] * 1024);
    aSin := (degSIN[Angle] * 1024);

    And then you do

    NX := mx + (RX * aSin + RY * aCos) shr 10;
    NY := my + (RY * aSin - RX * aCos) shr 10;


    3) You should put

    if ((DX > 0) and (DX < MAXX)) and
    ((DY > 0) and (DY < MAXY)) then

    outside the loop - you first find limits for DX and DY, and then you loop between them.


    4) Little trick: Change

    if (NX >= srcRect.x) and (NX <= srcRect.x + srcRect.w) then

    to

    if (UInt32(NX - srcRect.x) <= UInt32(srcRect.w)) then

    Also do the same with NY.


    5) You can completely avoid SX and SY from your calculations:
    SX := 0 -> RX := -OX
    Inc(SX) -> Inc(RX)
    SY := 0 -> RY := -OY
    Inc(SY) -> Inc(RY)


    Well, those are few thoughts that come to my mind. Hope they will help


    Best regards
    Alexa
    blog: http://alexionne.blogspot.com/

  9. #9

    WILL's Custom sdlutils.pas Modification

    I make extensive use of the AddBlit, Subtraction Blit, Add Rotate, Subtract Rotate functions in JEDI-SDL.. any speed increases in these would be greatly appreciated.

    'm using some 386asm versions too.. from a while back. Do they still exist in JEDI-SDL?

    I get fairly good performance with small sprites, but I could always use optimisations to these commonly called functions as things do slow down when there are lots of spinning particles on screen.

  10. #10
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    WILL's Custom sdlutils.pas Modification

    alexione: Thanks a ton! I've managed to incorporate a few of these already.

    Jason F.: I'll try. Whats the version of JEDI-SDL files you are currently using? I'm using sort of a hybrid of my 0.5 modifications (sdlutils.pas file only) with JEDI-SDL 1.0 Beta


    After working with these a bit, here are the functions as they exist right now.

    SDL_RotateDeg_AddAlpha();
    [pascal]procedure SDL_RotateDeg_AddAlpha(DstSurface, SrcSurface: PSDL_Surface; SrcRect: PSDL_Rect;
    DestX, DestY, OffsetX, OffsetY: Integer; Angle: Integer;
    Alpha: UInt;
    var
    aSin, aCos: Single;
    MX, MY, DX, DY, NX, NY, OX, OY, Width, Height, TX, TY, RX, RY, ROX, ROY: Integer;
    startDX, endDX, startDY, endDY: Integer;
    SrcColor, DstColor: UInt32;
    srcRR, srcGG, srcBB: UInt8;
    TempTransparentColour: UInt32;
    MAXX, MAXY: Integer;
    begin
    // Rotate the surface to the target surface.
    TempTransparentColour := SrcSurface.format.colorkey;

    maxx := DstSurface.w;
    maxy := DstSurface.h;
    aCos := degCOS[Angle];
    aSin := degSIN[Angle];

    Width := Round(abs(srcrect.h * aCos) + abs(srcrect.w * aSin));
    Height := Round(abs(srcrect.h * aSin) + abs(srcrect.w * aCos));

    OX := Width shr 1;
    OY := Height shr 1;
    MX := (srcRect.x + (srcRect.x + srcRect.w)) shr 1;
    MY := (srcRect.y + (srcRect.y + srcRect.h)) shr 1;
    ROX := (-(srcRect.w shr 1)) + Offsetx;
    ROY := (-(srcRect.h shr 1)) + OffsetY;
    Tx := ox + round(ROX * aSin - ROY * aCos);
    Ty := oy + round(ROY * aSin + ROX * aCos);
    RX := -OX;

    startDX := DestX - TX;
    if (startDX <= 0) then
    begin
    RX := RX + 1 - startDX;
    startDX := 1;
    end;

    endDX := DestX - TX + Width;
    if (endDX >= MAXX) then endDX := MAXX - 1;

    for DX := startDX to endDX do
    begin
    inc(RX);
    RY := -OY;

    startDY := DestY - TY;
    if (startDY <= 0) then
    begin
    RY := RY + 1 - startDY;
    startDY := 1;
    end;

    endDY := DestY - TY + Height;
    if (endDY >= MAXY) then
    endDY := MAXY - 1;

    for DY := startDY to endDY do
    begin
    NX := mx + Round(RX * aSin + RY * aCos); //
    NY := my + Round(RY * aSin - RX * aCos); //

    if (UInt32(NX - srcRect.x) <= UInt32(srcRect.w)) then
    begin
    if (UInt32(NY - srcRect.y) <= UInt32(srcRect.h)) then
    begin
    SrcColor := SDL_GetPixel(SrcSurface, NX, NY);
    if (SrcColor <> TempTransparentColour) then
    begin
    SDL_GetRGB(SrcColor, SrcSurface.format, @srcRR, @srcGG, @srcBB);

    SDL_AddPixel(DstSurface, DX, DY,
    SDL_MapRGB(DstSurface.format,
    (Alpha * srcRR) shr 8,
    (Alpha * srcGG) shr 8,
    (Alpha * srcBB) shr );
    end;
    end;
    end;
    inc(RY);
    end;
    end;
    end;[/pascal]

    SDL_RotateDeg_Alpha();
    [pascal]procedure SDL_RotateDeg_Alpha(DstSurface, SrcSurface: PSDL_Surface; SrcRect: PSDL_Rect;
    DestX, DestY, OffsetX, OffsetY: Integer; Angle: Integer;
    Alpha: UInt;
    var
    aSin, aCos: Single;
    MX, MY, DX, DY, NX, NY, OX, OY, Width, Height, TX, TY, RX, RY, ROX, ROY: Integer;
    startDX, endDX, startDY, endDY: Integer;
    SrcColor, DstColor: UInt32;
    srcRR, srcGG, srcBB, dstRR, dstGG, dstBB: UInt8;
    TempTransparentColour: UInt32;
    MAXX, MAXY: Integer;
    begin
    // Rotate the surface to the target surface.
    TempTransparentColour := SrcSurface.format.colorkey;

    maxx := DstSurface.w;
    maxy := DstSurface.h;
    aCos := degCOS[Angle];
    aSin := degSIN[Angle];

    Width := Round(abs(srcrect.h * aCos) + abs(srcrect.w * aSin));
    Height := Round(abs(srcrect.h * aSin) + abs(srcrect.w * aCos));

    OX := Width shr 1;
    OY := Height shr 1;
    MX := (srcRect.x + (srcRect.x + srcRect.w)) shr 1;
    MY := (srcRect.y + (srcRect.y + srcRect.h)) shr 1;
    ROX := (-(srcRect.w shr 1)) + Offsetx;
    ROY := (-(srcRect.h shr 1)) + OffsetY;
    Tx := ox + round(ROX * aSin - ROY * aCos);
    Ty := oy + round(ROY * aSin + ROX * aCos);
    RX := -OX;

    startDX := DestX - TX;
    if (startDX <= 0) then
    begin
    RX := RX + 1 - startDX;
    startDX := 1;
    end;

    endDX := DestX - TX + Width;
    if (endDX >= MAXX) then endDX := MAXX - 1;

    for DX := startDX to endDX do
    begin
    inc(RX);
    RY := -OY;

    startDY := DestY - TY;
    if (startDY <= 0) then
    begin
    RY := RY + 1 - startDY;
    startDY := 1;
    end;

    endDY := DestY - TY + Height;
    if (endDY >= MAXY) then
    endDY := MAXY - 1;

    for DY := startDY to endDY do
    begin
    NX := mx + Round(RX * aSin + RY * aCos); //
    NY := my + Round(RY * aSin - RX * aCos); //

    if (UInt32(NX - srcRect.x) <= UInt32(srcRect.w)) then
    begin
    if (UInt32(NY - srcRect.y) <= UInt32(srcRect.h)) then
    begin
    SrcColor := SDL_GetPixel(SrcSurface, NX, NY);
    if (SrcColor <> TempTransparentColour) then
    begin
    SDL_GetRGB(SrcColor, SrcSurface.format, @srcRR, @srcGG, @srcBB);

    DstColor := SDL_GetPixel(DstSurface, DX, DY);
    SDL_GetRGB(DstColor, DstSurface.format, @dstRR, @dstGG, @dstBB);

    SDL_PutPixel(DstSurface, DX, DY,
    SDL_MapRGB(DstSurface.format,
    (Alpha * (srcRR - dstRR)) shr 8 + dstRR,
    (Alpha * (srcGG - dstGG)) shr 8 + dstGG,
    (Alpha * (srcBB - dstBB)) shr 8 + dstBB));
    end;
    end;
    end;
    inc(RY);
    end;
    end;
    end;[/pascal]


    Notes on alexione's Suggestions:

    I was able to incorporate (4) + (5) without any trouble at all. (3) caused a small issue with the offset of the image's dst orientation until I factored in RX and RY into it. Works fine now. (1) I didn't fully understand... I think I need it explained to me in detail. And (2) I understand, but haven't been able to properly incorporate it without major issues [size=9px](the function stops working all together so far)[/size]

    Overall you actually notice a small bit or an improvement. Testing with about 11 60x60 textures you get about 3-5 frames difference. [size=9px](on top of whats already in my game engine: background+2 tile layers+2 sprites+3 lines of rastered font text)[/size] But I think with (2) implimented I can squeeze a bit more.


    There is one thing I'd like to try... and thats to replace SDL_AddPixel in form SDL_RotateDeg_AddAlpha() to try and optimize the calculation of the RGB values. Something I noticed was that the most intensive part of both of these functions is the calculation of the new color. And here I'm trying to do 2 sets of calculations instead of just one.


    Here is the existing SDL_AddPixel(); function:
    [pascal]procedure SDL_AddPixel( DstSurface : PSDL_Surface; x : cardinal; y : cardinal; Color :
    cardinal );
    var
    SrcColor : cardinal;
    Addr : cardinal;
    R, G, B : cardinal;
    begin
    if Color = 0 then
    exit;
    with DstSurface^ do
    begin
    Addr := cardinal( Pixels ) + y * Pitch + x * format.BytesPerPixel;
    SrcColor := PUInt32( Addr )^;
    case format.BitsPerPixel of
    8 :
    begin
    R := SrcColor and $E0 + Color and $E0;
    G := SrcColor and $1C + Color and $1C;
    B := SrcColor and $03 + Color and $03;
    if R > $E0 then
    R := $E0;
    if G > $1C then
    G := $1C;
    if B > $03 then
    B := $03;
    PUInt8( Addr )^ := R or G or B;
    end;
    15 :
    begin
    R := SrcColor and $7C00 + Color and $7C00;
    G := SrcColor and $03E0 + Color and $03E0;
    B := SrcColor and $001F + Color and $001F;
    if R > $7C00 then
    R := $7C00;
    if G > $03E0 then
    G := $03E0;
    if B > $001F then
    B := $001F;
    PUInt16( Addr )^ := R or G or B;
    end;
    16 :
    begin
    R := SrcColor and $F800 + Color and $F800;
    G := SrcColor and $07C0 + Color and $07C0;
    B := SrcColor and $001F + Color and $001F;
    if R > $F800 then
    R := $F800;
    if G > $07C0 then
    G := $07C0;
    if B > $001F then
    B := $001F;
    PUInt16( Addr )^ := R or G or B;
    end;
    24 :
    begin
    R := SrcColor and $00FF0000 + Color and $00FF0000;
    G := SrcColor and $0000FF00 + Color and $0000FF00;
    B := SrcColor and $000000FF + Color and $000000FF;
    if R > $FF0000 then
    R := $FF0000;
    if G > $00FF00 then
    G := $00FF00;
    if B > $0000FF then
    B := $0000FF;
    PUInt32( Addr )^ := SrcColor and $FF000000 or R or G or B;
    end;
    32 :
    begin
    R := SrcColor and $00FF0000 + Color and $00FF0000;
    G := SrcColor and $0000FF00 + Color and $0000FF00;
    B := SrcColor and $000000FF + Color and $000000FF;
    if R > $FF0000 then
    R := $FF0000;
    if G > $00FF00 then
    G := $00FF00;
    if B > $0000FF then
    B := $0000FF;
    PUInt32( Addr )^ := R or G or B;
    end;
    end;
    end;
    end;[/pascal]
    Jason McMillen
    Pascal Game Development
    Co-Founder





Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •