games202-hw/hw4/lut-gen/Eavg_IS.cpp

121 lines
3.6 KiB
C++
Raw Normal View History

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <sstream>
#include <fstream>
#include "vec.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
int resolution = 128;
int channel = 3;
Vec2f Hammersley(uint32_t i, uint32_t N) {
uint32_t bits = (i << 16u) | (i >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
float rdi = float(bits) * 2.3283064365386963e-10;
return {float(i) / float(N), rdi};
}
Vec3f ImportanceSampleGGX(Vec2f Xi, Vec3f N, float roughness) {
float a = roughness * roughness;
// TODO: Copy the code from your previous work - Bonus 1
return Vec3f(1.0f);
}
Vec3f IntegrateEmu(Vec3f V, float roughness, float NdotV, Vec3f Ei) {
Vec3f Eavg = Vec3f(0.0f);
const int sample_count = 1024;
Vec3f N = Vec3f(0.0, 0.0, 1.0);
for (int i = 0; i < sample_count; i++)
{
Vec2f Xi = Hammersley(i, sample_count);
Vec3f H = ImportanceSampleGGX(Xi, N, roughness);
Vec3f L = normalize(H * 2.0f * dot(V, H) - V);
float NoL = std::max(L.z, 0.0f);
float NoH = std::max(H.z, 0.0f);
float VoH = std::max(dot(V, H), 0.0f);
float NoV = std::max(dot(N, V), 0.0f);
// TODO: To calculate Eavg here - Bonus 1
}
return Vec3f(1.0);
}
void setRGB(int x, int y, float alpha, unsigned char *data) {
data[3 * (resolution * x + y) + 0] = uint8_t(alpha);
data[3 * (resolution * x + y) + 1] = uint8_t(alpha);
data[3 * (resolution * x + y) + 2] = uint8_t(alpha);
}
void setRGB(int x, int y, Vec3f alpha, unsigned char *data) {
data[3 * (resolution * x + y) + 0] = uint8_t(alpha.x);
data[3 * (resolution * x + y) + 1] = uint8_t(alpha.y);
data[3 * (resolution * x + y) + 2] = uint8_t(alpha.z);
}
Vec3f getEmu(int x, int y, int alpha, unsigned char *data, float NdotV, float roughness) {
return Vec3f(data[3 * (resolution * x + y) + 0],
data[3 * (resolution * x + y) + 1],
data[3 * (resolution * x + y) + 2]);
}
int main() {
unsigned char *Edata = stbi_load("./GGX_E_LUT.png", &resolution, &resolution, &channel, 3);
if (Edata == NULL)
{
std::cout << "ERROE_FILE_NOT_LOAD" << std::endl;
return -1;
}
else
{
std::cout << resolution << " " << resolution << " " << channel << std::endl;
// | -----> mu(j)
// |
// | roughi
// Flip it, if you want the data written to the texture
uint8_t data[resolution * resolution * 3];
float step = 1.0 / resolution;
Vec3f Eavg = Vec3f(0.0);
for (int i = 0; i < resolution; i++)
{
float roughness = step * (static_cast<float>(i) + 0.5f);
for (int j = 0; j < resolution; j++)
{
float NdotV = step * (static_cast<float>(j) + 0.5f);
Vec3f V = Vec3f(std::sqrt(1.f - NdotV * NdotV), 0.f, NdotV);
Vec3f Ei = getEmu((resolution - 1 - i), j, 0, Edata, NdotV, roughness);
Eavg += IntegrateEmu(V, roughness, NdotV, Ei) * step;
setRGB(i, j, 0.0, data);
}
for(int k = 0; k < resolution; k++)
{
setRGB(i, k, Eavg, data);
}
Eavg = Vec3f(0.0);
}
stbi_flip_vertically_on_write(true);
stbi_write_png("GGX_Eavg_LUT.png", resolution, resolution, channel, data, 0);
}
stbi_image_free(Edata);
return 0;
}