简体   繁体   English

镶嵌优化[OpenGL]

[英]Tessellation Optimizations [OpenGL]

Tessellation of the terrain: I'm rendering my terrain with clip-maps frustum culling and tessellation shaders. 地形的细分:我正在使用剪辑图截头锥体剔除和细分着色器渲染我的地形。 Now to improve performance more, I want to use some tessellation shaders in a more efficient way. 现在,要进一步提高性能,我想以更有效的方式使用一些曲面细分着色器。 My aim is to achieve a pretty high (~100 FPS) frame rate with decent visual quality, so I'm gonna combine 3 tessellation factors, a tessellation map, view dependent (pixels per edge) tessellation, and silhouette tessellation. 我的目标是实现相当高的视觉质量(约100 FPS),因此,我将结合3个细分因素,细分地图,视点相关(每个边缘的像素)细分和轮廓细分。

My idea is a weighted average of them: 我的想法是对它们进行加权平均:

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

with the 3 factors varying between 0...1, and the tesscoeff could be an uniform too to adjust the levels. 且3个因子在0 ... 1之间变化,而tesscoeff也可以是统一的,以调整水平。 I have the map and the edge radius factors but... 我有地图和边缘半径因子,但是...

Silhouettes: How to find the silhouette patches on a mesh described with a simple y(x,z) function? 轮廓:如何在用简单的y(x,z)函数描述的网格上找到轮廓补丁? I'm using vertex-texture-fetch so I know the neighboring vertices/normals. 我正在使用vertex-texture-fetch,所以我知道相邻的顶点/法线。 Is it a problem if I'm using quad patches, not triangles, or it doesn't make it harder to find them? 如果我使用的是四边形补丁而不是三角形,这是否有问题?或者它不会更难找到它们?

(EDITED TO BACK-PATCH) Backpatch Culling: Another problem I've encountered is the back-face culling. (编辑为BACK-PATCH) Backpatch剔除:我遇到的另一个问题是背面剔除。 As I've said, I'm using quad patches, so one may not lie on a plane. 就像我说的那样,我使用的是四边形补丁,因此可能不会躺在飞机上。 With triangles I would compare the normal to the eye direction, but on the quads I can't, or do not know how to do it. 对于三角形,我会将法线与眼睛的方向进行比较,但是在四边形上,我无法做到,或者不知道该怎么做。

Occlusion Culling: I'm rendering the terrain with geometry clip-maps, with the algorithm: 遮挡剔除:我正在使用几何剪贴图渲染地形,算法如下:

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

I have one single vertex buffer for a simple n*n quad shaped mess. 我有一个单一的顶点缓冲区,用于一个简单的n*n四边形混乱。 I have 4 index buffers for this mesh, one for each quadrant of this quad. 我有4个用于该网格的索引缓冲区,该四分之一的每个象限一个。 For LOD=0 I render the center/bottom left quad, and for the other levels I only render the L-shaped mess with the other 3 (top,topleft,left) quadrants, scaled by pow(2,LOD) . 对于LOD=0我渲染中间/底部左四边形,对于其他级别,我仅渲染与其他3个(上,左上,左,左)象限的L形混乱,按pow(2,LOD)缩放。 Then the whole mesh is scaled with a constant (gridscale). 然后将整个网格缩放为常数(网格比例)。

Since this whole mesh is positioned every frame in front of the camera, the mesh is always rendered quadrant by quadrant from the view origin. 由于整个网格都位于相机前面的每一帧,因此始终从视图原点开始逐个象限渲染网格。 Maybe it could be used for some culling like early-z or occlusion in the tessellation control shader? 也许可以将其用于细化控制着色器中的某些剔除,如Early-Z遮挡

I'm looking for some pointer on these because all I've found are some NVIDIA/AMD papers without much technical background. 我正在寻找有关这些技术的指导,因为我所发现的只是一些技术背景不多的NVIDIA / AMD论文。 http://www.geeks3d.com/20101201/amd-graphics-blog-tessellation-for-all/ the link to the full article is broken too... (from this post: OpenGL Low-Level Performance Questions ) http://www.geeks3d.com/20101201/amd-graphics-blog-tessellation-for-all/指向全文的链接也已损坏...(来自这篇文章: OpenGL低级性能问题

You can cull a triangle (3 points) using the following, 您可以使用以下方法剔除一个三角形(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;
}

You should be able to cull a patch by forming 4 triangles like [\\] (2 triangles from top left point to bottom right point) and [/] (2 triangles from top right to bottom left) from the 4 corner points of the patch and if all dot(vView, vFaceNormal) < -0.25f, it is pretty safe to say that the patch is facing away from the user's eye. 您应该能够通过从补丁的4个角点形成4个三角形,例如[\\](从左上角到右下角的2个三角形)和[/](从右上角到左下角的2个三角形)来剔除补丁。如果所有点(vView,vFaceNormal)<-0.25f,则可以很肯定地说该补丁背对着用户的眼睛。 But this is an approximation of averages (your 4 triangles from the corner points). 但这是平均值的近似值(从拐角点开始的四个三角形)。 Depending on your patch size, and how much crazy stuff (mountains and valleys) you have going on in the patch, this may not work in every situation, and that may be the reason there isn't much info on the net about it. 根据补丁程序的大小以及补丁程序中发生了多少疯狂的事情(山峰和山谷),这可能无法在每种情况下都起作用,这可能是网络上没有太多信息的原因。 You will just have to test and see. 您将只需要测试并查看。

I will say that you could even go a step further, if for some reason you see this not working in all your situations and absolutely want to cull in the hull shader that you could pass in the HeightMap as a texture and sample even more triangles (like get the mid points of the patch) to make [x] to get 4 more triangles even [*] to get 8 more triangles. 我要说的是,您甚至可以走得更远,如果由于某种原因您发现这种方法在所有情况下都无法解决,并且绝对想剔除可以在HeightMap中作为纹理传递并采样更多三角形的船体着色器(例如获得补丁的中点),使[x]获得另外4个三角形,甚至[*]获得另外8个三角形。

A safer way to accomplish the same thing without a huge amount of work is to frustum cull, pass in the planes of your bounding camera frustum and check the bounding box of the patch. 一种无需做大量工作即可完成同一任务的更安全的方法是,将视锥剔除,将相机的视锥面移入平面,然后检查补丁的边界框。 Here is the shader code; 这是着色器代码;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM