Multipass Shader thought Process

Hey guys,

I posted a thread last night which was really code heavy, and nobody has replied yet, so I thought I’d post another, which just contained my understanding of how to tackle a multipass shader program using 2 sets of different shaders, and then I’d post my questions at the end. No code attached, only thought process.

  1. Create an enum of unsigned int TextureIDs

  2. Generate textures based on the number of TextureIDs created. In my case, 4

  3. Bind textures to IDs and attach images to them if needed. In my case 3 of the 4 textures get images, the fourth one gets NULL data. Textures are unbound(?) after they are updated.

–Every time the screen needs to be updated–

  1. Create a framebuffer object, and bind it. First parameter is 1 so that it does not draw to the screen

  2. Create and set shaders for pass 1, and update them with the correct information. (in my case, the 3 textures with images are passed in as uniforms. Some data is sent to the vertex shader too)

  3. Bind empty (data = NULL) texture to the framebuffer as GL_COLOR_ATTACHMENT_0 using a glFrameBufferTexture call

  4. set location 0 to be GL_COLOR_ATTACHMENT_0 using a glDrawBuffers call

  5. draw, which handles drawing, and also calls active and bind on all 4 textures in a loop. The fragment shader outputs a vec3 to location 0 using layout(location = 0)

  6. create and setup new shaders for pass 2, and pass them the appropriate information(in my case, pass the previously empty texture to the fragment shader as a uniform)

  7. switch to the default framebuffer

  8. draw, which once again calls active and bind on all 4 textures, output final data using data from uniform passed in.

Now for my questions:

  1. I am unsure if attaching my texture to GL_COLOR_ATTACHMENT_0 and attaching location 0 to GL_COLOR_ATTACHMENT_0 outputs the data into my texture or if it does not.

  2. If that does output data to the texture, I am unsure if it is being clobbered by switching to the default framebuffer.

  3. I am unsure if I should create a separate draw function for the second pass, which only calls active and bind on the one texture I am using in that pass, or if I can keep it the way it is now.

  4. Why is there a call to glBindTexture(GL_TEXTURE_2D, 0) after each new texture is created?

Thanks to anyone who can tell me if my though process sounds correct, and/or can answer any of these questions

Texture 0 (AKA the default texture object) is a historical artefact going back to OpenGL1.0, which didn’t have texture objects. It does exist and it is a real and valid texture object that you can use: you can glBindTexture it, you can glTexImage it, you can draw stuff with it.

Binding texture 0 effectively reverts your program to the OpenGL1.0 behaviour.

There are a couple of reasons for why you may want to do this.

One reason is that maybe you’ve lifted over your code from a tutorial but you don’t fully understand what the tutorial is doing (maybe it’s just a bad tutorial?)

Another reason is that by binding texture 0 you ensure that future texture operations don’t have unwanted side-effects on the texture you’ve just created. It’s a way of making your code more robust: if you accidentally slip in a texture operation where you shouldn’t have, the texture you’ve just created remains intact.

Thank you very much! That answered question #4 quite nicely!

Does it look to you as if my overall logic is correct?

I haven’t really reviewed the rest of your question I’m afraid, and my familiarity with this kind of setup lies more in D3D than it does in GL (FBOs are cool but SetRenderTarget is just a nicer and cleaner API) so I’m going to pass on your #1 to #3 and leave them for someone who can answer better.