我使用SDL2。

目前,我唯一的着色器具有MVP矩阵,并使用其变换点。 br />
glm::lookAt(pos, pos + forward, up);
glm::perspective(fov, aspectRatio, zNear, zFar);


我进行了搜索,但我只能找到多个视口的旧版实现。它们都是一样的,除了每个摄像机的渲染屏幕不同。 (所以我想要4个视口具有相同的内容)

我该怎么做?抱歉,如果我没有提供足够的信息,请随时提问。

评论

您是专门执行4次渲染还是只渲染一次并在4个不同的位置显示结果?

进行渲染4次。我写的只是一个简化的示例,例如,我希望主摄像机在全窗口中渲染汽车,而另一个摄像机从侧面在一个角的小正方形中渲染汽车。

如果我正确理解了这一点,那么您需要将窗口分割为例如4个部分,然后在每个部分中渲染场景的其他部分,就像那样吗?

是的,但并非严格分为四个部分。我希望它具有灵活性。视口矩形的大小和位置灵活。

相关:stackoverflow.com/questions/726379/multiple-viewports-in-opengl/…

#1 楼

可以按以下步骤渲染到同一屏幕的不同视口(部分):

例如将屏幕分为四个部分,并使用不同的制服和不同的视口将同一场景四次渲染到每个角上四次:

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 default


评论


$ \ begingroup $
因此,使用glViewPort()可以定义下一个绘制位置,而使用glBlendFunc可以定义GPU如何将重叠区域(帧缓冲区)彼此融合。我对么?
$ \ endgroup $
– Tudvari
17年1月11日在15:30

$ \ begingroup $
是的,您可以随意设置参数。由于视口的参数是块的左下角的x,y和块的宽度,高度。通过融合,您可以进行实验。
$ \ endgroup $
–narthex
17年1月11日在15:36

$ \ begingroup $
为什么要混合?它与问题有什么关系?
$ \ endgroup $
– Raxvan
17年1月11日在15:38

$ \ begingroup $
您不需要混合或多个帧缓冲区。渲染不会写入当前glViewport矩形外部的任何像素,因此您可以依次设置和绘制每个视口。顺便说一句,如果您想要重叠的视口,还可以使用剪刀测试将间隙限制为某个矩形。
$ \ endgroup $
–内森·里德(Nathan Reed)
17年1月12日在1:02



$ \ begingroup $
混合与此无关,并且使答案更加混乱。只需设置视口即可
$ \ endgroup $
-默认
17年1月12日在15:34

#2 楼

如果您正在编写自己的“顶点/片段着色器”,则还有另一种可能性。它要复杂得多,但对您和/或其他人可能有用。另外,由于它仅使用一次对绘制命令的调用,因此可以加快整个绘制过程。视口的最大数量由GL_MAX_VIEWPORTS定义,通常为16。它可以定义一个视口数组。通过此方法创建的视口已分配了索引。

该索引可在“顶点着色器”中用于设置渲染场景的视口。 (您必须在着色器代码中包括“ ARB_shader_viewport_layer_array”扩展名)

对于您的情况,我建议您执行以下操作:


存储4个摄像头Shader存储缓冲区(矩阵4的矩阵)中的矩阵以将它们包含在Vertex Shader中。使用索引图,例如:glDrawElementsInstanced

使用Vertex Shader的gl_InstanceID中的构建来访问相机矩阵数组
将片段着色器中的内置变量输出变量gl_ViewportIndex设置为gl_InstanceID。 (有关详细信息,请参见ARB_fragment_layer_viewport)


评论


$ \ begingroup $
“此索引可在“顶点着色器”中用于设置渲染场景的视口。”不,它不能。好吧,并非没有ARB_shader_viewport_layer_array扩展或AMD等效产品。这些都不是GL 4.5中的标准。您可能正在考虑“几何着色器”。
$ \ endgroup $
–尼科尔·波拉斯(Nicol Bolas)
17年1月13日14:38



$ \ begingroup $
@Nicol,谢谢您的提示!我忘了提到,您必须包括扩展名。我将编辑我的答案。
$ \ endgroup $
– Christian_B
17年1月16日在7:26

#3 楼

这是@narthex答案的副本,只有视口除外,因为这就是您所需要的。我不确定为什么他的答案中包含了帧缓冲区/混合内容。

//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 default


#4 楼

这些都是很好的答案,但是还有另一种方法:(不是总是存在吗?)
由于虚拟现实的日益普及,OculusVR的开发人员开发了三重“ Multiview”扩展,称为: br />

OVR_multiview,

OVR_multiview2和&
OVR_multiview_multisampled_render_to_texture

这些扩展允许在同一场景中渲染多个视图一次绘制调用,从每只眼睛的角度消除了在相同状态下渲染相同场景的冗余。尽管出于VR的目的而创建,但开发人员并不一定仅限于两个视图。而是,此扩展允许使用MAX_VIEWS_OVR指定的尽可能多的视图。
在使用这些扩展之前,开发人员应通过添加以下代码来检查用户的图形驱动程序是否支持它们:
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 );
}

来自在那里,只需设置帧缓冲区即可利用此功能:
glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress("glFramebufferTextureMultisampleMultiviewOVR"));
glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);

同样在着色器中:
#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);
}

在受CPU约束的应用程序中,此扩展可以大大减少了渲染时间,尤其是对于更复杂的场景: