【问题标题】:Tessellation Optimizations [OpenGL]细分优化 [OpenGL]
【发布时间】:2013-12-05 21:58:59
【问题描述】:

地形细分: 我正在使用剪辑贴图截头体剔除和镶嵌着色器渲染我的地形。现在为了进一步提高性能,我想以更有效的方式使用一些曲面细分着色器。我的目标是实现相当高的帧速率(~100 FPS)和良好的视觉质量,所以我将结合 3 个细分因素、一个细分贴图、依赖于视图的细分(每个边缘的像素)细分和轮廓细分。

我的想法是它们的加权平均值:

tessfac = tesscoeff*(w1*tessmapfactor+w2*silhtessfactor+w3*ppetessfactor)/(w1+w2+w3);

这 3 个因素在 0...1 之间变化,并且 tesscoeff 也可以是统一的以调整水平。我有地图和边缘半径因素,但是......

剪影: 如何在使用简单y(x,z) 函数描述的网格上找到轮廓补丁?我正在使用 vertex-texture-fetch 所以我知道相邻的顶点/法线。如果我使用四边形而不是三角形,或者它不会使查找它们变得更加困难,这会不会有问题?

(已编辑回补丁) Backpatch Culling:我遇到的另一个问题是背面剔除。正如我所说,我正在使用四边形贴片,因此可能不会躺在平面上。对于三角形,我会将法线与眼睛方向进行比较,但在四边形上我不能,或者不知道该怎么做。

遮挡剔除:我正在使用几何剪辑贴图渲染地形,算法如下:

foreach(LOD)
    foreach(quarter)
        foreach(quad in quarter) //I mean x+z+, x-z+, x-z- and x+z- by quarters
            quad.clipFrustum();
            if(inFrustum) quad.render();
        endloop
    endloop
endloop

我有一个简单的n*n 四边形混乱的顶点缓冲区。我有这个网格的 4 个索引缓冲区,一个用于这个四边形的每个象限。对于LOD=0,我渲染 center/bottom left 四边形,而对于其他级别,我只渲染 L 形混乱与其他 3 个 (top,topleft,left) 象限,按pow(2,LOD) 缩放。然后用一个常数(gridscale)对整个网格进行缩放。

由于整个网格被放置在摄像机前面的每一帧中,因此网格总是从视图原点逐个象限地渲染。也许它可以用于镶嵌控制着色器中的一些剔除,如 early-zocclusion

我正在寻找一些关于这些的指针,因为我发现的只是一些没有太多技术背景的 NVIDIA/AMD 论文。 http://www.geeks3d.com/20101201/amd-graphics-blog-tessellation-for-all/全文链接也失效了……(来自这篇文章:OpenGL Low-Level Performance Questions

【问题讨论】:

  • 关于背面-face 剔除,您是否在此应用程序中绑定了原始程序集?背面剔除通常是一种光栅化操作,但在过去的几年中,原始设置非常昂贵,以至于引擎有时会在顶点级别剔除三角形(回想一下 Quake 3,它会计算每帧在 CPU 上绘制的三角形列表)。一些 PS3 游戏仍然这样做,因为这是一种让 CELL 处理器忙于工作以减少整体 RSX 负载的简单方法,但这些天大部分时间背面剔除是为了减少片段绑定应用程序的负载。
  • 我认为你会从 back-patch 剔除中受益更多。在您必须决定是否丢弃它们生成的单个图元之前,先剔除整个补丁。
  • 我要做的是通过将曲面细分级别设置为 0 来剔除背面补丁。这不是称为背面补丁剔除吗? (在编辑之前我写了'back-face',它被更正为'back-patch')

标签: performance opengl tessellation


【解决方案1】:

您可以使用以下方法剔除一个三角形(3 个点),

float3 vEdge0 = patch[1].PosW - patch[0].PosW;
float3 vEdge1 = patch[2].PosW - patch[0].PosW;

float3 vFaceNormal0 = normalize(cross(vEdge1, vEdge0));
float2 vView0 = normalize(patch[0].PosW - gEyePosW);

if (dot(vView0, vFaceNormal0) < -0.25f)
{
    pt.EdgeTess[0] = 0.0f;
    pt.EdgeTess[1] = 0.0f;
    pt.EdgeTess[2] = 0.0f;

    pt.InsideTess = 0.0f;

    return pt;
}

您应该能够通过从 4 个角点形成 4 个三角形来剔除补丁,例如 [\](从左上角到右下角的 2 个三角形)和 [/](从右上角到左下角的 2 个三角形)并且如果所有 dot(vView, vFaceNormal)

我会说你甚至可以更进一步,如果由于某种原因你发现这在你所有的情况下都不起作用,并且绝对想要剔除你可以在高度贴图中作为纹理传递的船体着色器,甚至采样更多的三角形(比如获得补丁的中点)使 [x] 获得更多的 4 个三角形,甚至 [*] 获得更多的 8 个三角形。

无需大量工作即可完成相同任务的更安全方法是平截头体剔除,传入边界相机平截头体的平面并检查补丁的边界框。这是着色器代码;

float3 vMin = float3(patch[0].PosW.x, minY, patch[0].PosW.z);
float3 vMax = float3(patch[3].PosW.x, maxY, patch[3].PosW.z);

if (!IntersectsOrContainsBoundingBox(vMin.x, vMin.y, vMin.z, vMax.x, vMax.y, vMax.z))
{
    pt.EdgeTess[0] = 0.0f;
    pt.EdgeTess[1] = 0.0f;
    pt.EdgeTess[2] = 0.0f;
    pt.EdgeTess[3] = 0.0f;

    pt.InsideTess[0] = 0.0f;
    pt.InsideTess[1] = 0.0f;

    return pt;
}

bool IntersectsOrContainsBoundingBox(float minWidth, float minHeight, float minDepth, float maxWidth, float maxHeight, float maxDepth)
{
// check box outside/inside of frustum
for (int i = 0; i < 6; i++)
{
    int output = 0;
    output += (((gWorldFrustumPlanes[i].x * minWidth) + (gWorldFrustumPlanes[i].y * minHeight) + (gWorldFrustumPlanes[i].z * minDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    output += (((gWorldFrustumPlanes[i].x * maxWidth) + (gWorldFrustumPlanes[i].y * minHeight) + (gWorldFrustumPlanes[i].z * minDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    output += (((gWorldFrustumPlanes[i].x * minWidth) + (gWorldFrustumPlanes[i].y * maxHeight) + (gWorldFrustumPlanes[i].z * minDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    output += (((gWorldFrustumPlanes[i].x * maxWidth) + (gWorldFrustumPlanes[i].y * maxHeight) + (gWorldFrustumPlanes[i].z * minDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    output += (((gWorldFrustumPlanes[i].x * minWidth) + (gWorldFrustumPlanes[i].y * minHeight) + (gWorldFrustumPlanes[i].z * maxDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    output += (((gWorldFrustumPlanes[i].x * maxWidth) + (gWorldFrustumPlanes[i].y * minHeight) + (gWorldFrustumPlanes[i].z * maxDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    output += (((gWorldFrustumPlanes[i].x * minWidth) + (gWorldFrustumPlanes[i].y * maxHeight) + (gWorldFrustumPlanes[i].z * maxDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    output += (((gWorldFrustumPlanes[i].x * maxWidth) + (gWorldFrustumPlanes[i].y * maxHeight) + (gWorldFrustumPlanes[i].z * maxDepth) + (gWorldFrustumPlanes[i].w * 1.0f) < 0.0) ? 1 : 0);
    if (output == 8)
    {
        return false;
    }
}

return true;
}

【讨论】:

  • 我已经问了2年了,所以现在已经解决了:D btw +1
猜你喜欢
  • 2018-07-12
  • 1970-01-01
  • 2011-05-15
  • 2013-10-29
  • 2020-02-29
  • 2011-02-16
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多