opengl - 简单来说,textureGrad()是什么?

标签 opengl graphics glsl

我在上面读了khronos wiki
但是我真的不明白它在说什么。 TextureGrad到底做什么?
我认为它会采样多个mipmap级别,并使用为其提供的显式导数向量来计算一些颜色混合。但我不确定。

最佳答案

对纹理进行采样时,需要特定的纹理坐标来对纹理数据进行采样。为了简单起见,我将假定一个2D纹理,因此该纹理坐标为2D矢量(s,t)。 (说明与其他维度类似)。

如果要对三角形进行纹理映射,通常使用两种策略之一来获取纹理坐标:

  • 纹理坐标是模型的一部分。每个顶点都包含2D纹理坐标作为顶点属性。在栅格化过程中,这些纹理坐标将在图元上进行插值。
  • 您指定一个数学映射。例如,您可以定义一些将3D对象坐标映射到某些2D纹理坐标的函数。例如,您可以定义一些投影,然后将纹理投影到表面上,就像真实的投影仪将图像投影到某些真实对象上一样。

  • 无论哪种情况,光栅化时生成的每个片段通常都具有不同的纹理坐标,因此屏幕上的每个绘制像素将获得纹理的不同部分。

    关键是:每个片段都具有2D像素坐标(x,y)和2D纹理坐标(s,t),因此我们可以将这种关系基本上解释为数学函数:
    (s,t) = T(x,y)
    

    由于这是2D像素位置向量(x,y)中的向量函数,因此我们还可以沿x方向(向右)和y方向(向上)构建偏导数,这表明使用了纹理坐标的变化率这些方向。
    dTdx中的dTdytextureGrad就是这样。

    那么GPU需要做什么呢?

    当您要实际过滤纹理时(与简单点采样相反),您需要知道纹理空间中的像素足迹。每个单个片段代表屏幕上一个像素的面积,您将使用纹理中的单个颜色值来代表整个像素(撇开多重采样)。现在,像素覆盖区表示像素在纹理空间中将具有的实际面积。我们可以通过不为像素中心插值texcoords,而是为4个像素角插值texcoords来计算它。生成的texcoords将在纹理空间中形成梯形。

    缩小纹理时,多个纹理像素将映射到同一像素(因此,像素足迹在纹理空间中很大)。放大时,每个像素将仅代表相应纹理像素的一小部分(因此,占用空间很小)。

    纹理足迹告诉您:
  • (如果纹理被缩小或放大)(GL在每种情况下具有不同的滤镜设置)
  • 每个像素将映射多少个纹理像素,因此哪个mipmap级别是合适的
  • 像素覆盖区中有多少各向异性。屏幕上的每个像素和纹理空间中的每个纹理像素基本上都是正方形,但是像素覆盖区可能会明显偏离正方形,并且可能比宽度或过渡距离高得多(尤其是在透视失真较大的情况下)。经典的双线性或三线性纹理滤镜始终使用正方形滤镜足迹,但是各向异性纹理滤镜将使用此信息来
    实际上会生成一个与实际像素足迹更匹配的过滤器足迹(以避免混入不应真正属于像素的texel数据)。

  • 代替计算所有像素角的纹理坐标,我们将使用片段中心的偏导数作为像素足迹的近似值。

    下图显示了几何关系:

    diagram of pixel footprint in texture space

    这表示纹理空间中四个相邻像素(2x2)的覆盖区,因此均匀网格为纹理像素,而4个梯形则代表4个像素覆盖区。
    现在计算实际导数将暗示我们具有如上所述的或多或少的显式公式T(x,y)。 GPU通常使用另一种近似值:
    只需查看每个2x2像素块中相邻片段(无论如何都将要计算)的实际texcoords,并通过有限差分来近似估算占位面积-只需将相邻片段的实际texcoords彼此相减即可。
    结果在图中以虚线平行四边形显示。

    在硬件中,这已实现为始终在同一扭曲/波前/SIMD-Group中并行阴影2x2像素四边形。 GLSL derivative functions like dFdx and dFdy 可以通过减去相邻片段的实际值来简单地工作。标准的texture函数仅在内部对纹理坐标参数使用此机制。 textureGrad函数绕过该函数,并允许您指定自己的值,这意味着您可以控制GPU在进行实际的过滤/mipmap级别选择时所采用的像素尺寸。

    关于opengl - 简单来说,textureGrad()是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52975878/

    相关文章:

    c++ - GLFW程序不画三角形

    c++ - OpenGL 三角形旋转

    haskell - 在屏幕上渲染纹理

    c++ - 在 C++ 中从中心按像素绘制实心圆?

    c++ - 通过在 GLSL 中为不同的屏幕区域着色来识别 mip 映射级别

    OpenGL:如何获取变换后特定点的坐标?

    graphics - "translate"图形对象是什么意思?

    Java:用drawLine绘制矩形螺旋线

    javascript - iOS 移动设备上的 Three.js 渲染问题

    c++ - 计算着色器不写入缓冲区?