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
, g_base
,
26 MAPDEF
, ImagingTypes
, Imaging
, ImagingUtility
;
31 //------------------------------------------------------------------
33 //------------------------------------------------------------------
35 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
36 procedure e_ResizeWindow(Width
, Height
: Integer);
37 function e_ResizeFramebuffer(Width
, Height
: Integer): Boolean;
38 procedure e_BlitFramebuffer(WinWidth
, WinHeight
: Integer);
39 procedure e_SetRenderTarget(Framebuffer
: Boolean);
41 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
42 Blending
: Boolean; Mirror
: TMirrorType
= TMirrorType
.None
);
43 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
44 Blending
: Boolean; Angle
: Single; RC
: PDFPoint
; Mirror
: TMirrorType
= TMirrorType
.None
);
45 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
46 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
47 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
48 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
50 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
51 AlphaChannel
: Boolean; Blending
: Boolean; ambientBlendMode
: Boolean=false);
53 procedure e_DrawFillX (id
: DWORD
; x
, y
, wdt
, hgt
: Integer; alpha
: Integer; alphachannel
: Boolean;
54 blending
: Boolean; scale
: Single; ambientBlendMode
: Boolean=false);
56 procedure e_AmbientQuad (x
, y
, w
, h
: Integer; r
, g
, b
, a
: Byte);
58 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
59 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
60 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
61 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
62 Blending
: TBlending
= TBlending
.None
);
63 procedure e_DarkenQuad (x0
, y0
, x1
, y1
: Integer; a
: Integer);
64 procedure e_DarkenQuadWH (x
, y
, w
, h
: Integer; a
: Integer);
66 function e_CreateTextureImg (var img
: TImageData
; var ID
: DWORD
): Boolean;
67 function e_CreateTexture(FileName
: string; var ID
: DWORD
): Boolean;
68 function e_CreateTextureEx(FileName
: string; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
69 function e_CreateTextureMem(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
): Boolean;
70 function e_CreateTextureMemEx(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
71 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
72 procedure e_DeleteTexture(ID
: DWORD
);
73 procedure e_RemoveAllTextures();
76 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
77 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
78 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
79 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
80 Color
: TRGB
; Scale
: Single = 1.0);
81 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
82 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
83 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
84 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
85 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
86 procedure e_CharFont_Remove(FontID
: DWORD
);
87 procedure e_CharFont_RemoveAll();
90 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
92 procedure e_TextureFontKill(FontID
: DWORD
);
93 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
94 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
95 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
96 procedure e_TextureFontPrintFmt(X
, Y
: GLint
; Text: string; FontID
: DWORD
;
97 Shadow
: Boolean = False; Newlines
: Boolean = False);
98 procedure e_TextureFontGetSize(ID
: DWORD
; out CharWidth
, CharHeight
: Byte);
99 procedure e_RemoveAllTextureFont();
101 function e_TextureFontCharWidth (ch
: Char; FontID
: DWORD
): Integer;
102 procedure e_TextureFontPrintCharEx (X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
104 procedure e_ReleaseEngine();
105 procedure e_BeginRender();
106 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
107 procedure e_Clear(Red
, Green
, Blue
: Single); overload
;
108 procedure e_Clear(); overload
;
109 procedure e_EndRender();
112 function e_GetGamma(win
: PSDL_Window
): Byte;
113 procedure e_SetGamma(win
: PSDL_Window
;Gamma
: Byte);
116 procedure e_MakeScreenshot(st
: TStream
; Width
, Height
: Word);
118 //function e_getTextGLId (ID: DWORD): GLuint;
126 paszlib
, crc
, utils
, g_options
;
133 TTextureFont
= record
144 Chars
: array[0..255] of
154 TSavedTexture
= record
161 e_Textures
: array of TTexture
= nil;
162 e_TextureFonts
: array of TTextureFont
= nil;
163 e_CharFonts
: array of TCharFont
;
164 //e_SavedTextures: array of TSavedTexture;
167 e_RBOSupported
: Boolean = True;
169 e_FrameW
: Integer = -1;
170 e_FrameH
: Integer = -1;
172 //function e_getTextGLId (ID: DWORD): GLuint; begin result := e_Textures[ID].tx.id; end;
174 //------------------------------------------------------------------
175 // Инициализирует OpenGL
176 //------------------------------------------------------------------
177 procedure e_InitGL();
181 e_DummyTextures
:= True;
187 glDisable(GL_DEPTH_TEST
);
188 glEnable(GL_SCISSOR_TEST
);
189 glClearColor(0, 0, 0, 0);
192 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
194 mat
: Array [0..15] of GLDouble
;
197 if e_NoGraphics
then Exit
;
199 glScissor(X
, Y
, Width
, Height
);
200 glViewport(X
, Y
, Width
, Height
);
201 //gluOrtho2D(0, Width, Height, 0);
203 glMatrixMode(GL_PROJECTION
);
205 mat
[ 0] := 2.0 / Width
;
211 mat
[ 5] := -2.0 / Height
;
225 glLoadMatrixd(@mat
[0]);
227 glMatrixMode(GL_MODELVIEW
);
231 //------------------------------------------------------------------
232 // Ищет свободный элемент в массиве текстур
233 //------------------------------------------------------------------
234 function FindTexture(): DWORD
;
238 if e_Textures
<> nil then
239 for i
:= 0 to High(e_Textures
) do
240 if e_Textures
[i
].tx
.Width
= 0 then
246 if e_Textures
= nil then
248 SetLength(e_Textures
, 32);
253 Result
:= High(e_Textures
) + 1;
254 SetLength(e_Textures
, Length(e_Textures
) + 32);
258 //------------------------------------------------------------------
260 //------------------------------------------------------------------
261 function e_CreateTexture(FileName
: String; var ID
: DWORD
): Boolean;
268 e_WriteLog('Loading texture from '+FileName
, TMsgType
.Notify
);
270 find_id
:= FindTexture();
272 if not LoadTexture(FileName
, e_Textures
[find_id
].tx
, e_Textures
[find_id
].tx
.Width
,
273 e_Textures
[find_id
].tx
.Height
, @fmt
) then Exit
;
280 function e_CreateTextureEx(FileName
: String; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
287 find_id
:= FindTexture();
289 if not LoadTextureEx(FileName
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
296 function e_CreateTextureMem(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
): Boolean;
303 find_id
:= FindTexture
;
305 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
;
312 function e_CreateTextureMemEx(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
319 find_id
:= FindTexture();
321 if not LoadTextureMemEx(pData
, dataSize
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
328 function e_CreateTextureImg (var img
: TImageData
; var ID
: DWORD
): Boolean;
334 find_id
:= FindTexture();
335 if not LoadTextureImg(img
, e_Textures
[find_id
].tx
, tw
, th
, @fmt
) then exit
;
340 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
342 if Width
<> nil then Width
^ := e_Textures
[ID
].tx
.Width
;
343 if Height
<> nil then Height
^ := e_Textures
[ID
].tx
.Height
;
346 procedure DestroyFramebuffer
;
348 glBindTexture(GL_TEXTURE_2D
, 0);
349 glBindRenderbuffer(GL_RENDERBUFFER
, 0);
350 glBindFramebuffer(GL_FRAMEBUFFER
, 0);
354 glDeleteTextures(1, @e_Frame
);
360 glDeleteRenderbuffers(1, @e_RBO
);
366 glDeleteFramebuffers(1, @e_FBO
);
371 function e_ResizeFramebuffer(Width
, Height
: Integer): Boolean;
375 if e_NoGraphics
then Exit
;
384 glGenFramebuffers(1, @e_FBO
);
386 if glGetError() <> GL_NO_ERROR
then
388 e_LogWriteln('GL: glGenFramebuffers failed');
392 glGenTextures(1, @e_Frame
);
393 glBindTexture(GL_TEXTURE_2D
, e_Frame
);
394 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, Width
, Height
, 0, GL_RGB
, GL_UNSIGNED_BYTE
, nil);
395 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
396 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
398 if glGetError() <> GL_NO_ERROR
then
400 e_LogWriteln('GL: can''t create FBO color buffer');
405 glBindFramebuffer(GL_FRAMEBUFFER
, e_FBO
);
406 glFramebufferTexture2D(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, e_Frame
, 0);
407 if glCheckFramebufferStatus(GL_FRAMEBUFFER
) <> GL_FRAMEBUFFER_COMPLETE
then
409 e_LogWriteln('GL: can''t construct framebuffer with color attachment');
415 if e_RBOSupported
then
417 glGenRenderbuffers(1, @e_RBO
);
418 glBindRenderbuffer(GL_RENDERBUFFER
, e_RBO
);
419 glRenderbufferStorage(GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
, Width
, Height
);
420 glFramebufferRenderbuffer(GL_FRAMEBUFFER
, GL_DEPTH_STENCIL_ATTACHMENT
, GL_RENDERBUFFER
, e_RBO
);
421 if glCheckFramebufferStatus(GL_FRAMEBUFFER
) <> GL_FRAMEBUFFER_COMPLETE
then
423 e_LogWriteln('GL: can''t construct framebuffer with depth+stencil attachment, trying without');
424 e_RBOSupported
:= False;
425 Result
:= e_ResizeFramebuffer(Width
, Height
);
434 procedure e_ResizeWindow(Width
, Height
: Integer);
438 e_SetViewPort(0, 0, Width
, Height
);
441 procedure drawTxQuad (x0
, y0
, w
, h
, tw
, th
: Integer; u
, v
: single; Mirror
: TMirrorType
);
443 x1
, y1
, tmp
: Integer;
445 if (w
< 1) or (h
< 1) then exit
;
448 if Mirror
= TMirrorType
.Horizontal
then begin tmp
:= x1
; x1
:= x0
; x0
:= tmp
; end
449 else if Mirror
= TMirrorType
.Vertical
then begin tmp
:= y1
; y1
:= y0
; y0
:= tmp
; end;
450 glTexCoord2f(0, v
); glVertex2i(x0
, y0
);
451 glTexCoord2f(0, 0); glVertex2i(x0
, y1
);
452 glTexCoord2f(u
, 0); glVertex2i(x1
, y1
);
453 glTexCoord2f(u
, v
); glVertex2i(x1
, y0
);
456 procedure e_SetRenderTarget(Framebuffer
: Boolean);
458 if (e_FBO
= 0) or e_NoGraphics
then exit
;
460 glBindFramebuffer(GL_FRAMEBUFFER
, e_FBO
)
462 glBindFramebuffer(GL_FRAMEBUFFER
, 0);
465 procedure e_BlitFramebuffer(WinWidth
, WinHeight
: Integer);
467 if (e_FBO
= 0) or (e_Frame
= 0) or e_NoGraphics
then exit
;
470 glEnable(GL_TEXTURE_2D
);
471 glBindTexture(GL_TEXTURE_2D
, e_Frame
);
472 glColor4ub(255, 255, 255, 255);
475 glTexCoord2f(0, 1); glVertex2i( 0, 0);
476 glTexCoord2f(0, 0); glVertex2i( 0, WinHeight
);
477 glTexCoord2f(1, 0); glVertex2i(WinWidth
, WinHeight
);
478 glTexCoord2f(1, 1); glVertex2i(WinWidth
, 0);
482 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
483 Blending
: Boolean; Mirror
: TMirrorType
= TMirrorType
.None
);
485 if e_NoGraphics
then Exit
;
486 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
488 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
493 if (AlphaChannel
) or (Alpha
> 0) then
494 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
497 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
500 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
502 glEnable(GL_TEXTURE_2D
);
503 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
506 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
);
508 //u := e_Textures[ID].tx.u;
509 //v := e_Textures[ID].tx.v;
512 if Mirror = M_NONE then
514 glTexCoord2f(u, 0); glVertex2i(X + e_Textures[id].tx.Width, Y);
515 glTexCoord2f(0, 0); glVertex2i(X, Y);
516 glTexCoord2f(0, -v); glVertex2i(X, Y + e_Textures[id].tx.Height);
517 glTexCoord2f(u, -v); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height);
520 if Mirror = M_HORIZONTAL then
522 glTexCoord2f(u, 0); glVertex2i(X, Y);
523 glTexCoord2f(0, 0); glVertex2i(X + e_Textures[id].tx.Width, Y);
524 glTexCoord2f(0, -v); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height);
525 glTexCoord2f(u, -v); glVertex2i(X, Y + e_Textures[id].tx.Height);
528 if Mirror = M_VERTICAL then
530 glTexCoord2f(u, -v); glVertex2i(X + e_Textures[id].tx.Width, Y);
531 glTexCoord2f(0, -v); glVertex2i(X, Y);
532 glTexCoord2f(0, 0); glVertex2i(X, Y + e_Textures[id].tx.Height);
533 glTexCoord2f(u, 0); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height);
542 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
543 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
547 if e_NoGraphics
then Exit
;
548 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
550 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
555 if (AlphaChannel
) or (Alpha
> 0) then
556 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
559 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
562 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
564 glEnable(GL_TEXTURE_2D
);
565 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
567 u
:= e_Textures
[ID
].tx
.u
;
568 v
:= e_Textures
[ID
].tx
.v
;
571 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
572 glTexCoord2f(u
, v
); glVertex2i(X
+ Width
, Y
);
573 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
+ Height
);
574 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ Height
);
580 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
581 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= TMirrorType
.None
);
583 if e_NoGraphics
then Exit
;
584 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
586 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
591 if (AlphaChannel
) or (Alpha
> 0) then
592 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
595 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
598 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
600 glEnable(GL_TEXTURE_2D
);
601 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
603 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
);
609 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
610 AlphaChannel
: Boolean; Blending
: Boolean; ambientBlendMode
: Boolean=false);
612 X2
, Y2
, dx
, w
, h
: Integer;
615 if e_NoGraphics
then Exit
;
616 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
617 ambientBlendMode
:= false;
619 if (Alpha
> 0) or AlphaChannel
or Blending
then
625 if not ambientBlendMode
then glDisable(GL_BLEND
);
627 if AlphaChannel
or (Alpha
> 0) then glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
628 if (Alpha
> 0) then glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
629 if Blending
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
631 if (XCount
= 0) then XCount
:= 1;
632 if (YCount
= 0) then YCount
:= 1;
634 glEnable(GL_TEXTURE_2D
);
635 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
637 X2
:= X
+e_Textures
[ID
].tx
.width
*XCount
;
638 Y2
:= Y
+e_Textures
[ID
].tx
.height
*YCount
;
640 //k8: this SHOULD work... i hope
641 if (e_Textures
[ID
].tx
.width
= e_Textures
[ID
].tx
.glwidth
) and (e_Textures
[ID
].tx
.height
= e_Textures
[ID
].tx
.glheight
) then
644 glTexCoord2i(0, YCount
); glVertex2i(X
, Y
);
645 glTexCoord2i(XCount
, YCount
); glVertex2i(X2
, Y
);
646 glTexCoord2i(XCount
, 0); glVertex2i(X2
, Y2
);
647 glTexCoord2i(0, 0); glVertex2i(X
, Y2
);
654 u
:= e_Textures
[ID
].tx
.u
;
655 v
:= e_Textures
[ID
].tx
.v
;
656 w
:= e_Textures
[ID
].tx
.width
;
657 h
:= e_Textures
[ID
].tx
.height
;
664 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
665 glTexCoord2f(u
, v
); glVertex2i(X
+w
, Y
);
666 glTexCoord2f(u
, 0); glVertex2i(X
+w
, Y
+h
);
667 glTexCoord2f(0, 0); glVertex2i(X
, Y
+h
);
682 //TODO: overflow checks
683 function intersectRect (var x0
, y0
, w0
, h0
: Integer; const x1
, y1
, w1
, h1
: Integer): Boolean;
688 if (w0
< 1) or (h0
< 1) or (w1
< 1) or (h1
< 1) then exit
;
689 // check for intersection
690 if (x0
+w0
<= x1
) or (y0
+h0
<= y1
) or (x1
+w1
<= x0
) or (y1
+h1
<= y0
) then exit
;
691 if (x0
>= x1
+w1
) or (y0
>= y1
+h1
) or (x1
>= x0
+h0
) or (y1
>= y0
+h0
) then exit
;
695 if (x0
< x1
) then x0
:= x1
;
696 if (y0
< y1
) then y0
:= y1
;
697 if (ex0
> x1
+w1
) then ex0
:= x1
+w1
;
698 if (ey0
> y1
+h1
) then ey0
:= y1
+h1
;
701 result
:= (w0
> 0) and (h0
> 0);
705 procedure e_DrawFillX (id
: DWORD
; x
, y
, wdt
, hgt
: Integer; alpha
: Integer; alphachannel
: Boolean;
706 blending
: Boolean; scale
: Single; ambientBlendMode
: Boolean=false);
711 scxywh: array[0..3] of GLint;
712 vpxywh: array[0..3] of GLint;
714 w
, h
, dw
, cw
, ch
, yofs
: Integer;
715 u
, v
, cu
, cv
: Single;
719 procedure setScissorGLInternal (x, y, w, h: Integer);
721 //if not scallowed then exit;
726 y := vpxywh[3]-(y+h);
727 if not intersectRect(x, y, w, h, scxywh[0], scxywh[1], scxywh[2], scxywh[3]) then
729 glScissor(0, 0, 0, 0);
733 //writeln(' (', x, ',', y, ')-(', w, ',', h, ')');
734 glScissor(x, y, w, h);
740 if e_NoGraphics
then exit
;
741 ambientBlendMode
:= false;
743 if (wdt
< 1) or (hgt
< 1) then exit
;
745 if (wdt
mod e_Textures
[ID
].tx
.width
= 0) and (hgt
mod e_Textures
[ID
].tx
.height
= 0) then
747 e_DrawFill(id
, x
, y
, wdt
div e_Textures
[ID
].tx
.width
, hgt
div e_Textures
[ID
].tx
.height
, alpha
, alphachannel
, blending
, ambientBlendMode
);
751 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
753 if (Alpha
> 0) or AlphaChannel
or Blending
then
759 if not ambientBlendMode
then glDisable(GL_BLEND
);
761 if AlphaChannel
or (Alpha
> 0) then glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
762 if (Alpha
> 0) then glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
763 if Blending
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
765 glEnable(GL_TEXTURE_2D
);
766 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
771 //k8: this SHOULD work... i hope
772 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
775 glTexCoord2f(0, hgt
/e_Textures
[ID
].tx
.height
); glVertex2i(x
, y
);
776 glTexCoord2f(wdt
/e_Textures
[ID
].tx
.width
, hgt
/e_Textures
[ID
].tx
.height
); glVertex2i(x2
, y
);
777 glTexCoord2f(wdt
/e_Textures
[ID
].tx
.width
, 0); glVertex2i(x2
, y2
);
778 glTexCoord2f(0, 0); glVertex2i(x
, y2
);
783 // hard day's night; setup scissor
785 glGetIntegerv(GL_VIEWPORT, @vpxywh[0]);
786 wassc := (glIsEnabled(GL_SCISSOR_TEST) <> 0);
787 if wassc then glGetIntegerv(GL_SCISSOR_BOX, @scxywh[0]) else glGetIntegerv(GL_VIEWPORT, @scxywh[0]);
788 //writeln('(', scxywh[0], ',', scxywh[1], ')-(', scxywh[2], ',', scxywh[3], ')');
789 //glEnable(GL_SCISSOR_TEST);
790 setScissorGLInternal(x, y, wdt, hgt);
793 u
:= e_Textures
[ID
].tx
.u
;
794 v
:= e_Textures
[ID
].tx
.v
;
795 w
:= e_Textures
[ID
].tx
.width
;
796 h
:= e_Textures
[ID
].tx
.height
;
798 if (hgt
> h
) then begin y
+= hgt
-h
; onlyOneY
:= false; end else onlyOneY
:= true;
802 if (hgt
>= h
) then begin ch
:= h
; cv
:= v
; yofs
:= 0; end else begin ch
:= hgt
; cv
:= v
/(h
/hgt
); yofs
:= h
-hgt
; end;
803 if onlyOneY
then yofs
:= 0;
809 if (dw
>= w
) then begin cw
:= w
; cu
:= u
; end else begin cw
:= dw
; cu
:= u
/(w
/dw
); end;
811 glTexCoord2f(0, cv
); glVertex2i(X
, Y
+yofs
);
812 glTexCoord2f(cu
, cv
); glVertex2i(X
+cw
, Y
+yofs
);
813 glTexCoord2f(cu
, 0); glVertex2i(X
+cw
, Y
+ch
+yofs
);
814 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ch
+yofs
);
820 //if wassc then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST);
827 procedure e_AmbientQuad (x
, y
, w
, h
: Integer; r
, g
, b
, a
: Byte);
829 if e_NoGraphics
then exit
;
830 if (w
< 1) or (h
< 1) then exit
;
831 if (a
<> 255) or ((r
or g
or b
) <> 0) then
834 glDisable(GL_TEXTURE_2D
);
835 glColor4ub(r
, g
, b
, a
);
836 if ((r
or g
or b
) <> 0) then
838 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
842 glVertex2i(x
+w
, y
+h
);
846 glBlendFunc(GL_ZERO
, GL_SRC_ALPHA
);
850 glVertex2i(x
+w
, y
+h
);
858 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
859 Blending
: Boolean; Angle
: Single; RC
: PDFPoint
; Mirror
: TMirrorType
= TMirrorType
.None
);
861 if e_NoGraphics
then Exit
;
863 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
865 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
870 if (AlphaChannel
) or (Alpha
> 0) then
871 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
874 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
877 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
879 if (Angle
<> 0) and (RC
<> nil) then
882 glTranslatef(X
+RC
.X
, Y
+RC
.Y
, 0);
883 glRotatef(Angle
, 0, 0, 1);
884 glTranslatef(-(X
+RC
.X
), -(Y
+RC
.Y
), 0);
887 glEnable(GL_TEXTURE_2D
);
888 glBindTexture(GL_TEXTURE_2D
, e_Textures
[id
].tx
.id
);
889 glBegin(GL_QUADS
); //0-1 1-1
891 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
);
900 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
902 if e_NoGraphics
then Exit
;
903 glDisable(GL_TEXTURE_2D
);
904 glColor3ub(Red
, Green
, Blue
);
907 if (Size
= 2) or (Size
= 4) then
911 glVertex2f(X
+0.3, Y
+1.0);
914 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
917 procedure e_LineCorrection(var X1
, Y1
, X2
, Y2
: Integer);
919 // Make lines only top-left/bottom-right and top-right/bottom-left
931 // Pixel-perfect hack
939 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
941 nX1
, nY1
, nX2
, nY2
: Integer;
943 if e_NoGraphics
then Exit
;
944 // Only top-left/bottom-right quad
961 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
966 glDisable(GL_TEXTURE_2D
);
967 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
970 nX1
:= X1
; nY1
:= Y1
;
971 nX2
:= X2
; nY2
:= Y1
;
972 e_LineCorrection(nX1
, nY1
, nX2
, nY2
); // Pixel-perfect lines
973 glVertex2i(nX1
, nY1
);
974 glVertex2i(nX2
, nY2
);
976 nX1
:= X2
; nY1
:= Y1
;
977 nX2
:= X2
; nY2
:= Y2
;
978 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
979 glVertex2i(nX1
, nY1
);
980 glVertex2i(nX2
, nY2
);
982 nX1
:= X2
; nY1
:= Y2
;
983 nX2
:= X1
; nY2
:= Y2
;
984 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
985 glVertex2i(nX1
, nY1
);
986 glVertex2i(nX2
, nY2
);
988 nX1
:= X1
; nY1
:= Y2
;
989 nX2
:= X1
; nY2
:= Y1
;
990 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
991 glVertex2i(nX1
, nY1
);
992 glVertex2i(nX2
, nY2
);
994 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
998 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
999 Blending
: TBlending
= TBlending
.None
);
1001 if e_NoGraphics
then Exit
;
1002 if (Alpha
> 0) or (Blending
<> TBlending
.None
) then
1005 glDisable(GL_BLEND
);
1008 TBlending
.None
: if Alpha
> 0 then glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1009 TBlending
.Blend
: glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
1010 TBlending
.Invert
: glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
);
1011 TBlending
.Filter
: glBlendFunc(GL_ZERO
, GL_SRC_COLOR
);
1014 glDisable(GL_TEXTURE_2D
);
1015 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
1027 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1028 glDisable(GL_BLEND
);
1032 // ////////////////////////////////////////////////////////////////////////// //
1033 procedure e_DarkenQuad (x0
, y0
, x1
, y1
: Integer; a
: Integer);
1035 if (a
< 0) then a
:= 0;
1036 if (a
> 255) then a
:= 255;
1038 glBlendFunc(GL_ZERO
, GL_SRC_ALPHA
);
1039 glDisable(GL_TEXTURE_2D
);
1040 glColor4ub(0, 0, 0, Byte(255-a
));
1047 //glRect(x, y, x+w, y+h);
1048 glColor4ub(1, 1, 1, 1);
1049 glDisable(GL_BLEND
);
1050 //glBlendEquation(GL_FUNC_ADD);
1053 procedure e_DarkenQuadWH (x
, y
, w
, h
: Integer; a
: Integer);
1055 if (w
> 0) and (h
> 0) then e_DarkenQuad(x
, y
, x
+w
, y
+h
, a
);
1059 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
1061 if e_NoGraphics
then Exit
;
1062 // Pixel-perfect lines
1064 e_LineCorrection(X1
, Y1
, X2
, Y2
);
1069 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1071 glDisable(GL_BLEND
);
1073 glDisable(GL_TEXTURE_2D
);
1074 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
1080 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1082 glDisable(GL_BLEND
);
1085 //------------------------------------------------------------------
1086 // Удаляет текстуру из массива
1087 //------------------------------------------------------------------
1088 procedure e_DeleteTexture(ID
: DWORD
);
1090 if not e_NoGraphics
then
1091 glDeleteTextures(1, @e_Textures
[ID
].tx
.id
);
1092 e_Textures
[ID
].tx
.id
:= 0;
1093 e_Textures
[ID
].tx
.Width
:= 0;
1094 e_Textures
[ID
].tx
.Height
:= 0;
1097 //------------------------------------------------------------------
1098 // Удаляет все текстуры
1099 //------------------------------------------------------------------
1100 procedure e_RemoveAllTextures();
1104 if e_Textures
= nil then Exit
;
1106 for i
:= 0 to High(e_Textures
) do
1107 if e_Textures
[i
].tx
.Width
<> 0 then e_DeleteTexture(i
);
1111 //------------------------------------------------------------------
1113 //------------------------------------------------------------------
1114 procedure e_ReleaseEngine();
1116 e_RemoveAllTextures
;
1117 e_RemoveAllTextureFont
;
1120 procedure e_BeginRender();
1122 if e_NoGraphics
then Exit
;
1123 glEnable(GL_ALPHA_TEST
);
1124 glAlphaFunc(GL_GREATER
, 0.0);
1127 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
1129 if e_NoGraphics
then Exit
;
1130 glClearColor(Red
, Green
, Blue
, 0);
1134 procedure e_Clear(Red
, Green
, Blue
: Single); overload
;
1136 if e_NoGraphics
then Exit
;
1137 glClearColor(Red
, Green
, Blue
, 0);
1138 glClear(GL_COLOR_BUFFER_BIT
);
1141 procedure e_Clear(); overload
;
1143 if e_NoGraphics
then Exit
;
1144 glClearColor(0, 0, 0, 0);
1145 glClear(GL_COLOR_BUFFER_BIT
);
1148 procedure e_EndRender();
1150 if e_NoGraphics
then Exit
;
1155 function e_GetGamma(win
: PSDL_Window
): Byte;
1157 ramp
: array [0..256*3-1] of Word;
1158 rgb
: array [0..2] of Double;
1167 if e_NoGraphics
then Exit
;
1172 SDL_GetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
1181 for j
:= min
to max
- 1 do
1184 B
:= (j
mod 256)/256;
1186 sum
:= sum
+ ln(A
)/ln(B
);
1189 rgb
[i
] := sum
/ count
;
1192 Result
:= 100 - Trunc(((rgb
[0] + rgb
[1] + rgb
[2])/3 - 0.23) * 100/(2.7 - 0.23));
1195 procedure e_SetGamma(win
: PSDL_Window
; Gamma
: Byte);
1197 ramp
: array [0..256*3-1] of Word;
1202 if e_NoGraphics
then Exit
;
1203 g
:= (100 - Gamma
)*(2.7 - 0.23)/100 + 0.23;
1205 for i
:= 0 to 255 do
1207 r
:= Exp(g
* ln(i
/256))*65536;
1208 if r
< 0 then r
:= 0
1209 else if r
> 65535 then r
:= 65535;
1210 ramp
[i
] := trunc(r
);
1211 ramp
[i
+ 256] := trunc(r
);
1212 ramp
[i
+ 512] := trunc(r
);
1215 SDL_SetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
1219 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
1223 e_WriteLog('Creating CharFont...', TMsgType
.Notify
);
1227 if e_CharFonts
<> nil then
1228 for i
:= 0 to High(e_CharFonts
) do
1229 if not e_CharFonts
[i
].alive
then
1235 if id
= DWORD(-1) then
1237 SetLength(e_CharFonts
, Length(e_CharFonts
) + 1);
1238 id
:= High(e_CharFonts
);
1241 with e_CharFonts
[id
] do
1243 for i
:= 0 to High(Chars
) do
1257 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
1259 with e_CharFonts
[FontID
].Chars
[Ord(c
)] do
1261 TextureID
:= Texture
;
1266 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1270 if e_NoGraphics
then Exit
;
1271 if Text = '' then Exit
;
1272 if e_CharFonts
= nil then Exit
;
1273 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1275 with e_CharFonts
[FontID
] do
1277 for a
:= 1 to Length(Text) do
1278 with Chars
[Ord(Text[a
])] do
1279 if TextureID
<> -1 then
1281 e_Draw(TextureID
, X
, Y
, 0, True, False);
1282 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1287 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
1288 Color
: TRGB
; Scale
: Single = 1.0);
1293 if e_NoGraphics
then Exit
;
1294 if Text = '' then Exit
;
1295 if e_CharFonts
= nil then Exit
;
1296 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1298 with e_CharFonts
[FontID
] do
1300 for a
:= 1 to Length(Text) do
1301 with Chars
[Ord(Text[a
])] do
1302 if TextureID
<> -1 then
1304 if Scale
<> 1.0 then
1307 glScalef(Scale
, Scale
, 0);
1312 e_Draw(TextureID
, X
, Y
, 0, True, False);
1315 if Scale
<> 1.0 then glPopMatrix
;
1317 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1322 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1324 a
, TX
, TY
, len
: Integer;
1328 if e_NoGraphics
then Exit
;
1329 if Text = '' then Exit
;
1330 if e_CharFonts
= nil then Exit
;
1331 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1339 len
:= Length(Text);
1341 e_CharFont_GetSize(FontID
, 'A', w
, h
);
1343 with e_CharFonts
[FontID
] do
1345 for a
:= 1 to len
do
1356 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1361 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1366 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1371 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1376 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1381 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1386 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1391 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1396 with Chars
[Ord(Text[a
])] do
1397 if TextureID
<> -1 then
1401 e_Draw(TextureID
, TX
, TY
, 0, True, False);
1404 TX
:= TX
+Width
+IfThen(a
= Length(Text), 0, Space
);
1410 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
1418 if Text = '' then Exit
;
1419 if e_CharFonts
= nil then Exit
;
1420 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1422 with e_CharFonts
[FontID
] do
1424 for a
:= 1 to Length(Text) do
1425 with Chars
[Ord(Text[a
])] do
1426 if TextureID
<> -1 then
1428 w
:= w
+Width
+IfThen(a
= Length(Text), 0, Space
);
1429 e_GetTextureSize(TextureID
, nil, @h2
);
1430 if h2
> h
then h
:= h2
;
1435 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
1437 a
, lines
, len
: Integer;
1438 h2
, w2
, tw
, th
: Word;
1445 if Text = '' then Exit
;
1446 if e_CharFonts
= nil then Exit
;
1447 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1450 len
:= Length(Text);
1452 with e_CharFonts
[FontID
] do
1454 for a
:= 1 to len
do
1456 if Text[a
] = #10 then
1459 if w2
> tw
then tw
:= w2
;
1464 with Chars
[Ord(Text[a
])] do
1465 if TextureID
<> -1 then
1467 w2
:= w2
+ Width
+ IfThen(a
= len
, 0, Space
);
1468 e_GetTextureSize(TextureID
, nil, @h2
);
1469 if h2
> th
then th
:= h2
;
1481 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
1487 if e_CharFonts
= nil then Exit
;
1488 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1490 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1491 Result
:= Max(Result
, e_CharFonts
[FontID
].Chars
[a
].Width
);
1494 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
1501 if e_CharFonts
= nil then Exit
;
1502 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1504 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1506 if e_CharFonts
[FontID
].Chars
[a
].TextureID
<> -1 then
1507 e_GetTextureSize(e_CharFonts
[FontID
].Chars
[a
].TextureID
, nil, @h2
)
1509 if h2
> Result
then Result
:= h2
;
1513 procedure e_CharFont_Remove(FontID
: DWORD
);
1517 with e_CharFonts
[FontID
] do
1518 for a
:= 0 to High(Chars
) do
1519 if Chars
[a
].TextureID
<> -1 then e_DeleteTexture(Chars
[a
].TextureID
);
1521 e_CharFonts
[FontID
].alive
:= False;
1524 procedure e_CharFont_RemoveAll();
1528 if e_CharFonts
= nil then Exit
;
1530 for a
:= 0 to High(e_CharFonts
) do
1531 e_CharFont_Remove(a
);
1536 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
1545 if e_NoGraphics
then Exit
;
1546 e_WriteLog('Creating texture font...', TMsgType
.Notify
);
1550 if e_TextureFonts
<> nil then
1551 for i
:= 0 to High(e_TextureFonts
) do
1552 if e_TextureFonts
[i
].Base
= 0 then
1558 if id
= DWORD(-1) then
1560 SetLength(e_TextureFonts
, Length(e_TextureFonts
) + 1);
1561 id
:= High(e_TextureFonts
);
1564 with e_TextureFonts
[id
] do
1567 Base
:= glGenLists(XCount
*YCount
);
1569 TextureID
:= e_Textures
[Tex
].tx
.id
;
1570 CharWidth
:= (e_Textures
[Tex
].tx
.Width
div XCount
)+Space
;
1571 CharHeight
:= e_Textures
[Tex
].tx
.Height
div YCount
;
1579 glBindTexture(GL_TEXTURE_2D
, e_Textures
[Tex
].tx
.id
);
1580 for loop1
:= 0 to XCount
*YCount
-1 do
1582 cx
:= (loop1
mod XCount
)/XCount
;
1583 cy
:= (loop1
div YCount
)/YCount
;
1585 glNewList(e_TextureFonts
[id
].Base
+loop1
, GL_COMPILE
);
1587 glTexCoord2f(cx
, 1.0-cy
-1/YCount
);
1588 glVertex2i(0, e_Textures
[Tex
].tx
.Height
div YCount
);
1590 glTexCoord2f(cx
+1/XCount
, 1.0-cy
-1/YCount
);
1591 glVertex2i(e_Textures
[Tex
].tx
.Width
div XCount
, e_Textures
[Tex
].tx
.Height
div YCount
);
1593 glTexCoord2f(cx
+1/XCount
, 1.0-cy
);
1594 glVertex2i(e_Textures
[Tex
].tx
.Width
div XCount
, 0);
1596 glTexCoord2f(cx
, 1.0-cy
);
1599 glTranslated((e_Textures
[Tex
].tx
.Width
div XCount
)+Space
, 0, 0);
1607 procedure e_TextureFontKill(FontID
: DWORD
);
1609 if e_NoGraphics
then Exit
;
1611 glDeleteLists(e_TextureFonts
[FontID
].Base
, 256);
1613 e_TextureFonts
[FontID
].Base
:= 0;
1616 {$IFNDEF NOGL_LISTS}
1617 procedure e_TextureFontDrawChar(ch
: Char; FontID
: DWORD
);
1622 Width
, Height
: Integer;
1623 XCount
, YCount
: Integer;
1625 index
:= Ord(ch
) - 32;
1626 Tex
:= e_TextureFonts
[FontID
].Texture
;
1627 Width
:= e_Textures
[Tex
].tx
.Width
;
1628 Height
:= e_Textures
[Tex
].tx
.Height
;
1629 XCount
:= e_TextureFonts
[FontID
].XC
;
1630 YCount
:= e_TextureFonts
[FontID
].YC
;
1631 cx
:= (index
mod XCount
)/XCount
;
1632 cy
:= (index
div YCount
)/YCount
;
1634 glTexCoord2f(cx
, 1 - cy
- 1/YCount
);
1635 glVertex2i(0, Height
div YCount
);
1636 glTexCoord2f(cx
+ 1/XCount
, 1 - cy
- 1/YCount
);
1637 glVertex2i(Width
div XCount
, Height
div YCount
);
1638 glTexCoord2f(cx
+ 1/XCount
, 1 - cy
);
1639 glVertex2i(Width
div XCount
, 0);
1640 glTexCoord2f(cx
, 1 - cy
);
1643 glTranslatef((e_Textures
[Tex
].tx
.Width
div XCount
) + e_TextureFonts
[FontID
].SPC
, 0, 0);
1646 procedure e_TextureFontDrawString(Text: String; FontID
: DWORD
);
1650 for i
:= 1 to High(Text) do
1651 e_TextureFontDrawChar(Text[i
], FontID
);
1655 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
1657 if e_NoGraphics
then Exit
;
1658 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1659 if Text = '' then Exit
;
1661 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1664 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1667 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1668 glEnable(GL_TEXTURE_2D
);
1669 glTranslatef(x
, y
, 0);
1671 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1672 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1674 e_TextureFontDrawString(Text, FontID
);
1676 glDisable(GL_TEXTURE_2D
);
1679 glDisable(GL_BLEND
);
1682 // god forgive me for this, but i cannot figure out how to do it without lists
1683 procedure e_TextureFontPrintChar(X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
1685 if e_NoGraphics
then Exit
;
1690 glColor4ub(0, 0, 0, 128);
1691 glTranslatef(X
+1, Y
+1, 0);
1693 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1695 e_TextureFontDrawChar(Ch
, FontID
);
1701 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1702 glTranslatef(X
, Y
, 0);
1704 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1706 e_TextureFontDrawChar(Ch
, FontID
);
1712 procedure e_TextureFontPrintCharEx (X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
1714 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1715 glEnable(GL_TEXTURE_2D
);
1716 //glListBase(DWORD(Integer(e_TextureFonts[FontID].Base)-32));
1718 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1720 e_TextureFontPrintChar(X
, Y
, Ch
, FontID
, Shadow
);
1721 glDisable(GL_TEXTURE_2D
);
1722 glDisable(GL_BLEND
);
1725 function e_TextureFontCharWidth (ch
: Char; FontID
: DWORD
): Integer;
1727 result
:= e_TextureFonts
[FontID
].CharWidth
;
1730 procedure e_TextureFontPrintFmt(X
, Y
: GLint
; Text: string; FontID
: DWORD
;
1731 Shadow
: Boolean = False; Newlines
: Boolean = False);
1733 a
, TX
, TY
, len
: Integer;
1737 if e_NoGraphics
then Exit
;
1738 if Text = '' then Exit
;
1739 if e_TextureFonts
= nil then Exit
;
1740 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1748 len
:= Length(Text);
1750 w
:= e_TextureFonts
[FontID
].CharWidth
;
1751 h
:= e_TextureFonts
[FontID
].CharHeight
;
1753 with e_TextureFonts
[FontID
] do
1755 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1756 glEnable(GL_TEXTURE_2D
);
1759 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1762 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1765 for a
:= 1 to len
do
1779 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1784 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1789 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1794 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1799 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1804 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1809 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1814 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1821 e_TextureFontPrintChar(TX
, TY
, Text[a
], FontID
, Shadow
);
1826 glDisable(GL_TEXTURE_2D
);
1827 glDisable(GL_BLEND
);
1831 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
1832 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
1834 if e_NoGraphics
then Exit
;
1835 if Text = '' then Exit
;
1838 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1839 glEnable(GL_TEXTURE_2D
);
1842 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1845 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1850 glColor4ub(0, 0, 0, 128);
1851 glTranslatef(x
+1, y
+1, 0);
1852 glScalef(Scale
, Scale
, 0);
1854 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1856 e_TextureFontDrawString(Text, FontID
);
1862 glColor4ub(Red
, Green
, Blue
, 255);
1863 glTranslatef(x
, y
, 0);
1864 glScalef(Scale
, Scale
, 0);
1866 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1868 e_TextureFontDrawString(Text, FontID
);
1871 glDisable(GL_TEXTURE_2D
);
1873 glColor3ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
);
1874 glDisable(GL_BLEND
);
1877 procedure e_TextureFontGetSize(ID
: DWORD
; out CharWidth
, CharHeight
: Byte);
1881 if e_NoGraphics
then Exit
;
1882 if Integer(ID
) > High(e_TextureFonts
) then
1884 CharWidth
:= e_TextureFonts
[ID
].CharWidth
;
1885 CharHeight
:= e_TextureFonts
[ID
].CharHeight
;
1888 procedure e_RemoveAllTextureFont();
1892 if e_NoGraphics
then Exit
;
1893 if e_TextureFonts
= nil then Exit
;
1895 for i
:= 0 to High(e_TextureFonts
) do
1896 if e_TextureFonts
[i
].Base
<> 0 then
1899 glDeleteLists(e_TextureFonts
[i
].Base
, 256);
1901 e_TextureFonts
[i
].Base
:= 0;
1904 e_TextureFonts
:= nil;
1907 procedure e_MakeScreenshot (st
: TStream
; Width
, Height
: Word);
1909 pixels
, obuf
, scln
, ps
, pd
: PByte;
1912 i
, x
, y
, res
: Integer;
1913 sign
: array [0..7] of Byte;
1914 hbuf
: array [0..12] of Byte;
1919 if e_NoGraphics
then Exit
;
1922 // first, extract and pack graphics data
1923 if (Width
mod 4) > 0 then Width
:= Width
+4-(Width
mod 4);
1925 GetMem(pixels
, Width
*Height
*3);
1927 FillChar(pixels
^, Width
*Height
*3, 0);
1928 glReadPixels(0, 0, Width
, Height
, GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
1929 //e_WriteLog('PNG: pixels read', MSG_NOTIFY);
1931 if e_FastScreenshots
then
1934 GetMem(scln
, (Width
*3+1)*Height
);
1938 Inc(ps
, (Width
*3)*(Height
-1));
1939 for i
:= 0 to Height
-1 do
1943 Move(ps
^, pd
^, Width
*3);
1955 obufsize
:= (Width
*3+1)*Height
*2;
1956 GetMem(obuf
, obufsize
);
1961 res
:= compress2(Pointer(obuf
), dlen
, Pointer(pixels
), (Width
*3+1)*Height
, 9);
1962 if res
= Z_OK
then break
;
1963 if res
<> Z_BUF_ERROR
then raise Exception
.Create('can''t pack data for PNG');
1964 obufsize
:= obufsize
*2;
1967 GetMem(obuf
, obufsize
);
1969 //e_WriteLog(Format('PNG: pixels compressed from %d to %d', [Integer(Width*Height*3), Integer(dlen)]), MSG_NOTIFY);
1982 st
.writeBuffer(sign
, 8);
1983 //e_WriteLog('PNG: signature written', MSG_NOTIFY);
1986 writeIntBE(st
, LongWord(13));
1991 st
.writeBuffer(sign
, 4);
1992 crc
:= crc32(0, @sign
[0], 4);
1995 hbuf
[2] := (Width
shr 8) and $ff;
1996 hbuf
[3] := Width
and $ff;
1999 hbuf
[6] := (Height
shr 8) and $ff;
2000 hbuf
[7] := Height
and $ff;
2001 hbuf
[8] := 8; // bit depth
2002 hbuf
[9] := 2; // RGB
2003 hbuf
[10] := 0; // compression method
2004 hbuf
[11] := 0; // filter method
2005 hbuf
[12] := 0; // no interlace
2006 crc
:= crc32(crc
, @hbuf
[0], 13);
2007 st
.writeBuffer(hbuf
, 13);
2008 writeIntBE(st
, crc
);
2009 //e_WriteLog('PNG: header written', MSG_NOTIFY);
2012 writeIntBE(st
, LongWord(dlen
));
2017 st
.writeBuffer(sign
, 4);
2018 crc
:= crc32(0, @sign
[0], 4);
2019 crc
:= crc32(crc
, obuf
, dlen
);
2020 st
.writeBuffer(obuf
^, dlen
);
2021 writeIntBE(st
, crc
);
2022 //e_WriteLog('PNG: image data written', MSG_NOTIFY);
2025 writeIntBE(st
, LongWord(0));
2030 st
.writeBuffer(sign
, 4);
2031 crc
:= crc32(0, @sign
[0], 4);
2032 writeIntBE(st
, crc
);
2033 //e_WriteLog('PNG: end marker written', MSG_NOTIFY);
2035 if obuf
<> nil then FreeMem(obuf
);
2040 Imaging
.SetOption(ImagingPNGCompressLevel
, 9);
2041 Imaging
.SetOption(ImagingPNGPreFilter
, 6);
2044 NewImage(Width
, Height
, TImageFormat
.ifR8G8B8
, img
);
2046 //writeln(stderr, 'moving pixels...');
2047 for y
:= Height
-1 downto 0 do
2049 for x
:= 0 to Width
-1 do
2051 clr
.r
:= ps
^; Inc(ps
);
2052 clr
.g
:= ps
^; Inc(ps
);
2053 clr
.b
:= ps
^; Inc(ps
);
2055 SetPixel32(img
, x
, y
, clr
);
2058 GlobalMetadata
.ClearMetaItems();
2059 GlobalMetadata
.ClearMetaItemsForSaving();
2060 //writeln(stderr, 'compressing image...');
2061 if not SaveImageToStream('png', st
, img
) then raise Exception
.Create('screenshot writing error');
2062 //writeln(stderr, 'done!');