使用DirectX 11的HLSL pow()函数的奇怪行为

时间:2018-03-21 18:41:45

标签: directx-11 hlsl pow terrain tessellation

我正在编写一个DX11 SM5.0地形船体着色器,就像Frank Luna的许多例子一样。在研究(线框)地形疯狂闪烁的原因时,我已经开始研究pow()函数的问题。

我计算曲面细分因子的代码是:

float CalcTessFactor(float3 p)
{
    float d = distance(p, cameraPosition);
    float s = saturate((d - 1000.0f) / (5000.0f - 1000.0f));
    //return pow(2, (lerp(6, 1, s)));
    return saturate((5000.0f - d) / 5000.0f)*64.0f;
}

硬编码的数字常量是我调试缩减的一部分。注释掉的行:“// return pow(...”是原始代码,我已将其替换为现在的行。

通过此替换,曲面细分完全稳定,并随着距离相机的距离而缩小。正如预期的那样,减少只是线性而不是对数,但至少它是有效的,很好地镶嵌细分并且没有闪烁的迹象。

使用原始代码,网格似乎在明显随机的镶嵌因子之间以帧速率切换。

有人可以建议可能出现的问题吗?

我的补丁常量函数是:

struct HullInputType
{
    float3 position : POSITION;
    float4 color : COLOR;
};

struct ConstantOutputType
{
    float edges[4] : SV_TessFactor;
    float inside[2] : SV_InsideTessFactor;
};

ConstantOutputType TerrainPatchConstantFunction(InputPatch<HullInputType, 4> patch, uint patchId : SV_PrimitiveID)
{
    ConstantOutputType output;

    // Compute midpoint on edges, and patch center
    // order of vertices is: 0 1
    //                       2 3
    float3 e0 = 0.5f*(patch[0].position + patch[2].position);
    float3 e1 = 0.5f*(patch[0].position + patch[1].position);
    float3 e2 = 0.5f*(patch[1].position + patch[3].position);
    float3 e3 = 0.5f*(patch[2].position + patch[3].position);
    float3 c = 0.25f*(patch[0].position + patch[1].position + patch[2].position + patch[3].position);

    // Set the tessellation factors for the four edges of the quad.
    output.edges[0] = CalcTessFactor(e0);
    output.edges[1] = CalcTessFactor(e1);
    output.edges[2] = CalcTessFactor(e2);
    output.edges[3] = CalcTessFactor(e3);

    // Set the tessellation factor for tessallating inside the quad.
    output.inside[0] = CalcTessFactor(c);
    output.inside[1] = output.inside[0];

    return output;
}

1 个答案:

答案 0 :(得分:1)

查看您的返回值。看起来你正在倒退。取消注释代码的价格。距离值的硬编码说1000.你应该得到一致的tesselation。如果你这样做,你应该没有闪烁。如果你断言或不断言它的功能函数不是那么你的距离向量是时髦的。

编辑:添加了我的细分功能以供参考。

  struct VertexOut
{
    float4 PosW : POSITION0;
    float4 waterAttributes : POSITION2;
    float4 direction : POSITION1;
//    float4 wind : POSITION2;
    float tessFactor : TESS;
};

//========================================================================================================================

[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("PatchHS")]
HullOut HSMain(InputPatch<VertexOut, 3> p,
           uint i : SV_OutputControlPointID,
           uint patchId : SV_PrimitiveID)
{
    HullOut hout;

    // Pass through shader.
    hout.PosW = p[i].PosW;
    hout.direction = p[i].direction;
    hout.waterAttributes = p[i].waterAttributes;
 //   hout.wind = p[i].wind;

    return hout;
}

PatchTess PatchHS(InputPatch<VertexOut, 3> patch,
                  uint patchID : SV_PrimitiveID)
{
    PatchTess pt;

    // Average tess factors along edges, and pick an edge tess factor for 
    // the interior tessellation.  It is important to do the tess factor
    // calculation based on the edge properties so that edges shared by 
    // more than one triangle will have the same tessellation factor.  
    // Otherwise, gaps can appear.
    pt.EdgeTess[0] = 0.5f * (patch[1].tessFactor + patch[2].tessFactor);
    pt.EdgeTess[1] = 0.5f * (patch[2].tessFactor + patch[0].tessFactor);
    pt.EdgeTess[2] = 0.5f * (patch[0].tessFactor + patch[1].tessFactor);
    pt.InsideTess = pt.EdgeTess[0];

    return pt;
}