Advertisement
Guest User

BRDF LUT

a guest
Mar 25th, 2022
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.77 KB | None | 0 0
  1. #include <DirectXTex.h>
  2.  
  3. #include <algorithm>
  4.  
  5. #include <DirectXMath.h>
  6.  
  7.  
  8. using namespace DirectX;
  9. using namespace std;
  10.  
  11.  
  12.  
  13.  
  14. #define IMAGE_SIZE 64
  15. #define BRDF_SAMPLES 1024
  16. #define FP_BITS 16
  17.  
  18.  
  19. float RadicalInverse_VdC(unsigned int bits)
  20. {
  21.     bits = (bits << 16u) | (bits >> 16u);
  22.     bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
  23.     bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
  24.     bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
  25.     bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
  26.     return float(bits) * 2.3283064365386963e-10; // / 0x100000000
  27. }
  28.  
  29.  
  30. XMFLOAT2 Hammersley(unsigned int i, unsigned int N)
  31. {
  32.     return XMFLOAT2(float(i) / float(N), RadicalInverse_VdC(i));
  33. }
  34.  
  35.  
  36. XMFLOAT3 ImportanceSampleGGX(XMFLOAT2 Xi, XMFLOAT3 N, float roughness)
  37. {
  38.     XMVECTOR N_simd = XMLoadFloat3(&N);
  39.  
  40.     float a = roughness * roughness;
  41.  
  42.     float phi = 2.0 * XM_PI * Xi.x;
  43.     float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
  44.     float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
  45.  
  46.     // from spherical coordinates to cartesian coordinates - halfway vector
  47.     XMFLOAT3 H;
  48.     H.x = cos(phi) * sinTheta;
  49.     H.y = sin(phi) * sinTheta;
  50.     H.z = cosTheta;
  51.  
  52.     // from tangent-space H vector to world-space sample vector
  53.     XMFLOAT3 up = fabs(N.z) < 0.999 ? XMFLOAT3(0.0, 0.0, 1.0) : XMFLOAT3(1.0, 0.0, 0.0);
  54.     XMVECTOR up_simd = XMLoadFloat3(&up);
  55.     XMVECTOR tangent_simd = XMVector3Normalize(XMVector3Cross(up_simd, N_simd));
  56.     XMVECTOR bitangent_simd = XMVector3Cross(N_simd, tangent_simd);
  57.  
  58.     XMVECTOR sampleVec_simd = tangent_simd * H.x + bitangent_simd * H.y + N_simd * H.z;
  59.     sampleVec_simd = XMVector3Normalize(sampleVec_simd);
  60.  
  61.     XMFLOAT3 sampleVec;
  62.     XMStoreFloat3(&sampleVec, sampleVec_simd);
  63.     return sampleVec;
  64. }
  65.  
  66.  
  67. float GeometrySchlickGGX(float NdotV, float roughness)
  68. {
  69.     // note that we use a different k for IBL
  70.     float a = roughness;
  71.     float k = (a * a) / 2.0;
  72.  
  73.     float nom = NdotV;
  74.     float denom = NdotV * (1.0 - k) + k;
  75.  
  76.     return nom / denom;
  77. }
  78.  
  79.  
  80. float GeometrySmith(XMFLOAT3 N, XMFLOAT3 V, XMFLOAT3 L, float roughness)
  81. {
  82.     XMVECTOR N_simd = XMLoadFloat3(&N);
  83.     XMVECTOR V_simd = XMLoadFloat3(&V);
  84.     XMVECTOR L_simd = XMLoadFloat3(&L);
  85.  
  86.     XMVECTOR NdotV_simd = XMVector3Dot(N_simd, V_simd);
  87.     float NdotV;
  88.     XMStoreFloat(&NdotV, NdotV_simd);
  89.     NdotV = max(NdotV, 0.0f);
  90.     XMVECTOR NdotL_simd = XMVector3Dot(N_simd, L_simd);
  91.     float NdotL;
  92.     XMStoreFloat(&NdotL, NdotL_simd);
  93.     NdotL = max(NdotL, 0.0f);
  94.     float ggx2 = GeometrySchlickGGX(NdotV, roughness);
  95.     float ggx1 = GeometrySchlickGGX(NdotL, roughness);
  96.  
  97.     return ggx1 * ggx2;
  98. }
  99.  
  100.  
  101. int main(int argc, char* argv[])
  102. {
  103.     CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  104.  
  105.     ScratchImage image;
  106.     image.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, IMAGE_SIZE, IMAGE_SIZE, 1, 1);
  107.  
  108.     for (size_t y = 0; y < IMAGE_SIZE; ++y)
  109.     {
  110.         for (size_t x = 0; x < IMAGE_SIZE; ++x)
  111.         {
  112.             float NdotV = (x + 0.5f) / static_cast<float>(IMAGE_SIZE);
  113.             float roughness = (y + 0.5f) / static_cast<float>(IMAGE_SIZE);
  114.  
  115.             XMFLOAT3 V;
  116.             V.x = sqrt(1.0 - NdotV * NdotV);
  117.             V.y = 0.0;
  118.             V.z = NdotV;
  119.             XMVECTOR V_simd = XMLoadFloat3(&V);
  120.  
  121.             float A = 0.0;
  122.             float B = 0.0;
  123.  
  124.             XMFLOAT3 N = XMFLOAT3(0.0, 0.0, 1.0);
  125.  
  126.             for (unsigned int i = 0; i < BRDF_SAMPLES; ++i)
  127.             {
  128.                 XMFLOAT2 Xi = Hammersley(i, BRDF_SAMPLES);
  129.                 XMFLOAT3 H = ImportanceSampleGGX(Xi, N, roughness);
  130.                 XMVECTOR H_simd = XMLoadFloat3(&H);
  131.                 XMVECTOR L_simd = XMVector3Normalize(2.0 * XMVector3Dot(V_simd, H_simd) * H_simd - V_simd);
  132.                 XMFLOAT3 L;
  133.                 XMStoreFloat3(&L, L_simd);
  134.  
  135.                 float NdotL = max(L.z, 0.0f);
  136.                 float NdotH = max(H.z, 0.0f);
  137.                 XMVECTOR VdotH_simd = XMVector3Dot(V_simd, H_simd);
  138.                 float VdotH;
  139.                 XMStoreFloat(&VdotH, VdotH_simd);
  140.                 VdotH = max(VdotH, 0.0f);
  141.  
  142.                 if (NdotL > 0.0)
  143.                 {
  144.                     float G = GeometrySmith(N, V, L, roughness);
  145.                     float G_Vis = (G * VdotH) / (NdotH * NdotV);
  146.                     float Fc = pow(1.0 - VdotH, 5.0);
  147.  
  148.                     A += (1.0 - Fc) * G_Vis;
  149.                     B += Fc * G_Vis;
  150.                 }
  151.             }
  152.             A /= float(BRDF_SAMPLES);
  153.             B /= float(BRDF_SAMPLES);
  154.  
  155.             float* pixelsPtr = reinterpret_cast<float*>(image.GetImage(0, 0, 0)->pixels) + (x + (IMAGE_SIZE - 1 - y) * IMAGE_SIZE) * 4;
  156.  
  157.             *pixelsPtr++ = A;
  158.             *pixelsPtr++ = B;
  159.             *pixelsPtr++ = 0.0f;
  160.             *pixelsPtr++ = 1.0f;
  161.         }
  162.     }
  163.  
  164.     ScratchImage imageFinal;
  165.  
  166.     if (FP_BITS == 16)
  167.     {
  168.         Convert(image.GetImages(),
  169.                 image.GetImageCount(),
  170.                 image.GetMetadata(),
  171.                 DXGI_FORMAT_R16G16B16A16_FLOAT,
  172.                 TEX_FILTER_DEFAULT,
  173.                 TEX_THRESHOLD_DEFAULT,
  174.                 imageFinal);
  175.     }
  176.     else
  177.     {
  178.         imageFinal = move(image);
  179.     }
  180.  
  181.     SaveToDDSFile(imageFinal.GetImages(), imageFinal.GetImageCount(), imageFinal.GetMetadata(), DDS_FLAGS_NONE, L"BrdfLut.dds");
  182.  
  183.     return EXIT_SUCCESS;
  184. }
  185.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement