Giter Club home page Giter Club logo

raytracing.github.io's Introduction

Ray Tracing in One Weekend Book Series

RT in One Weekend RT The Next Week RT The Rest of Your Life
In One Weekend The Next Week The Rest of Your Life

Getting the Books

The Ray Tracing in One Weekend series of books are now available to the public for free directly from the web.

We are currently hosting both the older v3.2.3 version and the latest v4.0.0-alpha.2 versions in the same project. The older v3 version (really v3.2.3) is provided for readers who are in the middle of going through the series so you can maintain continuity. For new readers, or readers newly starting one of the books, we strongly recommend that you jump aboard the v4 train.

Version 3.2.3

Version 4.0.0-alpha.2

These books have been formatted for both screen and print. For more information about printing your own copies, or on getting PDFs of the books, see PRINTING.md for more information.

Contributing

If you'd like to contribute a PR please read our contribution guidelines first.

Project Status

Ok, v4.0.0-alpha.2 is finally out the door, and we are now heads down on getting the final v4.0.0 version complete and shipped by SIGGRAPH 2024, July 28. At present, that means we are largely focused on Ray Tracing: The Rest of Your Life — the third book in the series.

v4.0.0-alpha.2 is released. Books one and two are largely complete, and we're now focusing on book three. You can find it at the regular spot: https://raytracing.github.io. We are temporarily preserving the final version of v3.2.3 inside the repo, so you can just grab the latest and reference both versions.

If you'd like to check out the latest updates and watch our progress, we're on the dev branch. You can also browse our release backlog to see what we're planning. Our relevant milestones are

If you're interested in contributing, email us! You can find our contact info at the head of each book. Or just start a new discussion or issue.

GitHub Discussions

Do you have general questions about raytracing code, issues with your own implmentation, or general raytracing ideas you'd like to share? Check out our GitHub discussions forum!

Directory Structure

The organization of this repository is meant to be simple and self-evident at a glance:

  • books/ -- This folder contains the three raytracing books (in HTML), and some supporting material.

  • images/ -- Contains all of the images and figures of the books. Can also be used to compare your results.

  • style/ -- Contains the css for the books and the site.

  • src/ -- Contains the source.

  • src/<book>/ -- Contains the final source code for each book.

  • v3/ -- All content (same general structure) for the v3.2.3 release (from December 2020).

  • v3/common -- Contains v3 headers that are common to two or more v3 books. This is also where external headers are stored.

Source Code

Intent

This repository is not meant to act as its own tutorial. The source is provided so you can compare your work when progressing through the book. We strongly recommend reading and following along with the book to understand the source. Ideally, you'll be developing your own implementation as you go, in order to deeply understand how a raytracer works.

Downloading The Source Code

The GitHub home for this project contains all source and documentation associated with the Ray Tracing in One Weekend book series. To clone or download the source code, see the green "Clone or download" button in the upper right of the project home page.

Programming Language

This book is written in C++, and uses some modern features of C++11. The language and features were chosen to be broadly understood by the largest collection of programmers. It is not meant to represent ideal (or optimized) C++ code.

Implementations in Other Languages

The Ray Tracing in One Weekend series has a long history of implementations in other programming languages (see Implementations in Other Languages), and across different operating systems. Feel free to add your own implementation to the list!

Branches

In general, ongoing development, with all of the latest changes, can be found in the dev branch, which may contain patch, minor and major changes, depending on the release in progress. We try to keep CHANGELOG.md up to date, so you can easily browse what's new in each development branch. We may from time to time use additional development branches, so stay up to date by reviewing the CONTRIBUTING page.

The release branch contains the latest released (and live) assets. This is the branch from which GitHub pages serves up https://raytracing.github.io/.

Building and Running

Copies of the source are provided for you to check your work and compare against. If you wish to build the provided source, this project uses CMake. To build, go to the root of the project directory and run the following commands to create the debug version of every executable:

$ cmake -B build
$ cmake --build build

You should run cmake -B build whenever you change your project CMakeLists.txt file (like when adding a new source file).

You can specify the target with the --target <program> option, where the program may be inOneWeekend, theNextWeek, theRestOfYourLife, or any of the demonstration programs. By default (with no --target option), CMake will build all targets.

$ cmake --build build --target inOneWeekend

Optimized Builds

CMake supports Release and Debug configurations. These require slightly different invocations across Windows (MSVC) and Linux/macOS (using GCC or Clang). The following instructions will place optimized binaries under build/Release and debug binaries (unoptimized and containing debug symbols) under build/Debug:

On Windows:

$ cmake -B build
$ cmake --build build --config Release  # Create release binaries in `build\Release`
$ cmake --build build --config Debug    # Create debug binaries in `build\Debug`

On Linux / macOS:

# Configure and build release binaries under `build/Release`
$ cmake -B build/Release -DCMAKE_BUILD_TYPE=Release
$ cmake --build build/Release

# Configure and build debug binaries under `build/Debug`
$ cmake -B build/Debug -DCMAKE_BUILD_TYPE=Debug
$ cmake --build build/Debug

We recommend building and running the Release version (especially before the final render) for the fastest results, unless you need the extra debug information provided by the (default) debug build.

CMake GUI on Windows

You may choose to use the CMake GUI when building on windows.

  1. Open CMake GUI on Windows
  2. For "Where is the source code:", set to location of the copied directory. For example, C:\Users\Peter\raytracing.github.io.
  3. Add the folder "build" within the location of the copied directory. For example, C:\Users\Peter\raytracing.github.io\build.
  4. For "Where to build the binaries", set this to the newly-created "build" directory.
  5. Click "Configure".
  6. For "Specify the generator for this project", set this to your version of Visual Studio.
  7. Click "Done".
  8. Click "Configure" again.
  9. Click "Generate".
  10. In File Explorer, navigate to build directory and double click the newly-created .sln project.
  11. Build in Visual Studio.

If the project is succesfully cloned and built, you can then use the native terminal of your operating system to simply print the image to file.

Running The Programs

You can run the programs by executing the binaries placed in the build directory:

$ build\Debug\inOneWeekend > image.ppm

or, run the optimized version (if you compiled with the release configuration):

$ build\Release\inOneWeekend > image.ppm

The generated PPM file can be viewed directly as a regular computer image, if your operating system supports this image type. If your system doesn't handle PPM files, then you should be able to find PPM file viewers online. We like ImageMagick.

Corrections & Contributions

If you spot errors, have suggested corrections, or would like to help out with the project, please review the CONTRIBUTING document for the most effective way to proceed.

raytracing.github.io's People

Contributors

ahcox avatar alanjian85 avatar armansito avatar avikav avatar bennetthardwick avatar celeph avatar dafhi avatar davidkretch avatar dmdrummond avatar doodlesepic avatar estshorter avatar fsan avatar hollasch avatar jammm avatar jc-progjava avatar kberna avatar lmancini avatar lollipopft avatar lorihollasch avatar matttree avatar mu-lambda avatar oxine avatar rjkilpatrick avatar ronaldfw avatar rupsis avatar shaunplee avatar tatsuya-ogawa avatar trevordblack avatar wlbksy avatar ymherklotz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

raytracing.github.io's Issues

The perlin_interp function not returning correct values?

When I followed the tutorial in the book, I found that just before the turbulence is added I encountered some issues with my scene not rendering correctly.

I expected it to look like this:
screenshot_1_expected
What I actually got was this:
screenshot_1_actual

After continuing the tutorial to the turbulence section, I noticed that fabs() was used on the accumulated total. I wondered if this would fix my issue with the perlin_interp function (i.e. noise.noise() not noise.turb()), so I used it at the end there.

It did get rid of the black boxes but the result was also still not quite what was intended:
screenshot_1

Perhaps this is because I used a scale value of 1, but setting it higher leads to results more similar to using turbulence.

Extraneous semi-colon in vec3.h

Enjoying the book so far, though I am only very early on so far.

I believe there may be an unneeded semicolon in the following line:

inline float& operator[](int i) { return e[i]; };

Lighting Oversaturation Problem

After working on the Cornell box, I noticed some trouble with the lighting, especially when I had a large light, which in the book said would help with the noise. I replaced one of the boxes with a glass sphere and noticed the obvious problem with the light of my image. Even with 1000 secondary rays, it didn't fix it.

HQ_with_light_artifact

I eventually figured out that there needed to be a value cap on the colors, so it wouldn't oversaturate. This might have been covered in the next book "Ray Tracing the Rest of Your Life", but with the final image of this book having a glass sphere and a very bright light, I figured it might be useful to mention it.
Here's my final image with that color cap:
HQ_final_product

Unused variable p in main.cc

p is never used in main.cc

89: vec3 p = r.point_at_parameter(2.0);
90: col += color(r, world,0);

should the r in 90: be p ?

consistent use of ffmax / ffmin

Although the use of ffmax and ffmin is advertised, for aabb surrounding_box(aabb box0, aabb box1) the functions fmax and fmin from the <math> library are used.

'MAXFLOAT' was not declared in this scope

Working my way though book, and this error caught me up at the end of chapter 5.

I tried compiling the code here, and I got this error as well.

I ended up fixing this by using FLT_MAX instead of MAXFLOAT. I'm assuming they are equivalent, but I really don't know.

Any idea what could be causing this? I'm using Slackware Linux 14.1, using GCC 4.8.2.

Add code commentary for sphere discriminant

The code for computing the ray-sphere intersection first appears incorrect, because a factor of two is introduced elsewhere. See commentary for issue #113.

Add code commentary to explain this easily-misunderstood line.

Confusing code over the two roots of ray-sphere intersection.

The code from line 42 (inluded) until line 49 (included) in the "sphere.h" is not needed? if it does can you please explain why? ( It does look to me as just a repetition of what has been already calculated.)

        temp = (-b + sqrt(discriminant)) / a;
        if (temp < t_max && temp > t_min) {
            rec.t = temp;
            rec.p = r.point_at_parameter(rec.t);
            rec.normal = (rec.p - center) / radius;
            rec.mat_ptr = mat_ptr;
            return true;
}

Chapter 5: constants missing from terms in sphere::hit

Within sphere::hit on Page 16

float discriminant = b*b - a*c;

should be

float discriminant = b*b - 4*a*c;

Similarly when expression is repeated in the two square root expressions a few lines below. Those should probably be sqrt(discriminant).

why changing in dielectric?

//cosine = ref_idx * dot(r_in.direction(), rec.normal) / r_in.direction().length();

---->

cosine = dot(r_in.direction(), rec.normal) / r_in.direction().length();
cosine = sqrt(1 - ref_idx*ref_idx*(1-cosine*cosine));

Lighting bug

Hi! I ported this to Rust (https://github.com/adihodos/raytracer.git), all went pretty smooth (I even added multithreadead support) until I added lighting support. Raytracing the Cornell box results in this ugliness :
raytraced.
Can you give me some hints as to why this is happening ?

vec3.h cross product - clarify

Hello Peter.
I have some question about Your "cross product" function.
wiki version of "cross product" is:
a×b=⟨a2b3−a3b2, a3b1 − a1b3, a1b2 − a2b1⟩
and Your is:
a×b=⟨a2b3−a3b2, -(a3b1 − a1b3), a1b2 − a2b1⟩
I'd be very grateful if You explain why your "y" is negative

'MAXFLOAT' was not declared in this scope

Working my way though book, and this error caught me up at the end of chapter 5.

I tried compiling the code here, and I got this error as well.

I ended up fixing this by using FLT_MAX instead of MAXFLOAT. I'm assuming they are equivalent, but I really don't know.

Any idea what could be causing this? I'm using Slackware Linux 14.1, using GCC 4.8.2.

logic error in dielectric::scatter

cosine = m_refIdx * -Dot( In.m_direction , Rec.normal ) / In.m_direction.Length( );

multiplying refraction index to cosine got rid of a black pixel artifact I was seeing on my render.

P.S: notice the minus sign next to the Dot, this is for the else part where Dot product is <=0.

FYI Only - Kotlin Conversion

Hi,

I was stuck in for a day and saw your nice mini-book. I thought it might be fun to see this working in kotlin, so I wrote it in kotlin....

I tried to keep variables etc the same as you mostly, so it should be very easy to compare.

There are a couple of changes - it uses coroutines (badly) (so uses all cores) and renders the image unto a UI window as its computing it (also badly!), so its a bit more interactive.

There may be some bugs in my conversion...

The code is at: https://github.com/time4tea/raytrace-in-a-weekend-kotlin

Hope that's useful.

Cheers

James

Importance sampling

Hi,

Thank you for the books, they were very helpful! I signalled an issue on the blog, but you might not visit it often, so I'll put it here, too.

I implemented a ray tracer with help from your books and blog. I think I found an issue with the importance sampling. I'll try to describe it here in words.

The idea is that there is a list of objects that are 'important' (like the light in your book). Now, the same object also exists in the scene. It might happen that both the origin point and the generated target point to be on the same object, which for a rectangle for example means along the surface. But the pdf value for such a vector is zero, which means a division by zero. In my code I just checked for such a case and tried sampling again if that was the case, in a loop until success.

Unable to see the output image after running main.cpp

I cloned the repository and build the solution file. Its been 2 hours and the execution window is still open.
after running through chapter 7 anti aliasing, It takes more time to run the code.

Is there anyway to know how much time its taking to render the ppm image.

Chapter 7: color function, stack overflow

I've gotten to chapter seven, when my program has stopped at 20% of image generation with exit code 3221225725.
Above number is 0xc00000fd in hex, which is stack overflow error in windows.

Dev C++'s debugger shows me quite an interesting trace:
image

Here's the code I've written:

vec3 rius(mt19937_64 rng) {
	vec3 p;
	do {
		p = 2.0*vec3(unif(rng), unif(rng), unif(rng)) - vec3(1,1,1);
	} while (p.squaredLength() >= 1.0);
	return p;
}

vec3 color(const ray & r, hitable *world, mt19937_64 rng)
{
	HitRecord rec;
	if (world->hit(r, 0.0, FLT_MAX, rec))
	{
		vec3 target = rec.p	+ rec.normal + rius(rng);
		return 0.5*color(ray(rec.p, target-rec.p), world, rng);
	}
	else
	{
		vec3 unitDirection = unit(r.direction());
		float t = 0.5 * (unitDirection.y() + 1.0);
		return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.2, 0.5, 1.0);
	}	
}

rng is just me passing a random number generator engine not to have scope issues.

From the backtrace provided, it would seem that the ray perhaps has hit the sphere on the inside?
The trace is very long and consists solely of the color() function, which would suggest me that it's due to function recursion.

Any help is appreciated, as I can't find any errors with the code above.

math error in sphere.h?

on line 33 in sphere.h
a little misleading perhaps...
if (discriminant > 0) -> if (discriminant >= 0) may be better?

'MAXFLOAT' was not declared in this scope

Working my way though book, and this error caught me up at the end of chapter 5.

I tried compiling the code here, and I got this error as well.

I ended up fixing this by using FLT_MAX instead of MAXFLOAT. I'm assuming they are equivalent, but I really don't know.

Any idea what could be causing this? I'm using Slackware Linux 14.1, using GCC 4.8.2.

Indexing bug in hitable_list::bounding_box()

bool hitable_list::bounding_box(float t0, float t1, aabb& box) const {
    if (list_size < 1) return false;
    aabb temp_box;
    bool first_true = list[0]->bounding_box(t0, t1, temp_box);
    if (!first_true)
        return false;
    else 
        box = temp_box;
    for (int i = 1; i < list_size; i++) {
        if(list[0]->bounding_box(t0, t1, temp_box)) {
            box = surrounding_box(box, temp_box);
        }
        else
            return false;
    }
    return true;
}

at the loop of list
why the index is always zero ??

More Lighting bug

When I use two light source, the RGB value is very large, almost 987, which means it is not overflow when convert from reals to int. And I have tried some method to solve this, but only one of them work, but it is a website converter, so I do not like that. Could someone give me a suggestion?

image

Ah...I know...

I can use this to add a color cap:

inline int colCap(int x) {
	return x > 255 ? 255 : x;
}

compile this project failed

||=== 构建文件: "无目标" 在 "无项目" 中 (编译器: 未知的) ===|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h||In function 'vec3 random_cosine_direction()':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h|7|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h||In function 'vec3 random_to_sphere(float, float)':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h|17|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h||In function 'vec3 random_in_unit_sphere()':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h|30|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h||In member function 'virtual vec3 mixture_pdf::generate() const':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\pdf.h|81|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\hitable_list.h||In member function 'virtual vec3 hitable_list::random(const vec3&) const':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\hitable_list.h|28|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\camera.h||In function 'vec3 random_in_unit_disk()':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\camera.h|8|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\camera.h||In member function 'ray camera::get_ray(float, float)':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\camera.h|36|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\perlin.h||In function 'vec3* perlin_generate()':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\perlin.h|59|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\perlin.h||In function 'void permute(int*, int)':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\perlin.h|65|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\material.h||In member function 'virtual bool dielectric::scatter(const ray&, const hit_record&, scatter_record&) const':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\material.h|84|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\aarect.h||In member function 'virtual vec3 xz_rect::random(const vec3&) const':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\aarect.h|39|error: 'drand48' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\main.cc||In function 'vec3 color(const ray&, hitable*, hitable*, int)':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\main.cc|29|error: 'MAXFLOAT' was not declared in this scope|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\main.cc||In function 'int main()':|
C:\Users\asus\Downloads\Compressed\raytracingtherestofyourlife-master\raytracingtherestofyourlife-master\main.cc|99|error: 'drand48' was not declared in this scope|
||=== 构建 失败: 13 error(s), 0 warning(s) (0 分, 0 秒) ===|

Need Source Code README

This repo could really use a short README that explains how to run the program when compiled. Thanks for writing the book and making this code available.

Chapter 5: unused but set variable

In one of the code snippets in chapter 5 there is this line of code (page 18, Version 1.54):

vec3 p = r.point_at_parameter(2.0);

There is a write to variable p but no read. It is an unused variable. Delete this code line!

bounding_box function in bvh_node has confusing naming

The bounding_box virtual function is declared in the bvh_node class as

virtual bool bounding_box(float t0, float t1, aabb& box) const;

but is defined outside the class as

bool bvh_node::bounding_box(float t0, float t1, aabb& b) const { b = box; return true; }

where box is a member variable of the class. I think the member should be declared as m_box and the last parameter of the function as box (as it is in the pure virtual function).

'MAXFLOAT' was not declared in this scope

Working my way though book, and this error caught me up at the end of chapter 5.

I tried compiling the code here, and I got this error as well.

I ended up fixing this by using FLT_MAX instead of MAXFLOAT. I'm assuming they are equivalent, but I really don't know.

Any idea what could be causing this? I'm using Slackware Linux 14.1, using GCC 4.8.2.

main.cc - used variable p

At line number 100 of "main.cc" :
vec3 p = r.point_at_parameter(2.0);
I think this is not needed at all, is it?

Chapter 7: tangent unit sphere clarity

In chapter 7, we have the sentences:

"Pick a random point s from the unit radius sphere that is tangent to the hitpoint, and send a ray
from the hitpoint p to the random point s. That sphere has center (p+N)."

After puzzling over this for a while (even with the picture) it finally dawned on me that it is the unit sphere itself that is tangent to the hitpoint p, and not the point s. It seems obvious in retrospect, but I think this point could be made clearer. I think my confusion comes from two facts:

  1. hitpoint p (and the ray that generates it) is not labeled in the diagram (so it was not obvious to me that the surface underneath the unit sphere is what is actually being hit by the ray)
  2. point s would be secant to hitpoint p

To trace my confusion: I originally imagined that the unit sphere was at the center of the sphere being hit and could therefore approximate a sphere of any size; then I imagined the unit sphere's center was at hitpoint p and we were looking for a point on the sphere tangent to it (which made no sense to me); and then finally I partially understood the unit sphere's tangency to p, but still thought point s would be secant to p and that the modifier "tangent" applied to s and not the sphere.

Lambertian BRDF is actually cosine squared brdf

The Lambertian brdf uses random_in_unit_sphere, however this induces a cosine squared brdf rather than a Lambertian one. To correct this, one has to use random_on_unit_sphere (this can be achieved through normalize(random_in_unit_sphere)). For more information see: https://github.com/vchizhov/Derivations/blob/master/Probability%20density%20functions%20of%20the%20projected%20offset%20disk%2C%20circle%2C%20ball%2C%20and%20sphere.pdf
Note that this is a mistake in both the book and the code.

Chapter 7, 8, 9 floating point intersection error

There is a small issue with the materials introduced in chapters 7, 8 and 9 (lambertian, metal, dielectric). Due to floating point error, it may happen that the intersection of a ray with some geometry (in this case a sphere) may be "on the wrong side" (let the ideal intersection be at t0, however due to precision error let one get t1: t1>t0, then r_in.point_at_parameter(t1) would be "on the wrong side"). That means that when we try to scatter a ray, it will start inside of the sphere resulting in self-intersection and a black pixel contribution in the final image (akin to shadow acne). This is valid for both lambertian and metal materials, it is especially obvious for perfect mirror materials (fuzz==0.0) when they are introduced in chapter 8 since we get black pixels where we're not supposed to. To mitigate this issue, one can define epsilon = 0.01 (depending on the scale of your geometry this value may have to be smaller or larger) and when returning the scattered ray, make it have origin not rec.p, but rather rec.p + epsilon*normal. Which leads me to another issue - if an object is intersected "from inside", the wrong normal is used for lambertian scattering and reflection (fortunately the right normal is used for refraction). To fix this, use this normal for lambertian scattering, reflection and refraction: normal = dot(r_in,rec.normal)<0.0f? rec.normal : -rec.normal. For refraction the scattered ray should rather start from rec.p - epsilon*normal (we want to be on the opposite side, to avoid self-intersection).
Another thing that may look like a mistake is: schlick(cosine, ref_idx) since based on the definition it should be schlick(cosine, ni_over_nt). However, in this case it is lucky that schlick(cosine, 1.0/ni_over_nt) == schlick(cosine, ni_over_nt) since ((1-ni_over_nt)/(1+ni_over_nt))^2 == ((1-1/ni_over_nt)/(1+1/ni_over_nt))^2.

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.