/*
								+--------------------------------+
								|								 |
								|	  ***	OpenGL 4.0	 ***	 |
								|								 |
								|  Copyright © -tHE SWINe- 2009  |
								|								 |
								|		  FrameBuffer.h 		 |
								|								 |
								+--------------------------------+
*/

#pragma once
#ifndef __RENDER_BUFFER2_INCLUDED
#define __RENDER_BUFFER2_INCLUDED

/**
 *	@file gl4/FrameBuffer.h
 *	@author -tHE SWINe-
 *	@date 2009
 *	@brief OpenGL 4.0 frame-buffer object
 *
 *	t_odo - clarify how do layered depth buffers work (by calling
 *		glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, n_array_or_3d_depth_texture, 0))
 *
 *	t_odo - will we emulate layered renderbuffers using automatically generated textures? no, all
 *		the texture types must be the same and it is not possible to anticipate texture type the
 *		framebuffer object will be used for or at least without loss of generality.
 *
 *	t_odo - clarify how do multiple viewports work. viewports are not explicitly mapped to draw
 *		buffers, geometry shader decides both which viewport and which layer to use. that actually
 *		makes sense with rendering several viewports to a single texture (such as hemicube in most
 *		of radiosity implementations), but it doesn't allow different size viewports in a layered
 *		texture as the texture levels must be the same size. also, depth-buffer must be layered
 *		texture. this restricts it's use to a very limited set of cases and it's probably fine
 *		to ignore it.
 *
 *	@date 2011-08-15
 *
 *	Reflown long lines, written most of the documentation comments.
 *
 *	@todo finish documenting TFrameBufferConfig, think about relaxing the restriction that all the
 *		renderbuffers need to have the same size
 *
 *	@date 2012-06-19
 *
 *	Added \#pragma once.
 */

#include "OpenGL40.h"
#include "Texture.h"

/**
 *	@def __GL_FRAMEBUFFER_STORE_CONFIG
 *	@brief if defined, framebuffer properties are stored in CGL4FrameBufferObject
 */
#define __GL_FRAMEBUFFER_STORE_CONFIG

/**
 *	@brief wrapper class for GL_ARB_frame_buffer_object
 */
class CGL4FrameBufferObject {
public:
	enum {
		max_DrawBuffer_Num = 16 /**< @brief maximal expected number of draw buffers */
	};

protected:
	/**
	 *	@brief a structure, containing framebuffer configuration
	 */
	struct TFrameBufferConfig {
		/**
		 *	@brief a structure, containing framebuffer image configuration
		 */
		struct TImageConfig {
			bool b_texture_target; /**< @brief texture target flag */
			GLenum n_internal_format; /**< @brief internal format name */
			int n_multisample_sample_num; /**< @brief number of samples: 0 = no multisampling,
											   1 and more = multisampling @note This is limited
											   by CGL4FrameBufferObject::n_MaxSample_Num()
											   or CGL4FrameBufferObject::n_MaxIntegerSample_Num(),
											   depending on n_internal_format, */

			/**
			 *	@brief allocates and attaches a new renderbuffer to accomodate the image
			 *
			 *	@param[in] n_width is image width
			 *	@param[in] n_height is image height
			 *	@param[in] n_attachment is the name of the framebuffer attachment point
			 *
			 *	@return Returns renderbuffer name on success or 0 on failure.
			 */
			GLuint Create_RenderBuffer(int n_width, int n_height, GLenum n_attachment) const
			{
				_ASSERTE(!b_texture_target);

				GLuint n_renderbuffer;
				glGenRenderbuffers(1, &n_renderbuffer);
				if(!n_renderbuffer)
					return 0;

				glBindRenderbuffer(GL_RENDERBUFFER, n_renderbuffer);
				if(n_multisample_sample_num == 0) {
					glRenderbufferStorage(GL_RENDERBUFFER, n_internal_format, n_width, n_height);
				} else {
					glRenderbufferStorageMultisample(GL_RENDERBUFFER, n_multisample_sample_num,
						n_internal_format, n_width, n_height);
				}
				glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, n_attachment, GL_RENDERBUFFER, n_renderbuffer);
				// create and attach renderbuffer

				return n_renderbuffer;
			}
		};

		int n_color_buffer_num; /**< @brief number of color images */
		TImageConfig p_color_buffer[max_DrawBuffer_Num]; /**< @brief configurations of color images */

		bool b_depth_stencil_buffer_packed; /**< @brief packed depth stencil flag @note if set,
												 only m_n_depth_rb is created, with
												 packed_depth_stencil format */

		bool b_depth_buffer; /**< @brief depth buffer flag */
		TImageConfig t_depth_buffer; /**< @brief depth buffer configuration */

		bool b_stencil_buffer; /**< @brief stencil buffer flag */
		TImageConfig t_stencil_buffer; /**< @brief stencil buffer configuration */

		/**
		 *	@brief default constructor; has no effect
		 */
		TFrameBufferConfig()
		{}

		/**
		 *	@brief constructor; fills the structure
		 *
		 *	@param[in] n_width is framebuffer width, in pixels
		 *	@param[in] n_height is framebuffer height, in pixels
		 *	@param[in] _n_color_buffer_num is number of color buffers
		 *		(can be 0 to min(n_MaxDrawBuffers(), n_MaxColorAttachments()) - 1)
		 *	@param[in] p_color_texture_target is list of booleans for
		 *		every color buffer, specifying whether image storage is
		 *		a texture (true) or a renderbuffer (false)
		 *	@param[in] p_color_internal_format is list of internal color formats
		 *		for every non-texture color buffer
		 *	@param[in] p_color_multisample_num is list of numbers of samples
		 *		per pixel for every non-texture color buffer (0 (no MSAA) or 1
		 *		to CGL4FrameBufferObject::n_MaxSample_Num()
		 *		or CGL4FrameBufferObject::n_MaxIntegerSample_Num(),
		 *		depending on internal format)
		 *	@param[in] _b_depth_buffer is depth buffer flag
		 *	@param[in] b_depth_texture_target is depth texture flag
		 *	@param[in] n_depth_internal_format 
		 *	@param[in] 
		 *	@param[in] 
		 *	@param[in] 
		 *	@param[in] 
		 */
		TFrameBufferConfig(int n_width, int n_height,
			int _n_color_buffer_num, const bool *p_color_texture_target,
			const GLenum *p_color_internal_format, const int *p_color_multisample_num,
			bool _b_depth_buffer, bool b_depth_texture_target,
			GLenum n_depth_internal_format, int n_depth_multisample_num,
			bool _b_depth_stencil_packed, bool _b_stencil_buffer, bool b_stencil_texture_target,
			GLenum n_stencil_internal_format, int n_stencil_multisample_num)
		{
			_ASSERTE(_n_color_buffer_num <= max_DrawBuffer_Num);

			n_color_buffer_num = _n_color_buffer_num;
			for(int i = 0; i < n_color_buffer_num; ++ i) {
				if((p_color_buffer[i].b_texture_target = p_color_texture_target[i])) {
					p_color_buffer[i].n_internal_format = 0;
					p_color_buffer[i].n_multisample_sample_num = 0; // ignored, if texture target
				} else {
					p_color_buffer[i].n_internal_format = p_color_internal_format[i];
					p_color_buffer[i].n_multisample_sample_num = p_color_multisample_num[i];
				}
			}
			// set color buffers

			b_depth_buffer = _b_depth_buffer;
			if((t_depth_buffer.b_texture_target = b_depth_texture_target)) {
				t_depth_buffer.n_internal_format = 0;
				t_depth_buffer.n_multisample_sample_num = 0; // ignored, if texture target
			} else {
				t_depth_buffer.n_internal_format = n_depth_internal_format;
				t_depth_buffer.n_multisample_sample_num = n_depth_multisample_num;
			}
			// set depth buffer

			if((b_depth_stencil_buffer_packed = _b_depth_stencil_packed)) {
				b_stencil_buffer = _b_depth_buffer;
				t_stencil_buffer = t_depth_buffer; // same as depth buffer then
			} else {
				b_stencil_buffer = _b_stencil_buffer;
				if((t_stencil_buffer.b_texture_target = b_stencil_texture_target)) {
					t_stencil_buffer.n_internal_format = 0;
					t_stencil_buffer.n_multisample_sample_num = 0; // ignored, if texture target
				} else {
					t_stencil_buffer.n_internal_format = n_stencil_internal_format;
					t_stencil_buffer.n_multisample_sample_num = n_stencil_multisample_num;
				}
			}
			// set stencil buffer
		}
	};

	int m_n_width; /**< @brief framebuffer width */
	int m_n_height; /**< @brief framebuffer height */

#ifdef __GL_FRAMEBUFFER_STORE_CONFIG
	TFrameBufferConfig m_t_config; /**< @brief framebuffer configuration */
#endif // __GL_FRAMEBUFFER_STORE_CONFIG

	GLuint m_n_framebuffer; /**< @brief framebuffer object handle */

	GLuint m_p_color_rb[max_DrawBuffer_Num]; /**< @brief color renderbuffers */
	GLuint m_n_depth_rb; /**< @brief depth renderbuffer */
	GLuint m_n_stencil_rb; /**< @brief stencil renderbuffer */
	// note it is not possible to delete those right atter attaching them to m_n_framebuffer
	// (renderbuffers are deleted immediately, unlike shader objects). therefore these need
	// to be stored to avoid calling glGetFramebufferAttachmentParameteriv()

public:
	/**
	 *	@brief default constructor
	 *
	 *	Creates FBO with n_width per n_height pixels (note dimensions of individual images in
	 *		a single FBO may be different, but it is impossible to set here; it is however posible
	 *		to render to textures of different resolutions). FBO may contain several color images,
	 *		some of them may be textures, the other will be stored in render-buffers. Each render
	 *		buffer may have different format and multi-sampling. FBO may have depth buffer and/or
	 *		stencil buffer or packed depth/stencil buffer. Each of those may be stored in texture
	 *		or render buffer, each render buffer may have different format and multi-sampling
	 *		again. When using packed depth-stencil, depth-stencil parameters are set trough the
	 *		corresponding depth parameters, while stencil parameters are ignored.
	 *
	 *	@param[in] n_width is framebuffer width, in pixels
	 *	@param[in] n_height is framebuffer height, in pixels
	 *
	 *	@param[in] n_color_buffer_num is number of color buffers (may be 0)
	 *	@param[in] p_color_texture_target contains n_color_buffer_num values,
	 *		true = color buffer will be rendered to texture,
	 *		false = color buffer will be rendered to render-buffer
	 *	@param[in] p_color_internal_format contains n_color_buffer_num internal formats for
	 *		the corresponding render-buffers. value is ignored if corresponding
	 *		p_color_texture_target is true
	 *	@param[in] p_color_multisample_num contains n_color_buffer_num numbers of samples per pixel
	 *		for the corresponding render-buffers; 0 = no multisampling or 1 to n_Max_Sample_Num()
	 *		to enable multisampling; value is ignored if corresponding p_color_texture_target
	 *		is true
	 *
	 *	@param[in] b_depth_buffer is depth buffer requirement flag. if not set, the following
	 *		depth-related parameters are ignored
	 *	@param[in] b_depth_texture_target is depth texture target flag (if set, depth values
	 *		will be rendered to texture, otherwise to render-buffer); only valid
	 *		if b_depth_buffer is set
	 *	@param[in] n_depth_internal_format is internal format for depth buffer
	 *		(one of GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32 if not
	 *		using packed depth/stencil, otherwise one of GL_DEPTH24_STENCIL8); only valid if
	 *		b_depth_buffer is set and b_depth_texture_target is not set
	 *	@param[in] n_depth_multisample_num is numbers of depth samples per depth buffer pixel;
	 *		0 = no multisampling or 1 to n_Max_Sample_Num() to enable multisampling; only valid if
	 *		b_depth_buffer is set and b_depth_texture_target is not set
	 *
	 *	@param[in] b_depth_stencil_packed chooses between separate or packed depth stencil.
	 *		if set, the following stencil related parameters are ignored, b_depth_buffer
	 *		must be set, and n_depth_internal_format must be one of DEPTH_STENCIL formats
	 *		(or b_depth_texture_target must be set, and bound texture must have
	 *		DEPTH_STENCIL format)
	 *
	 *	@param[in] b_stencil_buffer is stencil buffer requirement flag. if not set, the following
	 *		stencil-related parameters are ignored; only valid if b_depth_stencil_packed
	 *		is not set
	 *	@param[in] b_stencil_texture_target is stencil texture target flag (if set, stencil values
	 *		will be rendered to texture, otherwise to render-buffer); only valid if
	 *		b_stencil_buffer is set and b_depth_stencil_packed is not set
	 *	@param[in] n_stencil_internal_format is internal format for stencil buffer
	 *		(one of GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX8_EXT
	 *		or GL_STENCIL_INDEX16_EXT); only valid if b_stencil_buffer is set and
	 *		b_stencil_texture_target is not set and b_depth_stencil_packed is not set
	 *	@param[in] n_stencil_multisample_num is numbers of stencil samples per stencil
	 *		buffer pixel; 0 = no multisampling or 1 to n_Max_Sample_Num() to enable
	 *		multisampling; only valid if b_stencil_buffer is set and b_stencil_texture_target
	 *		is not set and b_depth_stencil_packed is not set
	 *
	 *	@note Constructor may or may not succeed, it is recommended to call b_Status()
	 *		immediately after constructor returns.
	 *	@note This is the most versatile constructor, and may be a little confusing.
	 *		There are other constructors with less parameters.
	 */
	CGL4FrameBufferObject(int n_width, int n_height,
		int n_color_buffer_num, const bool *p_color_texture_target,
		const GLenum *p_color_internal_format, const int *p_color_multisample_num,
		bool b_depth_buffer, bool b_depth_texture_target,
		GLenum n_depth_internal_format, int n_depth_multisample_num,
		bool b_depth_stencil_packed, bool b_stencil_buffer, bool b_stencil_texture_target,
		GLenum n_stencil_internal_format, int n_stencil_multisample_num);

	/**
	 *	@brief packed depth-stencil constructor
	 *
	 *	Creates FBO with n_width per n_height pixels (note dimensions of individual images
	 *		in a single FBO may be different, but it is impossible to set here; it is however
	 *		posible to render to textures of different resolutions). FBO may contain several
	 *		color images, some of them may be textures, the other will be stored in
	 *		render-buffers. Each render buffer may have different format and multi-sampling.
	 *		FBO may have packed depth/stencil buffer, stored in texture / render-buffer,
	 *		it is possible to select render-buffer format and multi-sampling again.
	 *
	 *	@param[in] n_width is framebuffer width, in pixels
	 *	@param[in] n_height is framebuffer height, in pixels
	 *
	 *	@param[in] n_color_buffer_num is number of color buffers (may be 0)
	 *	@param[in] p_color_texture_target contains n_color_buffer_num values,
	 *		true = color buffer will be rendered to texture,
	 *		false = color buffer will be rendered to render-buffer
	 *	@param[in] p_color_internal_format contains n_color_buffer_num internal formats for
	 *		the corresponding render-buffers. value is ignored if corresponding
	 *		p_color_texture_target is true.
	 *	@param[in] p_color_multisample_num contains n_color_buffer_num numbers of samples
	 *		per pixel for the corresponding render-buffers; 0 = no multisampling or 1 to
	 *		n_Max_Sample_Num() to enable multisampling; value is ignored if corresponding
	 *		p_color_texture_target is true.
	 *
	 *	@param[in] b_depth_stencil_buffer is depth/stencil buffer requirement flag. if not set,
	 *		all the following parameters are ignored
	 *	@param[in] b_depth_stencil_texture_target is depth/stencil texture target flag
	 *		(if set, depth/stencil values will be rendered to texture, otherwise
	 *		to render-buffer); only valid if b_depth_stencil_buffer is set
	 *	@param[in] n_depth_stencil_internal_format is internal format for depth/stencil
	 *		buffer (GL_DEPTH24_STENCIL8); only valid if b_depth_stencil_buffer is set and
	 *		b_depth_stencil_texture_target is not set
	 *	@param[in] n_depth_stencil_multisample_num is numbers of depth/stencil samples per pixel;
	 *		0 = no multisampling or 1 to n_Max_Sample_Num() to enable multisampling; only valid if
	 *		b_depth_stencil_buffer is set and b_depth_stencil_texture_target is not set
	 *
	 *	@note Constructor may or may not succeed, it is recommended to call b_Status()
	 *		immediately after constructor returns.
	 */
	CGL4FrameBufferObject(int n_width, int n_height,
		int n_color_buffer_num, const bool *p_color_texture_target,
		const GLenum *p_color_internal_format, const int *p_color_multisample_num,
		bool b_depth_stencil_buffer, bool b_depth_stencil_texture_target,
		GLenum n_depth_stencil_internal_format, int n_depth_stencil_multisample_num);

	/**
	 *	@brief separate depth stencil constructor
	 *
	 *	Creates FBO with n_width per n_height pixels (note dimensions of individual images
	 *		in a single FBO may be different, but it is impossible to set here; it is however
	 *		posible to render to textures of different resolutions). FBO may contain several
	 *		color images, some of them may be textures, the other will be stored in
	 *		render-buffers. Each render buffer may have different format and multi-sampling.
	 *		FBO may have depth buffer and/or stencil buffer (note currently only way to have
	 *		both is to use packed depth/stencil). Each of those may be stored in texture
	 *		or render buffer, each render buffer may have different format and multi-sampling
	 *		again.
	 *
	 *	@param[in] n_width is framebuffer width, in pixels
	 *	@param[in] n_height is framebuffer height, in pixels
	 *
	 *	@param[in] n_color_buffer_num is number of color buffers (may be 0)
	 *	@param[in] p_color_texture_target contains n_color_buffer_num values,
	 *		true = color buffer will be rendered to texture,
	 *		false = color buffer will be rendered to render-buffer
	 *	@param[in] p_color_internal_format contains n_color_buffer_num internal formats for
	 *		the corresponding render-buffers. value is ignored if corresponding
	 *		p_color_texture_target is true.
	 *	@param[in] p_color_multisample_num contains n_color_buffer_num numbers of samples
	 *		per pixel for the corresponding render-buffers; 0 = no multisampling or 1 to
	 *		n_Max_Sample_Num() to enable multisampling; value is ignored if corresponding
	 *		p_color_texture_target is true.
	 *
	 *	@param[in] b_depth_buffer is depth buffer requirement flag. if not set,
	 *		the following depth-related parameters are ignored
	 *	@param[in] b_depth_texture_target is depth texture target flag (if set, depth values
	 *		will be rendered to texture, otherwise to render-buffer); only valid
	 *		if b_depth_buffer is set
	 *	@param[in] n_depth_internal_format is internal format for depth buffer
	 *		(one of GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32);
	 *		only valid if b_depth_buffer is set and b_depth_texture_target is not set
	 *	@param[in] n_depth_multisample_num is numbers of depth samples per depth buffer pixel;
	 *		0 = no multisampling or 1 to n_Max_Sample_Num() to enable multisampling; only valid if
	 *		b_depth_buffer is set and b_depth_texture_target is not set
	 *
	 *	@param[in] b_stencil_buffer is stencil buffer requirement flag. if not set,
	 *		the following stencil-related parameters are ignored
	 *	@param[in] b_stencil_texture_target is stencil texture target flag (if set, stencil values
	 *		will be rendered to texture, otherwise to render-buffer); only valid if
	 *		b_stencil_buffer is set
	 *	@param[in] n_stencil_internal_format is internal format for stencil buffer
	 *		(one of GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX8_EXT or
	 *		GL_STENCIL_INDEX16_EXT); only valid if b_stencil_buffer is set and
	 *		b_stencil_texture_target is not set
	 *	@param[in] n_stencil_multisample_num is numbers of stencil samples per stencil
	 *		buffer pixel; 0 = no multisampling or 1 to n_Max_Sample_Num() to enable
	 *		multisampling; only valid if b_stencil_buffer is set and
	 *		b_stencil_texture_target is not set
	 *
	 *	@note Constructor may or may not succeed, it is recommended to call b_Status()
	 *		immediately after constructor returns.
	 */
	CGL4FrameBufferObject(int n_width, int n_height,
		int n_color_buffer_num, const bool *p_color_texture_target,
		const GLenum *p_color_internal_format, const int *p_color_multisample_num,
		bool b_depth_buffer, bool b_depth_texture_target,
		GLenum n_depth_internal_format, int n_depth_multisample_num,
		bool b_stencil_buffer, bool b_stencil_texture_target,
		GLenum n_stencil_internal_format, int n_stencil_multisample_num);

	/**
	 *	@brief packed depth-stencil constructor with all color buffers having the same properties
	 *
	 *	Creates FBO with n_width per n_height pixels (note dimensions of individual images
	 *		in a single FBO may be different, but it is impossible to set here; it is however
	 *		posible to render to textures of different resolutions). FBO may contain several
	 *		color images, those may be stored in textures, or in render-buffers. All
	 *		render-buffers have the same format and multi-sampling. FBO may have packed
	 *		depth/stencil buffer, stored in texture / render-buffer, it is possible to select
	 *		render-buffer format and multi-sampling again.
	 *
	 *	@param[in] n_width is framebuffer width, in pixels
	 *	@param[in] n_height is framebuffer height, in pixels
	 *
	 *	@param[in] n_color_buffer_num is number of color buffers (may be 0)
	 *	@param[in] b_color_texture_target chooses between color buffers stored in textures (true),
	 *		or color buffers stored in render-buffers (false)
	 *	@param[in] n_color_internal_format contains internal format of color render-buffer(s);
	 *		value is ignored if b_color_texture_target is true.
	 *	@param[in] n_color_multisample_num contains number of samples per pixel for
	 *		color render-buffer(s); 0 = no multisampling or 1 to n_Max_Sample_Num() to enable
	 *		multisampling; value is ignored if b_color_texture_target is true.
	 *
	 *	@param[in] b_depth_stencil_buffer is depth/stencil buffer requirement flag. if not set,
	 *		all the following parameters are ignored
	 *	@param[in] b_depth_stencil_texture_target is depth/stencil texture target flag (if set,,
	 *		depth/stencil values will be rendered to texture, otherwise to render-buffer);
	 *		only valid if b_depth_stencil_buffer is set
	 *	@param[in] n_depth_stencil_internal_format is internal format for depth/stencil buffer
	 *		(GL_DEPTH24_STENCIL8); only valid if b_depth_stencil_buffer is set and
	 *		b_depth_stencil_texture_target is not set
	 *	@param[in] n_depth_stencil_multisample_num is numbers of depth/stencil samples per pixel;
	 *		0 = no multisampling or 1 to n_Max_Sample_Num() to enable multisampling; only valid if
	 *		b_depth_stencil_buffer is set and b_depth_stencil_texture_target is not set
	 *
	 *	@note Constructor may or may not succeed, it is recommended to call b_Status()
	 *		immediately after constructor returns.
	 */
	CGL4FrameBufferObject(int n_width, int n_height,
		int n_color_buffer_num, bool b_color_texture_target,
		GLenum n_color_internal_format, int n_color_multisample_num,
		bool b_depth_stencil_buffer, bool b_depth_stencil_texture_target,
		GLenum n_depth_stencil_internal_format, int n_depth_stencil_multisample_num);

	/**
	 *	@brief separate depth stencil constructor with all color buffers having the same properties
	 *
	 *	Creates FBO with n_width per n_height pixels (note dimensions of individual images
	 *		in a single FBO may be different, but it is impossible to set here; it is however
	 *		posible to render to textures of different resolutions). FBO may contain several
	 *		color images, those may be stored in textures, or in render-buffers. All render-buffers
	 *		have the same format and multi-sampling. FBO may have depth buffer and/or stencil
	 *		buffer (note currently only way to have both is to use packed depth/stencil).
	 *		Each of those may be stored in texture / render buffer, each render buffer may have
	 *		different format and multi-sampling again.
	 *
	 *	@param[in] n_width is framebuffer width, in pixels
	 *	@param[in] n_height is framebuffer height, in pixels
	 *
	 *	@param[in] n_color_buffer_num is number of color buffers (may be 0)
	 *	@param[in] b_color_texture_target chooses between color buffers stored in textures (true),
	 *		or color buffers stored in render-buffers (false)
	 *	@param[in] n_color_internal_format contains internal format of color render-buffer(s);
	 *		value is ignored if b_color_texture_target is true.
	 *	@param[in] n_color_multisample_num contains number of samples per pixel for
	 *		color render-buffer(s); 0 = no multisampling or 1 to n_Max_Sample_Num() to enable
	 *		multisampling; value is ignored if b_color_texture_target is true.
	 *
	 *	@param[in] b_depth_buffer is depth buffer requirement flag. if not set, the following
	 *		depth-related parameters are ignored
	 *	@param[in] b_depth_texture_target is depth texture target flag (if set, depth values
	 *		will be rendered to texture, otherwise to render-buffer); only valid
	 *		if b_depth_buffer is set
	 *	@param[in] n_depth_internal_format is internal format for depth buffer
	 *		(one of GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32);
	 *		only valid if b_depth_buffer is set and b_depth_texture_target is not set
	 *	@param[in] n_depth_multisample_num is numbers of depth samples per depth buffer pixel;
	 *		0 = no multisampling or 1 to n_Max_Sample_Num() to enable multisampling; only valid if
	 *		b_depth_buffer is set and b_depth_texture_target is not set
	 *
	 *	@param[in] b_stencil_buffer is stencil buffer requirement flag. if not set,
	 *		following stencil-related parameters are ignored
	 *	@param[in] b_stencil_texture_target is stencil texture target flag (if set, stencil values
	 *		will be rendered to texture, otherwise to render-buffer); only valid if
	 *		b_stencil_buffer is set
	 *	@param[in] n_stencil_internal_format is internal format for stencil buffer
	 *		(one of GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX8_EXT or
	 *		GL_STENCIL_INDEX16_EXT); only valid if b_stencil_buffer is set and
	 *		b_stencil_texture_target is not set
	 *	@param[in] n_stencil_multisample_num is numbers of stencil samples per stencil
	 *		buffer pixel; 0 = no multisampling or 1 to n_Max_Sample_Num() to enable
	 *		multisampling; only valid if b_stencil_buffer is set and b_stencil_texture_target
	 *		is not set
	 *
	 *	@note Constructor may or may not succeed, it is recommended to call b_Status()
	 *		immediately after constructor returns.
	 */
	CGL4FrameBufferObject(int n_width, int n_height,
		int n_color_buffer_num, bool b_color_texture_target,
		GLenum n_color_internal_format, int n_color_multisample_num,
		bool b_depth_buffer, bool b_depth_texture_target,
		GLenum n_depth_internal_format, int n_depth_multisample_num,
		bool b_stencil_buffer, bool b_stencil_texture_target,
		GLenum n_stencil_internal_format, int n_stencil_multisample_num);
	
	/**
	 *	@brief destructor
	 *	Takes care of cleaning up allocated OpenGL objects.
	 */
	~CGL4FrameBufferObject();

	/**
	 *	@brief checks frame-buffer status
	 *	@return Returns true in case frame-buffer, specified by constructor parameters
	 *		was successfuly created.
	 *	@note To call glCheckFramebufferStatus(), use n_CheckStatus().
	 */
	bool b_Status() const;

	/**
	 *	@brief gets width of the render buffer
	 *	@return Returns width of the render buffer, in pixels.
	 */
	inline int n_Width() const
	{
		return m_n_width;
	}

	/**
	 *	@brief gets height of the render buffer
	 *	@return Returns height of the render buffer, in pixels.
	 */
	inline int n_Height() const
	{
		return m_n_height;
	}

	/**
	 *	@brief gets OpenGL name of color buffer with the specified index
	 *	@param[in] n_draw_buffer_index is zero-based index of draw buffer
	 *		(can be 0 to n_Color_Buffer_Num() - 1)
	 *	@return Returns OpenGL name of color buffer with zero based index n_draw_buffer_index.
	 *	@note Useful for manual copying of results of rendering to multiple buffers.
	 */
	inline GLenum n_Draw_Buffer(int n_draw_buffer_index) const
	{
		return GL_COLOR_ATTACHMENT0 + n_draw_buffer_index;
	}

#ifdef __GL_FRAMEBUFFER_STORE_CONFIG
	/**
	 *	@brief gets number of color (draw) buffers
	 *	@return Returns number of color (draw) buffers.
	 */
	inline int n_Color_Buffer_Num() const
	{
		return m_t_config.n_color_buffer_num;
	}

	/**
	 *	@brief determines whether a given color buffer is rendered to texture 
	 *	@param[in] n_draw_buffer_index is zero-based index of draw buffer
	 *		(can be 0 to n_Color_Buffer_Num() - 1)
	 *	@return Returns true if color buffer with zero based index n_draw_buffer_index is stored
	 *		in texture, otherwise returns false (color buffer is stored in render-buffer).
	 */
	inline bool b_Color_TextureTarget(int n_buffer_index) const
	{
		return m_t_config.p_color_buffer[n_buffer_index].b_texture_target;
	}

	/**
	 *	@brief gets OpenGL internal format of color buffer with the specified index
	 *	@param[in] n_draw_buffer_index is zero-based index of draw buffer
	 *		(can be 0 to n_Color_Buffer_Num() - 1)
	 *	@return Returns OpenGL internal format of color buffer with zero based
	 *		index n_draw_buffer_index. In case it is stored in texture, returns 0
	 *		(internal format depends on bound texture).
	 */
	inline GLenum n_Color_Format(int n_draw_buffer_index) const
	{
		return m_t_config.p_color_buffer[n_draw_buffer_index].n_internal_format;
	}

	/**
	 *	@brief gets number of samples per pixel of color buffer with the specified index
	 *	@param[in] n_draw_buffer_index is zero-based index of draw buffer
	 *		(can be 0 to n_Color_Buffer_Num() - 1)
	 *	@return Returns number of samples per pixel of color buffer with zero based
	 *		index n_draw_buffer_index. In case it is stored in texture, returns 0
	 *		(number of samples depends on bound texture).
	 */
	inline int n_Color_MultiSample_Sample_Num(int n_draw_buffer_index) const
	{
		return m_t_config.p_color_buffer[n_draw_buffer_index].n_multisample_sample_num;
	}

	/**
	 *	@brief determines whether there is a depth buffer
	 *	@return Returns true in case frame buffer has depth buffer (even in texture),
	 *		otherwise false.
	 */
	inline bool b_Depth_Buffer() const
	{
		return m_t_config.b_depth_buffer;
	}

	/**
	 *	@brief determines whether depth buffer is rendered to texture
	 *	@return Returns true in case depth is to be rendered to depth texture,
	 *		otherwise false (depth is either not present or rendered to render-buffer).
	 */
	inline bool b_Depth_TextureTarget() const
	{
		return m_t_config.t_depth_buffer.b_texture_target;
	}

	/**
	 *	@brief gets depth buffer internal format
	 *	@return Returns depth buffer internal format (only valid in case depth
	 *		buffer is present). In case depth buffer is stored in texture, returns 0
	 *		(internal format depends on bound texture).
	 */
	inline GLenum n_Depth_Format() const
	{
		return m_t_config.t_depth_buffer.n_internal_format;
	}

	/**
	 *	@brief gets number of samples per pixel of depth buffer
	 *	@return Returns number of samples per pixel of depth buffer (only valid
	 *		in case depth buffer is present). In case depth buffer is stored in texture,
	 *		returns 0 (number of samples depends on bound texture).
	 */
	inline int n_Depth_MultiSample_Sample_Num() const
	{
		return m_t_config.t_depth_buffer.n_multisample_sample_num;
	}

	/**
	 *	@brief determines whether depth and stencil fragments are stored in a single buffer
	 *		using packed format
	 *	@return Returns true if depth and stencil fragments are stored in a single buffer,
	 *		using packed depth/stencil pixel format, otherwise returns false.
	 */
	inline bool b_Packed_DepthStencil_Buffer() const
	{
		return m_t_config.b_depth_stencil_buffer_packed;
	}

	/**
	 *	@brief determines whether there is a stencil buffer
	 *	@return Returns true in case frame buffer has stencil buffer (even in texture),
	 *		otherwise false.
	 */
	inline bool b_Stencil_Buffer() const
	{
		return m_t_config.b_stencil_buffer;
	}

	/**
	 *	@brief determines whether stencil buffer is renderd to texture
	 *	@return Returns true in case stencil is to be rendered to stencil texture,
	 *		otherwise false (stencil is either not present or rendered to render-buffer).
	 */
	inline bool b_Stencil_TextureTarget() const
	{
		return m_t_config.t_stencil_buffer.b_texture_target;
	}

	/**
	 *	@brief gets stencil buffer internal format
	 *	@return Returns stencil buffer internal format (only valid in case stencil buffer
	 *		is present). In case stencil buffer is stored in texture, returns 0
	 *		(internal format depends on bound texture).
	 */
	inline GLenum n_Stencil_Format() const
	{
		return m_t_config.t_stencil_buffer.n_internal_format;
	}

	/**
	 *	@brief gets number of samples per pixel of stencil buffer
	 *	@return Returns number of samples per pixel of stencil buffer (only valid in case
	 *		stencil buffer is present). In case stencil buffer is stored in texture, returns 0
	 *		(number of samples depends on bound texture).
	 */
	inline int n_Stencil_MultiSample_Sample_Num() const
	{
		return m_t_config.t_stencil_buffer.n_multisample_sample_num;
	}
#endif // __GL_FRAMEBUFFER_STORE_CONFIG

	/**
	 *	@brief binds the framebuffer buffer as OpenGL output buffer
	 *	@return Returns true on success or false on failure
	 *	@note Binding the framebuffer to other value than GL_DRAW_FRAMEBUFFER will prevent
	 *		successful binding of textures and is only exposed for framebuffer blit.
	 */
	inline bool Bind(GLenum n_target = GL_DRAW_FRAMEBUFFER) const;

	/**
	 *	@brief checks frame-buffer status
	 *	@return Returns result of glCheckFramebufferStatus() (should be GL_FRAMEBUFFER_COMPLETE).
	 */
	GLenum n_CheckStatus() const;

	/**
	 *	@brief binds a whole color texture
	 *
	 *	Binds a whole depth-stencil texture n_texture to color attachment with zero-based index
	 *		n_attachment_index. In case it is layered, all the layers are bound. Frame-buffer
	 *		must be bound to do this. It fails in case the depth-stencil attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different
	 *		texture.
	 *
	 *	@param[in] n_attachment_index is zero-based index of the color attachment to bind to
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_ColorTexture(int n_attachment_index, GLuint n_texture, int n_level) const;

	/**
	 *	@brief binds a whole depth texture
	 *
	 *	Binds a whole depth texture n_texture. In case it is layered, all the layers
	 *		are bound. Frame-buffer must be bound to do this. It fails in case the depth
	 *		attachment was not specified as texture target in constructor (renders
	 *		to render-buffer). Binding texture with id 0 releases previously bound texture,
	 *		as does binding different texture.
	 *
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_DepthTexture(GLuint n_texture, int n_level) const;

	/**
	 *	@brief binds a whole stencil texture
	 *
	 *	Binds a whole stencil texture n_texture. In case it is layered, all the layers
	 *		are bound. Frame-buffer must be bound to do this. It fails in case the stencil
	 *		attachment was not specified as texture target in constructor (renders
	 *		to render-buffer). Binding texture with id 0 releases previously bound texture,
	 *		as does binding different texture.
	 *
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_StencilTexture(GLuint n_texture, int n_level) const;

	/**
	 *	@brief binds a whole depth-stencil texture
	 *
	 *	Binds a whole depth-stencil texture n_texture. In case it is layered, all the layers
	 *		are bound. Frame-buffer must be bound to do this. It fails in case the depth-stencil
	 *		attachment was not specified as texture target in constructor (renders
	 *		to render-buffer). Binding texture with id 0 releases previously bound texture,
	 *		as does binding different texture.
	 *
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_DepthStencilTexture(GLuint n_texture, int n_level) const;

	/**
	 *	@brief binds a single layer of a color texture
	 *
	 *	Binds a single layer of a color texture n_texture, selected by zero-based
	 *		index n_layer to color attachment point with zero-based index n_attachment_index.
	 *		Frame-buffer must be bound to do this. It fails in case the depth-stencil attachment
	 *		was not specified as texture target in constructor (renders to render-buffer).
	 *		Binding texture with id 0 releases previously bound texture, as does binding
	 *		different texture.
	 *
	 *	@param[in] n_attachment_index is zero-based index of the color attachment to bind to
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_ColorTextureLayer(int n_attachment_index,
		GLuint n_texture, int n_level, int n_layer) const;

	/**
	 *	@brief binds a single layer of a depth texture
	 *
	 *	Binds a single layer of a depth texture n_texture, selected by zero-based
	 *		index n_layer. Frame-buffer must be bound to do this. It fails in case the
	 *		depth attachment was not specified as texture target in constructor
	 *		(renders to render-buffer). Binding texture with id 0 releases previously
	 *		bound texture, as does binding different texture.
	 *
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_DepthTextureLayer(GLuint n_texture, int n_level, int n_layer) const;

	/**
	 *	@brief binds a single layer of a stencil texture
	 *
	 *	Binds a single layer of a stencil texture n_texture, selected by zero-based
	 *		index n_layer. Frame-buffer must be bound to do this. It fails in case the
	 *		depth-stencil attachment was not specified as texture target in constructor
	 *		(renders to render-buffer). Binding texture with id 0 releases previously
	 *		bound texture, as does binding different texture.
	 *
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_StencilTextureLayer(GLuint n_texture, int n_level, int n_layer) const;

	/**
	 *	@brief binds a single layer of a depth-stencil texture
	 *
	 *	Binds a single layer of a depth-stencil texture n_texture, selected by zero-based
	 *		index n_layer. Frame-buffer must be bound to do this. It fails in case the
	 *		depth-stencil attachment was not specified as texture target in constructor
	 *		(renders to render-buffer). Binding texture with id 0 releases previously
	 *		bound texture, as does binding different texture.
	 *
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_DepthStencilTextureLayer(GLuint n_texture, int n_level, int n_layer) const;

	// ARB/geometry_shader4.txt (but it is simulated using glFramebufferTexture2D())
	
	/**
	 *	@brief binds a single (two-dimensional) face of a color texture
	 *
	 *	Binds a single (two-dimensional) face of a color texture n_texture, named n_face (should be
	 *		one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) to color
	 *		attachment (draw buffer) with zero-based index n_attachment_index. Frame-buffer
	 *		must be bound to do this. It fails in case attachment n_attachment_index was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_ColorTextureFace(int n_attachment_index, GLuint n_texture,
		int n_level, GLenum n_face) const;

	/**
	 *	@brief binds a single (two-dimensional) face of a depth texture
	 *
	 *	Binds a single (two-dimensional) face of a depth texture n_texture, named n_face (should be
	 *		one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer
	 *		must be bound to do this. It fails in case the depth attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_DepthTextureFace(GLuint n_texture, int n_level, GLenum n_face) const;

	/**
	 *	@brief binds a single (two-dimensional) face of a stencil texture
	 *
	 *	Binds a single (two-dimensional) face of a stencil texture n_texture, named n_face
	 *		(should be one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer
	 *		must be bound to do this. It fails in case the stencil attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_StencilTextureFace(GLuint n_texture, int n_level, GLenum n_face) const;

	/**
	 *	@brief binds a single (two-dimensional) face of a depth-stencil texture
	 *
	 *	Binds a single (two-dimensional) face of a depth-stencil texture n_texture, named n_face
	 *		(should be one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer
	 *		must be bound to do this. It fails in case the depth-stencil attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_DepthStencilTextureFace(GLuint n_texture, int n_level, GLenum n_face) const;

	/**
	 *	@brief binds a whole color texture
	 *
	 *	Binds a whole depth-stencil texture r_texture to color attachment with zero-based index
	 *		n_attachment_index. In case it is layered, all the layers are bound. Frame-buffer
	 *		must be bound to do this. It fails in case the depth-stencil attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different
	 *		texture.
	 *
	 *	@param[in] n_attachment_index is zero-based index of the color attachment to bind to
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_ColorTexture(int n_attachment_index,
		const CGLTexture &r_texture, int n_level) const;

	/**
	 *	@brief binds a whole depth texture
	 *
	 *	Binds a whole depth texture r_texture. In case it is layered, all the layers
	 *		are bound. Frame-buffer must be bound to do this. It fails in case the depth
	 *		attachment was not specified as texture target in constructor (renders
	 *		to render-buffer). Binding texture with id 0 releases previously bound texture,
	 *		as does binding different texture.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_DepthTexture(const CGLTexture &r_texture, int n_level) const;

	/**
	 *	@brief binds a whole stencil texture
	 *
	 *	Binds a whole stencil texture r_texture. In case it is layered, all the layers
	 *		are bound. Frame-buffer must be bound to do this. It fails in case the stencil
	 *		attachment was not specified as texture target in constructor (renders
	 *		to render-buffer). Binding texture with id 0 releases previously bound texture,
	 *		as does binding different texture.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_StencilTexture(const CGLTexture &r_texture, int n_level) const;

	/**
	 *	@brief binds a whole depth-stencil texture
	 *
	 *	Binds a whole depth-stencil texture r_texture. In case it is layered, all the layers
	 *		are bound. Frame-buffer must be bound to do this. It fails in case the depth-stencil
	 *		attachment was not specified as texture target in constructor (renders
	 *		to render-buffer). Binding texture with id 0 releases previously bound texture,
	 *		as does binding different texture.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function requires the GL_ARB_framebuffer_object extension
	 *		(part of OpenGL 3.0 core).
	 */
	inline void Bind_DepthStencilTexture(const CGLTexture &r_texture, int n_level) const;

	/**
	 *	@brief binds a single layer of a color texture
	 *
	 *	Binds a single layer of a color texture r_texture, selected by zero-based
	 *		index n_layer to color attachment point with zero-based index n_attachment_index.
	 *		Frame-buffer must be bound to do this. It fails in case the depth-stencil attachment
	 *		was not specified as texture target in constructor (renders to render-buffer).
	 *		Binding texture with id 0 releases previously bound texture, as does binding
	 *		different texture.
	 *
	 *	@param[in] n_attachment_index is zero-based index of the color attachment to bind to
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_ColorTextureLayer(int n_attachment_index,
		const CGLTexture &r_texture, int n_level, int n_layer) const;

	/**
	 *	@brief binds a single layer of a depth texture
	 *
	 *	Binds a single layer of a depth texture r_texture, selected by zero-based
	 *		index n_layer. Frame-buffer must be bound to do this. It fails in case the
	 *		depth attachment was not specified as texture target in constructor
	 *		(renders to render-buffer). Binding texture with id 0 releases previously
	 *		bound texture, as does binding different texture.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_DepthTextureLayer(const CGLTexture &r_texture,
		int n_level, int n_layer) const;

	/**
	 *	@brief binds a single layer of a stencil texture
	 *
	 *	Binds a single layer of a stencil texture r_texture, selected by zero-based
	 *		index n_layer. Frame-buffer must be bound to do this. It fails in case the
	 *		depth-stencil attachment was not specified as texture target in constructor
	 *		(renders to render-buffer). Binding texture with id 0 releases previously
	 *		bound texture, as does binding different texture.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_StencilTextureLayer(const CGLTexture &r_texture,
		int n_level, int n_layer) const;

	/**
	 *	@brief binds a single layer of a depth-stencil texture
	 *
	 *	Binds a single layer of a depth-stencil texture r_texture, selected by zero-based
	 *		index n_layer. Frame-buffer must be bound to do this. It fails in case the
	 *		depth-stencil attachment was not specified as texture target in constructor
	 *		(renders to render-buffer). Binding texture with id 0 releases previously
	 *		bound texture, as does binding different texture.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is zero-based index of the layer to bind
	 *
	 *	@note This function requires the GL_ARB_geometry_shader4 extension
	 *		(part of OpenGL 3.2 core).
	 */
	inline void Bind_DepthStencilTextureLayer(const CGLTexture &r_texture,
		int n_level, int n_layer) const;

	/**
	 *	@brief binds a single (two-dimensional) face of a color texture
	 *
	 *	Binds a single (two-dimensional) face of a color texture r_texture, named n_face (should be
	 *		one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) to color
	 *		attachment (draw buffer) with zero-based index n_attachment_index. Frame-buffer
	 *		must be bound to do this. It fails in case attachment n_attachment_index was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_ColorTextureFace(int n_attachment_index,
		const CGLTexture &r_texture, int n_level, GLenum n_face) const;

	/**
	 *	@brief binds a single (two-dimensional) face of a depth texture
	 *
	 *	Binds a single (two-dimensional) face of a depth texture r_texture, named n_face (should be
	 *		one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer
	 *		must be bound to do this. It fails in case the depth attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_DepthTextureFace(const CGLTexture &r_texture,
		int n_level, GLenum n_face) const;

	/**
	 *	@brief binds a single (two-dimensional) face of a stencil texture
	 *
	 *	Binds a single (two-dimensional) face of a stencil texture r_texture, named n_face
	 *		(should be one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer
	 *		must be bound to do this. It fails in case the stencil attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_StencilTextureFace(const CGLTexture &r_texture,
		int n_level, GLenum n_face) const;

	/**
	 *	@brief binds a single (two-dimensional) face of a depth-stencil texture
	 *
	 *	Binds a single (two-dimensional) face of a depth-stencil texture r_texture, named n_face
	 *		(should be one of GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer
	 *		must be bound to do this. It fails in case the depth-stencil attachment was not
	 *		specified as texture target in constructor (renders to render-buffer). Binding
	 *		texture with id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
	 *		or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *
	 *	@note This function mimics glFramebufferTextureFaceARB(), proposed in the
	 *		GL_ARB_geometry_shader4 extension (part of OpenGL 3.2 core). The function
	 *		got left out of OpenGL, so it is implemented here using glFramebufferTexture2D().
	 *		As a result, no extensions are required.
	 */
	inline void Bind_DepthStencilTextureFace(const CGLTexture &r_texture,
		int n_level, GLenum n_face) const;

	/**
	 *	@brief binds one-dimensional color texture
	 *
	 *	Binds one-dimensional color texture n_texture of type n_target (should be GL_TEXTURE_1D)
	 *		to color attachment (draw buffer) with zero-based index n_attachment_index.
	 *		Frame-buffer must be bound to do this. It fails in case attachment n_attachment_index
	 *		was not specified as texture target in constructor (renders to render-buffer).
	 *		Binding texture with id 0 releases previously bound texture, as does binding
	 *		different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (GL_TEXTURE_1D)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_ColorTexture1D(int n_attachment_index, GLenum n_target,
		GLuint n_texture, int n_level = 0) const;

	/**
	 *	@brief binds two-dimensional color texture
	 *
	 *	Binds two-dimensional color texture n_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) to color attachment (draw buffer) with
	 *		zero-based index n_attachment_index. Frame-buffer must be bound to do this.
	 *		It fails in case attachment n_attachment_index was not specified as texture
	 *		target in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_ColorTexture2D(int n_attachment_index, GLenum n_target,
		GLuint n_texture, int n_level = 0) const;

	/**
	 *	@brief binds three-dimensional color texture
	 *
	 *	Binds one layer of three-dimensional color texture n_texture of type n_target
	 *		(should be GL_TEXTURE_3D) to color attachment (draw buffer) with
	 *		zero-based index n_attachment_index. Frame-buffer must be bound to do this.
	 *		It fails in case attachment n_attachment_index was not specified as texture
	 *		target in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (GL_TEXTURE_3D)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is 3D texture layer (zero-based index of 3D texture slice to render to)
	 */
	inline void Bind_ColorTexture3D(int n_attachment_index, GLenum n_target,
		GLuint n_texture, int n_level, int n_layer) const;

	/**
	 *	@brief binds two-dimensional depth texture
	 *
	 *	Binds two-dimensional depth texture n_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer must be bound to do this.
	 *		It fails in case depth attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was specified in constructor,
	 *		Bind_DepthStencilTexture2D() must be used in such case.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_DepthTexture2D(GLenum n_target, GLuint n_texture, int n_level) const;

	/**
	 *	@brief binds two-dimensional stencil texture
	 *
	 *	Binds two-dimensional stencil texture n_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer must be bound to do this.
	 *		It fails in case stencil attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was specified in constructor,
	 *		Bind_DepthStencilTexture2D() must be used in such case.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_StencilTexture2D(GLenum n_target, GLuint n_texture, int n_level) const;

	/**
	 *	@brief binds two-dimensional packed depth/stencil texture
	 *
	 *	Binds two-dimensional depth/stencil texture n_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer must be bound to do this.
	 *		It fails in case depth attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was not specified in constructor,
	 *		Bind_DepthTexture2D() and Bind_StencilTexture2D() must be used in such case
	 *		(with the same texture depth/stencil or with depth texture and another
	 *		stencil texture).
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] n_texture is id of the OpenGL texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_DepthStencilTexture2D(GLenum n_target, GLuint n_texture, int n_level) const;

	/**
	 *	@brief binds one-dimensional color texture
	 *
	 *	Binds one-dimensional color texture r_texture of type n_target (should be GL_TEXTURE_1D)
	 *		to color attachment (draw buffer) with zero-based index n_attachment_index.
	 *		Frame-buffer must be bound to do this. It fails in case attachment n_attachment_index
	 *		was not specified as texture target in constructor (renders to render-buffer).
	 *		Binding texture with id 0 releases previously bound texture, as does binding
	 *		different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (GL_TEXTURE_1D)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_ColorTexture1D(int n_attachment_index, GLenum n_target,
		CGLTexture_1D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds two-dimensional color texture
	 *
	 *	Binds two-dimensional color texture r_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) to color attachment (draw buffer) with
	 *		zero-based index n_attachment_index. Frame-buffer must be bound to do this.
	 *		It fails in case attachment n_attachment_index was not specified as texture
	 *		target in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_ColorTexture2D(int n_attachment_index, GLenum n_target,
		CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds three-dimensional color texture
	 *
	 *	Binds one layer of three-dimensional color texture r_texture of type n_target
	 *		(should be GL_TEXTURE_3D) to color attachment (draw buffer) with
	 *		zero-based index n_attachment_index. Frame-buffer must be bound to do this.
	 *		It fails in case attachment n_attachment_index was not specified as texture
	 *		target in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] n_target is texture target (GL_TEXTURE_3D)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is 3D texture layer (zero-based index of 3D texture slice to render to)
	 */
	inline void Bind_ColorTexture3D(int n_attachment_index, GLenum n_target,
		CGLTexture_3D_Base &r_texture, int n_level, int n_layer) const;

	/**
	 *	@brief binds two-dimensional depth texture
	 *
	 *	Binds two-dimensional depth texture r_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer must be bound to do this.
	 *		It fails in case depth attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was specified in constructor,
	 *		Bind_DepthStencilTexture2D() must be used in such case.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_DepthTexture2D(GLenum n_target,
		CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds two-dimensional stencil texture
	 *
	 *	Binds two-dimensional stencil texture r_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer must be bound to do this.
	 *		It fails in case stencil attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was specified in constructor,
	 *		Bind_DepthStencilTexture2D() must be used in such case.
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_StencilTexture2D(GLenum n_target,
		CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds two-dimensional packed depth/stencil texture
	 *
	 *	Binds two-dimensional depth/stencil texture r_texture of type n_target (should be
	 *		one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z). Frame-buffer must be bound to do this.
	 *		It fails in case depth attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was not specified in constructor,
	 *		Bind_DepthTexture2D() and Bind_StencilTexture2D() must be used in such case
	 *		(with the same texture depth/stencil or with depth texture and another
	 *		stencil texture).
	 *
	 *	@param[in] n_target is texture target (one of GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
	 *		GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
	 *		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_DepthStencilTexture2D(GLenum n_target,
		CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds one-dimensional color texture
	 *
	 *	Binds one-dimensional color texture r_texture to color attachment (draw buffer) with
	 *		zero-based index n_attachment_index.
	 *		Frame-buffer must be bound to do this. It fails in case attachment n_attachment_index
	 *		was not specified as texture target in constructor (renders to render-buffer).
	 *		Binding texture with id 0 releases previously bound texture, as does binding
	 *		different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_ColorTexture1D(int n_attachment_index,
		CGLTexture_1D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds two-dimensional color texture
	 *
	 *	Binds two-dimensional color texture r_texture to color attachment (draw buffer) with
	 *		zero-based index n_attachment_index. Frame-buffer must be bound to do this.
	 *		It fails in case attachment n_attachment_index was not specified as texture
	 *		target in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_ColorTexture2D(int n_attachment_index,
		CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds three-dimensional color texture
	 *
	 *	Binds one layer of three-dimensional color texture r_texture to color attachment
	 *		(draw buffer) with zero-based index n_attachment_index. Frame-buffer must be
	 *		bound to do this. It fails in case attachment n_attachment_index was not specified
	 *		as texture target in constructor (renders to render-buffer). Binding texture with
	 *		id 0 releases previously bound texture, as does binding different texture.
	 *
	 *	@param[in] n_attachment_index is color attachment index (0 to n_Color_Buffer_Num() - 1)
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 *	@param[in] n_layer is 3D texture layer (zero-based index of 3D texture slice to render to)
	 */
	inline void Bind_ColorTexture3D(int n_attachment_index,
		CGLTexture_3D_Base &r_texture, int n_level, int n_layer) const;

	/**
	 *	@brief binds two-dimensional depth texture
	 *
	 *	Binds two-dimensional depth texture r_texture. Frame-buffer must be bound to do this.
	 *		It fails in case depth attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was specified in constructor,
	 *		Bind_DepthStencilTexture2D() must be used in such case.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_DepthTexture2D(CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds two-dimensional stencil texture
	 *
	 *	Binds two-dimensional stencil texture r_texture. Frame-buffer must be bound to do this.
	 *		It fails in case stencil attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was specified in constructor,
	 *		Bind_DepthStencilTexture2D() must be used in such case.
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_StencilTexture2D(CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief binds two-dimensional packed depth/stencil texture
	 *
	 *	Binds two-dimensional depth/stencil texture r_texture. Frame-buffer must be bound
	 *		to do this. It fails in case depth attachment was not specified as texture target
	 *		in constructor (renders to render-buffer). Binding texture with id 0
	 *		releases previously bound texture, as does binding different texture.
	 *		It also fails, if packed depth stencil was not specified in constructor,
	 *		Bind_DepthTexture2D() and Bind_StencilTexture2D() must be used in such case
	 *		(with the same texture depth/stencil or with depth texture and another
	 *		stencil texture).
	 *
	 *	@param[in] r_texture is reference to the texture to be bound
	 *	@param[in] n_level is texture mip-map level
	 */
	inline void Bind_DepthStencilTexture2D(CGLTexture_2D_Base &r_texture, int n_level = 0) const;

	/**
	 *	@brief releases the render buffer from OpenGL output buffer binding
	 *	@param[in] n_target is target to bind the framebuffer to
	 *	@note The viewport state is not restored, it is probably necessary to call glViewport().
	 */
	static inline void Release(GLenum n_target = GL_DRAW_FRAMEBUFFER);

	/**
	 *	@brief gets maximal render-buffer size
	 *	@return Returns maximal render-buffer size in pixels.
	 *	@note This involves calling glGetIntegerv(), and may result in unwanted
	 *		CPU / GPU synchronization.
	 */
	static int n_Get_MaxSize();

	/**
	 *	@brief gets maximal number of samples per pixel
	 *	@return Returns maximal number of samples per pixel for multisampling.
	 *	@note This involves calling glGetIntegerv(), and may result in unwanted
	 *		CPU / GPU synchronization.
	 */
	static int n_Get_MaxSample_Num();

	/**
	 *	@brief gets maximal number of samples per pixel with integer format
	 *	@return Returns maximal number of samples per pixel for multisampling, this applies
	 *		to pixels with integer formats.
	 *	@note This involves calling glGetIntegerv(), and may result in unwanted
	 *		CPU / GPU synchronization.
	 *	@todo Clarify what kinds of formats are integer formats (GL_STENCIL_INDEX? GL_DEPTH_COMPONENT? GL_RGBA32I?).
	 */
	static int n_Get_MaxIntegerSample_Num();

	/**
	 *	@brief gets maximal number of draw buffers
	 *	@return Returns maximal number of OpenGL draw buffers
	 *		(1 where not supported, usually 8, up to 16 in the future).
	 *	@note This involves calling glGetIntegerv(), and may result in unwanted
	 *		CPU / GPU synchronization.
	 */
	static int n_Get_MaxDrawBuffer_Num();

	/**
	 *	@brief gets maximal number of color attachments
	 *	@return Returns maximal number of OpenGL color attachments (usually 8 or 16).
	 *	@note This involves calling glGetIntegerv(), and may result in unwanted
	 *		CPU / GPU synchronization.
	 */
	static int n_Get_MaxColorAttachment_Num();

protected:
	bool Create(int n_width, int n_height, const TFrameBufferConfig &r_t_config);
	void Delete();

private:
	inline CGL4FrameBufferObject(const CGL4FrameBufferObject &UNUSED(r_fbo)) {} /**< @brief copy-constructor (cannot be used) */
	inline CGL4FrameBufferObject &operator =(const CGL4FrameBufferObject &UNUSED(r_fbo)) { return *this; } /**< @brief copy-operator (cannot be used) */
};

#include "FrameBuffer.inl"
// fast inline functions

#endif // !__RENDER_BUFFER2_INCLUDED
