Sign in to follow this  

OpenGL Multiple Render Target Rules

This topic is 1979 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there,

in some presentations there are statements, that one can only use Render Targets of the same depth and number of channels. Is this still true for newer versions of OpenGL?

I tried looking it up in the specs, but i didn't find anything useful except framebuffer completeness rules. I wrote a sample program where i use different number of channels, different depths and so on, and it works.

I just need to know if this is officially supported or some implementation-specific "advantage".

Background is, when writing about deferred shading, some people said they're limited in what formats they can use due to resctrictions with multiple render targets. Now i need to know if that's true anymore.

thanks in advance,

Share this post

Link to post
Share on other sites
You are talking about FBO:s, aren't you? A FBO never has more than one depth buffer, but can have many render targets.

I am not sure what you mean by "channel", but I suppose you mean a render target. If you are talking about FBO:s with different sets of render targets, I can't see why and how there could be a restriction that all FBO:s have to use the same setup.

In my game, I use different FBO:s. One for the deferred lighting, one for shadow maps, one for terrain maps, etc. And they are all different.

Maybe you are thinking about the vertex attrib pointers. In that case, you should use the same numbers for these for every shader program that will be using the FBO. Do that either by using the layout directive in the shader logic (easiest), or by calling glBindAttribLocation() before the linking phase. That is, you define the index instead of query for them. If you do this, the same vertex attribute index will be used for all programs using your FBO, which means you can have a common logic for glVertexAttribPointer() and glEnableVertexAttribArray(). I do this by having a common program shader base class (in C++) that defines an enum with all render targets. The programs doesn't have to use all render targets available in the FBO. But you are still allowed to call glEnableVertexAttribArray() for all of them (making it easier to have common code).

Share this post

Link to post
Share on other sites
I believe the Op is talking about MRT, the use of multiple color attachments, render buffers, with a single FBO. Note that each render buffer is also considered an implementation of a Render Target, although this term is far more vague.

Yes, there are obvious restrictions to the types of the separate render buffers attached. All must have the same number of color channels. However, data types may differ. I have used 4 channel half-float and float buffers in MRT without problem.

Honestly, I am not sure about official support rules for MRT, nor do I know the current implementation details, but I thought it would be wise to clear up any confusion on the topic. That said, I would advise to keep using what layouts work for you, as it will likely work on other systems. If it ends up not working with a different driver or card, deal with it then. Edited by Ignifex

Share this post

Link to post
Share on other sites
Sorry, i shoud have made that more clear: i'm talking about Multiple Render Targets.

In my case i'm using 3 color attachments as textures:[list]
So it's possible - at least with my gpu (GL 3.3) - to have a different number of channels, as it all works as expected. I think i assume that it's not possible in general, i think.

Thanks for your help ;) Edited by weeska

Share this post

Link to post
Share on other sites
[quote name='Ignifex' timestamp='1345063580' post='4969941']
Yes, there are obvious restrictions to the types of the separate render buffers attached. All must have the same number of color channels. However, data types may differ. I have used 4 channel half-float and float buffers in MRT without problem.[/quote]

Are you absolutely certain that is still a requirements in newer versions? I remember reading (although the source currently eludes me) that it was at some time a requirement but was removed in one of the OpenGL revisions in between.
Also, I have a hobby project running on an AMD card (which generally make more of an effort to be standard compliant) which has a four channel byte render target and a one channel integer render buffer bound to the same FBO and I can render to both at the same time with the expected results.

Share this post

Link to post
Share on other sites
Hmm, well, as I said, I am not sure about official support. The last time I experimented with the possibilities on a GL 3.3 system (pre-Fermi card), I wasn't able to create such an FBO, although that has been a while.

Currently reading through the opengl Wiki pages. The [url=""]framebuffer completeness rules[/url] only provide one limitation:
- All images must have the same number of multisample samples
Also, on the Image Format page, a list of [url=""]required formats[/url] for render buffers is provided.
This says that 1, 2 and 4 channels with some typical formats must be supported. 3 channel textures and some other formats are optional for implementations. This does not appear to mention anything on multiple render targets.

Number of channels used to be a limitation, but clearly isn't anymore. If anyone can find a good source, it would help to clear this up. Edited by Ignifex

Share this post

Link to post
Share on other sites
[quote name='weeska' timestamp='1345070697' post='4969980'][list]
[/quote]Technically, the number of channels is a semantic quantity--the underlying hardware will use whichever internal format it wants to. E.g., RGB is almost always some for of RGBA under the covers, because hardware operates on ones and fours. For example, I would guess that RG16F would be stored in four 8-bit channels. You probably knew that though.

I regret that I don't know for sure whether it is a portability limitation to include color attachments/rendertargets of differing internal formats. It never occurred to me, but everything I've seen seems to suggest it is possible, including its working on my card. It's an interesting concern though.

A helpful analogy might be to compare FBOs to a standard OpenGL context, wherein you can request a number of different buffers--stencil, depth, color, accumulation, etc. These are necessarily different formats, but they've all cooperated with each other for as long as they've been around. A FBO is just like a standard context, except you can choose whether you want to be able to read the buffers directly (attach a texture instead of a renderbuffer to an attachment point). I see no reason why FBOs should be different.

-G Edited by Geometrian

Share this post

Link to post
Share on other sites
The rules should be more relaxed on OpenGL 3.0 and onwards. However if you look at it still says: "There's one more rule that can trip you up: The implementation likes your combination of attached image formats. (GL_FRAMEBUFFER_UNSUPPORTED when false)."

I've only used OpenGL 2.0 with EXT_framebuffer_object extension and with that, different color formats would work on recent GPUs on Windows/Linux, but OS X liked to play it strict and gave an error when the color formats differed. So if possible, I'd suggest testing on OS X to see if you're compatible.

Share this post

Link to post
Share on other sites
[quote name='AgentC' timestamp='1345200283' post='4970502']
The rules should be more relaxed on OpenGL 3.0 and onwards. However if you look at [url=""]http://www.opengl.or...mebuffer_Object[/url] it still says: "There's one more rule that can trip you up: The implementation likes your combination of attached image formats. (GL_FRAMEBUFFER_UNSUPPORTED when false)."

It also says:
"Basically, don't concern yourself with GL_FRAMEBUFFER_UNSUPPORTED too much. Check for it, but you'll be fine as long as you stick to the required formats."

The way i understand it is, use the formats that have to be supported, and there shouldn't be a problem.

Checking for support on OS X is no option nor needed at the moment, but it's always good to know who's strict with these optional parts.

Thanks for the answers so far ;)

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Similar Content

    • By xhcao
      Does sync be needed to read texture content after access texture image in compute shader?
      My simple code is as below,
      glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
      glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
      glDispatchCompute(1, 1, 1);
      // Does sync be needed here?
      glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
                                     GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
      glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
      Compute shader is very simple, imageLoad content from texture[0], and imageStore content to texture[1]. Does need to sync after dispatchCompute?
    • By Jonathan2006
      My question: is it possible to transform multiple angular velocities so that they can be reinserted as one? My research is below:
      // This works quat quaternion1 = GEQuaternionFromAngleRadians(angleRadiansVector1); quat quaternion2 = GEMultiplyQuaternions(quaternion1, GEQuaternionFromAngleRadians(angleRadiansVector2)); quat quaternion3 = GEMultiplyQuaternions(quaternion2, GEQuaternionFromAngleRadians(angleRadiansVector3)); glMultMatrixf(GEMat4FromQuaternion(quaternion3).array); // The first two work fine but not the third. Why? quat quaternion1 = GEQuaternionFromAngleRadians(angleRadiansVector1); vec3 vector1 = GETransformQuaternionAndVector(quaternion1, angularVelocity1); quat quaternion2 = GEQuaternionFromAngleRadians(angleRadiansVector2); vec3 vector2 = GETransformQuaternionAndVector(quaternion2, angularVelocity2); // This doesn't work //quat quaternion3 = GEQuaternionFromAngleRadians(angleRadiansVector3); //vec3 vector3 = GETransformQuaternionAndVector(quaternion3, angularVelocity3); vec3 angleVelocity = GEAddVectors(vector1, vector2); // Does not work: vec3 angleVelocity = GEAddVectors(vector1, GEAddVectors(vector2, vector3)); static vec3 angleRadiansVector; vec3 angularAcceleration = GESetVector(0.0, 0.0, 0.0); // Sending it through one angular velocity later in my motion engine angleVelocity = GEAddVectors(angleVelocity, GEMultiplyVectorAndScalar(angularAcceleration, timeStep)); angleRadiansVector = GEAddVectors(angleRadiansVector, GEMultiplyVectorAndScalar(angleVelocity, timeStep)); glMultMatrixf(GEMat4FromEulerAngle(angleRadiansVector).array); Also how do I combine multiple angularAcceleration variables? Is there an easier way to transform the angular values?
    • By dpadam450
      I have this code below in both my vertex and fragment shader, however when I request glGetUniformLocation("Lights[0].diffuse") or "Lights[0].attenuation", it returns -1. It will only give me a valid uniform location if I actually use the diffuse/attenuation variables in the VERTEX shader. Because I use position in the vertex shader, it always returns a valid uniform location. I've read that I can share uniforms across both vertex and fragment, but I'm confused what this is even compiling to if this is the case.
      #define NUM_LIGHTS 2
      struct Light
          vec3 position;
          vec3 diffuse;
          float attenuation;
      uniform Light Lights[NUM_LIGHTS];
    • By pr033r
      I have a Bachelor project on topic "Implenet 3D Boid's algorithm in OpenGL". All OpenGL issues works fine for me, all rendering etc. But when I started implement the boid's algorithm it was getting worse and worse. I read article ( inspirate from another code (here: but it still doesn't work like in tutorials and videos. For example the main problem: when I apply Cohesion (one of three main laws of boids) it makes some "cycling knot". Second, when some flock touch to another it scary change the coordination or respawn in origin (x: 0, y:0. z:0). Just some streng things. 
      I followed many tutorials, change a try everything but it isn't so smooth, without lags like in another videos. I really need your help. 
      My code (optimalizing branch):
      Exe file (if you want to look) and models folder (for those who will download the sources):
      Thanks for any help...

    • By Andrija
      I am currently trying to implement shadow mapping into my project , but although i can render my depth map to the screen and it looks okay , when i sample it with shadowCoords there is no shadow.
      Here is my light space matrix calculation
      mat4x4 lightViewMatrix; vec3 sun_pos = {SUN_OFFSET * the_sun->direction[0], SUN_OFFSET * the_sun->direction[1], SUN_OFFSET * the_sun->direction[2]}; mat4x4_look_at(lightViewMatrix,sun_pos,player->pos,up); mat4x4_mul(lightSpaceMatrix,lightProjMatrix,lightViewMatrix); I will tweak the values for the size and frustum of the shadow map, but for now i just want to draw shadows around the player position
      the_sun->direction is a normalized vector so i multiply it by a constant to get the position.
      player->pos is the camera position in world space
      the light projection matrix is calculated like this:
      mat4x4_ortho(lightProjMatrix,-SHADOW_FAR,SHADOW_FAR,-SHADOW_FAR,SHADOW_FAR,NEAR,SHADOW_FAR); Shadow vertex shader:
      uniform mat4 light_space_matrix; void main() { gl_Position = light_space_matrix * transfMatrix * vec4(position, 1.0f); } Shadow fragment shader:
      out float fragDepth; void main() { fragDepth = gl_FragCoord.z; } I am using deferred rendering so i have all my world positions in the g_positions buffer
      My shadow calculation in the deferred fragment shader:
      float get_shadow_fac(vec4 light_space_pos) { vec3 shadow_coords = / light_space_pos.w; shadow_coords = shadow_coords * 0.5 + 0.5; float closest_depth = texture(shadow_map, shadow_coords.xy).r; float current_depth = shadow_coords.z; float shadow_fac = 1.0; if(closest_depth < current_depth) shadow_fac = 0.5; return shadow_fac; } I call the function like this:
      get_shadow_fac(light_space_matrix * vec4(position,1.0)); Where position is the value i got from sampling the g_position buffer
      Here is my depth texture (i know it will produce low quality shadows but i just want to get it working for now):
      sorry because of the compression , the black smudges are trees ...
      EDIT: Depth texture attachment:
  • Popular Now