【问题标题】:OpenGL render portion of screen to textureOpenGL 将屏幕的一部分渲染到纹理
【发布时间】:2014-08-10 05:22:21
【问题描述】:

我正在尝试将屏幕的一小部分区域渲染为屏幕外纹理。这是我的应用程序中的屏幕截图功能的一部分,用户在屏幕上选择一个区域并将其保存到图像中。虽然屏幕上的区域可能是 250x250 像素,但保存的图像可以大很多,比如 1000x1000 像素。

我了解使用 FBO 渲染到纹理的过程。在定义剪辑场景的投影矩阵以便只渲染屏幕截图区域时,我大部分时间都被卡住了。

【问题讨论】:

  • 我不明白为什么保存的图像“可以大很多”。你能详细说明一下吗?
  • 我并没有真正截取传统意义上的截图,而是仅在该截图区域内渲染场景。如果渲染矩阵正确,那么我应该可以将视口设置为任意大小。
  • 你不能只使用glReadPixels 来保存选定的矩形吗?我想我错过了一些东西:)
  • 不,因为我正在尝试将该区域渲染为比屏幕上实际显示的更大的尺寸。
  • 为什么不把 glViewport 和你的投影矩阵设置为想要的大小,也许还设置 glScissors 来裁剪渲染,然后用 glReadPixels 复制结果?

标签: opengl screenshot render-to-texture projection-matrix


【解决方案1】:

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

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

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

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

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

为避免失真,您可能需要保持纵横比:

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

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

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

【讨论】:

    【解决方案2】:

    您可能想了解gluPickMatrix 的工作原理,并使用现代 OpenGL 方法复制其功能。您可以在 Mesa3D 的实现中找到 gluPickMatrix 源代码。

    虽然 gluPickMatrix 的初衷是用于选择模式渲染,但它也可以用于您想做的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2014-08-12
      • 2016-06-24
      • 1970-01-01
      相关资源
      最近更新 更多