Name EXT_render_target Name Strings GL_EXT_render_target Contributors Pat Brown Matt Craighead Cass Everitt Mark Kilgard Dale Kirkland Barthold Lichtenbelt Teri Morrison Paul Puey John Rosasco R. Jason Sams John Stauffer Contact Jeff Juliano, NVIDIA Corporation (jjuliano 'at' nvidia.com) Status Preliminary Version $Date: 2004/04/16 $ $Revision: #29 $ Number ???? Dependencies OpenGL 1.1 is required. ARB_make_current_read affects the definition of this extension. This extension is written against the OpenGL 1.4 specification. Overview This extension defines a simple interface for rendering to a texture or to many textures. A mechanism is provided for binding a texture as a logical buffer, or render target buffer. The framework is general enough that layered extensions could allow other object types to be bound as render target buffers. Previous extensions that enabled rendering to a texture are much more complicated. ARB_pbuffer and ARB_render_texture are both written to the window-system layer. They require calling MakeCurrent, an operation that may be expensive, to switch between the window and the pbuffer drawables. An application must create one pbuffer per renderable texture in order to portably use ARB_render_texture. If the format of the pbuffer is different from the format of the window, it is necessary to maintain a separate context for use with the pbuffer, which makes for an API that is both inefficient and cumbersome to use. EXT_render_target, on the other hand, is both simpler to use and more efficient. Only a single context is needed. The many-to-one relationship of drawables to textures is reversed so that a single drawable may be used for rendering to many textures. A new core GL function glRenderTargetBuffer binds a texture as a render target buffer. Instead of a window-system layer function such as wglMakeCurrent or glxMakeCurrent, the function glBindRenderTargetEXT is used to change the association of a single context to a different drawable, also called a render target object. Issues (1) Should this extension be proposed as an ARB or as an EXT? UNRESOLVED It was decided to use EXT for now. One option considered was to use ??? until a decision is made but that was voted down. (2) What should this extension be named? RESOLVED EXT_render_target was chosen. Previously it was named EXT_draw_texture. The name render_texture speaks more closely to the scope of this specific extension, but that name is already used by a window-system layer extension. The name render_target is good because this extension possesses framework generality that may lay the ground work for future render-to-* extensions. (2a) The function names have changed. How do the old names map to the new names? (This issue will be deleted eventually once the function renaming is no longer news.) glDrawable() has been renamed to glBindRenderTarget(). glBindRenderTarget() now takes a named render target object, where zero is special and refers to the drawable chosen by MakeCurrent. A render target object is roughly similar to a framebuffer object in the uberbuffers proposals. glRenderTarget() has been renamed to glRenderTargetBuffer(). glRenderTargetBuffer() operates on the currently bound render target object. This function is used to bind a texture object as a render target buffer. (3) Is it necessary to require that all the render target buffers of a render target object have the same dimensions? RESOLVED Require matching dimensions for simplicity. If the dimensions do not match the consistency check fails and INVALID_OPERATION is generated. It could be useful to use a single large depth buffer when rendering to many textures of several different sizes. This is something that could be added later by a layered extension that relaxes the matching dimension restriction. Supporting heterogeneous sized render target buffers requires defining where in a larger buffer the smaller results are written, and deciding what guarantees can be made and what should be left undefined. (4) What happens when TexImage or CopyTexImage is called on a texture object that is a render target buffer of the bound render target object? UNRESOLVED TexImage and CopyTexImage result in INVALID_OPERATION and do nothing when the target texture is bound for render-to-texture. ARB_render_texture introduced a similar but different restriction by implicitly unbinding the texture from the pbuffer when TexImage is called. Are the consistency rules alone good enough to handle this issue? The render target object becomes inconsistent when the size of the color texture is changed but the size of the depth texture is not changed. Allowing TexImage to change the texture format would be tricky and undesirable. (5) Why is render to vertex array missing? RESOLVED: Render to vertex array is separate functionality from render to texture. RTVA can be added as a separate extension. The framework is general enough to support more than one way of adding RTVA, without deciding today on the details of a particular RTVA implementation. One idea is to define a way to interpret a vertex array or buffer object, which is inherently byte-oriented linear, as a render target, which is inherently component-oriented and dimensioned, and then call glRenderTargetBuffer like this: glRenderTargetBuffer(GL_FRAMEBUFFER, GL_COLOR, GL_BUFFER_OBJECT, buffer_obj); A second idea is to add a new target type to BindRenderTarget: glBindRenderTarget(GL_ARRAY_BUFFER, rt_obj); An ARRAY_BUFFER render target object need not look like a FRAMEBUFFER render target object. A third idea is to define a general way to interpret a component-oriented dimensioned image, such as a texture or a color buffer, as a byte-oriented vertex stream. Using this approach one would render vertex attributes to a texture or to an AUX buffer and then use the image data as a vertex array directly. There is controversy over which RTVA method(s) should be supported. One goal of EXT_render_target is to ship render-to-texture functionality today while leaving the door open to one or more RTVA solutions in the future. (6) What function should perform the action of binding a texture to a render target for rendering purposes? RESOLVED Options considered include: overloading BindTexture, using RenderTargetParameter, or adding a new function. BindTexture is problematic because it creates a new texture object with default state if the name is previously unused, but the default state has no dimensions, dimensionality, or format. RenderTargetParameter is problematic because by convention it should not fail, but it can be given an unused name. Functions of the form *Parameter should not return a success/failure status because in an indirect rendering scenario that would mean a slow round-trip to the server. The decision was made to use a new function named RenderTargetBuffer, which does returns success/failure, but is used only for the purpose of binding an object as a render target buffer. RenderTargetBuffer fails if given a texture name that is unused or if the texture has no format, dimensions, or dimensionality. (7) What happens when DEPTH or COLOR is set to zero? To an unused texture name? UNRESOLVED Setting the color or depth texture to zero is useful as a way to render with no color or depth buffer. The function RenderTargetBuffer disallows setting the COLOR or DEPTH target to an unused texture name, or to the name of a texture object with the wrong component type. An open question is what happens when both COLOR and DEPTH render targets buffers are set to zero. (8) Should it be legal for the render target state to pass through invalid configurations? RESOLVED: Yes. It's easier for the application if the render target state is allowed to pass through invalid configurations when transitioning between two valid configurations. A consistency check is defined to determine if a configuration is valid. (9) What happens when the render target consistency check fails? RESOLVED Attempts to render to or read from an inconsistent render target object produce INVALID_OPERATION. Begin will fail, so no rendering will be performed. (10) Aside from attempting a drawing command, is there a way to determine if the current configuration is valid? UNRESOLVED Similar to glValidateProgram(), a new function could be added that returns a Boolean value indicating whether or not the current configuration is valid. (11) Do we really need GetRenderTargetParameterv, or is GetIntegerv good enough? RESOLVED GetRenderTargetParameterv is needed. The convention is that when a new function is added to set parameter values, such as TexParameter, then a corresponding query function is also added, such as GetTexParameter. (12) If a texture is bound for both rendering and texturing purposes, should the results of rendering be undefined or should INVALID_OPERATION be generated at glBegin()? UNRESOLVED Undefined results allow an application to render to a section of the texture that is not being sourced by normal texture operations. However it is highly desirable to define results in all cases, even if the result is defined as an error. (13) Should GL_GENERATE_MIPMAP generate mipmaps when rendering to the base level of a texture? RESOLVED: No. It is better to ignore GENERATE_MIPMAPS when rendering to a texture and instead introduce a new function that affects mipmap generation. The GENERATE_MIPMAPS property is set at a different time than when rendering happens. The property arranges for a side-effect to occur the next time the base level is updated. While this may be OK if a texture's surface is usable only through the texture object in which the GENERATE_MIPMAPS property is set, the concept does not extend well when a texture's surface can be used both through the texture object as well as through one or more render target objects. It would be strange and non-obvious if the action of rendering could sometimes results in the side effect of redefining texture image data, based on a parameter of the texture object. In this case the provoking action that would trigger mipmap generation in in the texture object would be a call to BindRenderTarget(0). Not at all obvious. (14) Are the contents of a texture preserved when alternating its use between texturing and rendering? RESOLVED Yes, the contents are preserved both when the usage of a texture object changes from texture to rendering and when it changes from rendering to texturing. This is useful for a) custom mipmap generation, and b) partial texture updates performed by rendering to a portion of a texture. A certain other 3D graphics API that supports rendering to a texture preserves the contents, and some real applications are known to rely on this behavior. ARB_render_texture left the contents undefined when usage switched from texturing to rendering. For implementations which must copy or transform the contents between use for texturing and rendering, leaving the contents undefined allows the implementation to avoid performing the copy in both directions. Maybe TexImage(..., NULL) could be used to invalidate the texture contents. (15) What happens to the contents of a renderable texture when one of the render target parameters LEVEL, FACE or IMAGE is changed, if the texture lacks the corresponding level of dimensionality (mipmap level, cube map face, or 3D image slice)? RESOLVED It was decided that textures possessing the corresponding trait honor the value of the parameter, but textures lacking the corresponding trait ignore the value of the parameter. For example, changing FACE will have no effect on a texture object that is not a cube map. For textures that possess the trait, changing the value of the parameter switches the view of the texture's contents. Each legal value of the property corresponds to a view of a different subset of the texture. For textures that do not possess the trait, changing the value of the parameter has no effect on the contents of the texture. It is the application's responsibility to clear the texture (glClear) when appropriate. There is a desire to use a color-renderable texture object that possesses a level of dimensionality (such as cube map, mipmap or 3-dimensional depth slices) along with a depth-renderable texture object that lacks that level of dimensionality. For example, there is no need to allocate six cube map faces of depth when rendering to a cube map color texture. (16) Must the depth texture be a mipmap if it is rendered to in conjunction with a color texture that is a mipmap? RESOLVED Yes and no. If the application renders to each level, then the depth texture must also be a mipmap. The rule is that after adjusting for the render target parameter LEVEL, the color and depth textures must have the same width and height. If the depth texture is not a mipmap, then LEVEL has no effect on the depth texture. Unless both color and depth are mipmaps or both are not mipmaps, the width and height will not match when LEVEL is changed. Note this rule does not prevent rendering to just the base level of a mipmap color texture along with a non-mipmap depth texture, as long as the depth texture has the same width and height as level zero of the color texture. This is useful if custom mipmap generation does not require a depth buffer for levels other than level zero. The application can work around this restriction either by creating a mipmap depth texture, or by using the depth texture only when rendering to the base level. This is not a problem for cube map or 3-dimensional textures because the values of FACE and IMAGE do not affect the effective width and height. (17) Is it necessary to support front/back and left/right? How could MRT be supported? RESOLVED If a render target is not scanned out to a display device, there does not seem to be much need for front/back and left/right. Instead, it is cleaner for the render target object to simply have N color buffers named COLOR0 through COLORN. The color target is named COLOR. When MRT support is added, COLOR and COLOR0 could alias the same target, or COLOR could be renamed to COLOR0. It's probably a good idea to reserve enumerate space so that the COLORn values can all be adjacent. (18) Should there be N MRT-style depth textures? UNRESOLVED (19) How could the read and draw buffers be specified differently? (similar to make_current_read) There are several ways this could be added. Three ideas are: add enumerates FRAMEBUFFER_READ and FRAMEBUFFER_DRAW that operate only on the read or draw framebuffer, or modify BindRenderTarget() to take a second argument that specifies the read drawable, or add a new function that specifies the read drawable. Rather than require make_current_read type support, this issue is ignored for now. If there is real demand a layered extension could be added later. With good render-to-texture support there may no longer be need for make_current_read style functionality. (20) How could multisample support be added? A layered extension could add multisample support by introducing a new render target parameter that specifies the number of sample bits. It is debatable whether the semantics should be resolve-on-render or resolve-on-read, and what happens when the number of samples is cleared or when a different texture is bound to the render target. (21) DEPTH_COMPONENT_STENCIL_INDEX is not described. Have not gotten to it yet. The intent is the obvious meaning...a depth component texture that carries stencil bits. I am not adding a new separate stencil texture type. Stencil components are not usable through texture operations, but are only accessible through operations that act on render targets. (22) There is no notion of "mipmap texture" in OpenGL. UNRESOLVED: re-word the text in this document that speaks to a "mipmap" texture property to be more in line with how the OpenGL specification describes mipmaps. (23) How could accumulation buffers be supported? UNRESOLVED: It may be desirable to support accumulation buffers when rendering to a texture. There are several ways accum buffers could be added. One idea is to add a new ACCUM_COMPONENT texture type, which either could or could not be used for normal texture operations. Another idea is to add a render target parameter that magically adds an accumulation buffer to the render target object. A third idea is to use the parameter to RenderTargetBuffer() to describe a type of object that is not a texture but that can be used as an accum buffer. If separate stencil is desired in the future it could be handled similarly. (24) What happens to the viewport and scissor when the render target parameter LEVEL is changed? UNRESOLVED: The viewport and scissor are not updated automatically. It is the application's responsibility to update the viewport and scissor if desired. This matches the behavior of ARB_render_texture. (25) Should any of the new functions be compiled into display lists? UNRESOLVED: This needs some thought. Some of the new functions are similar to existing functionality which does not get compiled into display lists. BindRenderTarget is similar to MakeCurrent, RenderTargetBuffer is similar to SetPixelFormat, RenderTargetParameter is similar to a window move/resize. GenerateMipmapEXT is similar to TexImage. (26) What happens if an RGBA4 texture is used as a render target buffer, but the hardware does not support rendering to RGBA4? The implementation is allowed to render to a surface with more precision than the texture's requested format. The texture object's format remains RGBA4. The driver is allowed to copy the texture contents from the RGBA4 surface to a surface with a format that can be rendered to, for example RGBA8, and then copy back from the RGBA8 surface to the RGBA4 texture. The actual surface format used for rendering must depend only on the (requested) formats of the texture and the other render target buffers. In this example, querying TEXTURE_RED_BITS will return 4 because the texture's requested format is RGBA4. But querying RED_BITS while the render target object is bound will return 8. The discrepancy is an indication to the application that a copy is happening behind the scenes. (27) What object model should be used by the new render target objects? OpenGL already has two object models; it is undesirable to add yet another. The new objects are written to follow the texture object model. It might be better to use the GLhandleARB model instead. New Procedures and Functions void BindRenderTargetEXT(enum target, int object); void DeleteRenderTargetsEXT(sizei n, uint *renderTargets); void GenRenderTargetsEXT(sizei n, uint *renderTargets); void RenderTargetBufferEXT(enum renderTarget, enum bufferTarget, enum type, int object); void RenderTargetParameter{if}EXT(enum target, enum pname, T param); void GetRenderTargetParameter{if}vEXT(enum target, enum value, T *data); void GenerateMipmapEXT(enum target); New Tokens Accepted by parameter of BindRenderTarget, RenderTargetBuffer, RenderTargetParameter, and GetRenderTargetParameterv, and by the parameter of GetIntegerv: FRAMEBUFFER_EXT 0x???? Accepted by the parameter of RenderTargetParameter, and by the parameter of GetRenderTargetParameterv: FACE_EXT 0x???? IMAGE_EXT 0x???? LEVEL_EXT 0x???? Accepted by the parameter of RenderTargetParameter and by the parameter of GetRenderTargetParameterv: COLOR_TYPE_EXT 0x???? DEPTH_TYPE_EXT 0x???? Additions to Chapter 2 of the 1.4 Specification (OpenGL Operation) None. Additions to Chapter 3 of the 1.4 Specification (Rasterization) None. Additions to Chapter 4 of the 1.4 Specification (Per-Fragment Operations and the Framebuffer) Add a new section "Render Targets" after section 4.3" "4.4 Render Targets A render target object has one or more logical buffers, which are also called render target buffers. One example of a render target is the default one specified by MakeCurrent or MakeContextCurrent window-system functions. The render target buffers in this case are the logical buffers specified by the pixel format. Render target objects can also be created by the application. Application-created render target objects provide a form of "off-screen" rendering. A texture can be bound as a logical buffer of a render target object, thereby providing a facility to "render to texture". 4.4.1 Binding and Managing Render Target Objects Normally the operations described in chapter 4 affect the default FRAMEBUFFER render target that is specified by MakeCurrent or MakeContextCurrent. Additional render target objects can be created and operated on. The namespace for render target objects is the unsigned integers, with zero reserved by the GL. A render target object is created by binding an unused name to FRAMEBUFFER. The binding is effected by calling void BindRenderTargetEXT(enum target, int object); with set to the desired render target and set to the unused name. The resulting render target object is a new state vector, comprising all the state values listed in section XXX, set to the same initial values. The new render target object is and remains a FRAMEBUFFER render target until it is deleted. BindRenderTargetEXT may also be used to bind an existing render target object to . If the bind is successful no change is made to the state of the bound render target object, and any previous binding to is broken. While a render target object is bound, GL operations on the target to which it is bound affect the bound object, and queries of the target to which it is bound return state from the bound object. In particular, queries of the values specified in table 6.30 (Implementation Dependent Pixel Depths) are derived from the currently bound render target object. In the initial state FRAMEBUFFER refers to the default object that was associated with the context by MakeCurrent or MakeContextCurrent. In order that access to the default FRAMEBUFFER is not lost, it is treated as a render target object whose name is zero. The default FRAMEBUFFER is operated on and queried while zero is bound to FRAMEBUFFER. On some implementations the properties of the default FRAMEBUFFER can change over time (e.g. in response to the window-system function MakeCurrent). The current FRAMEBUFFER binding can be queried as FRAMEBUFFER_EXT using GetIntegerv. The render target object currently bound to FRAMEBUFFER is used as the sinc of fragment operations and as the source of pixel reads such as ReadPixels, as described in chapter 4. Non-zero FRAMEBUFFER render target objects differ from the default FRAMEBUFFER render target in a few important ways. Render target objects own all of their pixels (no pixel ownership test). The values of DRAW_BUFFER and READ_BUFFER are ignored; instead the texture object bound to the COLOR render target is used for both draw and read operations (see section 4.4.2). Using RenderTargetBuffer it is possible to bind the logical buffers associated with a render target object to a texture as described in section 4.4.2, but RenderTargetBuffer cannot be used on the default render target object. XXX The right way to specify DRAW_BUFFER is to edit the affected section(s) of the core spec. Render target objects are deleted by calling void DeleteRenderTargetsEXT(sizei n, uint *objects); contains names of render target objects to be deleted. After a render target object is deleted its name is again unused. If a render target that is currently bound to FRAMEBUFFER is deleted, it is as though BindRenderTarget had been executed with the same and the zero. Unused names in are silently ignored, as is the value zero. The command void GenRenderTargetsEXT(sizei n, uint *objects); returns previously unused render target object names in . These names are marked as used, for the purposes of GenRenderTargetsEXT only, but they acquire state and type only when they are first bound, just as if they were unused. 4.4.2 Binding to a Render Target Buffer Like the default FRAMEBUFFER render target, named render targets can also have color, depth, and stencil logical (or render target) buffers. Initially a named render target object has no buffers of any kind. A texture object can be bound as one of the render target buffers of the currently bound render target object by calling void RenderTargetBufferEXT(enum renderTarget, enum bufferTarget, enum type, int object); must be FRAMEBUFFER. INVALID_OPERATION is generated if is currently bound to zero. is one of COLOR or DEPTH. must be NONE or TEXTURE. INVALID_OPERATION is generated if is NONE and is not zero, or if is zero and is not NONE. When is TEXTURE is the name of a texture object and INVALID_OPERATION is generated unless a texture with the name already exists and the dimensions of have been established. If is NONE and is zero, then any object previously bound to is unbound from . If is FRAMEBUFFER and is TEXTURE, then one of the following will occur: * INVALID_OPERATION is generated if is COLOR and is zero or does not name a color-format texture object. * INVALID_OPERATION is generated if is DEPTH and is zero or does not name either a DEPTH_COMPONENT or DEPTH_COMPONENT_STENCIL_INDEX texture object. * Otherwise the texture is bound as the render target buffer . Upon success the value of 's parameter BUFFER_NAME is set to and BUFFER_TYPE is set to . The object of type is said to be "attached to" or "bound to" the render target's buffer . For example, texture object number 5 is attached to the COLOR buffer of the FRAMEBUFFER render target. The object bound to can be queried with GetRenderTargetParameter. The default value of both COLOR and DEPTH render target buffers is zero. The default value of both COLOR_TYPE and DEPTH_TYPE is NONE. When either COLOR_TYPE or DEPTH_TYPE is set to NONE, the corresponding render target buffer is not bound to anything. Writes to that buffer are disabled and attempts to read from the buffer produce INVALID_OPERATION. XXX Is the above a correct way to describe this behavior? XXX How to word what happens when a pixel format lacks color or depth? DEPTH_COMPONENT_STENCIL_INDEX textures possess both depth and stencil content. When a DEPTH_COMPONENT_STENCIL_INDEX texture is bound to the DEPTH render target buffer, the render target object takes on both depth and stencil components. While a texture object is attached to a render target object that is bound (render-to-texture is enabled), INVALID_OPERATION will be generated if an attempt is made to modify the texture contents through texture operations such as TexImage or TexSubImage. XXX Modify definition of TexImage and TexSubImage. When a texture object is deleted while it is attached to at , the texture object is automatically unbound as if RenderTargetBuffer(, , TEXTURE, 0) were executed while is bound. 4.4.3 Render Target Parameters Various parameters control how a render target is treated when used for draw or read operations. These parameters are set by calling void RenderTargetParameter{if}EXT(enum target, enum pname, T param); must be FRAMEBUFFER. is a symbolic constant indicating the parameter to be set; the possible constants and corresponding parameters are summarized in table 6.32. is the value to which the parameter is set. 4.4.3.1 Selecting a Portion of a Texture A texture object may possess dimensionality (e.g. cube map, mipmap, 3D depth slices) that the FRAMEBUFFER does not. This section describes operations that control or affect how a portion of a texture is selected for use by the FRAMEBUFFER. FACE_EXT must be one of TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_Y, or TEXTURE_CUBE_MAP_NEGATIVE_Z. The parameter FACE_EXT determines the active face of cube map textures attached to a render target. If an attached texture is not a cube map texture, then value of FACE_EXT is ignored for that texture. The parameter IMAGE_EXT determines the active image layer of 3-dimensional textures attached to a render target. If an attached texture is not 3-dimensional, then the value of IMAGE_EXT is ignored for that texture. The parameter LEVEL_EXT determines the active mipmap level of textures attached to a render target. If only level zero of an attached texture has a non-zero size, then the value of LEVEL_EXT is ignored for that texture. 4.4.4 Textures as Render Target Buffers When a texture object is bound to a render target while at the same time the texture is fetchable through normal texture operations, attempts to use the texture object as a texture will produce undefined results if all of the following conditions hold: * is bound to FRAMEBUFFER. * is bound as one of the render target buffers of . * is bound to a texture unit that is enabled by conventional texture enables or configured by a vertex program, fragment program, vertex shader, or fragment shader. * The render target parameter LEVEL_EXT is inside the range of 's base level and max level (or just base level if mipmap filtering isn't active). The sum of these conditions describe the scenario where an attempt is made to texture from the same image that is being rendered to. When all of these conditions are met, any attempt to draw to or read from the through produces undefined results. 4.4.5 Generating Mipmaps While a texture object is bound to a render target , and if the texture parameter GENERATE_MIPMAP set to TRUE, then modification to the base level image of through does not trigger automatic mipmap generation. Mipmaps can be generated manually with the command void GenerateMipmapEXT(enum target); where is one of TEXTURE_1D, TEXTURE_2D, TEXTURE_CUBE_MAP, or TEXTURE_3D. Mipmap generation affects the texture object attached to . INVALID_OPERATION is generated if the BASE_LEVEL of the texture bound to is not defined. Array levels + 1 through p are replaced with the derived arrays, regardless of their previous contents. All other mipmap arrays, including the array, are left unchanged by this computation. The internal formats and border widths of the derived mipmap arrays all match those of the array, and the dimensions of the derived arrays follow the requirements described in section 3.8.10. The contents of the derived arrays are computed by repeated, filtered reduction of the array. No particular filter algorithm is required, though a 2x2 box filter is recommended as the default filter. In some implementations, filter quality may be affected by hints (section 5.6). 4.4.6 Framebuffer Render Target Consistency The render target object is said to be framebuffer-consistent if the render target buffers COLOR and DEPTH are consistently defined. is consistent if the following conditions all hold true. See section 3.8.10 for the rules describing various forms of texture completeness. See section 3.8.8 for the definition of "p". * If both COLOR_TYPE and DEPTH_TYPE are not NONE, then the objects named by COLOR and DEPTH must have the same width, height, and border size. * The render target parameter COLOR_TYPE is NONE, or COLOR_TYPE is TEXTURE and COLOR names a texture object which has a "color renderable" internal format. Depth texture formats are not "color renderable". Neither are fixed-point textures with signed components. Neither are compressed textures. Floating-point texture formats and (conventional) unsigned fixed-point (luminance, alpha, luminance-alpha, intensity, RGB, and RGBA) texture formats are "color renderable". * The render target parameter DEPTH_TYPE is NONE, or DEPTH_TYPE is TEXTURE and DEPTH names a texture object which has a "depth renderable" internal format. Only GL_DEPTH*COMPONENT* texture formats, including DEPTH_COMPONENT_STENCIL_INDEX formats, are "depth renderable". * If a texture object is bound as a render target buffer, then the texture object must be "mipmap complete" and must not be a proxy texture object. * If a cube map texture object is bound as a render target buffer, then the texture object must be "mipmap cube complete". * If texture object is bound as a render target buffer, and if at least one level of the texture object other than the base level has a non-zero size (mipmap), then LEVEL_EXT must not be smaller than level_base or larger than level_base+p. * If a 3-dimensional texture object is bound as a render target buffer, then IMAGE_EXT not be larger than the largest image (including border) in the texture. Effects of Consistency on Frame Buffer Operations If the render target object is bound to FRAMEBUFFER and is not consistent, then attempts to read from or draw to FRAMEBUFFER result in INVALID_OPERATION. Additions to Chapter 5 of the 1.4 Specification (Special Functions) Add to Section 5.4, as part of the discussion of what command are compiled into display lists: "Commands that are used to manage render targets are not included in display lists, but are executed immediately. These commands are BindRenderTargetEXT, RenderTargetBufferEXT, RenderTargetParameter{if}EXT, GetRenderTargetParameter{if}vEXT, and GenerateMipmapEXT." Additions to Chapter 6 of the 1.4 Specification (State and State Requests) Add to section 6.2, State Tables: Add to table 6.19, Render Target Control "Get value FRAMEBUFFER_EXT Type Z+ Get Cmnd GetIntegerv Initial Value 0 Description current render target object Sec. 4.4 Attribute -" Add new table 6.32, Render Target Control "Get value COLOR Type Z+ Get Cmnd GetRenderTargetParameterv Initial Value 0 Description name of object bound to COLOR Sec. 4.4 Attribute - Get value COLOR_TYPE_EXT Type Z+ Get Cmnd GetRenderTargetParameterv Initial Value NONE Description type of object bound to COLOR Sec. 4.4 Attribute - Get value DEPTH Type Z+ Get Cmnd GetRenderTargetParameterv Initial Value 0 Description name of object bound to DEPTH Sec. 4.4 Attribute - Get value DEPTH_TYPE Type Z+ Get Cmnd GetRenderTargetParameterv Initial Value NONE Description type of object bound to DEPTH Sec. 4.4 Attribute - Get value FACE_EXT Type Z+ Get Cmnd GetRenderTargetParameterv Initial Value TEXTURE_CUBE_MAP_POSITIVE_X Description selected face; ignored if buffer binding's texture target is not CUBE_MAP Sec. 4.4.1 Attribute - Get value IMAGE_EXT Type Z+ Get Cmnd GetRenderTargetParameterv Initial Value 0 Description selected depth image; ignored if binding's texture target is not TEXTURE_3D Sec. 4.4.1 Attribute - Get value LEVEL_EXT Type Z+ Get Cmnd GetRenderTargetParameterv Initial Value 0 Description selected level; ignored if buffer is not a mipmap texture Sec. 4.4.1 Attribute -" Dependencies on ARB_make_current_read If ARB_make_current_read is not supported, references to MakeContextCurrent should be removed. Errors INVALID_OPERATION is generated if BindRenderTargetEXT or RenderTargetParameter{if}EXT is executed between execution of Begin and the corresponding execution of End. INVALID_OPERATION is generated if an attempt is made to render to or read from a render target object while it is in an inconsistent state, according to the consistency rules described in section 4.4.5 INVALID_ENUM is generated if RenderTargetBufferEXT is executed with not equal to FRAMEBUFFER_EXT. INVALID_ENUM is generated if RenderTargetBufferEXT is executed with not equal to either COLOR or DEPTH. Usage Examples (1) Render-to-texture is simple // Enable render-to-texture glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); // Set up color_tex and depth_tex for render-to-texture glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR, GL_TEXTURE, color_tex); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH, GL_TEXTURE, depth_tex); // Re-enable rendering to the window glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, 0); glBindTexture(GL_TEXTURE_2D, color_tex); (2) Application that supports both RBBCTT (render back buffer, copy to texture) and RTT (render to texture). The migration path from RBBCTT to RTT is easy. if (useRenderTarget) { glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR, GL_TEXTURE, color_tex); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH, GL_TEXTURE, depth_tex); } draw_to_texture(); if (useRenderTarget) { glBindRenderTarget (GL_FRAMEBUFFER_EXT, 0); } else { // copy tex path glBindTexture (GL_TEXTURE_2D, color_tex); glCopyTexSubImage(...); } (3) Simple render-to-texture loop with initialization. Create an RGB8 texture and a 24-bit depth texture with stencil. In a loop, alternate between rendering to, and texturing out of, the color texture. glGenTextures(1, &color_tex); glGenTextures(1, &depth_tex); glGenRenderTargetsEXT(1, &rt); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); // initialize color texture glBindTexture(GL_TEXTURE_2D, color_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_INT, NULL); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR, GL_TEXTURE, color_tex); // initialize depth/stencil texture glBindTexture(GL_TEXTURE_2D, depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_STENCIL_INDEX8_EXT, 512, 512, 0, GL_DEPTH_COMPONENT_STENCIL_INDEX_EXT, GL_INT, NULL); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH, GL_TEXTURE, depth_tex); loop { glBindTexture(GL_TEXTURE_2D, 0); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, 0); glBindTexture(GL_TEXTURE_2D, color_tex); } (4) Render-to-texture loop with automatic mipmap generation. The depth texture is not a mipmap. glGenTextures(1, &color_tex); glGenTextures(1, &depth_tex); glGenRenderTargetsEXT(1, &rt); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); // initialize mipmap color texture glBindTexture(GL_TEXTURE_2D, color_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_INT, NULL); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR, GL_TEXTURE, color_tex); // initialize depth texture (not mipmap) glBindTexture(GL_TEXTURE_2D, depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 512, 512, 0, GL_DEPTH_COMPONENT, GL_INT, NULL); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH, GL_TEXTURE, depth_tex); loop { glBindTexture(GL_TEXTURE_2D, 0); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, 0); // automatically generate mipmaps glBindTexture(GL_TEXTURE_2D, color_tex); GenerateMipmapEXT(GL_TEXTURE_2D); } (5) Render-to-texture loop with manual (custom) mipmap generation. glGenTextures(1, &color_tex); glGenTextures(1, &depth_tex); glGenRenderTargetsEXT(1, &rt); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); // initialize mipmap color texture glBindTexture(GL_TEXTURE_2D, color_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_INT, NULL); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR, GL_TEXTURE, color_tex); // establish a mipmap chain for the color texture GenerateMipmapEXT(GL_TEXTURE_2D); // initialize depth texture (not mipmap) glBindTexture(GL_TEXTURE_2D, depth_tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 512, 512, 0, GL_DEPTH_COMPONENT, GL_INT, NULL); glRenderTargetBufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH, GL_TEXTURE, depth_tex); loop { glBindTexture(GL_TEXTURE_2D, 0); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, rt); glRenderTargetParameteriEXT(GL_FRAMEBUFFER_EXT, GL_LEVEL_EXT, 0); // custom-generate successive mipmap levels glBindTexture(GL_TEXTURE_2D, color_tex); foreach (level > 0) { glRenderTargetParameteriEXT(GL_FRAMEBUFFER_EXT, GL_LEVEL_EXT, level); glTexParameteri(TEXTURE_2D, TEXTURE_BASE_LEVEL, level-1); glTexParameteri(TEXTURE_2D, TEXTURE_MAX_LEVEL, level-1); } glTexParameteri(TEXTURE_2D, TEXTURE_BASE_LEVEL, 0); glTexParameteri(TEXTURE_2D, TEXTURE_MAX_LEVEL, max); glBindRenderTargetEXT(GL_FRAMEBUFFER_EXT, 0); }