【问题标题】:Mimic OpenGL texture mapping on CPU for reprojection在 CPU 上模拟 OpenGL 纹理映射以进行重投影
【发布时间】:2015-04-05 01:12:58
【问题描述】:

我正在尝试使用 UV gBuffer 对纹理重投影进行编码(这是一个纹理,其中包含在该像素处映射所需的 UV 值)

我觉得看这张图应该很容易理解(我不能附上,因为声誉太低了): http://www.andvfx.com/wp-content/uploads/2012/12/3-objectes.jpg

第一个图像(黑色/黄色/红色/绿色)是 UV gBuffer,它代表 uv 值,第二个是漫反射通道,第三个是期望的结果。

在 OpenGL 上实现这一点非常简单。

绘制一个简单的矩形并将此伪代码用作分段着色器:

float2 newUV=texture(UVgbufferTex,gl_TexCoord[0]).xy; float3 finalcolor=texture(DIFFgbufferTex,newUV);

return float4(finalcolor,0);

OpenGL 负责选择 mipmap 级别、各向异性过滤等,同时如果我在常规 CPU 进程中进行此操作,我会得到一个用于 finalcolor 的像素,所以我的结果很清晰。

这里有什么建议吗?我想知道手动计算一种mipmap并通过检查连续像素来选择级别,但不确定这是否是正确的方法,我也怀疑如何处理它,因为它可能在水平方向上快速变化但在垂直方向上变慢或反之亦然。

事实上,我不知道这是如何在 OpenGL/DirectX 内部计算的,因为我使用这种代码很长时间,但从未考虑过内部结构。

【问题讨论】:

  • 你的问题基本上是:OpenGL如何选择要使用的mipmap级别?

标签: c++ opengl graphics texture-mapping uv-mapping


【解决方案1】:

你在正确的轨道上。

要选择 mipmap 级别或应用各向异性过滤,您需要一个渐变。该梯度在 GL(在片段着色器中)中很自然,因为它是在光栅化之后为所有插值变量计算的。如果您尝试在顶点着色器中使用 mipmap 过滤对纹理进行采样,这一切都会变得非常明显。

您可以这样计算 LOD (lambda):

    ρ = max (((du/dx)2 + (dv/dx)2)1/2 , ((du/dy)2 + (dv/dy)2)1/2)

    λ = log2 ρ

【讨论】:

  • 这在extension specification 中解释了显式 LOD 纹理提取。虽然没有说明如果将 lambda 除以 2 可以消除平方根。
  • 谢谢!只是另一个小问题。 dx 是常规缓冲区的变化,而 du 是 uv 的变化,对吗?所以 dx 应该是 1.0/imagesize.x 的常数,对吧?从来没有做过这样的事情,而且比我预期的要难
  • @FrankEscobar:这些是偏导数,所以du/dxu 相对于x 的变化。在 GL 中,这很容易为每个片段计算出来。它使用 2x2 像素邻域(GPU 一次绘制 4 个像素),然后计算某个变量在 X 或 Y 方向(在屏幕空间中)的变化。它有函数dFdx (...)dFdy (...) 可以为你做这件事,你可能会从阅读这个related answer 中受益。
  • 由于dFdx (...)dFdy (...) 是通过使用相邻像素计算变量在X 或Y 方向上的变化来实现的,这意味着dx 将是一个常数1 像素,正如您所描述的那样。
【解决方案2】:

重新投影后根据屏幕上的大小选择纹理。发出三角形后,检查光栅化大小并选择适当的 mipmap。

至于过滤,手动实现双线性过滤并不难。

【讨论】:

  • 谢谢! Coleman 先生的回复更完整,但感谢您抽出宝贵时间。
猜你喜欢
  • 2014-05-09
  • 1970-01-01
  • 2016-10-13
  • 2014-12-19
  • 2017-12-21
  • 2013-02-10
  • 1970-01-01
  • 2018-07-13
  • 2011-05-04
相关资源
最近更新 更多