Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 26

Thread: I need some help with 2D drawing libraries

  1. #11
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    Code:
    unit jui_screen;
    
    {$mode objfpc}{$H+}
    {$i jui.inc}
    
    
    interface
    
    uses
      sysutils, SDL,
    
      SDL_Video,
    
      u_gl,
    
      JUI_const, JUI_log;
      
    type TVideoMode = record
         H : integer;
         V : integer;
         Bits : integer;
         Fullscreen : Boolean;
    end;
    
    const
    //Constant Video Mode Records, Treeitem.Data pointer asigned to these records
         Mode640_16 : TVideoMode = (H:640; V:480; Bits:24; FullScreen:false;);
         Mode640_16_FULL : TVideoMode = (H:640; V:480; Bits:24; FullScreen:true;);
         Mode640_32 : TVideoMode = (H:640; V:480; Bits:32; FullScreen:false;);
         Mode640_32_FULL : TVideoMode = (H:640; V:480; Bits:32; FullScreen:true;);
    
         Mode800_16 : TVideoMode = (H:800; V:600; Bits:24; FullScreen:false;);
         Mode800_16_FULL : TVideoMode = (H:800; V:600; Bits:24; FullScreen:true;);
         Mode800_32 : TVideoMode = (H:800; V:600; Bits:32; FullScreen:false;);
         Mode800_32_FULL : TVideoMode = (H:800; V:600; Bits:32; FullScreen:true;);
    
         Mode1024_16 : TVideoMode = (H:1024; V:768; Bits:24; FullScreen:false;);
         Mode1024_16_FULL : TVideoMode = (H:1024; V:768; Bits:24; FullScreen:true;);
         Mode1024_32 : TVideoMode = (H:1024; V:768; Bits:32; FullScreen:false;);
         Mode1024_32_FULL : TVideoMode = (H:1024; V:768; Bits:32; FullScreen:true;);
         Mode1280_32_FULL : TvideoMode = (H:1280; V:1024; Bits:32; Fullscreen:true;);
    
    
    
    
    type TJUIScreen = class
    
    public
       Width : integer;
       Height : integer;
    
       ProjectionMatrixGL : TGLMatrixd4;
       ViewPortGL : TGLVectori4;
    
       constructor create(WinTitle : shortstring; Xres,Yres,BPP : word;FullScreen : Boolean);
       destructor destroy;override;
    
    
       procedure SetOrthographic;
       procedure SetOrthographicFlipY;
       procedure SetOrthographic(x,y,awidth,aheight:integer);
       procedure SetVideomode(Vmode:TVideoMode);
    
    private
       Screen : PSDL_Surface;
       B_FullScreen : boolean;
       error : boolean;
       WindowTitle : string; //must be shortstring or string with $H-
       WindowBPP : word;
    
       procedure SetWindowTitle(Title:string);
       procedure SetupGL; //sets up 2d ortho mode
    
    published
        { Published declarations }
        property Caption: string read WindowTitle write SetWindowTitle;
    
    end;
    
    implementation
    
    constructor TJUIScreen.create(WinTitle : shortstring; Xres,Yres,BPP : word;FullScreen : Boolean);
    var
       I : integer;
       NumDrivers : integer;
       DriverName : PChar;
    begin
       NumDrivers := SDL_GetNumVideoDrivers;
       for I := 0 to NumDrivers-1 do
       begin
          DriverName := SDL_GetVideoDriver(I);
          JUILOG(self.classname,'SDL Video Driver : '+DriverName);
       end;
    
    
         JUIlog(self.classname,'Creating SDL Window...');
         error := false;
         Width := Xres;
         Height := Yres;
         WindowBPP := BPP;
    
    
         if FullScreen then
         screen := SDL_SetVideoMode(Width, Height, WindowBPP, SDL_OPENGL or SDL_ANYFORMAT or SDL_FULLSCREEN) //create the surface
         else
         screen := SDL_SetVideoMode(Width, Height, WindowBPP, SDL_OPENGL or SDL_ANYFORMAT {or SDL_NOFRAME or SDL_VIDEORESIZE}); //create the surface
    
         if not assigned(screen) then
         begin
              JUIlog(self.classname,'Couldn''t create a surface: '+SDL_GetError());
              error := true;
              exit;
         end;
         
         SetWindowTitle(WinTitle);     
         
    
         JUIlogdone;
    
    
         initopengl;
         ReadImplementationProperties;
         ReadExtensions;
    
         
         if not error then SetupGL;
         
    end;
    
    destructor TJUIScreen.destroy;
    begin
        inherited;
    end;
    
    procedure TJUIScreen.SetOrthographic;
    begin
       glViewport( 0, 0, Width, Height );
       //glGetIntegerv(GL_VIEWPORT, @viewportGL); //CALLING THIS IS *SLOW*!
       glMatrixMode( GL_PROJECTION );
       glLoadIdentity;
       glOrtho( 1, Width+1, Height+1, 1, -1.0, 1.0 );
       glmatrixmode(GL_TEXTURE);
       glloadidentity();
       glmatrixmode(GL_MODELVIEW);
       glloadidentity();
       glTranslatef(0.375, 0.375, 0.0);
    end;
    
    
    procedure TJUIScreen.SetOrthographicFlipY;
    begin
         glViewport( 0, 0, Width, Height );
        //glGetIntegerv(GL_VIEWPORT, @viewportGL); //CALLING THIS IS *SLOW*!
    
         glMatrixMode( GL_PROJECTION );
    
         glLoadIdentity;
         glOrtho( 1, Width+1, 1, Height+1, -1.0, 1.0 );
         
         glmatrixmode(GL_TEXTURE);
         glloadidentity();
    
         glmatrixmode(GL_MODELVIEW);
    
         glloadidentity();
          glTranslatef(0.375, 0.375, 0.0);
    end;
    
    procedure TJUIScreen.SetOrthographic(x,y,awidth,aheight:integer);
    begin
         glViewport( x, -y+Height-aheight, awidth, aheight ); // we flip our y coord upside down to match everything else
         //glGetIntegerv(GL_VIEWPORT, @viewportGL); //CALLING THIS IS *SLOW*!
         glMatrixMode( GL_PROJECTION );
         glLoadIdentity;
         glOrtho( 1, awidth+1, aheight+1, 1, -1.0, 1.0 );
    
         glmatrixmode(GL_TEXTURE); 
         glloadidentity();
         glmatrixmode(GL_MODELVIEW);
         glloadidentity();
          glTranslatef(0.375, 0.375, 0.0);
    
    end;
    
    
    
    
    procedure TJUIScreen.SetVideomode(Vmode:TVideoMode); // NOTE THIS DESTROYS AND RECREATES OUR OPENGL CONTEXT, ALL TEXTURES MUST BE RELOADED INCLUDING FONTS
    begin
    
              Width := vmode.H;
              Height := vmode.V;
              WindowBPP := vmode.Bits;
              B_Fullscreen := vmode.Fullscreen;
              
         //if we toggle fullscreen we MUST restore the original width and height
         if B_Fullscreen then
         begin
              screen := SDL_SetVideoMode(Width, Height, WindowBPP, SDL_OPENGL or SDL_ANYFORMAT or SDL_FULLSCREEN); //create the surface
              JUIlog(classname,'Setting FullScreen Mode - X:'+inttostr(Width) + ' Y:' + inttostr(Height)+' Depth:'+inttostr(WindowBPP));
         end else
         begin
              screen := SDL_SetVideoMode(Width, Height, WindowBPP, SDL_OPENGL or SDL_ANYFORMAT); //create the surface
              JUIlog(classname,'Setting windowmode Mode - X:'+inttostr(Width) + ' Y:' + inttostr(Height)+' Depth:'+inttostr(WindowBPP));
         end;
    
         SetWindowTitle(WindowTitle);     
         SetupGL; //this must be called because our window is destroyed and re-created, the context along with it
    end;
       
    procedure TJUIScreen.SetWindowTitle(Title:string);
    begin
         WindowTitle := Title;
         SDL_WM_SetCaption(pchar(WindowTitle),pchar(WindowTitle)); //set the window title
    end;
    
    procedure TJUIScreen.SetupGL; //this section contains all OpenGL init stuff
    var
       GlobalAmbient: array[0..3] of glFloat = (0.1, 0.1, 0.1, 1);  // Global Ambient
    
    begin
         JUIlog(classname,'Setting up OpenGL...');
    
         glEnable(GL_TEXTURE_2D);
         glEnable(GL_BLEND); 
         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    
         glClearColor(0.0, 0.0, 0.0, 1.0);
         glClearDepth(1.0); 
    
         glEnable(GL_DEPTH_TEST); // Enable Depth Buffer
         glDepthFunc(GL_LEQUAL);		
    
         glenable(GL_CULL_FACE);
         glCullFace(GL_BACK);   
     
         glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
         
    
         JUIlogdone;
    end;
    
    
    end.
    Please forgive the messy commenting, this unit is what I use for JUI. it will give you pixel perfect 2D Orthographic mode in OpenGL. load your texture when you load them as seen here :

    Code:
    function TJUITextureMan.LoadTGA(FileName : string;TextureID : integer):glint;
    var
      // Create storage space for the texture
      NewTextureID : GLint;
      texture : TTGAImage;
      x : integer;
      done : boolean;
    begin
         done := false;
         if fileexists(filename) then
         begin
              //this ensures existing textures dont get reloaded
              for x := 0 to Available do
             if lowercase(Textures[x].filename) = lowercase(Filename) then
             begin
                  done := true;
                  result := Textures[x].ID;
             end;
    
             if not done or reloadingtextures then
             begin
              texture := TTGAImage.create;
             texture.LoadFromFile(FileName);
    
            NewTextureID := GetNewTextureID(filename,TextureID);
    
            glBindTexture(GL_TEXTURE_2D, NewTextureID);
    
            // Generate The Texture
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // ( NEW )
              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // ( NEW )
    
            texture.BGRtoRGB;
    
            glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
             glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
             
    
              gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,texture.header.imgspec.width,
            texture.header.imgspec.height, GL_RGBA, GL_UNSIGNED_BYTE,
            texture.Data);
    
            Result := NewTextureID;
            texture.free;
            end;
        end else result := -1;
    end;
    All I can say is that it works perfectly for me.

    ensure that whatever QUAD your mapping your texture to is the same size as the texture itself plus both +1 to the width and +1 to the height.

    with the glTranslatef(0.375, 0.375, 0.0); you ensure that texture pixels are perfectly centered.

    if you are getting distortion in the texture, it's probably because you're mapping it to a quad and have not added the pixel. I'm not sure why, I never bothered to find out, but it's somthing to do with the OpenGL rasterizer.

    anyway, it's 0.375 because that value works for both ATI and Nvidia implementations, I've tested it extensivley, trust me
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  2. #12
    phibermon
    Too strange solution for me. I have never heard about it and never get problems with mine standard render code... Something like that(with half-pixel offset) I use only in mine Direct3D render.

  3. #13
    Quote Originally Posted by phibermon View Post
    glTranslatef(0.375, 0.375, 0.0);

    That is the most important line of code for 2D opengl. disable mipmapping/filtering on textures. All coordinates as integers.

    pixel perfect 2D. perfect for fonts and sprites
    That shouldn't be the case... There was time when different graphics cards drew with a little different coordinates but i think modern cards know better to do it from 0,0.

    If you draw a quad that fills the screen the coordinates are:
    0,0-Width,Height
    Do you see why it's not Width-1, Height-1? The same reason that if you want to draw a quad that fills 1 pixel only.
    To show a pixel at 5,5 use quad coordinates 5,5 - 6,6. (Or use GL_POINTS at 5.5, 5.5)

    But if you want to draw a GL_LINE on right edge:
    (width-0.5, 0.5) - (width-0.5, height-0.5)
    Because center of pixel is 0.5, 0.5.
    A sprite for example wants to utilize the whole pixel so it starts from 0,0.

  4. #14
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    I got it from the OpenGL red-book... And I quote :

    "An optimum compromise that allows all primitives to be specified at integer positions, while still ensuring predictable rasterization, is to translate x and y by 0.375, as shown in the following code fragment. Such a translation keeps polygon and pixel image edges safely away from the centers of pixels, while moving line vertices close enough to the pixel centers."

    But if you want to add 0.5, on the CPU, to both components of every coordinate you send, to the GPU, be my guest

    I'm no longer using immediate mode, will post if I find any problems getting unfiltered, pixel aligned fonts working under GL3 Core. (I may go down the vector font route if I can't figure out an elegant way to render bitmap fonts using shaders)
    Last edited by phibermon; 18-10-2010 at 09:36 PM.
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  5. #15

    Smile fds

    but waht is this JUI thing? ;0

  6. #16
    It's the GUI library he's working on:

    http://www.pascalgamedevelopment.com...UI-Another-GUI

    Keep in mind that we won't give you copy-pastable sollutions to your problems. The code snippet phibermon provided is from his own library and shows the way he fixed the issue. You have to study it for yourself and then try improve your own code.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  7. #17
    Quote Originally Posted by jonharkulsykkel View Post
    ok so i making a game in delphi and every frame it needs to render about 1200 16x16 images, then 1200 alpha blended pics then a dude.
    I think the problem isn't the library. You have 2401 blitting each frame, that's "too much". I'm sure you can do the same drawing less pictures.
    No signature provided yet.

  8. #18
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25
    Maybe if you tell us what all these images are for we may be able to help a bit better I think. I'm guessing it's a tiled engine? That may account for the "1200 16x16 images" in which case I must ask what your game's screen resolution with 16x16 sized sprites. So what are the 1200 alpha blended images?

    It almost seems like you are trying to swallow a whale without knowing how to... well... "fish" *ahem* pardon the expression. So lets start with what type of game it is and what gameplay features are you trying to put into it?
    Jason McMillen
    Pascal Game Development
    Co-Founder





  9. #19
    I'd go down the OpenGL path if I were you.

    So, can you provide use with a screenshot of your app. We would like to see what you are trying to do and how blurry the output actually is.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  10. #20
    What function specifically are you using in andorra? (do you mean additive blending?)
    Code:
    for i := 0 to 2400 do
    begin
       gui[1].DrawAdd(AdDraw,AdRect(0,0,16,16),1,250);
    end;
    I can do the above with an average of 300 FPS. I think it may be your computer or drivers, unless you consider 300 fps too slow...

Page 2 of 3 FirstFirst 123 LastLast

Tags for this Thread

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
  •