OpenGL将屏幕的一部分渲染为纹理 [英] OpenGL render portion of screen to texture

查看:345
本文介绍了OpenGL将屏幕的一部分渲染为纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将屏幕的一小部分呈现为屏幕外的纹理.这是我的应用程序中的屏幕截图功能的一部分,用户可以在其中选择屏幕上的一个区域并将其保存到图像中.尽管屏幕上的区域可能是250x250px,但保存的图像可能要大得多,例如1000x1000px.

I am trying to render a small region of the screen to an off-screen texture. This is part of a screenshot function in my app where the user selects a region on the screen and saves this to an image. While the region on the screen might be 250x250px, the saved image can be a lot larger like 1000x1000px.

我了解使用FBO渲染到纹理的过程.在定义用于裁剪场景的投影矩阵以便仅渲染屏幕截图区域时,我通常会陷入困境.

I understand the process of rendering to a texture using an FBO. I'm mostly stuck when it comes to defining the projection matrix that clips the scene so that only the screenshot region is rendered.

推荐答案

我相信您可以在不更改投影矩阵的情况下完成此操作.毕竟,如果您考虑一下,您实际上并不想更改投影.您想更改投影几何的哪一部分映射到渲染表面.投影后的坐标系为NDC(标准化设备坐标).控制NDC如何映射到渲染表面的变换是视口变换.您可以通过参数控制glViewport()的视口转换.

I believe you can do this without changing the projection matrix. After all, if you think about, you don't really want to change the projection. You want to change which part of the projected geometry gets mapped to your rendering surface. The coordinate system after projection is NDC (normalized device coordinates). The transform that controls how NDC is mapped to the rendering surface is the viewport transformation. You control the viewport transformation by the parameters to glViewport().

如果将视口尺寸设置为渲染表面的大小,则会将[-1.0,1.0]的NDC范围映射到渲染表面.要在表面上渲染该NDC范围的子范围,您需要相应地放大指定的视口大小.假设将原始图像的1/4映射到表面的宽度,则将视口宽度设置为表面宽度的4倍.

If you set the viewport dimensions to the size of your rendering surface, you map the NDC range of [-1.0, 1.0] to your rendering surface. To render a sub-range of that NDC range to your surface, you need to scale up the specified viewport size accordingly. Say to map 1/4 of your original image to the width of your surface, you set the viewport width to 4 times your surface width.

要将标准NDC范围的子范围映射到您的表面,还需要调整视口的原点.在这种情况下,视口原点值将变为负数.继续前面的示例,要映射1/4或从图像中间开始的原始图像,视口原点的x值将是表面宽度的-2倍.

To map a sub-range of the standard NDC range to your surface, you will also need to adjust the origin of the viewport. The viewport origin values become negative in this case. Continuing the previous example, to map 1/4 or the original image starting in the middle of the image, the x-value of your viewport origin will be -2 times the surface width.

这是我提出的有关如何调整视口的想法.使用以下定义:

Here is what I came up with on how the viewport needs to be adjusted. Using the following definitions:

winWidth: width of original window
winHeight: height of original window
xMin: minimum x-value of zoomed region in original window coordinates
xMax: maximum x-value of zoomed region in original window coordinates
yMin: minimum y-value of zoomed region in original window coordinates
yMax: maximum y-value of zoomed region in original window coordinates
fboWidth: width of FBO you use for rendering zoomed region
fboHeight: height of FBO you use for rendering zoomed region

为避免失真,您可能需要保持宽高比:

To avoid distortion, you will probably want to maintain the aspect ratio:

fboWidth / fboHeight = (xMax - xMin) / (yMax - yMin)

在以下所有内容中,大多数操作(尤其是除法)将必须在浮点中执行.如果原始变量是整数,请记住使用类型转换,并将结果四舍五入为最终结果.

In all of the following, most of the operations (particularly the divisions) will have to be executed in floating point. Remember to use type casts if the original variables are integers, and round the results back to integer for the final results.

xZoom = winWidth / (xMax - xMin);
yZoom = winHeight / (yMax - yMin);
vpWidth = xZoom * fboWidth;
vpHeight = yZoom * fboHeight;
xVp = -(xMin / (xMax - xMin)) * fboWidth;
yVp = -(yMin / (yMax - yMin)) * fboHeight;
glViewport(xVp, yVp, vpWidth, vpHeight);

这篇关于OpenGL将屏幕的一部分渲染为纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆