Class TGLRenderToTexture

Unit

Declaration

type TGLRenderToTexture = class(TObject)

Description

Rendering to texture with OpenGL. Uses framebuffer (if available), and has fallback to glCopyTexSubImage2D for (really) old OpenGL implementations.

Hierarchy

Overview

Methods

Public constructor Create(const AWidth, AHeight: Cardinal);
Public destructor Destroy; override;
Public procedure SetTexture(const ATexture: TGLTextureId; const ATextureTarget: TGLenum);
Public procedure GLContextOpen;
Public procedure GLContextClose;
Public procedure RenderBegin;
Public procedure RenderEnd(const RenderBeginFollows: boolean = false);
Public procedure GenerateMipmap;
Public function ColorBuffer: TColorBuffer;
Public function SaveScreen(const ImageClass: TCastleImageClass; const Rect: TRectangle): TCastleImage;

Properties

Public property Width: Cardinal read FWidth write FWidth;
Public property Height: Cardinal read FHeight write FHeight;
Public property Texture: TGLTextureId read FTexture default 0;
Public property TextureTarget: TGLenum read FTextureTarget default GL_TEXTURE_2D;
Public property CompleteTextureTarget: TGLenum read FCompleteTextureTarget write FCompleteTextureTarget default GL_TEXTURE_2D;
Public property DepthTexture: TGLTextureId read FDepthTexture write FDepthTexture;
Public property DepthTextureTarget: TGLenum read FDepthTextureTarget write FDepthTextureTarget default GL_TEXTURE_2D;
Public property Buffer: TGLRenderToTextureBuffer read FBuffer write FBuffer default tbColor;
Public property Stencil: boolean read FStencil write FStencil default true;
Public property ColorBufferAlpha: boolean read FColorBufferAlpha write FColorBufferAlpha default false;
Public property MultiSampling: Cardinal read FMultiSampling write FMultiSampling default 1;

Description

Methods

Public constructor Create(const AWidth, AHeight: Cardinal);

Constructor. Doesn't require OpenGL context, and doesn't initialize the framebuffer. You'll have to use GLContextOpen before actually making Render.

Public destructor Destroy; override;
 
Public procedure SetTexture(const ATexture: TGLTextureId; const ATextureTarget: TGLenum);

Change Texture and TextureTarget.

May be changed also when OpenGL stuff (framebuffer) is already initialized. This is useful, as it allows you to reuse framebuffer setup for rendering to different textures (as long as other settings are Ok, like Width and Height).

It may even be changed between RenderBegin and RenderEnd. In fact, this is advised, if you have to call SetTexture often: SetTexture call outside of RenderBegin / RenderEnd causes two costly BindFramebuffer calls, that may be avoided when you're already between RenderBegin / RenderEnd.

Public procedure GLContextOpen;

Initialize OpenGL stuff (framebuffer).

When OpenGL stuff is initialized (from GLContextOpen until GLContextClose or destruction) this class is tied to the current OpenGL context.

Exceptions raised
EFramebufferSizeTooLow
When required Width x Height is larger than maximum renderbuffer (single buffer within framebuffer) size.
EFramebufferInvalid
When framebuffer is used, and check glCheckFramebufferStatusEXT fails. This should not happen, it means a programmer error. Or "unsupported" result of glCheckFramebufferStatusEXT (that is possible regardless of programmer) we have a nice fallback to non-FBO implementation.
Public procedure GLContextClose;

Release all OpenGL stuff (if anything initialized). This is also automatically called in destructor.

Public procedure RenderBegin;

Begin rendering into the texture. Commands following this will render to the texture image.

When framebuffer is used, it's bound here.

When framebuffer is not used, this doesn't do anything. So note that all rendering will be done to normal screen in this case.

Public procedure RenderEnd(const RenderBeginFollows: boolean = false);

End rendering into the texture.

When framebuffer is used, this binds the normal screen back.

When framebuffer is not used, this does actual copying from the screen to the texture using glCopyTexSubImage2D. We use glCopyTexSubImage2D — which means texture internal format should already be initialized! If you don't have any initial texture data, you can always initialize by glTexImage2D with Nil as pointer to data.

During copying, we may change OpenGL bound 2D texture and read buffer. So their values are ignored, and may be changed arbitrarily, by this method.

Parameters
RenderBeginFollows
This allows for an optimizaion, to minimize the number of BindFramebuffer calls when you render many textures in the row using the same TGLRenderToTexture. If True, then you must call RenderBegin after this (before drawing anything else to OpenGL). We will internally leave framebuffer bound, which means that this RenderEnd and the very next RenderBegin will actually do nothing.
Public procedure GenerateMipmap;

Generate mipmaps for the texture. This will use glGenerateMipmap call, which is actually a part of EXT_framebuffer_object extension (or GL core together with framebuffer in GL core), so it will always raise EGenerateMipmapNotAvailable if framebuffer is not available.

You should use HasGenerateMipmap and never call this if not HasGenerateMipmap, if you don't want to get this exception.

Exceptions raised
EGenerateMipmapNotAvailable
If glGenerateMipmap not available.
Public function ColorBuffer: TColorBuffer;

Color buffer name. Use only when Buffer = tbNone, between GLContextOpen and GLContextClose. This is the buffer name that you should pass to SaveScreen_NoFlush, currently it's just rbColorAttachment0 if we actually have FBO or rbBack if not.

Public function SaveScreen(const ImageClass: TCastleImageClass; const Rect: TRectangle): TCastleImage;

Save the screen to an image. Call this between RenderBegin and RenderEnd.

Properties

Public property Width: Cardinal read FWidth write FWidth;

Width and height must correspond to texture initialized width / height. You cannot change them when OpenGL stuff is already initialized (after GLContextOpen and before GLContextClose or destructor).

Public property Height: Cardinal read FHeight write FHeight;
 
Public property Texture: TGLTextureId read FTexture default 0;

Texture associated with the rendered buffer image. If Buffer is tbColor or tbColorAndDepth then we will capture here color contents. If Buffer is tbDepth then we will capture here depth contents (useful e.g. for shadow maps). If If Buffer is tbNone, this is ignored.

We require this texture to be set to a valid texture (not 0) before GLContextOpen (unless Buffer is tbNone). Also, if you later change it, be careful to assign here other textures of only the same size and format. This allows us to call glCheckFramebufferStatusEXT (and eventually fallback to non-stencil version) right at GLContextOpen call, and no need to repeat it (e.g. at each RenderBegin).

Changed by SetTexture.

Public property TextureTarget: TGLenum read FTextureTarget default GL_TEXTURE_2D;

Target of texture associated with rendered buffer. This is GL_TEXTURE_2D for normal 2D textures, but may also be GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X etc. for other texture types.

Companion to Texture property, changed together by SetTexture.

Public property CompleteTextureTarget: TGLenum read FCompleteTextureTarget write FCompleteTextureTarget default GL_TEXTURE_2D;

Bind target of texture associated with rendered color buffer. "Bind target" means that it describes the whole texture, for example for cube map it should be GL_TEXTURE_CUBE_MAP.

Public property DepthTexture: TGLTextureId read FDepthTexture write FDepthTexture;

Depth texture used when Buffer = tbColorAndDepth. Note that this is not used when Buffer = tbDepth (the Texture and TextureTarget are used then). This must be set before GLContextOpen, and not modified later until GLContextClose.

Public property DepthTextureTarget: TGLenum read FDepthTextureTarget write FDepthTextureTarget default GL_TEXTURE_2D;
 
Public property Buffer: TGLRenderToTextureBuffer read FBuffer write FBuffer default tbColor;

Which buffer (color and/or depth) should we catch to the texture.

For tbDepth and tbColorAndDepth, the texture that will receive depth contents must have GL_DEPTH_COMPONENT* format, and we'll render depth buffer contents to it.

For tbDepth, if the framebuffer is used (normal on recent GPUs), we will not write to the color buffer at all, so this is quite optimal for rendering shadow maps.

This must be set before GLContextOpen, cannot be changed later.

Public property Stencil: boolean read FStencil write FStencil default true;

Should we require stencil buffer.

This is usually safe, as FBO spec even requires that some format with stencil buffer must be available.

However, this has a high chance to fail if you need Buffer = tbDepth or tbColorAndDepth. Reason: on GPU with packed depth and stencil buffer (see http://www.opengl.org/registry/specs/EXT/packed_depth_stencil.txt and https://www.khronos.org/registry/OpenGL/extensions/OES/OES_packed_depth_stencil.txt) FBO with separate depth and stencil may not be possible. And when your texture is GL_DEPTH_COMPONENT, this is a must. In the future, we could allow some flag to allow you to use texture with GL_DEPTH_STENCIL format, this would work with packed depth/stencil (actually, even require it). For now, it's advised to turn off Stencil when you use Buffer = tbDepth or tbColorAndDepth.

Public property ColorBufferAlpha: boolean read FColorBufferAlpha write FColorBufferAlpha default false;

Do we require color buffer with alpha channel. Relevant only when Buffer = tbNone (as in all other cases, we do not have the color buffer — colors either go into some texture or are ignored).

This must be set before GLContextOpen, cannot be changed later.

Public property MultiSampling: Cardinal read FMultiSampling write FMultiSampling default 1;

All buffers (color and such) will be created with the specified number of samples for multisampling. Values greater than 1 mean that multisampling is used, which enables anti-aliasing. Note that all your textures (in Texture, DepthTexture) must be created with the same number of samples.

Ignored if not GLFBOMultiSampling.


Generated by PasDoc 0.16.0.