<p>If you are writing your own Vertex/Fragment Shader there is another additional possibility to do this. It is much more complicated but might be useful for you and/or others. Additionally it speeds up the whole drawing process since it uses only one call to a draw command. The maximum number of Viewports is defined by GL_MAX_VIEWPORTS and is usually 16. </p>

<p>Since OpenGL 4.1 the method <a href="https://www.opengl.org/sdk/docs/man4/html/glViewportArray.xhtml" rel="noreferrer">glViewportArrayv</a> exists. It can define an array of Viewports. The Viewports which are created by this method have an index assigned. </p>

<p>This index can be used in the Vertex Shader to set the Viewport to which the scene is rendered. (You have to include the "<em>ARB_shader_viewport_layer_array</em>" extension in the shader code)</p>

<p>In your case I would suggest to do the following:</p>

<ul>
<li>Store the 4 camera matrices in a Shader Storage Buffer (Array of mat4) to have them in the Vertex Shader</li>
<li>Use <a href="https://learnopengl.com/#!Advanced-OpenGL/Instancing" rel="noreferrer">indexed drawing</a>, for example :<a href="https://www.opengl.org/sdk/docs/man/html/glDrawElementsInstanced.xhtml" rel="noreferrer">glDrawElementsInstanced</a></li>
<li>use the build in <a href="https://www.opengl.org/sdk/docs/man/html/gl_InstanceID.xhtml" rel="noreferrer">gl_InstanceID</a> of the Vertex Shader to access the camera matrix array</li>
<li>set the build in variable output variable gl_ViewportIndex in the Fragment Shader to the gl_InstanceID. (for details see <a href="https://www.opengl.org/registry/specs/ARB/fragment_layer_viewport.txt" rel="noreferrer">ARB_fragment_layer_viewport</a>)</li>
</ul>

CC BY-SA 3.0
2017-01-13T14:38:50.593Z
"*This index can be used in the Vertex Shader to set the Viewport to which the scene is rendered.*" No, it cannot. Well, not without the ARB_shader_viewport_layer_array extension, or the AMD equivalents. None of those are standard in GL 4.5. You are perhaps thinking of Geometry Shaders.
Nicol Bolas
CC BY-SA 3.0
2017-01-16T07:26:44.073Z
@Nicol, Thanks for this hint! I forgot to mention, that you have to include the extension. I will edit my answer.
Christian_B
CC BY-SA 3.0
2017-01-13T12:37:08.923Z
2017-01-19T14:17:18.273Z
2017-01-19T14:17:18.273Z
Christian_B
<p>This is a copy of @narthex's answer, except with only the viewports since that is all you need.  I'm not sure why the frame buffer / blend stuff is included in his answer.</p>

<pre><code>//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default
</code></pre>

CC BY-SA 3.0
2017-01-12T15:14:50.807Z
2017-01-12T15:14:50.807Z
default
<p>These are all good answers, and yet there is another way: (Isn't there always?)</p>
<p>Due to the growing popularity of virtual reality, the folks at OculusVR have developed a trio of &quot;Multiview&quot; extensions called:</p>
<ol>
<li><strong>OVR_multiview</strong>,</li>
<li><strong>OVR_multiview2</strong>, &amp;</li>
<li><strong>OVR_multiview_multisampled_render_to_texture</strong></li>
</ol>
<p>These extensions allow multiple views of the same scene to be rendered in a single draw call, eliminating the redundancy of rendering the same scene in the same state from the viewpoint of each eye. Although created for the purpose of VR, the developer is not necessarily limited to merely two views. Rather, this extension allows for as many views as <strong>MAX_VIEWS_OVR</strong> specifies.</p>
<p>Before using these extensions, the developer should check for their support in the user's graphics driver by adding the following code:</p>
<pre><code>const GLubyte* extensions = GL_CHECK( glGetString( GL_EXTENSIONS ) );
char * found_extension = strstr( (const char*)extensions, &quot;GL_OVR_multiview&quot; );
if (NULL == found_extension)
{
     exit( EXIT_FAILURE );
}
</code></pre>
<p>From there, it is a matter of setting up your framebuffer to utilize this feature:</p>
<pre><code>glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress(&quot;glFramebufferTextureMultisampleMultiviewOVR&quot;));
glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);
</code></pre>
<p>and likewise in the shader:</p>
<pre><code>#version 300 es
#extension GL_OVR_multiview : enable

layout(num_views = 2) in;
in vec3 vertexPosition;
uniform mat4 MVP[2];

void main(){
    gl_Position = MVP[gl_ViewID_OVR] * vec4(vertexPosition, 1.0f);
}
</code></pre>
<p>In a CPU-bound application, this extension can <em>dramatically</em> reduce rendering time, <em>especially with more complex scenes</em>:</p>
<p><a href="https://i.sstatic.net/6nrze.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/6nrze.png" alt="Relative CPU time between multiview and regular stereo. The smaller the better, with the number of cubes on the x-axis and the relative time on the y-axis." /></a></p>

CC BY-SA 4.0
2019-08-24T18:54:50.743Z
2019-08-24T18:54:50.743Z
2020-06-18T08:32:12.800Z
Jack
<p>Rendering to different viewports (parts) of the same screen can be done as follows:</p>

<p>For example splitting screen into four parts and rendering the same scene four times to each corner with different uniforms and different viewports:</p>

<pre><code>bindFramebuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene-&gt;setConstPerFrameUniforms();

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;setVarPerFrameUniforms(1);
scene-&gt;draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;setVarPerFrameUniforms(2);
scene-&gt;draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;setVarPerFrameUniforms(3);
scene-&gt;draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene-&gt;setVarPerFrameUniforms(4);
scene-&gt;draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default
</code></pre>

CC BY-SA 3.0
2017-01-11T15:30:29.633Z
So with glViewPort() I can define where I want to draw next, and with glBlendFunc I can define how the GPU should blend the overlapping areas (framebuffers) with each other. Am I correct?
Tudvari
CC BY-SA 3.0
2017-01-11T15:36:45.650Z
Yes, you are free to parametrize that. As parameters of `viewport` are x, y of left bottom corner of chunk  and width, height of chunk. With blending you can experiment.
mdkdy
CC BY-SA 3.0
2017-01-11T15:38:59.450Z
why blending? how is it related to the question ?
Raxvan
CC BY-SA 3.0
2017-01-11T17:27:15.027Z
@Tudvari you can do it in more modern way
mdkdy
CC BY-SA 3.0
2017-01-11T17:42:00.107Z
and what is that way?
Tudvari
CC BY-SA 3.0
2017-01-11T17:45:26.173Z
@Tudvari I edited my answer.
mdkdy
CC BY-SA 3.0
2017-01-12T01:02:54.347Z
You don't need blending or multiple framebuffers. Rendering will not write to any pixels outside the current glViewport rectangle, so you can just set up and draw each viewport in turn. BTW you can also use the [scissor test](https://www.khronos.org/opengl/wiki/Scissor_Test) to restrict clears to a certain rectangle, in case you want overlapping viewports.
Nathan Reed
CC BY-SA 3.0
2017-01-12T15:34:46.420Z
Blending has nothing to do with this and makes the answer more confusing. The setting up of the viewports is all that is needed
default
CC BY-SA 3.0
2017-01-12T15:48:10.990Z
@NathanReed No problem feel free to edit  or add info about scissor test
mdkdy
CC BY-SA 3.0
2017-01-11T14:51:02.887Z
2017-01-12T15:50:49.653Z
2017-01-12T15:50:49.653Z
mdkdy
<p>I use <strong>SDL2</strong>.</p>

<p>Currently my only shader has a <strong>MVP matrix</strong>, and transforms the points with it.</p>

<p><strong>I calculate my View and Projection matrix for a camera with GLM:</strong></p>

<pre><code>glm::lookAt(pos, pos + forward, up);
glm::perspective(fov, aspectRatio, zNear, zFar);
</code></pre>

<p>I searched it, but I can only find legacy implementation of multiple viewports.</p>

<p>If I create for example <strong>4 cameras</strong> and let's say that they <strong>all the same</strong>, except every camera has a <strong>different quarter of the screen</strong> to render. (So I want 4 viewports with the same content)</p>

<p>How can I do this? Sorry if I didn't give enough informations, feel free to ask.</p>

CC BY-SA 3.0
2017-01-11T12:50:07.020Z
Are you specifically looking to perform the rendering 4 times, or just to render once and display the result in 4 different places?
trichoplax is on Codidact now
CC BY-SA 3.0
2017-01-11T12:59:31.270Z
Perform the rendering 4 times. What I wrote is just a simplified example, for example I want the main camera to render a car at the full window, and another camera render the car from the side in a small square in one of the corners.
Tudvari
CC BY-SA 3.0
2017-01-11T14:15:03.163Z
If I understood this correctly so you need to split your window to for example 4 parts and in each part render other parts of the scene like [that](http://archive.gamedev.net/archive/reference/programming/features/3dmfc/viewerearly.jpg)?
mdkdy
CC BY-SA 3.0
2017-01-11T14:38:04.867Z
Yes, but not strictly 4 parts. I want it to be flexible.
Flexible size and position of viewport rectangle.
Tudvari
CC BY-SA 3.0
2018-02-21T22:50:19.510Z
Related: https://stackoverflow.com/questions/726379/multiple-viewports-in-opengl/36048277#36048277
Ciro Santilli OurBigBook.com
<opengl><glm>
Multiple viewports with modern OpenGL?
Tudvari
# Multiple viewports with modern OpenGL?

(Asked by: username_0 on 2017-01-11)

I use **SDL2**.

Currently my only shader has a **MVP matrix**, and transforms the points with it.

**I calculate my View and Projection matrix for a camera with GLM:**

```
glm::lookAt(pos, pos + forward, up);
glm::perspective(fov, aspectRatio, zNear, zFar);

```

I searched it, but I can only find legacy implementation of multiple viewports.

If I create for example **4 cameras** and let's say that they **all the same**, except every camera has a **different quarter of the screen** to render. (So I want 4 viewports with the same content)

How can I do this? Sorry if I didn't give enough informations, feel free to ask.

**Tags:** opengl, glm

> **Comments:**
> **username_1**: Are you specifically looking to perform the rendering 4 times, or just to render once and display the result in 4 different places?  
> **username_0**: Perform the rendering 4 times. What I wrote is just a simplified example, for example I want the main camera to render a car at the full window, and another camera render the car from the side in a small square in one of the corners.  
> **username_2**: If I understood this correctly so you need to split your window to for example 4 parts and in each part render other parts of the scene like [that](http://archive.gamedev.net/archive/reference/programming/features/3dmfc/viewerearly.jpg)?  
> **username_0**: Yes, but not strictly 4 parts. I want it to be flexible. Flexible size and position of viewport rectangle.  
> **username_3**: Related: https://stackoverflow.com/questions/726379/multiple-viewports-in-opengl/36048277#36048277  

---

## 4 answers

### Answer by username_2 on 2017-01-11. Score: 9 | Accepted answer

Rendering to different viewports (parts) of the same screen can be done as follows:

For example splitting screen into four parts and rendering the same scene four times to each corner with different uniforms and different viewports:

```
bindFramebuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene->setConstPerFrameUniforms();

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(1);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(2);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(3);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(4);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore username_6

```

> **Comments:**
> **username_0**: So with glViewPort() I can define where I want to draw next, and with glBlendFunc I can define how the GPU should blend the overlapping areas (framebuffers) with each other. Am I correct?  
> **username_2**: Yes, you are free to parametrize that. As parameters of `viewport` are x, y of left bottom corner of chunk  and width, height of chunk. With blending you can experiment.  
> **username_8**: why blending? how is it related to the question ?  
> **username_2**: @username_0 you can do it in more modern way  
> **username_0**: and what is that way?  
> **username_2**: @username_0 I edited my answer.  
> **username_9**: You don't need blending or multiple framebuffers. Rendering will not write to any pixels outside the current glViewport rectangle, so you can just set up and draw each viewport in turn. BTW you can also use the [scissor test](https://www.khronos.org/opengl/wiki/Scissor_Test) to restrict clears to a certain rectangle, in case you want overlapping viewports.  
> **username_6**: Blending has nothing to do with this and makes the answer more confusing. The setting up of the viewports is all that is needed  
> **username_2**: @username_9 No problem feel free to edit  or add info about scissor test  

---

### Answer by username_4 on 2017-01-13. Score: 11

If you are writing your own Vertex/Fragment Shader there is another additional possibility to do this. It is much more complicated but might be useful for you and/or others. Additionally it speeds up the whole drawing process since it uses only one call to a draw command. The maximum number of Viewports is defined by GL\_MAX\_VIEWPORTS and is usually 16.

Since OpenGL 4.1 the method [glViewportArrayv](https://www.opengl.org/sdk/docs/man4/html/glViewportArray.xhtml) exists. It can define an array of Viewports. The Viewports which are created by this method have an index assigned.

This index can be used in the Vertex Shader to set the Viewport to which the scene is rendered. (You have to include the "*ARB\_shader\_viewport\_layer\_array*" extension in the shader code)

In your case I would suggest to do the following:

* Store the 4 camera matrices in a Shader Storage Buffer (Array of mat4) to have them in the Vertex Shader
* Use [indexed drawing](https://learnopengl.com/#!Advanced-OpenGL/Instancing), for example :[glDrawElementsInstanced](https://www.opengl.org/sdk/docs/man/html/glDrawElementsInstanced.xhtml)
* use the build in [gl\_InstanceID](https://www.opengl.org/sdk/docs/man/html/gl_InstanceID.xhtml) of the Vertex Shader to access the camera matrix array
* set the build in variable output variable gl\_ViewportIndex in the Fragment Shader to the gl\_InstanceID. (for details see [ARB\_fragment\_layer\_viewport](https://www.opengl.org/registry/specs/ARB/fragment_layer_viewport.txt))

> **Comments:**
> **username_5**: "*This index can be used in the Vertex Shader to set the Viewport to which the scene is rendered.*" No, it cannot. Well, not without the ARB_shader_viewport_layer_array extension, or the AMD equivalents. None of those are standard in GL 4.5. You are perhaps thinking of Geometry Shaders.  
> **username_4**: @username_5, Thanks for this hint! I forgot to mention, that you have to include the extension. I will edit my answer.  

---

### Answer by username_6 on 2017-01-12. Score: 4

This is a copy of @narthex's answer, except with only the viewports since that is all you need. I'm not sure why the frame buffer / blend stuff is included in his answer.

```
//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore username_6

```


---

### Answer by username_7 on 2019-08-24. Score: 2

These are all good answers, and yet there is another way: (Isn't there always?)

Due to the growing popularity of virtual reality, the folks at OculusVR have developed a trio of "Multiview" extensions called:

1. **OVR\_multiview**,
2. **OVR\_multiview2**, &
3. **OVR\_multiview\_multisampled\_render\_to\_texture**

These extensions allow multiple views of the same scene to be rendered in a single draw call, eliminating the redundancy of rendering the same scene in the same state from the viewpoint of each eye. Although created for the purpose of VR, the developer is not necessarily limited to merely two views. Rather, this extension allows for as many views as **MAX\_VIEWS\_OVR** specifies.

Before using these extensions, the developer should check for their support in the user's graphics driver by adding the following code:

```
const GLubyte* extensions = GL_CHECK( glGetString( GL_EXTENSIONS ) );
char * found_extension = strstr( (const char*)extensions, "GL_OVR_multiview" );
if (NULL == found_extension)
{
     exit( EXIT_FAILURE );
}

```

From there, it is a matter of setting up your framebuffer to utilize this feature:

```
glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress("glFramebufferTextureMultisampleMultiviewOVR"));
glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);

```

and likewise in the shader:

```
#version 300 es
#extension GL_OVR_multiview : enable

layout(num_views = 2) in;
in vec3 vertexPosition;
uniform mat4 MVP[2];

void main(){
    gl_Position = MVP[gl_ViewID_OVR] * vec4(vertexPosition, 1.0f);
}

```

In a CPU-bound application, this extension can *dramatically* reduce rendering time, *especially with more complex scenes*:

[![Relative CPU time between multiview and regular stereo. The smaller the better, with the number of cubes on the x-axis and the relative time on the y-axis.](https://i.sstatic.net/6nrze.png)](https://i.sstatic.net/6nrze.png)


---

