-1

Checked the output and the seed is generating the same three numbers and it's annoying. Once, the seed-generator was working fine, however, it begin doing the same thing generating the same three numbers. In both the main and random_in_unit_sphere() function the random number generator prints the same number each time and- at times- skips the loop altogether. Here's the random number seed.

unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    
    std::mt19937 gen(seed);
   
    std::uniform_real_distribution<float> rn1(-1.0, 1.0)

I can't figure out why this is happening.

    // Algorithm from http://corysimon.github.io/articles/uniformdistn-on-sphere/
vecfloat random_in_unit_sphere()
{

    vecfloat p(0, 0, 0);
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    // static std::random_device rd;
    std::mt19937 gen(seed);
    ///Random number generator for reflections
    std::uniform_real_distribution<float> rn1(-1.0, 1.0);

    do
    {

        auto x = rn1(gen);
        auto y = rn1(gen);
        auto z = rn1(gen);
        std::cout << "Is it working?" << std::endl;
        p = ((vecfloat((float)x, (float)y, (float)z) * (float)2.0) - vecfloat(1.0f, 1.0f, 1.0f)) * 2.0;

        std::cout << (double)p.squared_length() << std::endl;
    } while ((double)p.squared_length() >= 1.0);
    std::cout << "Is this working?" << std::endl;

    return p;
}
vecfloat color(const ray &r, hittable *world)
{

    hit_record rec;
    //vecfloat unit_direction(0, 0, 0);
    // unit_direction = unit_direction.unit_vector(r.direction());

    // float t = 0.5 * (unit_direction.get_y() + 1.0);
    if (world->hit(r, 0.01, __FLT_MAX__, rec))
    {

        vecfloat target = (rec.p + rec.normal) + random_in_unit_sphere();
        //Recursive function that models real time shadows
        return color(ray(rec.p, target - rec.p), world) * 0.5;
    }
    else
    {

        vecfloat unit_direction(0, 0, 0);
        vecfloat get_unit_direction = unit_direction.unit_vector(r.direction());
        float t = 0.5 * (get_unit_direction.get_y() + 1.0);
        return vecfloat(1.0, 1.0, 1.0) * (float)(1.0 - t) + vecfloat(0.5, 0.7, 1.0) * t;
    }
}

int main()
{

    int nx = 200;
    int ny = 100;
    float ns = 100;

    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::mt19937 gen(seed);
    std::uniform_real_distribution<float> rn1(-1.0, 1.0);

    std::ofstream out("out.ppm");
    raycaster::camera cam;
    out << "P3\n"
        << nx << " " << ny << "\n255\n";

    vecfloat lower_left_corner(-2.0, -1.0, -1.0);
    vecfloat _horizontial(4.0, 0.0, 0.0);
    vecfloat vertical(0.0, 2.0, 0.0);
    vecfloat origin(0.0, 0.0, 0.0);
    hittable *list[2];
    vecfloat a1(0, 0, -1);
    vecfloat a2(0, -100.5, -1);
    list[0] = new sphere(a1, 0.5);
    list[1] = new sphere(a2, 100);
    hittable *world = new hittable_list(list, 2);

    for (int i = ny - 1; i >= 0; i--)
    {
        for (int j = 0; j < nx; j++)
        {
            vecfloat col(0, 0, 0);
            for (int s = 0; s < ns; s++)
            {

                auto x = rn1(gen);
                auto y = rn1(gen);

                float u = float(j + x) / float(nx);
                float v = float(i + y) / float(ny);

                // ray r(origin, (lower_left_corner + ((_horizontial * u) + (vertical * v))));
                ray r = cam.get_ray(u, v);

                vecfloat p = r.point_at_parameter(2.0);
                col += color(r, world);
            }
            col /= float(ns);
            col = col.squared_sides();

            int ir = int(255.99 * col.get_x());
            int ig = int(255.99 * col.get_y());
            int ib = int(255.99 * col.get_z());
            out << ir << " " << ig << " " << ib << "\n";
        }
    }

    return 0;
}
Justin
  • 1
  • 1
  • 4
  • Is it generating different seeds? It's possible your seed generator is counting seconds and produces the same seed multiple times in the same second. – Anonymous1847 Oct 24 '20 at 03:30
  • Does this answer your question? [C++ generating random numbers in a loop using default\_random\_engine](https://stackoverflow.com/questions/33131800/c-generating-random-numbers-in-a-loop-using-default-random-engine) – Sam Mason Oct 24 '20 at 14:45
  • don't create `std::mt19937` every time inside `random_in_unit_sphere` just create it once in `main`. it's relatively expensive to construct and the way you're doing it will only "change" once a second – Sam Mason Oct 24 '20 at 14:47
  • @SamMason if I only declare std:mt19937 in main how will I call it in randrom_in_unit_sphere? – Justin Oct 24 '20 at 19:16
  • make it global or pass it by reference... – Sam Mason Oct 25 '20 at 12:51
  • https://stackoverflow.com/a/64532843/1358308 suggests making it `thread_local` or `static` which would also work, but given that a mt19937 is about 5KB you don't want to do this too much – Sam Mason Oct 26 '20 at 15:51

1 Answers1

0

I am too tired to look at your code, but if you want to generate a random number, then you should do this:

#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
using namespace std;

int main()
{
    // initialize random number generator
    srand(time(0)); // set initial seed value to system clock

    // generate random number
    // ...

    return 0;
}

or this:

#include <random>
#include <iostream>

using namespace std;

int main()
{
    random_device rd;   // non-deterministic generator
    mt19937 gen(rd());  // to seed mersenne twister.
                        // replace the call to rd() with a
                        // constant value to get repeatable
                        // results.

    for (int i = 0; i < 5; ++i)
    {
        cout << gen() << " "; // print the raw output of the generator.
    }
}