В настоящее время я реализую зеркальный 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 для координат в касательном пространстве .