GithubHelp home page GithubHelp logo

computer-graphics-ray-tracing's Introduction

Computer Graphics โ€“ Ray Tracing

To get started: Clone this repository and its submodule using

git clone --recursive http://github.com/alecjacobson/computer-graphics-ray-tracing.git

Do not fork: Clicking "Fork" will create a public repository. If you'd like to use GitHub while you work on your assignment, then mirror this repo as a new private repository: https://stackoverflow.com/questions/10065526/github-how-to-make-a-fork-of-public-repository-private

Background

Read Sections 4.5-4.9 of Fundamentals of Computer Graphics (4th Edition).

Many of the classes and functions of this assignment are borrowed or adapted from the previous ray casting assignment.

Unlike that assignment, this ray tracer will produce approximately accurate renderings of scenes illuminated with light. Ultimately, the shading and lighting models here are useful hacks. The basic recursive structure of the program is core to many methods for rendering with global illumination effects (e.g., shadows, reflections, etc.).

Running ./raytracing ../data/sphere-and-plane.json should produce this image.

Floating point numbers

For this assignment we will use the Eigen::Vector3d to represent points and vectors, but also RGB colors. For all computation (before finally writing the .ppm file) we will use double precision floating point numbers and 0 will represent no light and 1 will represent the brightest color we can display.

Floating point numbers real numbers, they don't even cover all of the rational numbers. This creates a number of challenges in numerical method and rendering is not immune to them. We see this in the need for a fudge factor to discard ray-intersections when computing shadows or reflections that are too close to the originating surface (i.e., false intersections due to numerical error).

Question: If we build a ray and a plane with floating point coefficients, will the intersection point have floating point coefficients? What if we consider rational coefficients? What if we consider a sphere instead of a plane?

Hint: Can we exactly represent as a double? Can we represent as a rational?

Dynamic Range & Burning

Light obeys the superposition principle. Simply put, the light reflected of some part of an objects is the sum of contributions from light coming in all directions (e.g., from all light sources). If there are many bright lights in the scene and the object has a bright color, it is easy for this sum to add up to more than one. At first this seems counter-intuitive: How can we exceed 100% light? But this premise is false, the does not mean the physically brightest possible light in the world, but rather the brightest light our screen can display (or the brightest color we can store in our chosen image format). High dynamic range (HDR) images store a larger range beyond this usual [0,1]. For this assignment, we will simply clamp the total light values at a pixel to 1.

This issue is compounded by the problem that the Blinn-Phong shading does not correctly conserve energy as happens with light in the physical world.

Running ./raytracing ../data/bunny.json should produce this image. Notice the "burned out" white regions where the collected light has been clamped to [1,1,1] (white).

Question: Can we ever get a pixel value less than zero?

Hint: Can a light be more than off?

Side note: This doesn't stop crafty visual effects artists from using "negative lights" to manipulate scenes for aesthetic purposes.

Whitelist

There are many ways to "multiply" two vectors. One way is to compute the component-wise multiplication: or in index notation: . That is, multiply each corresponding component and store the result in the corresponding component of the output vector. Using the Eigen library this is accomplished by telling Eigen to treat each of the vectors as "array" (where matrix multiplication, dot product, cross product would not make sense) and then using the usual * multiplication:

Eigen::Vector3d a,b;
...
// Component-wise multiplication
Eigen::Vector3d c = (a.array() * b.array()).matrix();

The .matrix() converts the "array" view of the vector back to a "matrix" (i.e., vector) view of the vector.

Eigen also has a built in way to normalize a vector (divide a vector by its length): a.normalized().

C++ standard library includes a value for via #include <limits>. For example, for double floating point, use std::numeric_limits<double>::infinity().

Tasks

src/Plane.cpp,
src/Sphere.cpp,
src/Triangle.cpp,
src/TriangleSoup.cpp,
src/first_hit.cpp,
src/viewing_ray.cpp,
src/write_ppm.cpp

See the previous ray casting assignment.

PointLight::direction in src/PointLight.cpp

Compute the direction to a point light source and its parametric distance from a query point.

DirectionalLight::direction in src/DirectionalLight.cpp

Compute the direction to a direction light source and its parametric distance from a query point (infinity).

src/raycolor.cpp

Make use of first_hit.cpp to shoot a ray into the scene, collect hit information and use this to return a color value.

src/blinn_phong_shading.cpp

Compute the lit color of a hit object in the scene using Blinn-Phong shading model. This function should also shoot an additional ray to each light source to check for shadows.

It is recommended to add and debug each term in your shading model. The ambient term will look like a faint object-ID image. The diffuse term will illuminate the scene, and create a dull, Lambertian look to each object. The specular term will add shiny highlights. Then, mask the diffuse and specular terms by checking for shadows. Finally, add a recursive call to account for mirror reflections.

src/reflect.cpp

Given an "incoming" vector and a normal vector, compute the mirror reflected "outgoing" vector.

./raytracing ../data/sphere-packing.json should produce this image of highly reflective, metallic looking surfaces.

src/creative.json

Be creative! Design a scene using any of the available Object types (spheres, planes, triangles, triangle soups), Light types (directional, point), Material parameters, colors (materials and/or lights), and don't forget about the camera parameters.

The .json format is rather straightforward. But you may find this validator useful.

HW2 Solution

If you don't trust your solutions to the files from HW2:

src/Plane.cpp
src/Sphere.cpp
src/Triangle.cpp
src/TriangleSoup.cpp
src/first_hit.cpp
src/viewing_ray.cpp
src/write_ppm.cpp

You can use precompiled binaries (provided for linux, mac, and windows) using a the cmake command:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DHW2LIB_DIR=../lib/debug/linux/ ..
make

This will use the library at ../lib/debug/linux/libhw2.a instead of compiling the above files in src/.


Pro Tip: After you're confident that your program is working correctly, you can dramatic improve the performance simply by enabling compiler optimization:

mkdir build-release
cd build-release
cmake ../ -DCMAKE_BUILD_TYPE=Release
make

computer-graphics-ray-tracing's People

Contributors

abhimadan avatar alecjacobson avatar psarahdactyl avatar rarora7777 avatar texify[bot] avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

computer-graphics-ray-tracing's Issues

Error with the precompiled library

I get the this error when I run cmake -DCMAKE_BUILD_TYPE=Debug -DHW2LIB_DIR=../lib/debug/linux/ ..
and then make. I am using the ug machines.

ug135:~/csc418/computer-graphics-ray-tracing/build% make
[ 14%] Linking CXX executable raytracing
/usr/bin/ld: ../lib/debug/linux/libhw2.a(Plane.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: ../lib/debug/linux/libhw2.a(Sphere.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: ../lib/debug/linux/libhw2.a(Triangle.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: ../lib/debug/linux/libhw2.a(TriangleSoup.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: ../lib/debug/linux/libhw2.a(first_hit.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: ../lib/debug/linux/libhw2.a(viewing_ray.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: ../lib/debug/linux/libhw2.a(write_ppm.cpp.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC

Directional Light - 2 variables with the same name?

In DirectionLight we are supposed to find the d vector (direction from point toward light) but the DirectionalLight class also has a d vector (direction from light toward scene) which is different. Am I missing something in order to differ between these variables?

Parametrizing a ray from a point on an object to a point light

Should we express rays to point lights as:
q + t(p - q) or q + t(p-q)/||p-q||,
where q is the point on the surface, p is the point of the light and t is the parameter.

If we use the former, the output max_t in PointLight::direction will always be 1. In which case, the epsilon we use to find hits that cause shadows represents a fraction of real distance from an object to the point light. Would this not present a problem? Since, for a sufficiently large distance to the point light, the epsilon we use may cause us to skip over a nearby object?

In the latter approach, the epsilon value we use will represent a real distance away from the object which seems less problematic.

I am currently using the latter approach and am wondering if that is ok?

Image file will not appear

I don't know if it has something to do with the six files I edited for the assignment, but when I compile it and run ./raytracing, no image is outputted. I checked main.cpp and it should take the sphere and plane data and output rgb.ppm. Also, no error messages pop up during compiling or execution.

About creative.zip

Hi, I'm wondering more than the creative.json and necessary .stl files, do we have to (or be encouraged) to upload a preview image of render results within the .zip file?

Running Time for Creative.json

Is there a running time limit for creative.json? It could take a while (10 minutes) if we include multuple stl models.

Problem Regarding Using The Precompiled Code on CDF

I am currently trying to use the library provided by prof, however, it seems that I am not able to include the library in my program. When I was running cmake -DCMAKE_BUILD_TYPE=Debug -DHW2LIB_DIR=../lib/debug/linux/ .. on cdf, cmake gave me the following warning

  Manually-specified variables were not used by the project:

    HW2LIB_DIR

And when I was trying to ignore this warning and make the project directly, the making process just failed. Can anyone tell me how to fix this?

Reflection Recursive Cap

Wondering what should be the valid cap for reflection recursive? I've tested the sphere-packing.json and this returns me around 22 times of reflection to get a black color in most reflected areas, whereas the sphere-and-plane around 12 times. So wondering what should be the cap for us to set in this homework?

Some json files are incorrect or not properly defined

Hi, I was testing on the given JSON data files and realized that some files are incorrectly defined.

  • triangle.json currently outputs a square instead of a triangle because of line 18. [0,8660254038,0] should be [0,0.8660254038,0]. The second element is missing a 0.
  • inside-a-sphere.json and two-spheres-and-plane.json give segmentation faults because they're missing the materials attribute.

No i_a value?

Hi I have checked all header files and just cant seem to find the i_a value when calculating phong illumination model. Does anyone has the same issue?

Unable to compile with -DCMAKE_BUILD_TYPE=Release

When making build files using cmake .. -DCMAKE_BUILD_TYPE=Release, I seem to have some sort of linker error with Eigen that results in a failed build. I get the following output from make.

/usr/bin/ld: libhw2.a(Triangle.cpp.o): in function `Triangle::intersect(Ray const&, double, double&, Eigen::Matrix<double, 3, 1, 0, 3, 1>&) const':
Triangle.cpp:(.text+0xd7): undefined reference to `Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross_product_return_type<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::type Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) const'
/usr/bin/ld: Triangle.cpp:(.text+0x131): undefined reference to `Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross_product_return_type<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::type Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) const'
/usr/bin/ld: Triangle.cpp:(.text+0x18e): undefined reference to `Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross_product_return_type<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::type Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) const'
/usr/bin/ld: Triangle.cpp:(.text+0x1ea): undefined reference to `Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross_product_return_type<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::type Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) const'
/usr/bin/ld: Triangle.cpp:(.text+0x24f): undefined reference to `Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross_product_return_type<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::type Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) const'
/usr/bin/ld: libhw2.a(Triangle.cpp.o):Triangle.cpp:(.text+0x2bc): more undefined references to `Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross_product_return_type<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::type Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) const' follow
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/raytracing.dir/build.make:160: raytracing] Error 1
make[1]: *** [CMakeFiles/Makefile2:105: CMakeFiles/raytracing.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Any ideas as to what I'm doing wrong here? cmake .. (Debug build) seems to work fine. I had this same issue with the previous assignment as well.

Resolving failure to build A3 on release mode.

My code could be builded with cmake on debug mode, whereas when I try to do the release mode, I got a weird error like

libhw2.a(Triangle.cpp.o): In function Triangle::intersect(Ray const&, double, double&, Eigen::Matrix<double, 3, 1, 0, 3, 1>&) const':
Triangle.cpp:(.text+0x2db): undefined reference to Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross_product_return_type<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::type Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >::cross<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) const' collect2: error: ld returned 1 exit status CMakeFiles/raytracing.dir/build.make:225: recipe for target 'raytracing' failed make[2]: *** [raytracing] Error 1 CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/raytracing.dir/all' failed make[1]: *** [CMakeFiles/raytracing.dir/all] Error 2 Makefile:83: recipe for target 'all' failed make: *** [all] Error 2 b2210-10:~/CSC418/ray_tracing/release% make

The reason why this happens is that we miss an #include <Eigen/Geometry> in include/Triangle.h.
Hope this may help people who has similar issues...

ps. I mistakenly post this issue to the wrong repo, now fixed...

How to get light source in PointLight?

I am a bit confused about the PointLight.cpp. It gives a query point (the hit point?) and asks for the direction and parametric distance, why the light source is not given in the parameter so we can make the subtraction?

I could see from read_json, parse_lights function actually calls the PointLight() first, then set the attribute p for position and I for intensity and finally push it back to the lights array. Shouldn't the right order be parsing the position first, pass it into PointLight() to do the calculation about direction, then push back to the light array? May anyone explains why its been written like this? Did I understand anything wrong?

Unable to use pre-compiled binaries

Environment:
Device: MacBook Pro (Mid 2015)
OS: macOS Big Sur Version 11.5.2
Processor: 2.2 GHz Quad-Core Intel Core i7
Memory: 16 GB 1600 MHz DDR3
Graphics: Intel Iris PRo 1536 MB

Expected Behaviour:
I should be able to use pre-compiled binaries (rather than A2 code), by using the following CMAKE command:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DHW2LIB_DIR=../lib/debug/mac/ ..
make

Current Behaviour:
When I run these commands, I get the following warning:

ld: warning: direct access in function 'write_ppm(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<unsigned char, std::__1::allocator > const&, int, int, int)' from file '../lib/debug/mac/libhw2.a(write_ppm.cpp.o)' to global weak symbol 'std::__1::basic_ostream<char, std::__1::char_traits >& std::__1::endl<char, std::__1::char_traits >(std::__1::basic_ostream<char, std::__1::char_traits >&)' from file 'CMakeFiles/raytracing.dir/main.cpp.o' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.

Notes: Upon searching the issue myself, it seems to have to do with an fvisibility flag (but I'm not sure how to approach it).

DirectionalLight.cpp access Public vector d in header file

Hi,

For file DirectionalLight.cpp, we have 2 vector with the same name: direction vector of the directional light public d(in header file) and direction from source to light local d.

Online it says to use ::d to access the global d, but it turns out not working. I tried using this->d and it works.

Could someone explain abit on why ::d doesn't work in this case?

Files from HW2

We can use the precompiled binaries for the files from HW2, but do we still need to submit these files from HW2 again on Markus?

Assignment tasks

I might be missing something but aren't the reflection and blinn_phong_shading functions subsets of the raycolor function?
or is the ray colour responsible for adding the ambient component of the colour only?

Submitting a stl for creative.json

Is it possible to submit an .stl for the creative.json, I was under the impression we were allowed to use anything we wanted for the triangle soup. So I used a small (2MB) stl file from the internet. But the problem is MarkUs doesn't let me upload any files other than the ones specified in the input.

Is there a way to modify the MarkUs submission requirements, or maybe give us a place to email them?

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.