diff options
Diffstat (limited to 'Build/source/utils/asymptote/cudareflect/main.cc')
-rw-r--r-- | Build/source/utils/asymptote/cudareflect/main.cc | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/cudareflect/main.cc b/Build/source/utils/asymptote/cudareflect/main.cc new file mode 100644 index 00000000000..2450b5dd846 --- /dev/null +++ b/Build/source/utils/asymptote/cudareflect/main.cc @@ -0,0 +1,305 @@ +/** + * @file main.cpp + * @author Supakorn "Jamie" Rassameemasmuang <jamievlin@outlook.com> + * Program for loading image and writing the irradiated image. + */ + +#include "common.h" +#include <fstream> + +#ifdef _WIN32 +// use vcpkg getopt package for this +#undef _UNICODE +#include <getopt.h> +#include <Windows.h> +#else +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#endif + +#include "kernel.h" +#include "ReflectanceMapper.cuh" +#include "EXRFiles.h" + +size_t const MIN_WIDTH = 2; +size_t const MIN_HEIGHT = 2; + + +struct Args +{ + char mode = 'a'; + bool webgl = false; + char const* file_in = nullptr; + char const* directory = nullptr; + + size_t count; + + bool validate() + { + if (mode == 0) + return false; + + if ((mode == 'a' || mode == 'b' || mode == 'i' || mode == 'r') && !file_in) + { + return false; + } + + return true; + } +}; + +void usage() +{ + std::cerr << "reflect [-a|-i|-r|-b] inputEXRFile [-d outputDirectory]" << + std::endl; + std::cerr << "Options: " << std::endl; + std::cerr << "-h\t\t help" << std::endl; + std::cerr << "-d\t\t output directory" << std::endl; + std::cerr << "-a\t\t generate irradiance and reflectance images (default)" + << std::endl; + std::cerr << "-i\t\t generate irradiance image diffuse.exr" << std::endl; + std::cerr << "-r\t\t generate reflectance images reflN.exr" << std::endl; + std::cerr << "-b\t\t generate brdf image refl.exr (independent of image)" + << std::endl; +} + +Args parseArgs(int argc, char* argv[]) +{ + Args arg; + int c; + while ((c = getopt(argc, argv, "abd:hir")) != -1) + { + switch (c) + { + case 'a': + arg.mode = 'a'; + break; + case 'i': + arg.mode = 'i'; + break; + case 'r': + arg.mode = 'r'; + break; + case 'b': + arg.mode = 'b'; + break; +/* + case 'c': + { + std::stringstream ss; + ss << optarg; + ss >> arg.count; + } + break; +*/ + case 'd': + arg.directory = optarg; + break; + case 'h': + usage(); + exit(0); + break; + default: + usage(); + exit(1); + } + } + + arg.file_in = argv[optind]; + + if (!arg.validate()) + { + usage(); + exit(1); + } + return arg; +} + +struct image_t +{ + float4* im; + int width, height; + + int sz() const { return width * height; } + + image_t(float4* im, int width, int height) : + im(im), width(std::move(width)), height(std::move(height)) {} +}; + +void irradiate_im(image_t& im, std::string const& prefix) +{ + std::vector<float3> out_proc(im.sz()); + std::stringstream out_name; + out_name << prefix; + std::cout << "Irradiating image..." << std::endl; + irradiate_ker(im.im, out_proc.data(), im.width, im.height); + out_name << "diffuse.exr"; + + std::string out_name_str(std::move(out_name).str()); + OEXRFile ox(out_proc, im.width, im.height); + + std::cout << "copying data back" << std::endl; + std::cout << "writing to: " << out_name_str << std::endl; + ox.write(out_name_str); +} + +std::string generate_refl_file(std::string const& prefix, int const& i, std::string const suffix="") +{ + std::stringstream out_name; + out_name << prefix << "refl" << i << suffix << ".exr"; + return out_name.str(); +} + +void map_refl_im(image_t& im, std::string const& prefix, float const& step, int const& i, std::pair<size_t, size_t> const& outSize, bool halve=false) +{ + float roughness = step * i; + auto [outWidth, outHeight] = outSize; + std::vector<float3> out_proc(outWidth * outHeight); + + std::string out_name_str = generate_refl_file(prefix, i, + halve ? "w" : ""); + std::cout << "Mapping reflectance map..." << std::endl; + map_reflectance_ker(im.im, out_proc.data(), im.width, im.height, roughness, outWidth, outHeight); + OEXRFile ox(out_proc, outWidth, outHeight); + std::cout << "copying data back" << std::endl; + std::cout << "writing to: " << out_name_str << std::endl; + ox.write(out_name_str); +} + +std::string const INVALID_FILE_ATTRIB = "Intermediate directories do not exist"; + +void make_dir(std::string const& directory) +{ + // different implementation for windows vs linux +#ifdef _WIN32 + DWORD ret = CreateDirectoryA(directory.c_str(), nullptr); + if (ret == 0 && GetLastError() != ERROR_ALREADY_EXISTS) + { + std::cerr << INVALID_FILE_ATTRIB << std::endl; + exit(1); + } +#else + struct stat st; + if (stat(directory.c_str(), &st) == -1) + { + mkdir(directory.c_str(), 0755); + } +#endif +} + +void copy_file(std::string const& in, std::string const& out) +{ + std::ifstream ifs(in, std::ios::binary); + std::ofstream ofs(out, std::ios::binary); + + ofs << ifs.rdbuf(); + +} + +void generate_brdf_refl( + int res, std::string const& outdir, std::string const& outname="refl.exr") +{ + std::vector<float2> out_proc(res * res); + std::string finalName = outdir + "/" + outname; + std::cout << "generating Fresnel/Roughness/cos_v data" << std::endl; + std::cout << "writing to " << finalName << std::endl; + generate_brdf_integrate_lut_ker(res, res, out_proc.data()); + OEXRFile ox(out_proc, res, res); + ox.write(finalName); +} + +inline float length(float3 v) +{ + return sqrt(v.x*v.x+v.y*v.y+v.z*v.z); +} + +int main(int argc, char* argv[]) +{ + Args args = parseArgs(argc, argv); + std::vector<float4> im_proc; + int width = 0; + int height = 0; + + std::cout << "Loading file " << args.file_in << std::endl; + EXRFile im(args.file_in); + width = im.getWidth(); + height = im.getHeight(); + std::vector<float3> out_proc; + std::cout << "Image dimensions: " << width << "x" << height << std::endl; + for (int i = 0; i < height; ++i) + { + for (int j = 0; j < width; ++j) + { + // index is i*height+j <-> (i,j) + float3 frag3=im.getPixel3(j, i); + // Clamp oversaturated values. + float norm=0.02*length(frag3); + if(norm > 1.0) { + frag3.x /= norm; + frag3.y /= norm; + frag3.z /= norm; + } + out_proc.emplace_back(frag3); + im_proc.emplace_back(make_float4(frag3.x,frag3.y,frag3.z,1.0f)); + } + // std::cout << "pushed row " << i << " into array" << std::endl; + } + std::cout << "finished converting to float3" << std::endl; + + std::stringstream outss; + if (args.directory) + { + make_dir(args.directory); + } + else + { + args.directory = "."; + } + + outss << args.directory << "/"; + + if(args.mode != 'b') { + std::ofstream readme(outss.str()+"README"); + readme << "The image files in this directory were generated from " << args.file_in << std::endl; + readme.close(); + } + + std::string outprefix(outss.str()); + + image_t imt(im_proc.data(), width, height); + + if (args.mode == 'b') + { + generate_brdf_refl(200, "."); + } + if (args.mode == 'i' || args.mode == 'a') + { + irradiate_im(imt, outprefix); + } + if (args.mode == 'r' || args.mode == 'a') + { + OEXRFile ox(out_proc, width, height); + std::string out_name_str = generate_refl_file(outprefix, 0); + std::cout << "writing to: " << out_name_str << std::endl; + ox.write(out_name_str); + + for(size_t halve=0; halve < 2; ++halve) { + size_t count=halve ? 8 : 10; + float step = 1.0f / count; + + unsigned int out_width = width; + unsigned int out_height = height; + + for (size_t i = 1; i <= count; ++i) + { + if (halve && out_width >= MIN_WIDTH && out_height >= MIN_HEIGHT) + { + out_width = out_width >> 1; + out_height = out_height >> 1; // halve + } + map_refl_im(imt, outprefix, step, i, std::pair<size_t,size_t>(out_width, out_height), halve); + } + } + } +} |