Class TDrawableImage

Unit

Declaration

type TDrawableImage = class(TNoParameterlessContructor)

Description

Image that can be drawn. This image can be drawn in various rendering methods and events, e.g. inside overridden TCastleUserInterface.Render or from events TCastleWindow.OnRender or TCastleControl.OnRender.

See the manual about drawing using TDrawableImage: https://castle-engine.io/manual_2d_ui_custom_drawn.php . See the description how to render 2D stuff using Castle Game Engine: https://castle-engine.io/how_to_render_2d .

We have a few (probably too many) ways to show a 2D image. Alternatives to TDrawableImage are:

Hierarchy

Overview

Nested Types

Published TColorTreatment = (...);

Fields

Public nested const DefaultBlendingSourceFactor = bsSrcAlpha;
Public nested const DefaultBlendingDestinationFactor = bdOneMinusSrcAlpha;
Public nested const DefaultBlendingConstantColor: TVector4 = (X: 1; Y: 1; Z: 1; W: 1);

Methods

Public constructor Create(const AImage: TEncodedImage; const ASmoothScaling: boolean; const AOwnsImage: boolean); overload;
Public constructor Create(const AURL: string; const ASmoothScaling: boolean = true); overload;
Public constructor Create(const AURL: string; const LoadAsClass: array of TEncodedImageClass; const ResizeToX: Cardinal = 0; const ResizeToY: Cardinal = 0; const Interpolation: TResizeInterpolation = riBilinear); overload;
Public constructor Create(const AURL: string; const LoadAsClass: array of TEncodedImageClass; const ASmoothScaling: boolean); overload;
Public destructor Destroy; override;
Public function Rect: TRectangle;
Public procedure Draw(const X, Y: Single); overload;
Public procedure Draw(const X, Y, DrawWidth, DrawHeight: Single); overload;
Public procedure Draw(const X, Y, DrawWidth, DrawHeight: Single; const ImageX, ImageY, ImageWidth, ImageHeight: Single); overload;
Public procedure Draw(const Pos: TVector2Integer); overload;
Public procedure Draw(const ScreenRect: TFloatRectangle); overload;
Public procedure Draw(const ScreenRect, ImageRect: TFloatRectangle); overload;
Public procedure Draw(const ScreenRect: TRectangle); overload;
Public procedure Draw(const ScreenRect: TRectangle; const ImageX, ImageY, ImageWidth, ImageHeight: Single); overload;
Public procedure Draw(const ScreenRect, ImageRect: TRectangle); overload;
Public procedure Draw(ScreenRects, ImageRects: PFloatRectangleArray; const Count: Integer); overload; virtual;
Public procedure DrawFlipped(const ScreenRect: TRectangle; const FlipHorizontal, FlipVertical: boolean); overload;
Public procedure DrawFlipped(const ScreenRect: TFloatRectangle; const FlipHorizontal, FlipVertical: boolean); overload;
Public procedure DrawFlipped(const ScreenRect: TFloatRectangle; ImageRect: TFloatRectangle; const FlipHorizontal, FlipVertical: boolean); overload;
Public procedure Draw3x3(const X, Y, DrawWidth, DrawHeight: Single; const CornerTop, CornerRight, CornerBottom, CornerLeft: Single); overload;
Public procedure Draw3x3(const X, Y, DrawWidth, DrawHeight: Single; const Corner: TVector4Integer); overload;
Public procedure Draw3x3(const ScreenRect: TRectangle; const Corner: TVector4Integer); overload;
Public procedure Draw3x3(const ScreenRect: TFloatRectangle; const Corner: TVector4Integer); overload;
Public procedure Draw3x3(const ScreenRect: TFloatRectangle; const Corner: TVector4); overload;
Public procedure Load(const AImage: TEncodedImage); virtual;
Public procedure PrepareResources;
Public function GetContents(const ImageClass: TCastleImageClass): TCastleImage;
Public procedure RenderToImageBegin(const SetAndRestoreViewport: boolean = true);
Public procedure RenderToImageEnd;
Public procedure RenderToImageFree;
Public procedure DrawFrom(const SourceImage: TDrawableImage; const DestinationRect, SourceRect: TFloatRectangle);

Properties

Public property Width: Cardinal read FWidth;
Public property Height: Cardinal read FHeight;
Public property Alpha: TAutoAlphaChannel read FAlpha write FAlpha default acAuto;
Public property BlendingSourceFactor: TBlendingSourceFactor read FBlendingSourceFactor write FBlendingSourceFactor default DefaultBlendingSourceFactor;
Public property BlendingDestinationFactor: TBlendingDestinationFactor read FBlendingDestinationFactor write FBlendingDestinationFactor default DefaultBlendingDestinationFactor;
Public property BlendingConstantColor: TVector4 read FBlendingConstantColor write FBlendingConstantColor;
Public property ScaleCorners: Single read FScaleCorners write FScaleCorners default 1;
Public property IgnoreTooLargeCorners: boolean read FIgnoreTooLargeCorners write FIgnoreTooLargeCorners default true;
Public property Color: TCastleColor read FColor write FColor;
Public property SmoothScaling: boolean read FSmoothScaling write SetSmoothScaling;
Public property ScalingPossible: boolean read FSmoothScaling write SetSmoothScaling; deprecated 'use SmoothScaling';
Public property CenterX: Single read GetCenterX write SetCenterX default 0.5; deprecated 'use RotationCenter';
Public property CenterY: Single read GetCenterY write SetCenterY default 0.5; deprecated 'use RotationCenter';
Public property RotationCenter: TVector2 read FRotationCenter write FRotationCenter;
Public property Rotation: Single read FRotation write FRotation default 0;
Public property Clip: boolean read FClip write FClip;
Public property ClipLine: TVector3 read FClipLine write FClipLine;
Public property Texture: TGLTextureId read FTexture;
Public property CustomShader: TGLSLProgram read FCustomShader write FCustomShader;
Public property Image: TEncodedImage read FImage write SetImage;
Public property OwnsImage: boolean read FOwnsImage write FOwnsImage;
Public property URL: String read FURL write SetURL;
Public property RepeatS: Boolean read FRepeatS write SetRepeatS default false;
Public property RepeatT: Boolean read FRepeatT write SetRepeatT default false;

Description

Nested Types

Published TColorTreatment = (...);

Used only in shader pipeline

Values
  • ctPureTexture: Use texture color to draw.
  • ctColorMultipliesTexture: Use constant color * texture (on all RGBA channels).
  • ctColorMultipliesTextureAlpha: Use constant color for RGB, for alpha use constant color.a * texture. Useful when texture has no alpha information.

Fields

Public nested const DefaultBlendingSourceFactor = bsSrcAlpha;
 
Public nested const DefaultBlendingDestinationFactor = bdOneMinusSrcAlpha;
 
Public nested const DefaultBlendingConstantColor: TVector4 = (X: 1; Y: 1; Z: 1; W: 1);
 

Methods

Public constructor Create(const AImage: TEncodedImage; const ASmoothScaling: boolean; const AOwnsImage: boolean); overload;

Prepare image for drawing.

Parameters
Image
Initial image contents. The Image instance passed here must exist throughout the whole lifetime of this TDrawableImage instance (so don't free it earlier). It can be automatically freed by us, if OwnsImage = True.

It can be Nil.

Exceptions raised
EImageClassNotSupportedForOpenGL
When Image class is not supported by OpenGL.
Public constructor Create(const AURL: string; const ASmoothScaling: boolean = true); overload;

Load image from disk, and prepare for drawing.

Parameters
AURL
URL (or filename) from which to load the image. Often you want to use here castle-data:/ protocol to load application data, like:

Image := TDrawableImage.Create('castle-data:/textures/my_image.png', ...);

See https://castle-engine.io/manual_data_directory.php

ASmoothScaling
The initial value of SmoothScaling, determines whether the image scaling is smooth (bilinear filtering) or not (nearest-pixel filtering). You can always change it later through the SmoothScaling property. But each change has a small cost, so it's more efficient to just set the initial value correctly.
Public constructor Create(const AURL: string; const LoadAsClass: array of TEncodedImageClass; const ResizeToX: Cardinal = 0; const ResizeToY: Cardinal = 0; const Interpolation: TResizeInterpolation = riBilinear); overload;

Load image from disk, and prepare for drawing.

Parameters
AURL
URL (or filename) from which to load the image. Usually you want to use here URL starting with the "castle-data:" protocol, to load an image from application data, like this:

Image := TDrawableImage.Create('castle-data:/textures/my_image.png', ...);

LoadAsClass
Constrain the possible image classes to load into. This can force removing (or adding) an alpha channel, or converting contents to grayscale or RGB, regardless of the preferred image file format. Must be a subset of PixelsImageClasses, as other classes cannot be loaded into OpenGL 2D images, otherwise you may get EImageClassNotSupportedForOpenGL exception. Pass empty set [] to load into any allowed class (it's equivalent to passing LoadAsClass = PixelsImageClasses).

You can pass e.g. [TRGBImage] to force loading into an RGB image without an alpha channel (it will be stripped from the image if necessary).

ResizeToX
After loading, resize to given width. Pass 0 to not resize width.
ResizeToY
After loading, resize to given height. Pass 0 to not resize height.
Interpolation
If any resizing will be needed (if ResizeToX / ResizeToY parameters request some specific size, and it is different than loaded image size) then the resize operation will use given interpolation.
Exceptions raised
EImageClassNotSupportedForOpenGL
When image class is not supported by OpenGL.
Public constructor Create(const AURL: string; const LoadAsClass: array of TEncodedImageClass; const ASmoothScaling: boolean); overload;

Load image from disk, and prepare for drawing.

Parameters
AURL
URL (or filename) from which to load the image. Often you want to pass here the result ot ApplicationData function, like:

Image := TDrawableImage.Create('castle-data:/textures/my_image.png', ...);

LoadAsClass
Constrain the possible image classes to load into. This can force removing (or adding) an alpha channel, or converting contents to grayscale or RGB, regardless of the preferred image file format. Must be a subset of PixelsImageClasses, as other classes cannot be loaded into OpenGL 2D images, otherwise you may get EImageClassNotSupportedForOpenGL exception. Pass empty set [] to load into any allowed class (it's equivalent to passing LoadAsClass = PixelsImageClasses).

You can pass e.g. [TRGBImage] to force loading into an RGB image without an alpha channel (it will be stripped from the image if necessary).

ASmoothScaling
The initial value of SmoothScaling, determines whether the image scaling is smooth (bilinear filtering) or not (nearest-pixel filtering). You can always change it later through the SmoothScaling property. But each change has a small cost, so it's more efficient to just set the initial value correctly.
Public destructor Destroy; override;
 
Public function Rect: TRectangle;

Rectangle representing the inside of this image. Always (Left,Bottom) are zero, and (Width,Height) correspond to image sizes.

Public procedure Draw(const X, Y: Single); overload;

Draw the image as 2D on screen.

The X, Y parameters determine where the left-bottom corner of the image will be placed (from 0 to size - 1).

You should only use this inside TCastleUserInterface.Render. We require that current projection is 2D and lighting / depth test and such are off, which is the default state there.

The image is drawn in 2D. In normal circumstances 1 pixel of the image is just placed over 1 pixel of the screen, and we draw the whole image. But you can use the overloaded versions where you specify DrawWidth, DrawHeight or ScreenRect, and then the indicated image portion is stretched over the designated screen area. Note: if you plan to use such stretching when drawing the image, then you usually want to create the image with SmoothScaling = True (otherwise the scaling will look pixelated).

Note that the image position (ImageX, ImageY) is specified like a texture coordinate. So (0, 0) is actually the left-bottom corner of the left-bottom pixel, and (Width,Height) is the right-top corner of the right-top pixel. That is why image position and sizes are floats, it makes sense to render partial pixels this way (make sure you have SmoothScaling = True to get nice scaling of image contents).

You can also flip the image horizontally or vertically, e.g. use ImageX = Width and ImageWidth = -Width to mirror image horizontally. Although it's usually more comfortable to flip using DrawFlipped methods.

Public procedure Draw(const X, Y, DrawWidth, DrawHeight: Single); overload;
 
Public procedure Draw(const X, Y, DrawWidth, DrawHeight: Single; const ImageX, ImageY, ImageWidth, ImageHeight: Single); overload;
 
Public procedure Draw(const Pos: TVector2Integer); overload;
 
Public procedure Draw(const ScreenRect: TFloatRectangle); overload;
 
Public procedure Draw(const ScreenRect, ImageRect: TFloatRectangle); overload;
 
Public procedure Draw(const ScreenRect: TRectangle); overload;
 
Public procedure Draw(const ScreenRect: TRectangle; const ImageX, ImageY, ImageWidth, ImageHeight: Single); overload;
 
Public procedure Draw(const ScreenRect, ImageRect: TRectangle); overload;
 
Public procedure Draw(ScreenRects, ImageRects: PFloatRectangleArray; const Count: Integer); overload; virtual;
 
Public procedure DrawFlipped(const ScreenRect: TRectangle; const FlipHorizontal, FlipVertical: boolean); overload;
 
Public procedure DrawFlipped(const ScreenRect: TFloatRectangle; const FlipHorizontal, FlipVertical: boolean); overload;
 
Public procedure DrawFlipped(const ScreenRect: TFloatRectangle; ImageRect: TFloatRectangle; const FlipHorizontal, FlipVertical: boolean); overload;
 
Public procedure Draw3x3(const X, Y, DrawWidth, DrawHeight: Single; const CornerTop, CornerRight, CornerBottom, CornerLeft: Single); overload;

Draw the image on the screen, divided into 3x3 parts for corners, sides, and inside.

Just like the regular Draw method, this fills a rectangle on the 2D screen, with bottom-left corner in (X, Y), and size (DrawWidth, DrawHeight). The image is divided into 3 * 3 = 9 parts:

  • 4 corners, used to fill the corners of the screen rectangle. They are not stretched.

  • 4 sides, used to fill the sides of the screen rectangle between the corners. They are scaled in one dimension, to fill the space between corners completely.

  • the inside. Used to fill the rectangular inside. Scaled in both dimensions as necessary.

Public procedure Draw3x3(const X, Y, DrawWidth, DrawHeight: Single; const Corner: TVector4Integer); overload;
 
Public procedure Draw3x3(const ScreenRect: TRectangle; const Corner: TVector4Integer); overload;
 
Public procedure Draw3x3(const ScreenRect: TFloatRectangle; const Corner: TVector4Integer); overload;
 
Public procedure Draw3x3(const ScreenRect: TFloatRectangle; const Corner: TVector4); overload;
 
Public procedure Load(const AImage: TEncodedImage); virtual;

Load the given image contents. Use this to efficiently replace the image contents on GPU. Updates the Width, Height, Alpha to correspond to new image.

It is valid (and reasonable) to call this with AImage instance equal to the image instance that you used when creating this TDrawableImage. That's because TDrawableImage does not automatically update the image contents (once they were loaded to GPU) when you change the underlying TEncodedImage instance.

It is valid to pass Nil as parameter.

Do not call this method too often. This methos copies the image contents from TEncodedImage to GPU, which is not something you want to do every frame. Doing this occasionally, or during the loading/preparation stage, is OK. Doing this often, e.g. during every TCastleWindow.OnRender or TCastleWindow.OnUpdate, will hurt your performance. During the game, it's most efficient to treat the TDrawableImage instances as "constant" – avoid changing their contents, avoid creating new ones.

Public procedure PrepareResources;

Prepare all the possible resources. Since we may load OpenGL resources on-demand (if the TDrawableImage instance was created when OpenGL context was not available yet), this method can be used to force loading OpenGL resources now (if possible). This is only useful if you want to avoid slowdown when loading it later, and prefer to do the loading now.

Public function GetContents(const ImageClass: TCastleImageClass): TCastleImage;

Get the image contents from GPU to CPU.

Exceptions raised
ECannotSaveTextureContents
If we cannot get texture contents (not supported on OpenGLES).
Public procedure RenderToImageBegin(const SetAndRestoreViewport: boolean = true);

Start rendering to this image, using an efficient GPU method ("Framebuffer Object", FBO). Remember that the result lives only on GPU (the underlying TEncodedImage, in normal RAM memory, is not updated by this drawing in any way).

Between RenderToImageBegin and RenderToImageEnd you can use various rendering methods, like

Calling the RenderToImageBegin for the first time automatically creates a TGLRenderToTexture descendant suitable for rendering to this texture. It is automatically released on certain events, you can also explicitly release it by RenderToImageFree.

Public procedure RenderToImageEnd;
 
Public procedure RenderToImageFree;
 
Public procedure DrawFrom(const SourceImage: TDrawableImage; const DestinationRect, SourceRect: TFloatRectangle);

Draw a SourceImage over this image.

The drawing is done completely on GPU (using the RenderToImageBegin). This is a much faster alternative to drawing using TCastleImage.DrawFrom (that happens on CPU). The result "lives" only on GPU (the underlying TEncodedImage, in normal RAM memory, is not updated by this drawing in any way).

If you use this only occasionally, it's nice to later free the resources by RenderToImageFree.

Properties

Public property Width: Cardinal read FWidth;
 
Public property Height: Cardinal read FHeight;
 
Public property Alpha: TAutoAlphaChannel read FAlpha write FAlpha default acAuto;

How to render the alpha channel of the texture.

  • acAuto means to guess correct alpha channel from the loaded image contents, and the current Color. We use alpha blending if the loaded image alpha indicates so, or Color[3] < 1. Otherwise we use alpha testing if the loaded image alpha indicates so. Otherwise we don't use any alpha, we render image opaque.

  • acNone means to ignore it.

  • acTest means to render with alpha-test.

  • acBlending means to render with blending.

This is initialized based on loaded image class and data. This means that e.g. if you have smooth alpha channel in the image, it will be automatically rendered with nice blending.

You can change the value of this property to force a specific rendering method, for example to force using alpha test or alpha blending regardless of alpha values. Or to disable alpha channel usage, because your image must always cover pixels underneath.

Remember that you can also change the alpha channel existence at loading: use LoadAsClass parameters of LoadImage or TDrawableImage.Create to force your image to have/don't have an alpha channel (e.g. use LoadAsClass=[TRGBImage] to force RGB image without alpha, use LoadAsClass=[TRGBAlphaImage] to force alpha channel).

Public property BlendingSourceFactor: TBlendingSourceFactor read FBlendingSourceFactor write FBlendingSourceFactor default DefaultBlendingSourceFactor;

Blending source factor, if we use blending (see Alpha).

Public property BlendingDestinationFactor: TBlendingDestinationFactor read FBlendingDestinationFactor write FBlendingDestinationFactor default DefaultBlendingDestinationFactor;

Blending destination factor, if we use blending (see Alpha).

Public property BlendingConstantColor: TVector4 read FBlendingConstantColor write FBlendingConstantColor;

For some blending source or destination factors (see BlendingSourceFactor, BlendingDestinationFactor), this constant color (or it's alpha value) take part in the blending equation. Used only if blending (see Alpha). By default, opaque white.

Public property ScaleCorners: Single read FScaleCorners write FScaleCorners default 1;

In case of Draw3x3 the corners on screen are scaled by this amount. This is especially useful for UI scaling, see TCastleContainer.UIScaling and TCastleUserInterface.UIScale.

Public property IgnoreTooLargeCorners: boolean read FIgnoreTooLargeCorners write FIgnoreTooLargeCorners default true;

Ignore (do not log to CastleLog) situations when Draw3x3 cannot work because corners are larger than draw area size. Set this to True when it's perfectly possible (you do not want to even see it in log) for Draw3x3 calls to fail because corners are larger than draw area size.

This is True by default now, since it's safer for UI rendering. Otherwise causing this problem makes a flood of errors to the log file, and it's easy to make this problem when your UI adjusts to the screen size.

Public property Color: TCastleColor read FColor write FColor;

Color to multiply the texture contents (all RGBA channels). By default this is White, which is (1, 1, 1, 1) as RGBA, and it means that texture contents are not actually modified. This case is also optimized when possible, to no multiplication will actually happen.

When the color's alpha is < 1, then we automatically use blending, if Alpha is acAuto (regardless of the image alpha channel, in this case).

Note that if you use TGrayscaleImage with TGrayscaleImage.TreatAsAlpha (which means that texture does not contain any RGB information), then only this color's RGB values determine the drawn RGB color.

Public property SmoothScaling: boolean read FSmoothScaling write SetSmoothScaling;

Is the image scaling mode smooth (bilinear filtering) or not (nearest-pixel filtering). This is important if you draw the image such that one image pixel does not perfectly fit one screen pixel.

If you will not ever do any scaling, then set this to False. It may cause minimally faster drawing, and avoids any possible artifacts from bilinear filtering.

If you will do scaling, you usually want to set this to True, unless you deliberately want a pixelated look (for pixelart).

Note that switching this property after this object is constructed is possible, but costly.

Public property ScalingPossible: boolean read FSmoothScaling write SetSmoothScaling; deprecated 'use SmoothScaling';

Warning: this symbol is deprecated: use SmoothScaling

 
Public property CenterX: Single read GetCenterX write SetCenterX default 0.5; deprecated 'use RotationCenter';

Warning: this symbol is deprecated: use RotationCenter

X coordinate of the center of rotation. Value from 0 to 1. Default value 0.5.

Public property CenterY: Single read GetCenterY write SetCenterY default 0.5; deprecated 'use RotationCenter';

Warning: this symbol is deprecated: use RotationCenter

Y coordinate of the center of rotation. Value from 0 to 1. Default value 0.5.

Public property RotationCenter: TVector2 read FRotationCenter write FRotationCenter;

Center of rotation. Expressed as a fraction within the drawn ScreenRectangle, (0,0) means bottom-left corner, (1,1) means top-right corner. Default (0.5,0.5).

Public property Rotation: Single read FRotation write FRotation default 0;

Rotation in radians. Increase to rotate in a counter-clockwise direction. Hint: use function like ArcTan2 from Math unit to convert 2D direction into a rotation angle.

Public property Clip: boolean read FClip write FClip;

Clip the image by an arbitrary 2D line defined in ClipLine.

Public property ClipLine: TVector3 read FClipLine write FClipLine;

If Clip, this is the line equation used to determine whether we clip the given pixel. Given a line (A, B, C) and pixel (x, y), the pixel is clipped (rejected) if A * x + B * y + C < 0.

The line equation works in texture coordinates. If the image is drawn complete on the screen, texture coordinates span from (0,0) at bottom-left to (1,1) top-right.

For example ClipLine = (1, 0, -0.5) means that we reject pixels where 1 * x + 0 * y - 0.5 < 0. In other words, we reject pixels where x < 0.5, so we reject the left half of the image.

Public property Texture: TGLTextureId read FTexture;

Internal OpenGL texture identifier.

You cannot free it (e.g. by glFreeTexture), and you cannot change it's parameters (because TDrawableImage assumes it controls all the texture parameters). For normal drawing, you do not need this (use Draw or other rendering routines in this class), but it may be useful to integrate with external rendering systems.

Public property CustomShader: TGLSLProgram read FCustomShader write FCustomShader;

Use a custom shader for image rendering.

The shader must define the same uniform variables and attributes as the standard TDrawableImage shader, like viewport_size, vertex, tex_coord. See for example our default shader code: https://github.com/castle-engine/castle-engine/blob/master/src/images/opengl/glsl/source/image.vs https://github.com/castle-engine/castle-engine/blob/master/src/images/opengl/glsl/source/image.fs .

See also example examples/images_videos/image_render_custom_shader.lpr .

Note that some uniforms/attributes are only used in some cases. For example, when TDrawableImage.Color is White (1, 1, 1, 1), then we don't pass "color" uniform. When TDrawableImage.Clip is False, then we don't pass "clip_line" uniform. When assigning your custom shader, you take responsibility of setting the shader that matches the current TDrawableImage properties.

You can (and should, if possible) reuse a single TGLSLProgram instance for many TDrawableImage and TCastleImageControl instances (as TDrawableImage.CustomShader and TCastleImageControl.CustomShader). You can also use your own uniforms in your shader code, of course.

Public property Image: TEncodedImage read FImage write SetImage;
 
Public property OwnsImage: boolean read FOwnsImage write FOwnsImage;
 
Public property URL: String read FURL write SetURL;

URL of currently loaded image. Non-empty only if the image was loaded from URL.

Public property RepeatS: Boolean read FRepeatS write SetRepeatS default false;

Repeat or clamp texture in S (width) or T (height) dimensions.

Public property RepeatT: Boolean read FRepeatT write SetRepeatT default false;
 

Generated by PasDoc 0.16.0.