1 (* Copyright (C) Doom 2D: Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 {$INCLUDE ../shared/a_modes.inc}
21 {$INCLUDE ../nogl/noGLuses.inc}
25 SysUtils
, Classes
, Math
, e_log
, e_texture
,
26 MAPDEF
, ImagingTypes
, Imaging
, ImagingUtility
;
29 TMirrorType
=(None
, Horizontal
, Vertical
);
30 TBlending
=(None
, Blend
, Filter
, Invert
);
41 Left
, Top
, Right
, Bottom
: Integer;
59 //------------------------------------------------------------------
61 //------------------------------------------------------------------
63 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
64 procedure e_ResizeWindow(Width
, Height
: Integer);
66 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
67 Blending
: Boolean; Mirror
: TMirrorType
= TMirrorType
.None
);
68 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
69 Blending
: Boolean; Angle
: Single; RC
: PDFPoint
; Mirror
: TMirrorType
= TMirrorType
.None
);
70 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
71 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
72 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
73 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
75 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
76 AlphaChannel
: Boolean; Blending
: Boolean; ambientBlendMode
: Boolean=false);
78 procedure e_DrawFillX (id
: DWORD
; x
, y
, wdt
, hgt
: Integer; alpha
: Integer; alphachannel
: Boolean;
79 blending
: Boolean; scale
: Single; ambientBlendMode
: Boolean=false);
81 procedure e_AmbientQuad (x
, y
, w
, h
: Integer; r
, g
, b
, a
: Byte);
83 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
84 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
85 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
86 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
87 Blending
: TBlending
= TBlending
.None
);
88 procedure e_DarkenQuad (x0
, y0
, x1
, y1
: Integer; a
: Integer);
89 procedure e_DarkenQuadWH (x
, y
, w
, h
: Integer; a
: Integer);
91 function e_CreateTextureImg (var img
: TImageData
; var ID
: DWORD
): Boolean;
92 function e_CreateTexture(FileName
: string; var ID
: DWORD
): Boolean;
93 function e_CreateTextureEx(FileName
: string; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
94 function e_CreateTextureMem(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
): Boolean;
95 function e_CreateTextureMemEx(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
96 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
97 procedure e_DeleteTexture(ID
: DWORD
);
98 procedure e_RemoveAllTextures();
101 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
102 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
103 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
104 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
105 Color
: TRGB
; Scale
: Single = 1.0);
106 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
107 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
108 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
109 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
110 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
111 procedure e_CharFont_Remove(FontID
: DWORD
);
112 procedure e_CharFont_RemoveAll();
115 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
117 procedure e_TextureFontKill(FontID
: DWORD
);
118 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
119 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
120 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
121 procedure e_TextureFontPrintFmt(X
, Y
: GLint
; Text: string; FontID
: DWORD
;
122 Shadow
: Boolean = False; Newlines
: Boolean = False);
123 procedure e_TextureFontGetSize(ID
: DWORD
; out CharWidth
, CharHeight
: Byte);
124 procedure e_RemoveAllTextureFont();
126 function e_TextureFontCharWidth (ch
: Char; FontID
: DWORD
): Integer;
127 procedure e_TextureFontPrintCharEx (X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
129 procedure e_ReleaseEngine();
130 procedure e_BeginRender();
131 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
132 procedure e_Clear(); overload
;
133 procedure e_EndRender();
136 function e_GetGamma(win
: PSDL_Window
): Byte;
137 procedure e_SetGamma(win
: PSDL_Window
;Gamma
: Byte);
140 procedure e_MakeScreenshot(st
: TStream
; Width
, Height
: Word);
142 function _RGB(Red
, Green
, Blue
: Byte): TRGB
;
143 function _Point(X
, Y
: Integer): TPoint2i
;
144 function _Rect(X
, Y
: Integer; Width
, Height
: Word): TRectWH
;
145 function _TRect(L
, T
, R
, B
: LongInt): TRect
;
147 //function e_getTextGLId (ID: DWORD): GLuint;
151 e_NoGraphics
: Boolean = False;
152 e_FastScreenshots
: Boolean = true; // it's REALLY SLOW with `false`
153 g_dbg_scale
: Single = 1.0;
167 TTextureFont
= record
178 Chars
: array[0..255] of
188 TSavedTexture
= record
195 e_Textures
: array of TTexture
= nil;
196 e_TextureFonts
: array of TTextureFont
= nil;
197 e_CharFonts
: array of TCharFont
;
198 //e_SavedTextures: array of TSavedTexture;
200 //function e_getTextGLId (ID: DWORD): GLuint; begin result := e_Textures[ID].tx.id; end;
202 //------------------------------------------------------------------
203 // Èíèöèàëèçèðóåò OpenGL
204 //------------------------------------------------------------------
205 procedure e_InitGL();
209 e_DummyTextures
:= True;
215 glDisable(GL_DEPTH_TEST
);
216 glEnable(GL_SCISSOR_TEST
);
217 glClearColor(0, 0, 0, 0);
220 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
222 mat
: Array [0..15] of GLDouble
;
225 if e_NoGraphics
then Exit
;
227 glScissor(X
, Y
, Width
, Height
);
228 glViewport(X
, Y
, Width
, Height
);
229 //gluOrtho2D(0, Width, Height, 0);
231 glMatrixMode(GL_PROJECTION
);
233 mat
[ 0] := 2.0 / Width
;
239 mat
[ 5] := -2.0 / Height
;
253 glLoadMatrixd(@mat
[0]);
255 glMatrixMode(GL_MODELVIEW
);
259 //------------------------------------------------------------------
260 // Èùåò ñâîáîäíûé ýëåìåíò â ìàññèâå òåêñòóð
261 //------------------------------------------------------------------
262 function FindTexture(): DWORD
;
266 if e_Textures
<> nil then
267 for i
:= 0 to High(e_Textures
) do
268 if e_Textures
[i
].tx
.Width
= 0 then
274 if e_Textures
= nil then
276 SetLength(e_Textures
, 32);
281 Result
:= High(e_Textures
) + 1;
282 SetLength(e_Textures
, Length(e_Textures
) + 32);
286 //------------------------------------------------------------------
288 //------------------------------------------------------------------
289 function e_CreateTexture(FileName
: String; var ID
: DWORD
): Boolean;
296 e_WriteLog('Loading texture from '+FileName
, TMsgType
.Notify
);
298 find_id
:= FindTexture();
300 if not LoadTexture(FileName
, e_Textures
[find_id
].tx
, e_Textures
[find_id
].tx
.Width
,
301 e_Textures
[find_id
].tx
.Height
, @fmt
) then Exit
;
308 function e_CreateTextureEx(FileName
: String; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
315 find_id
:= FindTexture();
317 if not LoadTextureEx(FileName
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
324 function e_CreateTextureMem(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
): Boolean;
331 find_id
:= FindTexture
;
333 if not LoadTextureMem(pData
, dataSize
, e_Textures
[find_id
].tx
, e_Textures
[find_id
].tx
.Width
, e_Textures
[find_id
].tx
.Height
, @fmt
) then exit
;
340 function e_CreateTextureMemEx(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
347 find_id
:= FindTexture();
349 if not LoadTextureMemEx(pData
, dataSize
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
356 function e_CreateTextureImg (var img
: TImageData
; var ID
: DWORD
): Boolean;
362 find_id
:= FindTexture();
363 if not LoadTextureImg(img
, e_Textures
[find_id
].tx
, tw
, th
, @fmt
) then exit
;
368 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
370 if Width
<> nil then Width
^ := e_Textures
[ID
].tx
.Width
;
371 if Height
<> nil then Height
^ := e_Textures
[ID
].tx
.Height
;
374 procedure e_ResizeWindow(Width
, Height
: Integer);
378 e_SetViewPort(0, 0, Width
, Height
);
381 procedure drawTxQuad (x0
, y0
, w
, h
, tw
, th
: Integer; u
, v
: single; Mirror
: TMirrorType
);
383 x1
, y1
, tmp
: Integer;
385 if (w
< 1) or (h
< 1) then exit
;
388 if Mirror
= TMirrorType
.Horizontal
then begin tmp
:= x1
; x1
:= x0
; x0
:= tmp
; end
389 else if Mirror
= TMirrorType
.Vertical
then begin tmp
:= y1
; y1
:= y0
; y0
:= tmp
; end;
390 //HACK: make texture one pixel shorter, so it won't wrap
391 if (g_dbg_scale
<> 1.0) then
396 glTexCoord2f(0, v
); glVertex2i(x0
, y0
);
397 glTexCoord2f(0, 0); glVertex2i(x0
, y1
);
398 glTexCoord2f(u
, 0); glVertex2i(x1
, y1
);
399 glTexCoord2f(u
, v
); glVertex2i(x1
, y0
);
402 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
403 Blending
: Boolean; Mirror
: TMirrorType
= TMirrorType
.None
);
405 if e_NoGraphics
then Exit
;
406 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
408 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
413 if (AlphaChannel
) or (Alpha
> 0) then
414 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
417 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
420 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
422 glEnable(GL_TEXTURE_2D
);
423 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
426 drawTxQuad(X
, Y
, e_Textures
[id
].tx
.width
, e_Textures
[id
].tx
.height
, e_Textures
[id
].tx
.width
, e_Textures
[id
].tx
.height
, e_Textures
[ID
].tx
.u
, e_Textures
[ID
].tx
.v
, Mirror
);
428 //u := e_Textures[ID].tx.u;
429 //v := e_Textures[ID].tx.v;
432 if Mirror = M_NONE then
434 glTexCoord2f(u, 0); glVertex2i(X + e_Textures[id].tx.Width, Y);
435 glTexCoord2f(0, 0); glVertex2i(X, Y);
436 glTexCoord2f(0, -v); glVertex2i(X, Y + e_Textures[id].tx.Height);
437 glTexCoord2f(u, -v); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height);
440 if Mirror = M_HORIZONTAL then
442 glTexCoord2f(u, 0); glVertex2i(X, Y);
443 glTexCoord2f(0, 0); glVertex2i(X + e_Textures[id].tx.Width, Y);
444 glTexCoord2f(0, -v); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height);
445 glTexCoord2f(u, -v); glVertex2i(X, Y + e_Textures[id].tx.Height);
448 if Mirror = M_VERTICAL then
450 glTexCoord2f(u, -v); glVertex2i(X + e_Textures[id].tx.Width, Y);
451 glTexCoord2f(0, -v); glVertex2i(X, Y);
452 glTexCoord2f(0, 0); glVertex2i(X, Y + e_Textures[id].tx.Height);
453 glTexCoord2f(u, 0); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height);
462 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
463 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
467 if e_NoGraphics
then Exit
;
468 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
470 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
475 if (AlphaChannel
) or (Alpha
> 0) then
476 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
479 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
482 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
484 glEnable(GL_TEXTURE_2D
);
485 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
487 u
:= e_Textures
[ID
].tx
.u
;
488 v
:= e_Textures
[ID
].tx
.v
;
491 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
492 glTexCoord2f(u
, v
); glVertex2i(X
+ Width
, Y
);
493 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
+ Height
);
494 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ Height
);
500 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
501 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
503 if e_NoGraphics
then Exit
;
504 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
506 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
511 if (AlphaChannel
) or (Alpha
> 0) then
512 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
515 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
518 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
520 glEnable(GL_TEXTURE_2D
);
521 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
523 drawTxQuad(X
, Y
, Width
, Height
, e_Textures
[id
].tx
.width
, e_Textures
[id
].tx
.height
, e_Textures
[ID
].tx
.u
, e_Textures
[ID
].tx
.v
, Mirror
);
529 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
530 AlphaChannel
: Boolean; Blending
: Boolean; ambientBlendMode
: Boolean=false);
532 X2
, Y2
, dx
, w
, h
: Integer;
535 if e_NoGraphics
then Exit
;
536 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
537 ambientBlendMode
:= false;
539 if (Alpha
> 0) or AlphaChannel
or Blending
then
545 if not ambientBlendMode
then glDisable(GL_BLEND
);
547 if AlphaChannel
or (Alpha
> 0) then glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
548 if (Alpha
> 0) then glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
549 if Blending
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
551 if (XCount
= 0) then XCount
:= 1;
552 if (YCount
= 0) then YCount
:= 1;
554 glEnable(GL_TEXTURE_2D
);
555 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
557 X2
:= X
+e_Textures
[ID
].tx
.width
*XCount
;
558 Y2
:= Y
+e_Textures
[ID
].tx
.height
*YCount
;
560 //k8: this SHOULD work... i hope
561 if (e_Textures
[ID
].tx
.width
= e_Textures
[ID
].tx
.glwidth
) and (e_Textures
[ID
].tx
.height
= e_Textures
[ID
].tx
.glheight
) then
564 glTexCoord2i(0, YCount
); glVertex2i(X
, Y
);
565 glTexCoord2i(XCount
, YCount
); glVertex2i(X2
, Y
);
566 glTexCoord2i(XCount
, 0); glVertex2i(X2
, Y2
);
567 glTexCoord2i(0, 0); glVertex2i(X
, Y2
);
574 u
:= e_Textures
[ID
].tx
.u
;
575 v
:= e_Textures
[ID
].tx
.v
;
576 w
:= e_Textures
[ID
].tx
.width
;
577 h
:= e_Textures
[ID
].tx
.height
;
584 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
585 glTexCoord2f(u
, v
); glVertex2i(X
+w
, Y
);
586 glTexCoord2f(u
, 0); glVertex2i(X
+w
, Y
+h
);
587 glTexCoord2f(0, 0); glVertex2i(X
, Y
+h
);
602 //TODO: overflow checks
603 function intersectRect (var x0
, y0
, w0
, h0
: Integer; const x1
, y1
, w1
, h1
: Integer): Boolean;
608 if (w0
< 1) or (h0
< 1) or (w1
< 1) or (h1
< 1) then exit
;
609 // check for intersection
610 if (x0
+w0
<= x1
) or (y0
+h0
<= y1
) or (x1
+w1
<= x0
) or (y1
+h1
<= y0
) then exit
;
611 if (x0
>= x1
+w1
) or (y0
>= y1
+h1
) or (x1
>= x0
+h0
) or (y1
>= y0
+h0
) then exit
;
615 if (x0
< x1
) then x0
:= x1
;
616 if (y0
< y1
) then y0
:= y1
;
617 if (ex0
> x1
+w1
) then ex0
:= x1
+w1
;
618 if (ey0
> y1
+h1
) then ey0
:= y1
+h1
;
621 result
:= (w0
> 0) and (h0
> 0);
625 procedure e_DrawFillX (id
: DWORD
; x
, y
, wdt
, hgt
: Integer; alpha
: Integer; alphachannel
: Boolean;
626 blending
: Boolean; scale
: Single; ambientBlendMode
: Boolean=false);
631 scxywh: array[0..3] of GLint;
632 vpxywh: array[0..3] of GLint;
634 w
, h
, dw
, cw
, ch
, yofs
: Integer;
635 u
, v
, cu
, cv
: Single;
639 procedure setScissorGLInternal (x, y, w, h: Integer);
641 //if not scallowed then exit;
646 y := vpxywh[3]-(y+h);
647 if not intersectRect(x, y, w, h, scxywh[0], scxywh[1], scxywh[2], scxywh[3]) then
649 glScissor(0, 0, 0, 0);
653 //writeln(' (', x, ',', y, ')-(', w, ',', h, ')');
654 glScissor(x, y, w, h);
660 if e_NoGraphics
then exit
;
661 ambientBlendMode
:= false;
663 if (wdt
< 1) or (hgt
< 1) then exit
;
665 if (wdt
mod e_Textures
[ID
].tx
.width
= 0) and (hgt
mod e_Textures
[ID
].tx
.height
= 0) then
667 e_DrawFill(id
, x
, y
, wdt
div e_Textures
[ID
].tx
.width
, hgt
div e_Textures
[ID
].tx
.height
, alpha
, alphachannel
, blending
, ambientBlendMode
);
671 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
673 if (Alpha
> 0) or AlphaChannel
or Blending
then
679 if not ambientBlendMode
then glDisable(GL_BLEND
);
681 if AlphaChannel
or (Alpha
> 0) then glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
682 if (Alpha
> 0) then glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
683 if Blending
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
685 glEnable(GL_TEXTURE_2D
);
686 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
691 //k8: this SHOULD work... i hope
692 if {false and} (e_Textures
[ID
].tx
.width
= e_Textures
[ID
].tx
.glwidth
) and (e_Textures
[ID
].tx
.height
= e_Textures
[ID
].tx
.glheight
) then
695 glTexCoord2f(0, hgt
/e_Textures
[ID
].tx
.height
); glVertex2i(x
, y
);
696 glTexCoord2f(wdt
/e_Textures
[ID
].tx
.width
, hgt
/e_Textures
[ID
].tx
.height
); glVertex2i(x2
, y
);
697 glTexCoord2f(wdt
/e_Textures
[ID
].tx
.width
, 0); glVertex2i(x2
, y2
);
698 glTexCoord2f(0, 0); glVertex2i(x
, y2
);
703 // hard day's night; setup scissor
705 glGetIntegerv(GL_VIEWPORT, @vpxywh[0]);
706 wassc := (glIsEnabled(GL_SCISSOR_TEST) <> 0);
707 if wassc then glGetIntegerv(GL_SCISSOR_BOX, @scxywh[0]) else glGetIntegerv(GL_VIEWPORT, @scxywh[0]);
708 //writeln('(', scxywh[0], ',', scxywh[1], ')-(', scxywh[2], ',', scxywh[3], ')');
709 //glEnable(GL_SCISSOR_TEST);
710 setScissorGLInternal(x, y, wdt, hgt);
713 u
:= e_Textures
[ID
].tx
.u
;
714 v
:= e_Textures
[ID
].tx
.v
;
715 w
:= e_Textures
[ID
].tx
.width
;
716 h
:= e_Textures
[ID
].tx
.height
;
718 if (hgt
> h
) then begin y
+= hgt
-h
; onlyOneY
:= false; end else onlyOneY
:= true;
722 if (hgt
>= h
) then begin ch
:= h
; cv
:= v
; yofs
:= 0; end else begin ch
:= hgt
; cv
:= v
/(h
/hgt
); yofs
:= h
-hgt
; end;
723 if onlyOneY
then yofs
:= 0;
729 if (dw
>= w
) then begin cw
:= w
; cu
:= u
; end else begin cw
:= dw
; cu
:= u
/(w
/dw
); end;
731 glTexCoord2f(0, cv
); glVertex2i(X
, Y
+yofs
);
732 glTexCoord2f(cu
, cv
); glVertex2i(X
+cw
, Y
+yofs
);
733 glTexCoord2f(cu
, 0); glVertex2i(X
+cw
, Y
+ch
+yofs
);
734 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ch
+yofs
);
740 //if wassc then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST);
747 procedure e_AmbientQuad (x
, y
, w
, h
: Integer; r
, g
, b
, a
: Byte);
749 if e_NoGraphics
then exit
;
750 if (w
< 1) or (h
< 1) then exit
;
751 if (a
<> 255) or ((r
or g
or b
) <> 0) then
754 glDisable(GL_TEXTURE_2D
);
755 glColor4ub(r
, g
, b
, a
);
756 if ((r
or g
or b
) <> 0) then
758 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
762 glVertex2i(x
+w
, y
+h
);
766 glBlendFunc(GL_ZERO
, GL_SRC_ALPHA
);
770 glVertex2i(x
+w
, y
+h
);
778 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
779 Blending
: Boolean; Angle
: Single; RC
: PDFPoint
; Mirror
: TMirrorType
= TMirrorType
.None
);
781 if e_NoGraphics
then Exit
;
783 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
785 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
790 if (AlphaChannel
) or (Alpha
> 0) then
791 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
794 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
797 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
799 if (Angle
<> 0) and (RC
<> nil) then
802 glTranslatef(X
+RC
.X
, Y
+RC
.Y
, 0);
803 glRotatef(Angle
, 0, 0, 1);
804 glTranslatef(-(X
+RC
.X
), -(Y
+RC
.Y
), 0);
807 glEnable(GL_TEXTURE_2D
);
808 glBindTexture(GL_TEXTURE_2D
, e_Textures
[id
].tx
.id
);
809 glBegin(GL_QUADS
); //0-1 1-1
811 drawTxQuad(X
, Y
, e_Textures
[id
].tx
.width
, e_Textures
[id
].tx
.height
, e_Textures
[id
].tx
.width
, e_Textures
[id
].tx
.height
, e_Textures
[ID
].tx
.u
, e_Textures
[ID
].tx
.v
, Mirror
);
820 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
822 if e_NoGraphics
then Exit
;
823 glDisable(GL_TEXTURE_2D
);
824 glColor3ub(Red
, Green
, Blue
);
827 if (Size
= 2) or (Size
= 4) then
831 glVertex2f(X
+0.3, Y
+1.0);
834 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
837 procedure e_LineCorrection(var X1
, Y1
, X2
, Y2
: Integer);
839 // Make lines only top-left/bottom-right and top-right/bottom-left
851 // Pixel-perfect hack
859 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
861 nX1
, nY1
, nX2
, nY2
: Integer;
863 if e_NoGraphics
then Exit
;
864 // Only top-left/bottom-right quad
881 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
886 glDisable(GL_TEXTURE_2D
);
887 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
890 nX1
:= X1
; nY1
:= Y1
;
891 nX2
:= X2
; nY2
:= Y1
;
892 e_LineCorrection(nX1
, nY1
, nX2
, nY2
); // Pixel-perfect lines
893 glVertex2i(nX1
, nY1
);
894 glVertex2i(nX2
, nY2
);
896 nX1
:= X2
; nY1
:= Y1
;
897 nX2
:= X2
; nY2
:= Y2
;
898 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
899 glVertex2i(nX1
, nY1
);
900 glVertex2i(nX2
, nY2
);
902 nX1
:= X2
; nY1
:= Y2
;
903 nX2
:= X1
; nY2
:= Y2
;
904 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
905 glVertex2i(nX1
, nY1
);
906 glVertex2i(nX2
, nY2
);
908 nX1
:= X1
; nY1
:= Y2
;
909 nX2
:= X1
; nY2
:= Y1
;
910 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
911 glVertex2i(nX1
, nY1
);
912 glVertex2i(nX2
, nY2
);
914 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
918 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
919 Blending
: TBlending
= TBlending
.None
);
921 if e_NoGraphics
then Exit
;
922 if (Alpha
> 0) or (Blending
<> TBlending
.None
) then
927 if Blending
= TBlending
.Blend
then
928 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
)
930 if Blending
= TBlending
.Filter
then
931 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
)
933 if Blending
= TBlending
.Invert
then
934 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
)
937 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
939 glDisable(GL_TEXTURE_2D
);
940 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
952 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
958 // ////////////////////////////////////////////////////////////////////////// //
959 procedure e_DarkenQuad (x0
, y0
, x1
, y1
: Integer; a
: Integer);
961 if (a
< 0) then a
:= 0;
962 if (a
> 255) then a
:= 255;
964 glBlendFunc(GL_ZERO
, GL_SRC_ALPHA
);
965 glDisable(GL_TEXTURE_2D
);
966 glColor4ub(0, 0, 0, Byte(255-a
));
973 //glRect(x, y, x+w, y+h);
974 glColor4ub(1, 1, 1, 1);
976 //glBlendEquation(GL_FUNC_ADD);
979 procedure e_DarkenQuadWH (x
, y
, w
, h
: Integer; a
: Integer);
981 if (w
> 0) and (h
> 0) then e_DarkenQuad(x
, y
, x
+w
, y
+h
, a
);
985 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
987 if e_NoGraphics
then Exit
;
988 // Pixel-perfect lines
990 e_LineCorrection(X1
, Y1
, X2
, Y2
);
995 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
999 glDisable(GL_TEXTURE_2D
);
1000 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
1006 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1008 glDisable(GL_BLEND
);
1011 //------------------------------------------------------------------
1012 // Óäàëÿåò òåêñòóðó èç ìàññèâà
1013 //------------------------------------------------------------------
1014 procedure e_DeleteTexture(ID
: DWORD
);
1016 if not e_NoGraphics
then
1017 glDeleteTextures(1, @e_Textures
[ID
].tx
.id
);
1018 e_Textures
[ID
].tx
.id
:= 0;
1019 e_Textures
[ID
].tx
.Width
:= 0;
1020 e_Textures
[ID
].tx
.Height
:= 0;
1023 //------------------------------------------------------------------
1024 // Óäàëÿåò âñå òåêñòóðû
1025 //------------------------------------------------------------------
1026 procedure e_RemoveAllTextures();
1030 if e_Textures
= nil then Exit
;
1032 for i
:= 0 to High(e_Textures
) do
1033 if e_Textures
[i
].tx
.Width
<> 0 then e_DeleteTexture(i
);
1037 //------------------------------------------------------------------
1039 //------------------------------------------------------------------
1040 procedure e_ReleaseEngine();
1042 e_RemoveAllTextures
;
1043 e_RemoveAllTextureFont
;
1046 procedure e_BeginRender();
1048 if e_NoGraphics
then Exit
;
1049 glEnable(GL_ALPHA_TEST
);
1050 glAlphaFunc(GL_GREATER
, 0.0);
1053 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
1055 if e_NoGraphics
then Exit
;
1056 glClearColor(Red
, Green
, Blue
, 0);
1060 procedure e_Clear(); overload
;
1062 if e_NoGraphics
then Exit
;
1063 glClearColor(0, 0, 0, 0);
1064 glClear(GL_COLOR_BUFFER_BIT
);
1067 procedure e_EndRender();
1069 if e_NoGraphics
then Exit
;
1074 function e_GetGamma(win
: PSDL_Window
): Byte;
1076 ramp
: array [0..256*3-1] of Word;
1077 rgb
: array [0..2] of Double;
1086 if e_NoGraphics
then Exit
;
1091 SDL_GetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
1100 for j
:= min
to max
- 1 do
1103 B
:= (j
mod 256)/256;
1105 sum
:= sum
+ ln(A
)/ln(B
);
1108 rgb
[i
] := sum
/ count
;
1111 Result
:= 100 - Trunc(((rgb
[0] + rgb
[1] + rgb
[2])/3 - 0.23) * 100/(2.7 - 0.23));
1114 procedure e_SetGamma(win
: PSDL_Window
; Gamma
: Byte);
1116 ramp
: array [0..256*3-1] of Word;
1121 if e_NoGraphics
then Exit
;
1122 g
:= (100 - Gamma
)*(2.7 - 0.23)/100 + 0.23;
1124 for i
:= 0 to 255 do
1126 r
:= Exp(g
* ln(i
/256))*65536;
1127 if r
< 0 then r
:= 0
1128 else if r
> 65535 then r
:= 65535;
1129 ramp
[i
] := trunc(r
);
1130 ramp
[i
+ 256] := trunc(r
);
1131 ramp
[i
+ 512] := trunc(r
);
1134 SDL_SetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
1138 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
1142 e_WriteLog('Creating CharFont...', TMsgType
.Notify
);
1146 if e_CharFonts
<> nil then
1147 for i
:= 0 to High(e_CharFonts
) do
1148 if not e_CharFonts
[i
].alive
then
1154 if id
= DWORD(-1) then
1156 SetLength(e_CharFonts
, Length(e_CharFonts
) + 1);
1157 id
:= High(e_CharFonts
);
1160 with e_CharFonts
[id
] do
1162 for i
:= 0 to High(Chars
) do
1176 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
1178 with e_CharFonts
[FontID
].Chars
[Ord(c
)] do
1180 TextureID
:= Texture
;
1185 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1189 if e_NoGraphics
then Exit
;
1190 if Text = '' then Exit
;
1191 if e_CharFonts
= nil then Exit
;
1192 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1194 with e_CharFonts
[FontID
] do
1196 for a
:= 1 to Length(Text) do
1197 with Chars
[Ord(Text[a
])] do
1198 if TextureID
<> -1 then
1200 e_Draw(TextureID
, X
, Y
, 0, True, False);
1201 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1206 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
1207 Color
: TRGB
; Scale
: Single = 1.0);
1212 if e_NoGraphics
then Exit
;
1213 if Text = '' then Exit
;
1214 if e_CharFonts
= nil then Exit
;
1215 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1217 with e_CharFonts
[FontID
] do
1219 for a
:= 1 to Length(Text) do
1220 with Chars
[Ord(Text[a
])] do
1221 if TextureID
<> -1 then
1223 if Scale
<> 1.0 then
1226 glScalef(Scale
, Scale
, 0);
1231 e_Draw(TextureID
, X
, Y
, 0, True, False);
1234 if Scale
<> 1.0 then glPopMatrix
;
1236 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1241 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1243 a
, TX
, TY
, len
: Integer;
1247 if e_NoGraphics
then Exit
;
1248 if Text = '' then Exit
;
1249 if e_CharFonts
= nil then Exit
;
1250 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1258 len
:= Length(Text);
1260 e_CharFont_GetSize(FontID
, 'A', w
, h
);
1262 with e_CharFonts
[FontID
] do
1264 for a
:= 1 to len
do
1275 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1280 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1285 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1290 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1295 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1300 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1305 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1310 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1315 with Chars
[Ord(Text[a
])] do
1316 if TextureID
<> -1 then
1320 e_Draw(TextureID
, TX
, TY
, 0, True, False);
1323 TX
:= TX
+Width
+IfThen(a
= Length(Text), 0, Space
);
1329 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
1337 if Text = '' then Exit
;
1338 if e_CharFonts
= nil then Exit
;
1339 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1341 with e_CharFonts
[FontID
] do
1343 for a
:= 1 to Length(Text) do
1344 with Chars
[Ord(Text[a
])] do
1345 if TextureID
<> -1 then
1347 w
:= w
+Width
+IfThen(a
= Length(Text), 0, Space
);
1348 e_GetTextureSize(TextureID
, nil, @h2
);
1349 if h2
> h
then h
:= h2
;
1354 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
1356 a
, lines
, len
: Integer;
1357 h2
, w2
, tw
, th
: Word;
1364 if Text = '' then Exit
;
1365 if e_CharFonts
= nil then Exit
;
1366 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1369 len
:= Length(Text);
1371 with e_CharFonts
[FontID
] do
1373 for a
:= 1 to len
do
1375 if Text[a
] = #10 then
1378 if w2
> tw
then tw
:= w2
;
1383 with Chars
[Ord(Text[a
])] do
1384 if TextureID
<> -1 then
1386 w2
:= w2
+ Width
+ IfThen(a
= len
, 0, Space
);
1387 e_GetTextureSize(TextureID
, nil, @h2
);
1388 if h2
> th
then th
:= h2
;
1400 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
1406 if e_CharFonts
= nil then Exit
;
1407 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1409 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1410 Result
:= Max(Result
, e_CharFonts
[FontID
].Chars
[a
].Width
);
1413 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
1420 if e_CharFonts
= nil then Exit
;
1421 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1423 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1425 if e_CharFonts
[FontID
].Chars
[a
].TextureID
<> -1 then
1426 e_GetTextureSize(e_CharFonts
[FontID
].Chars
[a
].TextureID
, nil, @h2
)
1428 if h2
> Result
then Result
:= h2
;
1432 procedure e_CharFont_Remove(FontID
: DWORD
);
1436 with e_CharFonts
[FontID
] do
1437 for a
:= 0 to High(Chars
) do
1438 if Chars
[a
].TextureID
<> -1 then e_DeleteTexture(Chars
[a
].TextureID
);
1440 e_CharFonts
[FontID
].alive
:= False;
1443 procedure e_CharFont_RemoveAll();
1447 if e_CharFonts
= nil then Exit
;
1449 for a
:= 0 to High(e_CharFonts
) do
1450 e_CharFont_Remove(a
);
1455 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
1464 if e_NoGraphics
then Exit
;
1465 e_WriteLog('Creating texture font...', TMsgType
.Notify
);
1469 if e_TextureFonts
<> nil then
1470 for i
:= 0 to High(e_TextureFonts
) do
1471 if e_TextureFonts
[i
].Base
= 0 then
1477 if id
= DWORD(-1) then
1479 SetLength(e_TextureFonts
, Length(e_TextureFonts
) + 1);
1480 id
:= High(e_TextureFonts
);
1483 with e_TextureFonts
[id
] do
1486 Base
:= glGenLists(XCount
*YCount
);
1488 TextureID
:= e_Textures
[Tex
].tx
.id
;
1489 CharWidth
:= (e_Textures
[Tex
].tx
.Width
div XCount
)+Space
;
1490 CharHeight
:= e_Textures
[Tex
].tx
.Height
div YCount
;
1498 glBindTexture(GL_TEXTURE_2D
, e_Textures
[Tex
].tx
.id
);
1499 for loop1
:= 0 to XCount
*YCount
-1 do
1501 cx
:= (loop1
mod XCount
)/XCount
;
1502 cy
:= (loop1
div YCount
)/YCount
;
1504 glNewList(e_TextureFonts
[id
].Base
+loop1
, GL_COMPILE
);
1506 glTexCoord2f(cx
, 1.0-cy
-1/YCount
);
1507 glVertex2i(0, e_Textures
[Tex
].tx
.Height
div YCount
);
1509 glTexCoord2f(cx
+1/XCount
, 1.0-cy
-1/YCount
);
1510 glVertex2i(e_Textures
[Tex
].tx
.Width
div XCount
, e_Textures
[Tex
].tx
.Height
div YCount
);
1512 glTexCoord2f(cx
+1/XCount
, 1.0-cy
);
1513 glVertex2i(e_Textures
[Tex
].tx
.Width
div XCount
, 0);
1515 glTexCoord2f(cx
, 1.0-cy
);
1518 glTranslated((e_Textures
[Tex
].tx
.Width
div XCount
)+Space
, 0, 0);
1526 procedure e_TextureFontKill(FontID
: DWORD
);
1528 if e_NoGraphics
then Exit
;
1530 glDeleteLists(e_TextureFonts
[FontID
].Base
, 256);
1532 e_TextureFonts
[FontID
].Base
:= 0;
1535 {$IFNDEF NOGL_LISTS}
1536 procedure e_TextureFontDrawChar(ch
: Char; FontID
: DWORD
);
1541 Width
, Height
: Integer;
1542 XCount
, YCount
: Integer;
1544 index
:= Ord(ch
) - 32;
1545 Tex
:= e_TextureFonts
[FontID
].Texture
;
1546 Width
:= e_Textures
[Tex
].tx
.Width
;
1547 Height
:= e_Textures
[Tex
].tx
.Height
;
1548 XCount
:= e_TextureFonts
[FontID
].XC
;
1549 YCount
:= e_TextureFonts
[FontID
].YC
;
1550 cx
:= (index
mod XCount
)/XCount
;
1551 cy
:= (index
div YCount
)/YCount
;
1553 glTexCoord2f(cx
, 1 - cy
- 1/YCount
);
1554 glVertex2i(0, Height
div YCount
);
1555 glTexCoord2f(cx
+ 1/XCount
, 1 - cy
- 1/YCount
);
1556 glVertex2i(Width
div XCount
, Height
div YCount
);
1557 glTexCoord2f(cx
+ 1/XCount
, 1 - cy
);
1558 glVertex2i(Width
div XCount
, 0);
1559 glTexCoord2f(cx
, 1 - cy
);
1562 glTranslatef((e_Textures
[Tex
].tx
.Width
div XCount
) + e_TextureFonts
[FontID
].SPC
, 0, 0);
1565 procedure e_TextureFontDrawString(Text: String; FontID
: DWORD
);
1569 for i
:= 1 to High(Text) do
1570 e_TextureFontDrawChar(Text[i
], FontID
);
1574 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
1576 if e_NoGraphics
then Exit
;
1577 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1578 if Text = '' then Exit
;
1580 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1583 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1586 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1587 glEnable(GL_TEXTURE_2D
);
1588 glTranslatef(x
, y
, 0);
1590 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1591 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1593 e_TextureFontDrawString(Text, FontID
);
1595 glDisable(GL_TEXTURE_2D
);
1598 glDisable(GL_BLEND
);
1601 // god forgive me for this, but i cannot figure out how to do it without lists
1602 procedure e_TextureFontPrintChar(X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
1604 if e_NoGraphics
then Exit
;
1609 glColor4ub(0, 0, 0, 128);
1610 glTranslatef(X
+1, Y
+1, 0);
1612 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1614 e_TextureFontDrawChar(Ch
, FontID
);
1620 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1621 glTranslatef(X
, Y
, 0);
1623 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1625 e_TextureFontDrawChar(Ch
, FontID
);
1631 procedure e_TextureFontPrintCharEx (X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
1633 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1634 glEnable(GL_TEXTURE_2D
);
1635 //glListBase(DWORD(Integer(e_TextureFonts[FontID].Base)-32));
1637 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1639 e_TextureFontPrintChar(X
, Y
, Ch
, FontID
, Shadow
);
1640 glDisable(GL_TEXTURE_2D
);
1641 glDisable(GL_BLEND
);
1644 function e_TextureFontCharWidth (ch
: Char; FontID
: DWORD
): Integer;
1646 result
:= e_TextureFonts
[FontID
].CharWidth
;
1649 procedure e_TextureFontPrintFmt(X
, Y
: GLint
; Text: string; FontID
: DWORD
;
1650 Shadow
: Boolean = False; Newlines
: Boolean = False);
1652 a
, TX
, TY
, len
: Integer;
1656 if e_NoGraphics
then Exit
;
1657 if Text = '' then Exit
;
1658 if e_TextureFonts
= nil then Exit
;
1659 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1667 len
:= Length(Text);
1669 w
:= e_TextureFonts
[FontID
].CharWidth
;
1670 h
:= e_TextureFonts
[FontID
].CharHeight
;
1672 with e_TextureFonts
[FontID
] do
1674 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1675 glEnable(GL_TEXTURE_2D
);
1678 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1681 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1684 for a
:= 1 to len
do
1698 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1703 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1708 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1713 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1718 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1723 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1728 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1733 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1740 e_TextureFontPrintChar(TX
, TY
, Text[a
], FontID
, Shadow
);
1745 glDisable(GL_TEXTURE_2D
);
1746 glDisable(GL_BLEND
);
1750 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
1751 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
1753 if e_NoGraphics
then Exit
;
1754 if Text = '' then Exit
;
1757 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1758 glEnable(GL_TEXTURE_2D
);
1761 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1764 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1769 glColor4ub(0, 0, 0, 128);
1770 glTranslatef(x
+1, y
+1, 0);
1771 glScalef(Scale
, Scale
, 0);
1773 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1775 e_TextureFontDrawString(Text, FontID
);
1781 glColor4ub(Red
, Green
, Blue
, 255);
1782 glTranslatef(x
, y
, 0);
1783 glScalef(Scale
, Scale
, 0);
1785 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1787 e_TextureFontDrawString(Text, FontID
);
1790 glDisable(GL_TEXTURE_2D
);
1792 glColor3ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
);
1793 glDisable(GL_BLEND
);
1796 procedure e_TextureFontGetSize(ID
: DWORD
; out CharWidth
, CharHeight
: Byte);
1800 if e_NoGraphics
then Exit
;
1801 if Integer(ID
) > High(e_TextureFonts
) then
1803 CharWidth
:= e_TextureFonts
[ID
].CharWidth
;
1804 CharHeight
:= e_TextureFonts
[ID
].CharHeight
;
1807 procedure e_RemoveAllTextureFont();
1811 if e_NoGraphics
then Exit
;
1812 if e_TextureFonts
= nil then Exit
;
1814 for i
:= 0 to High(e_TextureFonts
) do
1815 if e_TextureFonts
[i
].Base
<> 0 then
1818 glDeleteLists(e_TextureFonts
[i
].Base
, 256);
1820 e_TextureFonts
[i
].Base
:= 0;
1823 e_TextureFonts
:= nil;
1826 function _RGB(Red
, Green
, Blue
: Byte): TRGB
;
1833 function _Point(X
, Y
: Integer): TPoint2i
;
1839 function _Rect(X
, Y
: Integer; Width
, Height
: Word): TRectWH
;
1843 Result
.Width
:= Width
;
1844 Result
.Height
:= Height
;
1847 function _TRect(L
, T
, R
, B
: LongInt): TRect
;
1856 procedure e_MakeScreenshot (st
: TStream
; Width
, Height
: Word);
1858 pixels
, obuf
, scln
, ps
, pd
: PByte;
1861 i
, x
, y
, res
: Integer;
1862 sign
: array [0..7] of Byte;
1863 hbuf
: array [0..12] of Byte;
1868 if e_NoGraphics
then Exit
;
1871 // first, extract and pack graphics data
1872 if (Width
mod 4) > 0 then Width
:= Width
+4-(Width
mod 4);
1874 GetMem(pixels
, Width
*Height
*3);
1876 FillChar(pixels
^, Width
*Height
*3, 0);
1877 glReadPixels(0, 0, Width
, Height
, GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
1878 //e_WriteLog('PNG: pixels read', MSG_NOTIFY);
1880 if e_FastScreenshots
then
1883 GetMem(scln
, (Width
*3+1)*Height
);
1887 Inc(ps
, (Width
*3)*(Height
-1));
1888 for i
:= 0 to Height
-1 do
1892 Move(ps
^, pd
^, Width
*3);
1904 obufsize
:= (Width
*3+1)*Height
*2;
1905 GetMem(obuf
, obufsize
);
1910 res
:= compress2(Pointer(obuf
), dlen
, Pointer(pixels
), (Width
*3+1)*Height
, 9);
1911 if res
= Z_OK
then break
;
1912 if res
<> Z_BUF_ERROR
then raise Exception
.Create('can''t pack data for PNG');
1913 obufsize
:= obufsize
*2;
1916 GetMem(obuf
, obufsize
);
1918 //e_WriteLog(Format('PNG: pixels compressed from %d to %d', [Integer(Width*Height*3), Integer(dlen)]), MSG_NOTIFY);
1931 st
.writeBuffer(sign
, 8);
1932 //e_WriteLog('PNG: signature written', MSG_NOTIFY);
1935 writeIntBE(st
, LongWord(13));
1940 st
.writeBuffer(sign
, 4);
1941 crc
:= crc32(0, @sign
[0], 4);
1944 hbuf
[2] := (Width
shr 8) and $ff;
1945 hbuf
[3] := Width
and $ff;
1948 hbuf
[6] := (Height
shr 8) and $ff;
1949 hbuf
[7] := Height
and $ff;
1950 hbuf
[8] := 8; // bit depth
1951 hbuf
[9] := 2; // RGB
1952 hbuf
[10] := 0; // compression method
1953 hbuf
[11] := 0; // filter method
1954 hbuf
[12] := 0; // no interlace
1955 crc
:= crc32(crc
, @hbuf
[0], 13);
1956 st
.writeBuffer(hbuf
, 13);
1957 writeIntBE(st
, crc
);
1958 //e_WriteLog('PNG: header written', MSG_NOTIFY);
1961 writeIntBE(st
, LongWord(dlen
));
1966 st
.writeBuffer(sign
, 4);
1967 crc
:= crc32(0, @sign
[0], 4);
1968 crc
:= crc32(crc
, obuf
, dlen
);
1969 st
.writeBuffer(obuf
^, dlen
);
1970 writeIntBE(st
, crc
);
1971 //e_WriteLog('PNG: image data written', MSG_NOTIFY);
1974 writeIntBE(st
, LongWord(0));
1979 st
.writeBuffer(sign
, 4);
1980 crc
:= crc32(0, @sign
[0], 4);
1981 writeIntBE(st
, crc
);
1982 //e_WriteLog('PNG: end marker written', MSG_NOTIFY);
1984 if obuf
<> nil then FreeMem(obuf
);
1989 Imaging
.SetOption(ImagingPNGCompressLevel
, 9);
1990 Imaging
.SetOption(ImagingPNGPreFilter
, 6);
1993 NewImage(Width
, Height
, TImageFormat
.ifR8G8B8
, img
);
1995 //writeln(stderr, 'moving pixels...');
1996 for y
:= Height
-1 downto 0 do
1998 for x
:= 0 to Width
-1 do
2000 clr
.r
:= ps
^; Inc(ps
);
2001 clr
.g
:= ps
^; Inc(ps
);
2002 clr
.b
:= ps
^; Inc(ps
);
2004 SetPixel32(img
, x
, y
, clr
);
2007 GlobalMetadata
.ClearMetaItems();
2008 GlobalMetadata
.ClearMetaItemsForSaving();
2009 //writeln(stderr, 'compressing image...');
2010 if not SaveImageToStream('png', st
, img
) then raise Exception
.Create('screenshot writing error');
2011 //writeln(stderr, 'done!');