Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'll begin by apologizing for any dumb assumptions you might find in the code below since I'm still pretty much green when it comes to OpenGL programming.

I'm currently trying to implement deferred shading by using FBO's and their associated targets (textures in my case).

I have a simple (I think :P) geometry+fragment shader program and I'd like to write its Fragment Shader stage output to three different render targets (previously bound by a call to glDrawBuffers()), like so:

#version 330

in vec3 WorldPos0;
in vec2 TexCoord0;
in vec3 Normal0;
in vec3 Tangent0;

layout(location = 0) out vec3 WorldPos;
layout(location = 1) out vec3 Diffuse;
layout(location = 2) out vec3 Normal;

uniform sampler2D gColorMap;
uniform sampler2D gNormalMap;

vec3 CalcBumpedNormal() {

    vec3 Normal = normalize(Normal0);
    vec3 Tangent = normalize(Tangent0);

    Tangent = normalize(Tangent - dot(Tangent, Normal) * Normal);
    vec3 Bitangent = cross(Tangent, Normal);
    vec3 BumpMapNormal = texture(gNormalMap, TexCoord0).xyz;

    BumpMapNormal = 2 * BumpMapNormal - vec3(1.0, 1.0, -1.0);

    vec3 NewNormal;
    mat3 TBN = mat3(Tangent, Bitangent, Normal);
    NewNormal = TBN * BumpMapNormal;
    NewNormal = normalize(NewNormal);

    return NewNormal;
}

void main() {
    WorldPos = WorldPos0;
    Diffuse = texture(gColorMap, TexCoord0).xyz;
    Normal = CalcBumpedNormal();
}

If my render target textures are configured as:

RT1:(GL_RGB32F, GL_RGB, GL_FLOAT, GL_TEXTURE0, GL_COLOR_ATTACHMENT0)
RT2:(GL_RGB32F, GL_RGB, GL_FLOAT, GL_TEXTURE1, GL_COLOR_ATTACHMENT1)
RT3:(GL_RGB32F, GL_RGB, GL_FLOAT, GL_TEXTURE2, GL_COLOR_ATTACHMENT2)

And assuming that each texture has an internal format capable of contaning the incoming data, will the fragment shader write the corresponding values to the expected texture targets?

On a related note, do the textures need to be bound to the OpenGL context when they are Multiple Render Targets?

From some Googling, I think there are two other ways to output to MRTs:

1: Output each component to gl_FragData[n]. Some forum posts say this method is deprecated. However, looking at the latest OpenGL 3.3 and 4.0 specifications at opengl.org, the core profiles still mention this approach.

2: Use a typed output array variable for the expected type. In this case, I think it would be something like this:

out vec3 [3] output;

void main() {
    output[0] = WorldPos0;
    output[1] = texture(gColorMap, TexCoord0).xyz;
    output[2] = CalcBumpedNormal();
}

So which is then the recommended approach? Is there a recommended approach at all if I plan to code on top of OpenGL 3.3?

Thanks for your time and help!

share|improve this question
    
Unfortunate that you don't have any answers yet. I would be interested in potential performance differences between the different solutions. Perhaps you can implement all 3 of them (the one you explained in detail will certainly work), compare, and post results as your own answer (reaping glorious answer rep points?). Many would thank you for it. –  TravisG Oct 27 '13 at 13:39

1 Answer 1

The second approach is the new one. they will not perform differently, it is just a flexibility of naming.

Also: yes your values will be written as-is to your textures.

now, you may want to use RGB16F targets because RGB32F are VERY taxing on the ROPs and the bus bandwidth which is what medium/small-end graphic cards does NOT have. (only the high-end cards can biund full-HD 3x 128 bits render targets at >60 FPS)

when using 16F (half floats) your values will loose precision during encoding reduction (the ROPs are operating this conversion), so careful about the range of your values (after ~32000 each step is a multi-integers jump, you don't get decimals anymore etc.)

Now, you ALSO want to reduce the number of targets to 2, by using RGBA and packing your normal as components of A of the first target and A of the second target.

Use a view-space encoding trick to store your normal in only 2 components.

This is THE resource you want to read about that: http://aras-p.info/texts/CompactNormalStorage.html

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.