Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top