PDA

View Full Version : glx.pas for JEDI_SDL



grudzio
18-04-2006, 12:36 PM
There is an error in function InitGLXFromLibrary. The if statement should be

if not LoadModule( libGLX, dll ) then exit; not

if LoadModule( libGLX, dll ) then exit;
In present form it loads library and exits witout initialising glx functions.

savage
18-04-2006, 12:37 PM
Thanks for pointing it out. I'll try and commit the change to CVS this evening.

cragwolf
18-04-2006, 12:53 PM
I've never used glx; the X-Windows library gives me the shakes. I've had a go at gtkglext, though. Looks pretty cool, but I think I'll stick with JEDI-SDL while it's still cooking.

savage
18-04-2006, 06:38 PM
The fix is now part of CVS. Thanks again.

grudzio
18-04-2006, 10:29 PM
I've never used glx; the X-Windows library gives me the shakes. I've had a go at gtkglext, though. Looks pretty cool, but I think I'll stick with JEDI-SDL while it's still cooking.
I only need glxUseXFont to create fonts in my app. And yes, xlib programing
is even more dificult than Win API :wink:

cragwolf
19-04-2006, 12:00 AM
I only need glxUseXFont to create fonts in my app.

Have you tried sdl_ttf? I suppose that's another possibility. I just use premade font textures; it's simple but not as flexible.


And yes, xlib programing is even more dificult than Win API :wink:

Heheh, WinAPI is a distant memory for me having used Linux for the past few years. 8)

grudzio
19-04-2006, 01:27 PM
The problem with textured font is that you need a texture :D. I could not find any font generating utility for linux and was too lazy to make my own.
As for SDL_TTF, I dont like the idea of generating new openGL texture each time I want to print something an the screen. So I am stuck with glxUseFont.

cragwolf
19-04-2006, 04:22 PM
The problem with textured font is that you need a texture :D. I could not find any font generating utility for linux and was too lazy to make my own.

Yes, I created my fonts in the GIMP, and used a monospace font to be sure of the spacing. It was very tedious.

vgo
19-04-2006, 05:23 PM
Creating the font texture on-the-fly is easy if you have some kind of surface to draw the fonts in the system to, like TBitMap. ;)

Here's some old code of mine, should be easy to port to Lazarus:


{$R-}
unit J3D_Text;

interface

uses Windows, OpenGL, Graphics;

type
ThTexture = array [0..0] of Byte;
TTexture = ^ThTexture;

TTextureFont = record
S1, T1, S2, T2: Single;
Width, Height: Integer;
end;

var
TextureFont: array [' ' .. '~'] of TTextureFont;
TextureID: Longword;
TextureSize: Longword;
FontTexture: TTexture; // Texture


procedure Text_LoadFont(Fontname: String; Size: Integer; Color: TColor);

implementation

procedure Text_LoadFont(Fontname: String; Size: Integer; Color: TColor);

const
z: Integer = 0;
var
BitMap: TBitMap;
x: Integer;
y: Integer;
y2: Integer;
z2: Integer;
Delphi_Color: TColor;
Font: TFont;

FontHeight: Integer;
r: TRect;
CharWidths: array [0..255] of Integer;
CharHeights: array [0..255] of Integer;
FontWidth: Integer;
Step: Single;
Chr: Char;
begin
// Create and load bitmap
BitMap := TBitMap.Create;
//BitMap.LoadFromFile(FileName);
BitMap.PixelFormat := pf24bit;

BitMap.Width := 256;
BitMap.Height := 256;

r.Left := 0;
r.Right := 256;
r.Top := 0;
r.Bottom := 256;

BitMap.Canvas.Brush.Color := clBlack;
BitMap.Canvas.Brush.Style := bsSolid;
BitMap.Canvas.Pen.Color := clBlack;
BitMap.Canvas.FillRect(r);
BitMap.Canvas.Font.Name := Fontname; // Arial
BitMap.Canvas.Font.Size := Size; // 18
BitMap.Canvas.Font.Color := Color; //clWhite
BitMap.Canvas.Font.Style := [];
FontWidth := BitMap.Canvas.Font.Size - 4;
FontHeight := Round(BitMap.Canvas.Font.Size * BitMap.Canvas.Font.PixelsPerInch / 72);

for x := 0 to 255 do
CharWidths[x] := BitMap.Canvas.TextWidth(Char(x));

FontHeight := 0;
for x := 0 to 255 do
begin
CharHeights[x] := BitMap.Canvas.TextHeight(Char(x));
if BitMap.Canvas.TextHeight(Char(x)) > FontHeight then
FontHeight := BitMap.Canvas.TextHeight(Char(x));
end;

Step := 1 / 256;

x := 0;
y := 255 - FontHeight;
y2 := 0;
for z2 := 32 to 126 do
begin
Chr := Char(z);
FontWidth := CharWidths[z2];
//FontHeight := CharHeights[z];
if (x + FontWidth) > 255 then
begin
x := 0;
y := y - FontHeight;
//y := y + FontHeight;
y2 := y2 + FontHeight;
end;

TextureFont[Char(z2)].S1 := x * Step;
TextureFont[Char(z2)].T1 := y2 * Step;
TextureFont[Char(z2)].Width := FontWidth-1;
TextureFont[Char(z2)].S2 := (x + FontWidth-1) * Step;
TextureFont[Char(z2)].T2 := (y2 + CharHeights[z2]) * Step;
TextureFont[Char(z2)].Height := CharHeights[z2];
BitMap.Canvas.TextOut(x, y, Char(z2));
x := x + FontWidth;
end;

// Create and set size of texture
TextureSize := BitMap.Width * BitMap.Height;

GetMem(FontTexture, TextureSize * 3);

//BitMap.SaveToFile('c:\temp\font.bmp');

// Position in texture
z := 0;
for y := BitMap.Height - 1 downto 0 do
begin
for x := 0 to BitMap.Width - 1 do
begin
// Converts Delphi Color value to RGB values, no Alpha
Delphi_Color := BitMap.Canvas.Pixels[x, y];
FontTexture[z] := Lo(LoWord(Delphi_Color));
Inc(z);
FontTexture[z] := Hi(LoWord(Delphi_Color));
Inc(z);
FontTexture[z] := Lo(HiWord(Delphi_Color));
Inc(z);
end;
end;
// glGenTextures(1, TextureID);
TextureID := 100;
glBindTexture(GL_TEXTURE_2D, TextureID);

// Used texture format is size = 256x256, format = 3 (RGB) and type unsigned byte
glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, FontTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

BitMap.Free;
end;

initialization

finalization
if FontTexture <> NIL then
FreeMem(FontTexture, TextureSize * 3);

end.

cragwolf
20-04-2006, 01:23 AM
Thanks for the code. That's a nice solution for users of the Delphi VCL or the Lazarus LCL.

vgo
20-04-2006, 07:14 AM
I'll turn that into a class some day for easier use, when I get to the GUI part in my engine. :)

cairnswm
20-04-2006, 07:30 AM
Thanks for the Code - I'm going to incorporate it into my libraries.

grudzio
20-04-2006, 12:42 PM
Thanks vgo. I think I will convert your code, that it uses SDL_TTF instead of VCL (or LCL).

vgo
20-04-2006, 01:51 PM
That would be nice, post the code here if possible. :)

savage
20-04-2006, 02:12 PM
JEDI-SDL does have a SDL_ttf demo that shows how to use it with OpenGL. Look in the SDL_ttf sub-directory.

grudzio
21-04-2006, 12:12 AM
All right, here goes the SDL_TTF version of vgo's code. I also used some code from SDL_TTF glfont demo.


unit glFont;

interface

uses
SDL, SDL_TTF, GL;

const
white : TSDL_Color = ( r : $FF; g : $FF; b : $FF; unused : 0 );

type

TFontInfo = record
name : string;
size : integer;
bold,
italic : boolean;
end;

TTextureFont = record
S1, T1, S2, T2: Single;
Width, Height: Integer;
end;

function CreateGLTexture(surface : PSDL_Surface) : gluint;
function CreateFontSurface(info : TFontInfo) : PSDL_Surface;
function BuildFont : gluint;
procedure KillFont(list : gluint);
procedure KillTexture(tex : gluint);

var
TextureFont: array [32 .. 255] of TTextureFont;

implementation

uses
SysUtils;

function CreateFontSurface(info : TFontInfo) : PSDL_Surface;
var
font : PTTF_Font;
surface : PSDL_Surface;
glyphs : array[32..255] of PSDL_Surface;
i,style : integer;
charWidths : array[0..255] of integer;
fontHeight : integer;
textureSize : integer;
x, y, y2 : Integer;
minx,maxx, advance,w : integer;
maxy,miny : integer;
step : single;
r : TSDL_Rect;
begin
//load font
font := TTF_OpenFont(pchar(info.name),info.size);
//set font style
style := TTF_STYLE_NORMAL;
if info.bold then
style := style or TTF_STYLE_BOLD;
if info.italic then
style := style or TTF_STYLE_ITALIC;
TTF_SetFontStyle(font,style);
//set font height and texture size
//TTF_FontHeight returns the maximum height of font
fontHeight := TTF_FontHeight(font);
if fontHeight > 16 then
textureSize := 512
else
textureSize := 256;

writeln(FontHeight);
surface := SDL_CreateRGBSurface(
SDL_SWSURFACE,
textureSize, textureSize,
32,
{$IFDEF IA32} (* OpenGL RGBA masks *)
$000000FF,
$0000FF00,
$00FF0000,
$FF000000
{$ELSE}
$FF000000,
$00FF0000,
$0000FF00,
$000000FF
{$ENDIF}
);

x := 0;
y := textureSize - FontHeight;
y2 := 0;
Step := 1 / textureSize;
//blit char glyphs to the font texture.
for i := 32 to 255 do begin
TTF_GlyphMetrics(font, i,minx, maxx, miny,maxy, advance);
CharWidths[i] := advance;
w := advance;

if (x + w) > textureSize then begin
x := 0;
y := y - FontHeight;
y2 := y2 + FontHeight;
end;

TextureFont[i].S1 := x * Step;
TextureFont[i].T1 := y2 * Step;
TextureFont[i].Width := w;
TextureFont[i].S2 := (x + w) * Step;
TextureFont[i].T2 := (y2 + fontHeight) * Step;
TextureFont[i].Height := FontHeight;
//glyphs[i] := TTF_RenderGlyph_Blended(font,i,white);
glyphs[i] := TTF_RenderGlyph_Solid(font,i,white);
//SDL_SaveBMP(glyphs[i],pchar('glyph'+IntToStr(i)+'.bmp'));
r.x := x;
r.y := y2+(TTF_FontAscent(font)-maxy);
SDL_BlitSurface(glyphs[i],nil,surface,@r);
x := x + w;
end;

SDL_SaveBMP(surface, PChar(info.name+'.bmp'));

for i := 32 to 255 do
SDL_FreeSurface(glyphs[i]);
TTF_CloseFont(font);
Result := surface;
end;

function CreateGLTexture(Surface : PSDL_Surface) : gluint;
var
texture : GLuint;
w, h : integer;
begin
w := surface^.w;
h := surface^.h;
(* Create an OpenGL texture for the image *)
glGenTextures( 1, @texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexImage2D( GL_TEXTURE_2D,
0,
GL_RGBA,
w, h,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
surface^.pixels );
result := texture;
end;
//stores font in OpenGL display list
function BuildFont : gluint;
const
CHAR_SEP = 2;
var
base : gluint;
i : word;
begin
base := glGenLists(255);
for i := 32 to 255 do begin
glNewList(base+i,GL_COMPILE);
glBegin(GL_QUADS);
glTexCoord2f(textureFont[i].s1, textureFont[i].t1);
glVertex2i(0,0);
glTexCoord2f(textureFont[i].s2, textureFont[i].t1);
glVertex2i(textureFont[i].width,0);
glTexCoord2f(textureFont[i].s2, textureFont[i].t2);
glVertex2i(textureFont[i].width,textureFont[i].height);
glTexCoord2f(textureFont[i].s1, textureFont[i].t2);
glVertex2i(0,textureFont[i].height);
glEnd;
glTranslatef(textureFont[i].width+CHAR_SEP,0,0);
glEndList;
end;
Result := base;
end;

procedure KillFont(list : gluint);
begin
glDeleteLists(list,255);
end;

procedure KillTexture(tex : gluint);
begin
glDeleteTextures(1,@tex);
end;

end.



And here is test app.

program test_font;

uses
SysUtils,
SDL,
SDL_ttf,GL, glfont;

const
SCREEN_WIDTH = 640;
SCREEN_HEIGHT = 480;
SCREEN_BPP = 0;

var
event : TSDL_Event;
done : boolean;
screen, fontSurface : PSDL_Surface;
fontInfo : TFontInfo = (name : 'freesansbold.ttf'; size : 24; bold : false; italic : false);
fontListBase : gluint;
fontTexture : glUint;

procedure printText(x,y : integer; txt : string);
begin
glPushMAtrix;
glTranslatef(x,y,0);
glPushAttrib(GL_LIST_BIT);
glListBase(fontListBase);
glCallLists(Length(txt),GL_UNSIGNED_BYTE,PChar(txt ));
glPopMatrix;
glPopAttrib;
end;

procedure ShutDownApplication( HaltStatus : integer );
begin
TTF_Quit;
SDL_Quit;
Halt( HaltStatus );
end;

begin
{ Initialize SDL }
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then
begin
SDL_Quit;
end;

if ( TTF_Init < 0 ) then
begin
//fprintf(stderr, 'Couldn't initialize TTF: %s',SDL_GetError);
SDL_Quit;
end;

{ Set a 640x480x8 video mode }
screen := SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL );
if ( screen = nil ) then
begin
ShutDownApplication( 2 );
end;

// Set the window manager title bar
// SDL_WM_SetCaption( 'JEDI-SDL 3D TTF Demo', 'glfont' );
glViewport( 0, 0, screen_width, screen_height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity;
glOrtho( 0.0, screen_width, screen_height, 0.0, -1.0, 1.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity;
glEnable(GL_TEXTURE_2D);


fontSurface := createFontSurface(fontInfo);
fontTexture := CreateGLTexture(fontSurface);
fontListBase := BuildFont;
SDL_FreeSurface(fontSurface);

done := false;
while ( not done ) do
begin
while ( SDL_PollEvent( @event ) <> 0 ) do
begin
case event.type_ of
SDL_KEYDOWN, SDL_QUITEV : done := true;
end;
end;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;

glBindTexture(GL_TEXTURE_2D,fontTexture);
printText(0,0, 'The quick brown fox jumps over the lazy dog.');
SDL_GL_SwapBuffers;
end;

KillFont(fontListBase);
KillTexture(fontTexture);
ShutDownApplication( 0 );
end.


There are problems when font is bold and/or italic. It displays font but aved bmp looks weird. Same problem is when instead of TTF_GlyphRender_solid, TTF_GlyphRender_Blended is used.
Ok. Its time to get some sleep. I am starting to see to many quick brown foxes jumping over lazy dogs...

begin
28-04-2006, 12:28 PM
xiexie everybody!

savage
28-04-2006, 02:27 PM
Ni hao ma? Ni huay shuo xing wen ma?