0
\$\begingroup\$

I'm so excited to learn ray tracing and did a lot of fun. But I'm stuck at rendering empty Cornell Box scene.

image image (1)

It has some darker color along the bright color and it's seem different with the image in the book. Sorry if my English confuses you because I'm still learning it.

My source code about this project for someone want to check. https://github.com/trinhlehainam/StudyRayTracing

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Hi, welcome to GDSE! Please post your solution as an answer to the question, instead of editing it into the question. This way others can find help more easily in the future, as they can see that the question has an answer! \$\endgroup\$
    – user35344
    Feb 3, 2021 at 9:37
  • 2
    \$\begingroup\$ @Tyyppi_77 thanks for remine me. I just edit my answer. This is first time I post so I don't have experiment. \$\endgroup\$ Feb 3, 2021 at 11:42
  • 1
    \$\begingroup\$ For future reference, you might want to ask questions like this on the Computer Graphics StackExchange instead. Uses of raytracing and path tracing in games are still an emerging field, but better established in offline rendering. \$\endgroup\$
    – DMGregory
    Feb 3, 2021 at 18:43
  • \$\begingroup\$ @DMGregory Great site for discussing about Graphics Programming. Thanks for suggestion. \$\endgroup\$ Feb 4, 2021 at 1:16

2 Answers 2

1
\$\begingroup\$

I solved this.

The bright color is look like rectangle because the light that is reflected by Lambertian material is scattered randomly in unit cube (with center is the unit normal) . I fixed this by just allow ray is scattered randomly point in unit sphere.

image (2)

image (1)

Final result image

Example code :

Function to generate random vector

vec3 random(float min, float max)
{
    return { Random(min, max), Random(min, max), Random(min, max) };
}

Code show generate random position in unit sphere, with using dot product to check the the vector is in radius of unit sphere, and reject it when vector is generated outside the unit sphere.

vec3 random_in_unit_sphere()
{
    vec3 v = random(-1.0f, 1.0f);
    while (dot(v, v) >= 1)
        v = random(-1.0f, 1.0f);
    return v;
}

Then from the hit point we just use normal vector of hit surface like the center of unit sphere, and add with random vector position in unit sphere. This random vector will work as direction vector that bend normal vector to direction of scatter ray.

scatter_ray.direction = hit_surface.normal + random_in_unit_sphere();
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Can you show the code you changed to make the scattering happen in a sphere instead of a cube? \$\endgroup\$
    – DMGregory
    Feb 3, 2021 at 12:12
  • \$\begingroup\$ @DMGregory I just add my code as expend answer. Sorry for my bad English. Every things I learned is from Ray tracing series github.com/RayTracing/raytracing.github.io. \$\endgroup\$ Feb 3, 2021 at 13:12
0
\$\begingroup\$

I guess u did something like

vec3 vec3::random_unit_vector()
{
    auto x = drand(-1, 1);
    auto y = drand(-1, 1);
    auto z = drand(-1, 1);
    return vec3::unit(vec3(x, y, z);
}

I came across this post because I made the same error, normalize an uniformly distributed random vector is wrong, each axis has to be normally distributed.

Personally I don't like the retry idea, so I use the cylinder surface mapping to get random vec3 on unit sphere surface

vec3 vec3::random_unit_vector()
{
    // use cylinder surface mapping
    auto theta = 2.0 * M_PI * drand(0, 1);
    auto z = drand(-1, 1);
    auto r = ::sqrt(1.0 - z * z);

    return vec3
    {
        r * cos(theta),
        r * sin(theta),
        z
    };
}

and

vec3 vec3::random_unit_sphere()
{
    double u = drand();
    return cbrt(u) * vec3::random_unit_vector();
}

to get random vector inside unit sphere

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .