How to render a radial field in OpenGL?

How to blend shaders/render the scene with multiple shaders at once/multipass shaders in opengl

  • Answer:

    Each polygon primitive being rendered can only have a single shader. But that single shader is free to pull in multiple textures and procedural effects. But if you wanted to. You could combine shaders by either: Rendering the same geometry repeatedly with different shaders - and blending turned on. Or you could render scenes to different buffers and then compose those buffers.

Glyn Williams at Quora Visit the source

Was this solution helpful to you?

Other answers

Well, I am not sure whether i got your question correctly. You can create multiple objects within the same context and so that you can use multiple shaders. Other way is that OpenGL 3.3 supports "blend_func_extended" feature with the help of which you can have multiple output variables in fragment shader and these are supplied to blend equations. For this you need to bind output variables before linking of the program. BTW, what is your use case? what do you want to achieve by this? For details you can refer to this: http://www.opengl.org/registry/specs/ARB/blend_func_extended.txt

Roshan Chaudhari

Usually for multipass rendering, http://www.opengl.org/wiki/Framebuffer_Objects are your friend. In simple terms, Framebuffer object is just another screen which will not be visible on your monitor but processes in the background. This technique of Dynamic Rendering is also commonly known as "Render To Texture". Here is how it works in simple steps. 1. Since you will be rendering to a texture, you must generate a new texture. Use the following snippet in Python (It is similar usage as C/C++). [code] def createTexture(size=(500,500),depth=False):      id = gl.glGenTextures(1)      gl.glBindTexture(gl.GL_TEXTURE_2D, id)      gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,        gl.GL_LINEAR)      gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,        gl.GL_LINEAR)      gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S,              gl.GL_CLAMP_TO_EDGE)      gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T,              gl.GL_CLAMP_TO_EDGE)      type = gl.GL_RGBA      format = gl.GL_UNSIGNED_BYTE      if depth is True:      type = gl.GL_DEPTH_COMPONENT      format = gl.GL_FLOAT      gl.glTexImage2D(gl.GL_TEXTURE_2D,0,type,size[0],size[1],0, type, format,      None)      gl.glBindTexture(gl.GL_TEXTURE_2D, 0)      return id [/code] (You can safely ignore the Depth component right now. Focus on the color component, Note the None argument. It represents a texture with no data but only reserved space). 2. Now you must tell OpenGL to render to the texture you have generated above. So you create a new Framebuffer object. [code] fbo = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbo) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, id, 0)   #use id from 1. gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)   #NEVER FORGET THIS [/code] Now you have told OpenGL, that whenever I use the Framebuffer object with id fbo, render into the empty texture with id id. 3. Now you are all set. Whenever you are drawing some object. You draw into this Framebuffer texture (with id= id). All the pixels that you draw will be saved into this texture you render into. [code] gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbo) gl.glClear(gl.GL_COLOR_BUFFER_BIT)     #For depth you must clear depth bit //Draw your scene here as you would do normally. gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)    #AGAIN!! NEVER FORGET THIS [/code] (Framebuffer with id=0 is the default framebuffer, your display which you see. If you don't do this after you are finished drawing into the Framebuffer, you will end up seeing nothing on your main display, which trust me get really irritating) So, now you are setup with a Framebuffer. When you need to do multi-pass rendering, what is essentially done is that you render into the target texture (id above), and then create another target texture into which you will render the new modified scene based on your original drawing. I'll take the example of a Gaussian Blur. Say you have an image loaded into a 2D Texture with id "img" 1. You draw your texture normally into the Framebuffer. (Rendering onto a quad with a Fragment Shader, binding "img"). 2. Generate another empty texture and change the rendering target texture using the following command wherever you like, say into the NEW_ID. gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, NEW_ID, 0). 3. Now the next time you draw something it will be drawn into the NEW_ID texture. (And this time when you bind a texture onto a quad as in Step 1, bind the "id" rather than "img") 4. You can then alternate between both these texture id's ("NEW_ID" and "id")  to achieve more blurring. The more passes you do, more is the blur. [To get a clearer Idea check out Ping-Pong Shading] It's called Ping-Pong because you alternate between binding the textures. This way you can do multipass rendering based on your requirement. Say you need a rounded-corner grayscale image. Render into the Framebuffer texture with a GrayScale Fragment Shader that you make, and then use another empty texture to render into the corners rounded version of the same image. [Though you could do this in a single pass with one Fragment Shader itself but just for practice.] NOTE: OpenGL-ES does not allow you to have multiple color attachments within the same Framebuffer object, so you must create multiple and use the same technique as above.

Sanyam Kapoor

Related Q & A:

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.