Внедрение GGX VNDF выборки важности с DXR - PullRequest
0 голосов
/ 05 октября 2019

В настоящее время я реализую зеркальный BRDF GGX в трассировщике лучей DXR, используя метод выборки важности, описанный Heitz

Я выполняю выборку VNDF с помощью:

//https://hal.archives-ouvertes.fr/hal-01509746/document
inline float3 VNDF_GGX(in float3 wo, float roughness2, float rand1, float rand2)
{
    //Strecht view vector
    float3 view = normalize(float3(wo.x * roughness2, wo.y, wo.z * roughness2));

    //Orthonormal basis
    float3 lensq = pow(view.x, 2) + pow(view.z, 2);
    float3 t1 = (lensq > 0.0f) ? normalize(cross(view, float3(0.0f, 1.0f, 0.0f))) : float3(1, 0, 0);
    float3 t2 = cross(view, t1);

    //project
    float r = sqrt(rand1);
    float phi = 2.0f * pi * rand2;
    float p1 = r * cos(phi);
    float p2 = r * sin(phi);

    float s = 0.5f * (1.0f + view.y);
    p2 = (1.0f - s) * sqrt(1.0f - pow(p1, 2.0f)) + s * p2;

    float3 n = p1 * t1 + p2 * t2 + sqrt(max(0.0f, 1.0f - pow(p1, 2.0f) - pow(p2, 2.0f))) * view;

    //unstrech normal and renormalize
    float3 n_out = normalize(float3(roughness2 * n.x, max(0.0f, n.y), roughness2 * n.z));

    return n_out;
}

где wo - направление обзора в касательном пространстве, шероховатость2 - шероховатость материала [0; 1] в квадрате, а rand1 / rand2 - случайные случайные числа [0; 1], взятые из текстуры. Я использую точный алгоритм, описанный Heitz, за исключением использования y-up вместо z-up.

Использование нормального микрофасчета m , рассчитанного таким образом, затем я получаюнаправление образца wi путем отражения направления мирового луча -два в касательном пространстве к нормальному микроразмеру м .

void ImportanceSampleGGXVNDF(float3 wo, Material material, inout float3 wi, inout float reflectance, float2 randSeed, bool isInVec, inout float fschlick)
{
    float roughness2 = pow(material.roughness, 2.0f);
    float3 m = VNDF_GGX(wo, roughness2, randSeed.x, randSeed.y);

    wi = normalize(reflect(-wo, m));

    float3 normalTangentSpace = float3(0.0f, 1.0f, 0.0f);

    fschlick = FresnelSchlick(m, wi, isInVec ? material.ior1 : 1.0f, isInVec ? 1.0f : material.ior1);
    float G1 = SmithMaskingGGX(wi, wo, normalTangentSpace, pow(roughness2, 2));
    float G2 = SmithShdowingGGX(wo, wi, normalTangentSpace, pow(roughness2, 2));

    reflectance = fschlick *(G2 / G1);
}

Где wo - направление обзора, wi - направление выборки в касательном пространстве, коэффициент отражения равен термину BRDF (все остальное компенсируется согласно Heitz! См. здесь детали деривации)

Однако, похоже, это приводит к неправильным направлениям выборки для направлений лучей с отрицательными значениями в компоненте y или z, что приводит к неправильным датчикам света. недопустимые выборки для отрицательного направления z

Сравнение с аналогичными реализациями (включая: здесь , реализующий точно такой же метод, здесь , также реализующий тот же методи здесь с использованием алгоритма, описанного в более старой статье, также опубликованной Heitz ), к сожалению, не дал решения.

Окончательный выходной цвет вычисляется с помощью

    ImportanceSampleGGXVNDF(tangentSpaceDir, halfVec, l_materialCB[0], rayDir, reflectance, rand, isInVec, fschlick);

    newRayDir = tangentToWorldSpace(rayDir, tangent, bitangent, triangleNormal);

    ray.Direction = newRayDir;
    ray.TMin = 0.0001f;
    ray.TMax = 10000.0; //Maximum travel distance of ray
    reflected = TraceReflectiveRay(ray, currNumRecursions);

    reflected *= reflectance;

Я решил поменять метод случайной выборки с выборки из текстуры однородных случайных чисел, генерируемых мерсенским твистером, на выборку из двухмерной последовательности Халтона. Также я попытался использовать оригинальную конфигурацию Z-Up. Обе комбинации привели к этому с одним световым зондом на удар по поверхности: выборка последовательности Халтона плюс использование z-up для координат в касательном пространстве .

...