Unit GLImages

DescriptionusesClasses, Interfaces, Objects and RecordsFunctions and ProceduresTypesConstantsVariables

Description

Using images in OpenGL (as textures and as normal images).

This unit implements various OpenGL utilities relates to handling images in TImage classes. This includes

See Images unit for functions to load, save, process images. Images unit is the non-OpenGL-related helper of this unit.

This unit hides from you some specifics of OpenGL images handling :

Internally, this unit depends on the knowledge on how pixels are stored in TRGBImage and similar classes. For example we know that TRGBImage stores image in format that OpenGL would call "GL_RGB using GL_UNSIGNED_BYTE, without any alignment". Which means that Image.RGBPixels is a pointer to array like packed array[0..Image.Height - 1, 0..Image.Width - 1] of TVector3Byte. So we have rows of TVector3Byte structures, stored from lowest row to highest row.

uses

Overview

Functions and Procedures

function ImageGLFormat(const Img: TImage): TGLenum;
function ImageGLType(const Img: TImage): TGLenum;
function LoadImageToDisplayList(const FileName: string; const LoadAsClass: array of TImageClass; const LoadForbiddenConvs: TImageLoadConversions; const ResizeToX, ResizeToY: Cardinal): TGLuint; overload;
procedure ImageDraw(const Image: TImage);
procedure ImageDrawRows(const Image: TImage; Row0, RowsCount: integer);
procedure ImageDrawCutted(const image: TImage; cutx, cuty: cardinal);
function ImageDrawToDisplayList(const img: TImage): TGLuint;
procedure SaveScreen_noflush(const FileName: string; ReadBuffer: TGLenum); overload;
function SaveScreen_noflush(ReadBuffer: TGLenum): TRGBImage; overload;
function SaveScreen_noflush(xpos, ypos, width, height: integer; ReadBuffer: TGLenum): TRGBImage; overload;
function SaveScreenToDisplayList_noflush(ReadBuffer: TGLenum): TGLuint; overload;
function SaveScreenToDisplayList_noflush(xpos, ypos, width, height: integer; ReadBuffer: TGLenum): TGLuint; overload;
procedure ResizeForTextureSize(var r: TImage);
function ResizeToTextureSize(const r: TImage): TImage;
function IsTextureSized(const r: TImage): boolean;
function LoadGLTexture(const image: TImage; minFilter, magFilter: TGLenum; GrayscaleIsAlpha: boolean = false): TGLuint; overload;
function LoadGLTexture(const image: TImage; minFilter, magFilter, WrapS, WrapT: TGLenum; GrayscaleIsAlpha: boolean = false): TGLuint; overload;
function LoadGLTexture(const FileName: string; minFilter, magFilter, WrapS, WrapT: TGLenum; GrayscaleIsAlpha: boolean = false): TGLuint; overload;
procedure LoadGLGeneratedTexture(texnum: TGLuint; const image: TImage; minFilter, magFilter, wrapS, wrapT: TGLenum; GrayscaleIsAlpha: boolean = false); overload;
procedure LoadGLGeneratedTexture(texnum: TGLuint; const image: TImage; minFilter, magFilter: TGLenum; GrayscaleIsAlpha: boolean = false); overload;
function LoadGLTextureModulated(const Image: TImage; MinFilter, MagFilter, WrapS, WrapT: TGLenum; ColorModulatorByte: TColorModulatorByteFunc): TGLuint;

Constants

GLImageClasses: array [0..2] of TImageClass = ( TRGBImage, TAlphaImage, TGrayscaleImage);

Description

Functions and Procedures

function ImageGLFormat(const Img: TImage): TGLenum;

These functions return appropriate GL_xxx format and type for given TImage descendant. If you will pass here Img that is not a descendant of one of GLImageClasses, they will return GL_INVALID_ENUM.

Note that OpenGL does not guarantee that GL_INVALID_ENUM <> GL_RGB, GL_RGBA etc. (even if every OpenGL implementation has constants defined that in a way that satisfies this). So better to not assume that instead of checking InImageClasses(MyImage, GLImageClasses) you can simply check ImageGLFormat(MyImage) <> GL_INVALID_ENUM.

(But this fact can be used to make routines in this unit like ImageDraw work faster, because I don't guarantee anywhere that ImageDraw will check at runtime that passed Image has class in GLImageClasses. So ImageDraw simply passes to OpenGL values returned by ImageGLFormat/Type, so in case of incorrect Image class OpenGL will get GL_INVALID_ENUM. Since it's not guaranteed that GL_INVALID_ENUM <> GL_RGB etc., it's not guaranteed that OpenGL will singal error, but it was never guaranteed that ImageDraw will signal some error in this case.

So this way ImageDraw does not do any checks using GLImageFormats, even when compiled with -dDEBUG. Everything is done in OpenGL. And, in practice, current OpenGL implementations *will* signal errors so things are checked.).

function ImageGLType(const Img: TImage): TGLenum;
 
function LoadImageToDisplayList(const FileName: string; const LoadAsClass: array of TImageClass; const LoadForbiddenConvs: TImageLoadConversions; const ResizeToX, ResizeToY: Cardinal): TGLuint; overload;

This calls Images.LoadImage and creates a display-list with an ImageDraw call for this image. Image will be loaded with AllowedImageClasses = LoadAsClass and ForbiddenConvs = LoadForbiddenConvs, see Images.LoadImage for description what these parameters mean. LoadAsClass may contain only classes present in GLImageClasses.

procedure ImageDraw(const Image: TImage);

Draws the image as 2D on screen. This calls OpenGL glDrawPixels command on this image.

Don't worry about OpenGL's UNPACK_ALIGNMENT, we will take care here about this (changing it and restoring to previous value if necessary).

procedure ImageDrawRows(const Image: TImage; Row0, RowsCount: integer);

Same as ImageDraw, but will draw only RowsCount rows starting from Row0.

procedure ImageDrawCutted(const image: TImage; cutx, cuty: cardinal);

Same as ImageDraw, but will omit 1st CutX columns (1st from the left) and 1st CutY rows (1st from down).

This is implemented using glPixelStorei(GL_UNPACK_ROW_LENGTH / GL_UNPACK_SKIP_PIXELS / GL_UNPACK_SKIP_ROWS). So it works fast. Don't worry, we will take care here of changing (and later restoring to previous values) such unpack settings, just like GL_UNPACK_ALIGNMENT.

function ImageDrawToDisplayList(const img: TImage): TGLuint;

This creates new display list with a call to ImageDraw(Img) inside.

procedure SaveScreen_noflush(const FileName: string; ReadBuffer: TGLenum); overload;

Saves the current color buffer contents to an image file or to TRGBImage object. Sidenote: useful function to generate image filename for game screenshots is FnameAutoInc in KambiUtils unit.

It does glReadBuffer(ReadBuffer) and then glReadPixels with appropriate parameters. In case of overloaded version that takes a FileName, it then saves image to file using SaveImage.

It has such strange name (_noflush) to remind you that this function does not do anything like TGLWindow.FlushRedisplay but you should usually take care of doing something like that before saving contents of OpenGL front buffer. In other words, remember that this function saves the *current* contents of color buffer – so be sure that it contains what you want before using this function.

Note that you can pass here any ReadBuffer value allowed by glReadBuffer OpenGL function).

function SaveScreen_noflush(ReadBuffer: TGLenum): TRGBImage; overload;
 
function SaveScreen_noflush(xpos, ypos, width, height: integer; ReadBuffer: TGLenum): TRGBImage; overload;
 
function SaveScreenToDisplayList_noflush(ReadBuffer: TGLenum): TGLuint; overload;

Saves the current color buffer (captured like SaveScreen_noflush) into the display list to redraw it. That is, it returns newly created display list that contains call to ImageDraw on a captured image.

function SaveScreenToDisplayList_noflush(xpos, ypos, width, height: integer; ReadBuffer: TGLenum): TGLuint; overload;
 
procedure ResizeForTextureSize(var r: TImage);

Resizes the image to a size accepted as texture size for OpenGL. It tries to resize to larger size, not smaller, to avoid losing image information. Usually you don't have to call this, LoadGLTexture* functions call it automatically when needed.

function ResizeToTextureSize(const r: TImage): TImage;
 
function IsTextureSized(const r: TImage): boolean;

Tests if texture has proper size for OpenGL, that is for passing it to glTexImage2d. This checks glGet(GL_MAX_TEXTURE_SIZE), so requires initialized OpenGL context.

function LoadGLTexture(const image: TImage; minFilter, magFilter: TGLenum; GrayscaleIsAlpha: boolean = false): TGLuint; overload;

Load new texture. It generates new texture number by glGenTextures. This takes care of UNPACK_ALIGNMENT (if needed, we'll change it and later revert back, so that the texture is correctly loaded).

If you omit WrapS / WrapT parameters then they will not be set (so default OpenGL values will be used, since we always initialize new texture here).

Changes currently bound texture to this one (returned).

GrayscaleIsAlpha is meaningful only if the image is TGrayscaleImage class. If GrayscaleIsAlpha is False, then we'll load GL_LUMINANCE texture (this basically behaves like normal RGB texture, except that it has only one channel and stores grayscale colors). If GrayscaleIsAlpha is True, the texture will be loaded as GL_ALPHA texture (it will modify only the fragments alpha value, it doesn't have any "color" in the normal sense, it's only for opacity).

function LoadGLTexture(const image: TImage; minFilter, magFilter, WrapS, WrapT: TGLenum; GrayscaleIsAlpha: boolean = false): TGLuint; overload;
 
function LoadGLTexture(const FileName: string; minFilter, magFilter, WrapS, WrapT: TGLenum; GrayscaleIsAlpha: boolean = false): TGLuint; overload;
 
procedure LoadGLGeneratedTexture(texnum: TGLuint; const image: TImage; minFilter, magFilter, wrapS, wrapT: TGLenum; GrayscaleIsAlpha: boolean = false); overload;

Load texture into already reserved texture number.

Besides this, works exactly like LoadGLTexture. If you omit WrapS / WrapT parameters then they will not be set. Changes currently bound texture to TexNum.

You can use this to set "default unnamed OpenGL texture" parameters by passing TexNum = 0.

procedure LoadGLGeneratedTexture(texnum: TGLuint; const image: TImage; minFilter, magFilter: TGLenum; GrayscaleIsAlpha: boolean = false); overload;
 
function LoadGLTextureModulated(const Image: TImage; MinFilter, MagFilter, WrapS, WrapT: TGLenum; ColorModulatorByte: TColorModulatorByteFunc): TGLuint;

As LoadGLTexture, but the texture will be modified using ColorModulatorByte. If not Assigned(ColorModulatorByte) then this will simply return LoadGLTexture(Image, MinFilter, MagFilter, WrapS, WrapT). Else it will return LoadGLTexture(ImageModulated(Image), MinFilter, MagFilter, WrapS, WrapT) (without introducing any memoty leaks).

Constants

GLImageClasses: array [0..2] of TImageClass = ( TRGBImage, TAlphaImage, TGrayscaleImage);

All routines in this unit that take TImage paramater accept only TImage descendants enumerated here. Note that *not everywhere* this is checked (especially if you compile with -dRELEASE) so just be sure that you're always passing only TImage instances of correct class (e.g. using InImageClasses(MyImage, GLImageClasses)).


Generated by PasDoc 0.10.0 on 2008-02-25 00:00:30