0

I need to render the depth of a scene from multiple views, is it possible to do it in a single rendering pass?

The depth value could be saved in any form of 2D texture.

shapeare
  • 4,133
  • 7
  • 28
  • 39
  • Let me know if I understand this correctly. You want to render the depth buffer using different camera positions for the same scene in one rendering pass ? – MichaelCMS Jul 31 '14 at 13:05
  • @MichaelCMS Yes, you're right. I would like to do it within a shader program. – shapeare Jul 31 '14 at 14:46
  • @shapeare:Will it be possible for you to post screen-shots of desired/implemented rendering ? This will help in understanding the problem and the use-case of the same – proton Aug 01 '14 at 14:16
  • @ppu.spu Sorry, I haven't yet finished the implementation. I have just implemented the regular shadow map algorithm in a spot light case. I would like to extend my program to using an area light by approximating it with several spot light, and that's why I try to render the geometry from several spot light positions. Due to the consideration of efficiency, I prefer to render the shadow maps of all these spot light in a single pass. – shapeare Aug 02 '14 at 03:13

3 Answers3

4

This should be possible with a bit of creativity. With the introduction of ARB_viewport_array (glViewportIndexed, glDepthRangeIndexed) on opengl 3.2 it has been possible to specify multiple viewports (up to six to be exact so cubemaps could be rendered in a single pass). With the help of a geometry shader the geometry can be duplicated to target specific viewports/layers, see also gl_ViewportIndex, gl_Layer​. Depending on how you exactly want to render i.e. split-screen or separated buffers you might need to conditionally output the fragments to different buffers, or different portions of the screen accordingly. See also Rendering to cube map

Community
  • 1
  • 1
Lawrence Kok
  • 1,568
  • 11
  • 29
1

You might be able to do it with a geometry shader, and by breaking up the viewport into separate sub-windows. For example, you could render the scene from 4 different views, and you'll render each view as 1/4 of the current viewport (e.g. the top-left quarter of the viewport will be one "view" of the scene).

You would have a pass-through vertex shader, and then have the 4 model-view-projection matrices given to the geometry shader as uniforms. The geometry shader would take triangles as input, and for each input triangle, output 4 triangles (12 vertices):

#version 150 core
uniform mat4 MVP_TopLeft;
uniform mat4 MVP_TopRight;
uniform mat4 MVP_BottomLeft;
uniform mat4 MVP_BottomRight;
layout(triangles) in;
layout(GL_TRIANGLES​, max_vertices = 12​) out;
out int SubWindowID;
void main(void) {
    SubWindowID = 0;
    for (int i = 0; i < 3; i++) {
        gl_Position = MVP_TopLeft*gl_in[i].gl_Position;
        //Shift the coordinates into the mini-window
        gl_Position.x = (0.5*gl_Position.x - 0.5);
        gl_Position.y = (0.5*gl_Position.y + 0.5);
        EmitVertex();
    }
    EmitPrimitive();

    SubWindowID = 1;
    for (int i = 0; i < 3; i++) {
        gl_Position = MVP_TopRight*gl_in[i].gl_Position;
        //Shift the coordinates into the mini-window
        gl_Position.x = (0.5*gl_Position.x + 0.5);
        gl_Position.y = (0.5*gl_Position.y + 0.5);
        EmitVertex();
    }
    EmitPrimitive();

    SubWindowID = 2;
    for (int i = 0; i < 3; i++) {
        gl_Position = MVP_BottomLeft*gl_in[i].gl_Position;
        //Shift the coordinates into the mini-window
        gl_Position.x = (0.5*gl_Position.x - 0.5);
        gl_Position.y = (0.5*gl_Position.y - 0.5);
        EmitVertex();
    }
    EmitPrimitive();

    SubWindowID = 3;
    for (int i = 0; i < 3; i++) {
        gl_Position = MVP_BottomRight*gl_in[i].gl_Position;
        //Shift the coordinates into the mini-window
        gl_Position.x = (0.5*gl_Position.x + 0.5);
        gl_Position.y = (0.5*gl_Position.y - 0.5);
        EmitVertex();
    }
    EmitPrimitive();
}

Then, in the fragment shader, you would have in int SubWindowID; declared above the main function, and that int would correspond to which sub-window that fragment was being drawn in.

Jon Simpkins
  • 152
  • 1
  • 10
  • In the fragment shader, how can I know which viewport the fragment should render to? – shapeare Aug 01 '14 at 03:13
  • By doing some reading, I found the GS actually can output a variable called gl_ViewportIndex​, I may probably rely on this. Therefore, in the fragment shader, I would probably write: if(gl_ViewportIndex == 0) texture0 = vec4(depth); else if(gl_ViewportIndex == 1) texture1 = vec4(depth)..... something like this. Am I on the right track? – shapeare Aug 01 '14 at 03:27
  • All the fragments will render to the actual viewport (the one set by glViewport), but if you need to figure out which sub-window the fragment renders to, you could pass an attribute from the geometry shader. Answer above will be edited shortly to help with that. – Jon Simpkins Aug 01 '14 at 03:58
  • Sorry, I should clarify: in the example above, there's just the one viewport being used, although it's possible to use multiple viewports as an alternative approach – Jon Simpkins Aug 01 '14 at 04:00
  • Crap, I just realized why this might not work: the clipping of the triangles is going to happen with respect to the overall viewport, not the individual sub-windows. So if you have a triangle in the top-left subwindow that extends into the top-right subwindow, the whole triangle would be rendered, even the part that should be cut off. Sorry about that, this might have been a step in the wrong direction. – Jon Simpkins Aug 01 '14 at 04:12
  • How should I configure the GL_COLOR_ATTACHMENT if I want to save the rendering to texture? – shapeare Aug 01 '14 at 05:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/58465/discussion-between-shapeare-and-jon-simpkins). – shapeare Aug 01 '14 at 06:00
-1

What you are suggesting is not possible because of the way the rendering pipeline works :

  • you send a bunch of vertexes to the pipeline
  • during vertex shading phase, the video card takes in the projection Matrix and puts each vertex at the position in projection space according to the projection matrix uniform
  • with the vertices now properly set in the projection space rasterization occurs and fragments appear thus fragment shading phase starts
  • fragments write in the depth buffer

What you are suggesting would mean for phase 2 to have two outputs instead of one, which is not possible. You will can send to the shader a projection matrix for each camera in your scene, but you will only have 1 exit vertex in projection space (vertex shader end result is a position in space, not a set of positions).

MichaelCMS
  • 4,703
  • 2
  • 23
  • 29