【问题标题】:opengl es render screen portion to textureopengl es 将屏幕部分渲染到纹理
【发布时间】:2014-11-14 19:54:51
【问题描述】:

我正在使用 FBO,我需要将屏幕的一部分渲染为纹理。我需要限制全屏渲染,所以我只得到一个渲染到纹理的屏幕小窗口(然后我将模糊该部分并将其作为纹理渲染回屏幕)。

问题是我对如何处理视口、透视图和视图矩阵有些困惑。有人可以帮忙吗?

【问题讨论】:

  • 这与stackoverflow.com/questions/24310536/… 几乎完全相同。您可能想在那里查看答案。我不能正式提名这是一个重复,因为没有一个答案被赞成。我的回答提供了一个更简单的解决方案,不需要对透视和视图矩阵进行任何修改。

标签: android opengl-es


【解决方案1】:

我假设您正在绘制一些场景,并且您只想将该屏幕的一部分渲染到 FBO,该 FBO 的大小取决于您希望重绘的部分。或者换句话说,FBO 与您希望重绘的屏幕部分一样大。

创建适当大小的 FBO(可能需要 POT 尺寸)后,您需要将视口设置为与您正在重绘的部分的大小相同,并且原点保持在 (0,0)。接下来需要更改的是矩阵的投影部分,在大多数情况下为glOrthoglFrustum。这两个都有 4 个边框参数(左、右、上、下)。这些参数需要设置为您正在重绘的场景的哪个部分,这取决于两者,您的边框参数是如何在主场景上设置的,以及您的重绘矩形是在什么坐标系中定义的。例如,如果您想重绘屏幕左上角的 100x100 部分并使用glOrtho 和边框参数作为(0,0,viewWidth,viewHeight),那么您的新边框参数就是(0,0,100,100)。但是,如果您使用 (-1,-1,1,1) 之类的东西,则需要根据您的屏幕(缓冲区)大小来计算这些参数。

无论如何,您应该能够通过仅更改这两种方法来管理它。完成对 FBO 的绘图后不要忘记重置它们。

编辑:坐标系变换

虽然这个问题已经回答了很多次,但这里有一些数学代码可以从一个坐标系转换到另一个坐标系。通常从原始场景中插入您的真实参数,这应该为您提供转换后的边界参数,您应该将其插入到 FBO 平截头体中。

(我没有测试这个,所以可能已经犯了错误)

    BorderParameters screenRect; // for instance (0, 0, 360, 480) (left, top, right, bottom)
    BorderParameters redrawRect; // for instance (0, 0, 36, 48) (left, top, right, bottom)
    BorderParameters frustumRect; // for instance (-1, ratio, 1, -ratio) (left, top, right, bottom)

    BorderParameters outputRect; // result (insert into ortho or frustum)

    outputRect.left = frustumRect.left + ((redrawRect.left-screenRect.left)/(screenRect.right-screenRect.left))*(frustumRect.right-frustumRect.left);
    // -1 + ((0-0)/(360-0))*(1+1) = -1
    outputRect.right = frustumRect.left + ((redrawRect.right-screenRect.left)/(screenRect.right-screenRect.left))*(frustumRect.right-frustumRect.left);
    // -1 + ((36-0)/(360-0))*(1+1) = -.8
    outputRect.bottom = frustumRect.top + ((redrawRect.bottom-screenRect.top)/(screenRect.bottom-screenRect.top))*(frustumRect.bottom-frustumRect.top);
    // ratio + ((48-0)/(480-0))*(-ratio-ratio) = ratio - .2*ratio = .8*ratio
    outputRect.top = frustumRect.top + ((redrawRect.top-screenRect.top)/(screenRect.bottom-screenRect.top))*(frustumRect.bottom-frustumRect.top);
    // ratio + ((0-0)/(480-0))*(-ratio-ratio) = ratio

我有 50% 的把握,现在我想到了整个过程将与截锥体一起工作,但是,重绘部分可能会有轻微的偏移(如果它很大,则参数有问题)。 无论如何,更常见的做法是将整个场景绘制到 FBO,然后通过后期处理将其重绘到主缓冲区,而不是将所有元素重绘到一个小的 FBO,因为可能有很多元素需要重绘到 FBO。此外,如果您希望屏幕的许多(例如 10 个)小部分同时模糊,您会重绘整个场景 11 次以获得该场景加上 10 个 FBO 吗?

【讨论】:

  • 非常非常有帮助,谢谢。我一直在做更多的研究,比如这里::songho.ca/opengl/gl_transform.html#example2。如何根据要渲染到缓冲区的区域的屏幕坐标计算所需的 glFrustrum?
猜你喜欢
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多