gpt4 book ai didi

c++ - DirectX大型平面 segmentation

转载 作者:行者123 更新时间:2023-12-04 07:05:06 27 4
gpt4 key购买 nike

只是有关DirectX11镶嵌的问题。

在“船体着色器”中,可以设置的最大镶嵌因子为64(不确定原因)。现在,尽管对于小型飞机已经足够了,但是对于大型飞机来说,这还远远不够,所以我想知道如何渲染大型飞机?

以下代码生成我的四边形,其中R是半径:

vertices[0] = D3DXVECTOR3(-R, 0.0f,  R); //Top left
vertices[1] = D3DXVECTOR3( R, 0.0f, R); //Top right
vertices[2] = D3DXVECTOR3( R, 0.0f, -R); //Bottom right
vertices[3] = D3DXVECTOR3(-R, 0.0f, -R); //Bottom left
vertices[4] = D3DXVECTOR3(-R, 0.0f, R); //Top left
vertices[5] = D3DXVECTOR3( R, 0.0f, -R); //Bottom right

indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
indices[4] = 4;
indices[5] = 5;

我确实修改了它,方法是将其放在一个循环中以在3x3网格中生成多个四边形。但是,当我将其传递给镶嵌 segmentation 着色器时,它对于第一个四边形来说还可以,但是其他的四边形却搞砸了。
vector<D3DXVECTOR3> verts;
vector<D3DXVECTOR2> tex;

float R = 1000;

for(int z = 0; z < 4; z++)
{
for(int x = 0; x < 4; x++)
{
float xOffset = x * (2*R);
float zOffset = z * (2*R);

// Load the vertex array with data.
verts.push_back( D3DXVECTOR3(-R+ xOffset, 0.0f, R+ zOffset) ); //Top left
verts.push_back( D3DXVECTOR3( R+ xOffset, 0.0f, R+ zOffset) ); //Top right
verts.push_back( D3DXVECTOR3( R+ xOffset, 0.0f, -R+ zOffset) ); //Bottom right
verts.push_back( D3DXVECTOR3(-R+ xOffset, 0.0f, -R+ zOffset) ); //Bottom left
verts.push_back( D3DXVECTOR3(-R+ xOffset, 0.0f, R+ zOffset) ); //Top left
verts.push_back( D3DXVECTOR3( R+ xOffset, 0.0f, -R+ zOffset) ); //Bottom right

tex.push_back( D3DXVECTOR2(0.0f, 0.0f) );
tex.push_back( D3DXVECTOR2(1.0f, 0.0f) );
tex.push_back( D3DXVECTOR2(0.0f, 1.0f) );
tex.push_back( D3DXVECTOR2(0.0f, 1.0f) );
tex.push_back( D3DXVECTOR2(1.0f, 0.0f) );
tex.push_back( D3DXVECTOR2(1.0f, 1.0f) );
}
}

// Set the number of vertices in the vertex array.
m_vertexCount = verts.size();

// Set the number of indices in the index array.
m_indexCount = verts.size();

// Create the vertex array.
vertices = new VertexType[m_vertexCount];
if(!vertices)
{
return false;
}

// Create the index array.
indices = new unsigned long[m_indexCount];
if(!indices)
{
return false;
}

for(int i = 0; i < m_vertexCount; i++)
{
vertices[i].position = verts[i];
vertices[i].texture = tex[i];
indices[i] = i;
}

这是渲染环形平面时的外观:

使用多个四边形时,为什么不能正确 segmentation ?
我是否应该通过在图形类中创建一个循环来解决此问题,然后在该循​​环中一次又一次地转换和渲染相同的四边形以创建网格?

希望这是有道理的。

最佳答案

您是否真的想对整个平面进行 segmentation 是非常令人怀疑的-您只是在浪费时间 segmentation 整个平面,而当观看者甚至无法分辨远处的差异时。考虑实现某种实时的详细程度(LOD)算法。 LOD的概念是为较近的对象提供更多细节,同时使较远的对象更简单,以节省渲染时间。如果您没有“获得” LOD,可以使用以下图片来帮助您:
High tessellation <-------------------------------> Low tessellation
尽管这些特定模型是在Maya等建模软件中手动创建的,但反对在GPU上实时 segmentation ,但您还是希望您能理解。当相机远离模型时,在右侧渲染兔子,当它靠近时,渲染更详细的兔子,直到相机紧邻对象为止(当您以完整的美感进行渲染时)。

在我的时间里,我发现了两种我认为优于所有其他方法的实时LOD方法。第一个是为水绘制而开发的,它的链接是here-我真的无法比他们更好地解释它。现在,当我尝试解释另一个时,请惊奇地观察(如果失败,请指向并笑)!

GPU地形 segmentation 和 segmentation

  • 来源:Wolfgang Engel在书GPU Pro 4中的第一项
  • 如果您斜视一下,则发布的图像可能类似于严重倾斜的地形。由于此方法是为地形开发的,因此它可能比为水渲染设计的其他方法更容易实现。

  • 正如任何消息灵通的GPU程序员所知道的那样,CPU速度更快,GPU速度更快。复杂图形的主要瓶颈是CPU与GPU之间的数据传输。它需要永远。

    此方法专为地形渲染而开发,是一种几乎完全基于GPU的算法,旨在创建具有基于距离的LOD的 segmentation 网格。尽管性能在很大程度上取决于所安装硬件的支持能力,但此方法针对速度进行了高度优化。

    几乎,该方法反复 segmentation 一个,直到达到所需的LOD为止-由程序员传递的一些参数表示。此外,还在算法的每次迭代中执行剔除操作,从而避免了对 viewing frustum之外的区域进行许多不必要的处理或 segmentation 。

    由于此方法使用的所有数据都保留在GPU上并进行了优化,因此CPU大部分可用于执行其他任务。此外,我们还利用平滑的LOD转换方案来展示 segmentation 算法的实际应用。最终输出(带有部分重叠的线框的该图像)非常酷:

    现在,我不会说谎。该算法很难吞咽。因此,我将竭尽全力为您提供帮助。这是行话:
    Viewable region用变量R表示的可视区域被定义为表示要 segmentation 和/或渲染的区域的轴对齐(通常朝上)的四边形。该区域由沿每个轴在正方向和负方向上延伸的中心位置和宽度定义(请参见下图)。中心位置用RC表示。所施加的偏移用Rλ表示。该区域的边界点由P1,P2,P3和P4表示。绘制一个可见区域跨度,如下所示:
    Viewable region span给定点P和应用的偏移量λ,可通过以下函数来量化由θ表示的可见区域范围:

    θ(P,λ)= | PScreenR − PScreenL |

    PScreenL =(PVProjLxy)/PProjLw

    PScreenR =(PProjRxy)/PProjRw

    PProjL = PWL×matProjection

    PProjR = PWR×matProjection

    PWL =(PWx −λ,PWy)

    PWR =(PWx +λ,PWy)

    PW = P×matWorldView

    可视区域跨度是其可视区域在屏幕上的宽度。
    Maximum viewable region span最大可视区域跨度,表示为
    θmax,是最大允许的可见区域范围。由用户设置的该值是LOD算法中的主要因素之一,并且在 segmentation 算法中也起着关键作用。在LOD算法中,如果任何给定的可视区域的可视区域跨度大于θmax,则将其 segmentation 为4个新的可视区域。
    Relative quadrant code此代码标识拆分的可视区域相对于其父可视区域的相对位置。此代码在 segmentation 算法中计算,并由LOD转换算法使用。通常将其编码为2位掩码,此代码成为可见区域定义的一部分。

    该算法具有三个主要步骤。

    步骤1(准备工作):“初始化” +“中间区域缓冲区”
  • 刚刚设置;我不会不厌其烦地解释它。

  • 步骤2( segmentation 算法):循环,包括“处置区域”和“最终区域缓冲区”

    步骤3(LOD算法):“最终缓冲区” +“LOD” +“输出”

    第2阶段- segmentation 算法

    对于循环的每次迭代,将可见区域的输入流馈送到渲染管线的几何着色器阶段。第一次迭代的输入流是在阶段1中创建的初始输入流。所有后续迭代都使用前一个的中间输出流。
    迭代作为输入。

    在几何着色器中使用了两个输出流。中间输出流用于保存旨在进行进一步处理的可视区域。最终输出流用于保存在下一次​​迭代中无需进一步处理的可视区域,并将其呈现为算法第3阶段的一部分。在几何着色器中,将处理每个可见区域,并执行以下三个操作之一:
  • 如果确定可见区域与 View 不相交
    截锥体,将其丢弃。剔除的可见区域不会添加到中间或最终输出流中。在确定可见区域是否与视锥相交时,请确保在算法的第3阶段考虑位移。
  • 如果可视区域跨度θ(写为θ(RC,Rλ))大于最大可视区域跨度θmax,则可视区域R会分为四个象限(R1,R2,R3,R4)。然后将每个象限本身变为可见区域的象限,将其添加到中间输出流中,以在循环的下一次迭代时进行重新处理。它们的相对象限代码(每个象限唯一)也添加到输出流中,以标识拆分的可视区域与其父可视区域的相对位置。渲染每个可见区域时,LOD转换算法随后会使用此代码。要拆分可见区域R,请创建四个新的可见区域(R1,R2,R3,R4),并分别设置其中心位置(R1C,R2C,R3C,R4C)和应用的偏移量(R1λ,R2λ,R3λ,R4λ) :

  • R1C =(RCx − .5×Rλ,RCy + .5×Rλ)

    R2C =(RCx + .5×Rλ/,RCy + .5×Rλ)

    R3C =(RCx + .5×Rλ,RCy − .5×Rλ)

    R4C =(RCx − .5×Rλ,RCy − .5×Rλ)

    R1λ= 0.5×Rλ

    R2λ= 0.5×Rλ

    R3λ= 0.5×Rλ

    R4λ= 0.5×Rλ
  • 如果可视区域跨度θ(RC,Rλ)小于
    或等于最大可视区域跨度θmax,则将可视区域R添加到可视区域的最终输出流中。

  • 还要注意,在循环的最后一次迭代中,必须在阶段2中将所有可见区域添加到输出流中。

    第3阶段-LOD转换算法

    在算法的第3阶段,呈现了可见区域的流。需要阶段3:给定的具有Rλ偏移的可见区域R可能与另一个具有Rλ大小的一半或两倍的偏移的可见区域相邻。如果在两个不同大小的可见区域之间不执行平滑过渡,则渲染时将出现可见的不连续性或其他视觉异常。

    为避免 segmentation 中出现裂纹,通过将可视区域划分为四个四边形(分别由Q1,Q2,Q3和Q4表示)来呈现每个可视区域。由静态边界点(P1,P2,P3,P4)和变形边界点(PL,PT,PR,PB,PC)的集合组成的每个四边形的边界点定义如下:

    这些不重叠的四边形将共同覆盖相同的表面
    区域作为创建它们的可见区域。每个的边界点
    计算四边形以与相邻可见区域四边形的边界点对齐。变形四边形边界点(PL,PT,PR,PB,PC)的计算公式如下:

    给定点P处的可见区域跨度θ和施加的偏移λ,记作θ(P,λ),请使用以下公式计算变形因子-记为T(P,λ):

    我们为可见的对象计算每个常规变形因子(TL,TT,TR,TB,TC)
    具有中心位置RC并应用偏移Rλ的区域R如下:



    问题是,这些常规变形因子仅在相邻的可见区域具有与Rλ相同的应用偏移时才起作用。参见下图:计算一般变形因子时所使用的各种位置的示意图。

    在计算时,我们需要处理两种特殊的边界情况
    变形因素。当一个可视区域与施加偏移量λ较大或较小的另一个可视区域相邻时,会出现这些特殊情况。案例定义如下:

    特殊边界案例1

    施加了偏移Rλ的可视区域R与a相邻
    较小的可见区域,施加的偏移为.5Rλ。
    我们将有条件地设置以下变形因子,如下所示:

    以上一组条件测试适用于相邻可见的情况
    区域已划分为较小的可见区域。因此,我们需要
    将受影响的变形因子锁定为1。这是为了确保所有
    重叠的四边形顶点与较小的四边形顶点完全匹配
    相邻的可见区域。下图提供了各种图表
    计算边界情况1的变形因子时使用的位置。

    边界案例2

    具有应用偏移Rλ的可视区域与具有应用偏移2Rλ的较大可视区域相邻。为了能够测试这种情况,我们需要确保我们拥有一些有关正在渲染的当前可见区域的附加信息。在算法的第2阶段,我们需要为每个可见区域存储相对象限代码。现在,这可用于正确计算较大的相邻可见区域的中心位置。这也使我们能够计算与较大的相邻可视区域相邻的可视区域的边缘。我们将根据以下条件有条件地设置以下变形因子:
    在可见区域的相对象限代码上:


    以上一组条件测试用于以下情况:相邻的可视区域尚未拆分为与当前可视区域相同的大小,而是应用了2Rλ的偏移量。因此,我们需要将受影响的变形因子锁定为0,以确保所有重叠的四边形顶点与较大的相邻可见区域的顶点完全匹配。下图提供了基于可见区域的相对象限代码计算边界案例2的变形因子时每个可见区域使用的各种位置的示意图:



    耶!你做到了!就像我开始喜欢用桌子砸头一样!等等,你问什么?代码示例?好吧,当然! Here you go-包括VC++ 2008和VC++ 2010版本。享受!

    关于c++ - DirectX大型平面 segmentation ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20909213/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com