首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HLSL:对于TextureCube.SampleGrad(),需要哪些DDX?

HLSL:对于TextureCube.SampleGrad(),需要哪些DDX?
EN

Stack Overflow用户
提问于 2020-01-22 14:33:59
回答 1查看 820关注 0票数 1

我想知道SampleGrad()函数对TextureCube对象期望的DDX值。我知道这是二维纹理的UV坐标的变化。因此,我想,这将是改变的方向在这个案例。然而,情况似乎并非如此。

如果我尝试使用示例函数与SampleGrad,则得到不同的结果:

示例:

代码语言:javascript
复制
// calculate reflected ray
float3 reflRay = reflect(-viewDir, normal);
// reflection map lookup
return reflectionMap.Sample(linearSampler, reflRay);

SampleGrad:

代码语言:javascript
复制
// calculate reflected ray
float3 reflRay = reflect(-viewDir, normal);
// reflection map lookup
float3 dxr = ddx(reflRay);
float3 dyr = ddy(reflRay);
return reflectionMap.SampleGrad(linearSampler, reflRay, dxr, dyr);

EN

回答 1

Stack Overflow用户

发布于 2020-01-23 12:19:58

我仍然不知道DDX和DDY需要哪些值,但是如果找到一个可以接受的解决方法,它可以计算渐变的细节级别。不幸的是,这个解的质量不如一个实际的各向异性滤波样本函数。

如果有人需要,计算将在:https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#LODCalculation中描述。

我的HLSL实现:

代码语言:javascript
复制
// calculate reflected ray
float3 reflRay = reflect(-viewDir, normal);
// reflection map lookup
float3 dxr = ddx(reflRay);
float3 dyr = ddy(reflRay);
// cubemap size for lod computation
float reflWidth, reflHeight;
reflectionMap.GetDimensions(reflWidth, reflHeight);
// calculate lod based on raydiffs
float lod = calcLod(getCubeDiff(reflRay, dxr).xy * reflWidth, getCubeDiff(reflRay, dyr).xy * reflHeight);
return reflectionMap.SampleLevel(linearSampler, reflRay, lod).rgb;

帮助者职能:

代码语言:javascript
复制
float pow2(float x) {
    return x * x;
}

// calculates texture coordinates [-1, 1] for the view direction (xy values must be divided by axisMajorValue for proper [-1, 1] range).else
// z coordinate is the faceId
float3 getCubeCoord(float3 viewDir, out float axisMajorValue)
{
    // according to dx spec: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#PointSampling
    // Choose the largest magnitude component of the input vector. Call this magnitude of this value AxisMajor. In the case of a tie, the following precedence should occur: Z, Y, X. 
    int axisMajor = 0;
    int axisFlip = 0;
    axisMajorValue = 0.0;
    [unroll] for (int i = 0; i < 3; ++i)
    {
        if (abs(viewDir[i]) >= axisMajorValue)
        {
            axisMajor = i;
            axisFlip = viewDir[i] < 0.0f ? 1 : 0;
            axisMajorValue = abs(viewDir[i]);
        }
    }

    int faceId = axisMajor * 2 + axisFlip;

    // Select and mirror the minor axes as defined by the TextureCube coordinate space. Call this new 2d coordinate Position.

    int axisMinor1 = axisMajor == 0 ? 2 : 0; // first coord is x or z
    int axisMinor2 = 3 - axisMajor - axisMinor1;
    // Project the coordinate onto the cube by dividing the components Position by AxisMajor. 
    //float u = viewDir[axisMinor1] / axisMajorValue;
    //float v = -viewDir[axisMinor2] / axisMajorValue;
    // don't project for getCubeDiff function!
    float u = viewDir[axisMinor1];
    float v = -viewDir[axisMinor2];

    switch (faceId)
    {
        case 0:
        case 5:
            u *= -1.0f;
            break;
        case 2:
            v *= -1.0f;
            break;
    }

    return float3(u, v, float(faceId));
}

float3 getCubeDiff(float3 ray, float3 diff)
{
    // from: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#LODCalculation
    // Using TC, determine which component is of the largest magnitude, as when calculating the texel location. If any of the components are equivalent, precedence is as follows: Z, Y, X. The absolute value of this will be referred to as AxisMajor. 
    // select and mirror the minor axes of TC as defined by the TextureCube coordinate space to generate TC'.uv 
    float axisMajor;
    float3 tuv = getCubeCoord(ray, axisMajor);
    // select and mirror the minor axes of the partial derivative vectors as defined by the TextureCube coordinate space, generating 2 new partial derivative vectors dX'.uv & dY'.uv. 
    float derivateMajor;
    float3 duv = getCubeCoord(diff, derivateMajor);
    // Calculate 2 new dX and dY vectors for future calculations as follows:
    // dX.uv = (AxisMajor*dX'.uv - TC'.uv*DerivativeMajorX)/(AxisMajor*AxisMajor)
    float3 res;
    res.z = 0.0;
    res.xy = (axisMajor * duv.xy - tuv.xy * derivateMajor) / (axisMajor * axisMajor);

    return res * 0.5;
}

// dx, dy in pixel coordinates
float calcLod(float2 dX, float2 dY)
{
    // from: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#LODCalculation
    float A = pow2(dX.y) + pow2(dY.y);
    float B = -2.0 * (dX.x * dX.y + dY.x * dY.y);
    float C = pow2(dX.x) + pow2(dY.x);
    float F = pow2(dX.x * dY.y - dY.x * dX.y);

    float p = A - C;
    float q = A + C;
    float t = sqrt(pow2(p) + pow2(B));

    float lengthX = sqrt(abs(F * (t+p) / ( t * (q+t))) + abs(F * (t-p) / ( t * (q+t))));
    float lengthY = sqrt(abs(F * (t-p) / ( t * (q-t))) + abs(F * (t+p) / ( t * (q-t))));

    return log2(max(lengthX,lengthY));
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59862011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档