Giter VIP home page Giter VIP logo

yocto-gl-vpt's People

Contributors

emanuelegiacomini avatar rickymexx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

yocto-gl-vpt's Issues

Regarding spectral tracking code wrong (eval_spectral_tracking)

I suspect that the implementation of spectral tracking is wrong. I have a smoke medium with 20% scattering and 80% absorption.
With delta tracking, I get this result.
image

but spectral tracking gives me this result which is clearly wrong as I should get similar result as delta tracking.
image

I have managed to fix it. Following is my code which is as per the original spectral decomposition paper.

std::pair<float, vec3f> eval_spectral_tracking(vsdf& vsdf, float max_distance, rng_state& rng, const ray3f& ray) {
      auto object = vsdf.object;
      auto density_vol = object->density_vol;
      auto emission_vol = object->emission_vol;
      auto max_density = density_vol->max_voxel * object->density_mult;
      auto majorant_density = max_density;
      auto imax_density = 1.0f / max_density;
      auto path_length = 0.0f;
      auto tr = vec3f(1);
      auto f = vec3f(1);
      auto sigma_s = vsdf.scatter * max_density;
      auto Ps = sigma_s * imax_density;

      while (true) {
          path_length -= log(1 - rand1f(rng)) * imax_density;
          if (path_length >= max_distance)
              break;
          auto current_pos = ray.o + path_length * ray.d;
          auto sigma_t = vec3f(eval_vpt_density(vsdf, current_pos));
          auto sigma_n = majorant_density - sigma_t;
          auto sigma_a = sigma_t - sigma_s;
          auto Pt = sigma_t * imax_density;          
          auto Pn = sigma_n * imax_density;
          auto Pa = 1.0 - Ps - Pn;

          auto contrib = zero3f;

          tr *= exp(-sigma_t*path_length);  
 
          if (max(Pa) > rand1f(rng)) {    //ABSORPTION
              contrib = sigma_a / (majorant_density * Pa);
              contrib /= max(contrib);
              vsdf.event = EVENT_ABSORB;
              vsdf.density = sigma_t;
              return { path_length,  tr * contrib };
          }
          else if (max(Pt) > rand1f(rng)) {              // SCATTER
              contrib = sigma_s / (majorant_density * Ps);
              contrib /= max(contrib);
              vsdf.event = EVENT_SCATTER;
              vsdf.density = sigma_t;
              return { path_length, tr * contrib }; 
          }
          contrib = sigma_n;
          contrib /= max(contrib);
          f *= contrib;
      }
      return { max_distance, f };
  }

Following is the correct output.
image

Regarding unidirectional spectral MIS code (eval_unidirectional_spectral_mis)

Slight issues in the spectral MIS code. The original code treats both absorption and scattering the same as follows

if (e == EVENT_ABSORB || e == EVENT_SCATTER) { 
    vsdf.event = e;
    vsdf.density = sigma_t;
    f *= tr;
    break;
}

and returns path_length, f/mean(p) for both these case. However, as per algorithm 1 in the original paper, the division is to be carried out for absorption only.

EDIT: I have made these changes and tried to reduce branches as much and following is my code. It gives the same output as the original function but its slightly faster.

std::pair<float, vec3f> eval_unidirectional_spectral_mis(vsdf& vsdf, float max_distance,
							   rng_state& rng, const ray3f& ray) {
    auto object           = vsdf.object;
    auto density_vol      = object->density_vol;
    auto emission_vol     = object->emission_vol;
    auto max_density      = density_vol->max_voxel * object->density_mult;
    auto imax_density     = 1.0f / max_density;
    auto path_length      = 0.0f;
    auto f                = vec3f(1);
    auto p                = vec3f(1);
    auto cc               = clamp((int)(rand1f(rng) * 3), 0, 2);
    auto current_pos      = ray.o; 
    auto majorant_density = max_density;
    auto tr               = vec3f(1);
    
    while (true) {
      path_length     -= majorant_density == 0.0f ? -flt_max :	log(1 - rand1f(rng)) / majorant_density;
      if (path_length >= max_distance)
	    break;
      current_pos = ray.o + path_length * ray.d;
      auto sigma_t     = vec3f(eval_vpt_density(vsdf, current_pos));
      auto sigma_s     = sigma_t * vsdf.scatter;
      auto sigma_a     = sigma_t - sigma_s;
      auto sigma_n     = vec3f(max_density) - sigma_t;
      vec3f sigma[3] = { sigma_n, sigma_s, sigma_a };
 
      tr *= exp(-sigma_t * path_length); 
      // Sample event 
      auto e = sample_event(sigma_a[cc] * imax_density,  sigma_s[cc] * imax_density, sigma_n[cc] * imax_density, rand1f(rng));

      if (e == EVENT_NULL)
          continue;
 
      f *= sigma[e];
      p  = f;
      
      // Populate vsdf with medium interaction information and return
      vsdf.event = e;
      vsdf.density = sigma_t;
      f *= tr;
      f = f / mean(p);       
      break;
    }    
    return {path_length, f };
  }

Regarding loading public openvdb volumes

HI thanks for sharing your work. I tried to add openvdb support using yovdbload but it fails to load the openvdb datasets available here. I managed to load the data myself using the latest openvdb library. Here is my code to get the openvdb data loaded using the openvdb library and dump in a bin file.

#include <yocto/yocto_cli.h>
#include <yocto/yocto_math.h>
#include <yocto/yocto_trace.h>
#include <yocto/yocto_image.h>

//openvdb includes
#include <openvdb/openvdb.h> 

#include <iostream>
  
using namespace yocto;
 
static inline bool save_yvol(
    const char* filename, int w, int h, int d, int nc, const float* voxels) {
    FILE* fp;
    fopen_s(&fp, filename, "wb");
    if (!fp) return false;
    auto fs_guard = std::unique_ptr<FILE, void (*)(FILE*)>{
        fp, [](FILE* f) { fclose(f); } };

    if (fprintf(fp, "YVOL\n") < 0) return false;
    if (fprintf(fp, "%d %d %d %d\n", w, h, d, nc) < 0) return false;
    auto nvalues = (size_t)w * (size_t)h * (size_t)d * (size_t)nc;
    if (fwrite(voxels, sizeof(float), nvalues, fp) != nvalues) return false;

    return true;
}

int main(int argc, char** argv)
{  

    if (argc != 2)
    {
        std::cout << "Usage: TestOpenVDB.exe [OpenVDB filename]" << std::endl; 
    }
    else
    {
        openvdb::initialize();
        openvdb::io::File file(argv[1]);
        file.open();
         
        openvdb::GridBase::Ptr baseGrid;

        for (openvdb::io::File::NameIterator nameIter = file.beginName(); nameIter != file.endName(); ++nameIter)
        {
            if (nameIter.gridName() == "density")
            {
                baseGrid = file.readGrid(nameIter.gridName());
            }
            else
            {
                std::cout << "Ignoring Grid: " << nameIter.gridName() << std::endl;
            }
        }

        openvdb::FloatGrid::Ptr grid = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrid);
        
        int min_x = 10000;
        int min_y = 10000;
        int min_z = 10000;

        int max_x = -10000;
        int max_y = -10000;
        int max_z = -10000;
         

        // Print all active ("on") voxels by means of an iterator.
        for (openvdb::FloatGrid::ValueOnCIter iter = grid->cbeginValueOn(); iter; ++iter)  
        {
            openvdb::Coord xyz = iter.getCoord(); 
            min_x = min(min_x, xyz.x());
            min_y = min(min_y, xyz.y());
            min_z = min(min_z, xyz.z());

            max_x = max(max_x, xyz.x());
            max_y = max(max_y, xyz.y());
            max_z = max(max_z, xyz.z());
 
        } 
        
        file.close();
        std::cout << "Input: " << argv[1] << std::endl;
         
        std::cout << "BB bounds: (" << min_x << ", " << min_y << ", " << min_z << ")" << std::endl;  
        std::cout << "BB bounds: (" << max_x << ", " << max_y << ", " << max_z << ")" << std::endl; 

        min_x = fabs(min_x);
        min_y = fabs(min_y);
        min_z = fabs(min_z);
        max_x = max_x + min_x + 1;
        max_y = max_y + min_y + 1;
        max_z = max_z + min_z + 1;
        std::cout << "BB bounds after shift: (" << max_x << ", " << max_y << ", " << max_z << ")" << std::endl;

        std::vector<float> odata(max_x * max_y * max_z, 0.0f);
        for (openvdb::FloatGrid::ValueOnCIter iter = grid->cbeginValueOn(); iter; ++iter)
        {
            openvdb::Coord xyz = iter.getCoord();
            odata[(xyz.z() + min_z) * max_y * max_x + (xyz.y() + min_y) * max_x + (xyz.x() + min_x)] = *iter;
        }
        
        std::string output = argv[1];
        output = output.substr(0, output.find_last_of(".")) + ".bin";
        save_yvol(output.c_str(), max_x, max_y, max_z, 1, odata.data());
         
        std::cout << "Volume file saved ["<< output << "]";
    }
    return 0;
}

I was wondering why cant we simply load the openvdb file directly instead of generating an intermediate (.bin) file? I notice that openvdb data is highly compressed so we can sort of uncompress data from openvdb on demand before handing it to yocto pathtracer?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.