Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ To build the project and run locally,
cmake --build build
./build/Rendera/Rendera
```

```bash
cmake -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_C_COMPILER=gcc-11 -S. -Bbuild -DCMAKE_BUILD_TYPE=Release
```
43 changes: 37 additions & 6 deletions Rendera/include/cube.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@
#include "ray.hpp"
#include "material.hpp"


//debug
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this comment mean?

class HitInfo{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HitInfo struct should be in its own header file.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a class? It should be a struct.

bool if_hit;
vec3 dist_v;
Material mat;
ray r;
int depth;

public:
HitInfo(bool if_hit, vec3 v, Material m, ray r, int d):if_hit{if_hit}, dist_v{v}, mat{m}, r{r}, depth{d}{};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Members of structs are public by default. Also, this constructor is not needed. The compiler will auto-generate it for you.


};

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are there so many blank spaces?


//

// checks which point is farther going along the ray
vec3 max(vec3 a, vec3 b, ray r)
{
Expand Down Expand Up @@ -41,7 +58,8 @@ class Cube
vec3 m_position;
vec3 m_a, m_b, m_c;
Material m_material;
static const double m_epsilon = 1e-5;
vec3 int_pt;
const double m_epsilon = 1e-5;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you make m_epsilon a non-static member?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you make this a non-static member? Now every Cube object will have its own copy of m_epsilon.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it static constexpr double m_epsilon = 1e-5;


public:
Cube(vec3 position, vec3 a, vec3 b, vec3 c, Material mat) : m_position{position}, m_a{a}, m_b{b}, m_c{c}, m_material{mat} {};
Expand Down Expand Up @@ -163,7 +181,7 @@ class Cube
(all occurences are referenced when traversing along the ray direction)
*/

HitInfo hit(const ray &r, int recursion_depth)
bool hit(const ray &r)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change the function signature?

{
vec3 temp_a = plane_intersect(cross(m_b, m_c), m_position, r);
vec3 temp_b = plane_intersect(cross(m_b, m_c), m_position + m_a, r);
Expand All @@ -183,20 +201,33 @@ class Cube
// if the ray is outside the cube amin comes after amax when going along the ray
if(dot((amin-r.get_origin()),r.get_direction())>dot((amax-r.get_origin()),r.get_direction()))
{
return {false, vec3(0,0,0), m_material, r, recursion_depth};
// return {false, vec3(0,0,0), m_material, r, recursion_depth};
return false;

}
else if(dot(r.get_direction(),amax - r.get_origin())<0 ) // checks if both intersection are behind the r.origin
{
return {false, vec3(0,0,0), m_material, r, recursion_depth};
// return {false, vec3(0,0,0), m_material, r, recursion_depth};
return false;
}
else if(dot(r.get_direction(),amin - r.get_origin())<0) // checks if r.origin is inside the cube
{
return {true, amax, m_material, r, recursion_depth-1};
// return {true, amax, m_material, r, recursion_depth-1};
int_pt = amax;
return true;
}

return {true, amin, m_material, r, recursion_depth-1}; // if two intersections, returns the closest one
// return {true, amin, m_material, r, recursion_depth-1}; // if two intersections, returns the closest one
int_pt = amin;
return true;

}
vec3 get_int_pt(){
return int_pt;
}
Material mat(){
return m_material;
}
};

#endif // CUBE_HPP
113 changes: 86 additions & 27 deletions Rendera/include/scene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "sphere.hpp"
#include "intersection.hpp"
#include "camera.hpp"

#include "cube.hpp"
class Hitinfo{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a One Definition Rule (ODR) violation. You can only have definition for a class. Why did you define HitInfo multiple times?

public:
bool ishitting = false;
Expand All @@ -16,6 +16,7 @@ class Hitinfo{
color shade_new = {0,0,0};
color rgb;
ray ref_ray;
Hitinfo() = default;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this line is not needed because the compiler will auto-generate it for you.

};

color lighting(Material mat, ray cam_ray, ray normal, vec3 point, vec3 light_src, color intensity){
Expand Down Expand Up @@ -54,21 +55,25 @@ color lighting(Material mat, ray cam_ray, ray normal, vec3 point, vec3 light_src

class Scene{
public:
int n_sphere;
int n_sphere = 1;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two variables (n_sphere and n_cube) shouldn't be hard-coded in the Scene class.

int n_cube = 0;
uint16_t img_width;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this a 32 bit int (std::uint32_t). To use these types, you should also include <cstddef>.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for img_height.

uint16_t img_height;
Hitinfo *hitinfo = new Hitinfo[img_height*img_width];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line because we are going depth-first.

sphere *hitable_sphere = new sphere[n_sphere];
std::vector<Sphere> hitable_sphere;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You used std::vector but didn't include the <vector> header.

std::vector<Cube> hitable_cube;


vec3 light_src = {-5,3,5};
color light_col = {1,1,1};
vec3 light_src2 = {0, 10, 0};



vec3 cam_origin = {0,0,0};
float port_width = 8;
float port_height = 8;
float focal_length = 2;
vec3 cam_origin = {0,0,1};
float port_width = 10;
float port_height = 10;
float focal_length = 4;
int max_col = 255;
Camera cam;

Expand All @@ -85,29 +90,34 @@ class Scene{

}
~Scene(){
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't a manually defined destructor because we are removing the array of HitInfo structs.

delete hitable_sphere;
delete hitinfo;
}
void set_sphere(int index, vec3 center, float radius, Material mat){
if (index < n_sphere)
hitable_sphere[index] = sphere(center, radius, mat);
else
std::cout<<"accessing wrong index"<<std::endl;
void add_sphere(vec3 center, float radius, Material mat){
n_sphere++;
hitable_sphere.push_back(Sphere(center, radius, mat));
}
void add_cube(vec3 position, vec3 a, vec3 b, vec3 c, Material mat){
n_cube++;
hitable_cube.push_back(Cube(position, a, b, c, mat));
}



void hit_object(int x, int y){
hitinfo[y*img_width + x].ray_ = ray(cam.get_ray(x, y));
for(int i = 0; i < n_sphere; i++){
std::vector<Sphere>::iterator sp;
std::vector<Cube>::iterator cb;
Comment on lines +107 to +108
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two lines of code are unnecessary because from C++11 onwards, you can use auto.

hitinfo[y*img_width + x].ray_ = cam.get_ray(x, y);
// std::cout<<cam.get_ray(x, y).get_direction();
for(sp = hitable_sphere.begin(); sp != hitable_sphere.end(); ++sp){
Intersection i_;
bool hits = i_.hit(hitable_sphere[i], hitinfo[y*img_width + x].ray_);
bool hits = i_.hit(*sp, hitinfo[y*img_width + x].ray_);
if (hitinfo[y*img_width + x].ishitting && hits){
if (hitinfo[y*img_width + x].dist > i_.dist_1()){
hitinfo[y*img_width + x].dist = i_.dist_1();
hitinfo[y*img_width + x].intersection_pt = hitinfo[y*img_width + x].ray_.fetch(hitinfo[y*img_width + x].dist);
hitinfo[y*img_width + x].normal = hitable_sphere[i].normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade = lighting(hitable_sphere[i].mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].normal = (*sp).normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade = lighting((*sp).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].shade += lighting((*sp).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src2, light_col);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is a massive wall of text as it stands. Surely there is a way to make it easier on the eyes?

hitinfo[y*img_width + x].rgb = hitinfo[y*img_width + x].shade.get_int();
hitinfo[y*img_width + x].ref_ray = reflect(hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal);
}
Expand All @@ -116,43 +126,92 @@ class Scene{
hitinfo[y*img_width + x].ishitting = true;
hitinfo[y*img_width + x].dist = i_.dist_1();
hitinfo[y*img_width + x].intersection_pt = hitinfo[y*img_width + x].ray_.fetch(hitinfo[y*img_width + x].dist);
hitinfo[y*img_width + x].normal = hitable_sphere[i].normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade = lighting(hitable_sphere[i].mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].normal = (*sp).normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade = lighting((*sp).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].shade += lighting((*sp).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src2, light_col);
hitinfo[y*img_width + x].rgb = hitinfo[y*img_width + x].shade.get_int();
hitinfo[y*img_width + x].ref_ray = reflect(hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal);

}
}

for(cb = hitable_cube.begin(); cb != hitable_cube.end(); ++cb){
bool hits = (*cb).hit(hitinfo[y*img_width + x].ray_);
if(hitinfo[y*img_width + x].ishitting && hits){
float d = (*cb).get_int_pt().norm();
if (hitinfo[y*img_width + x].dist>d){
hitinfo[y*img_width + x].ishitting = true;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here. If you are writing massive walls of text like this, you are doing something wrong.

hitinfo[y*img_width + x].intersection_pt = (*cb).get_int_pt();
hitinfo[y*img_width + x].dist = d;
hitinfo[y*img_width + x].normal = (*cb).normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade = lighting((*cb).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].shade += lighting((*cb).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src2, light_col);
hitinfo[y*img_width + x].rgb = hitinfo[y*img_width + x].shade.get_int();
hitinfo[y*img_width + x].ref_ray = reflect(hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal);
}

}
else if(hits){
hitinfo[y*img_width + x].ishitting = true;
hitinfo[y*img_width + x].intersection_pt = (*cb).get_int_pt();
hitinfo[y*img_width + x].dist = hitinfo[y*img_width + x].intersection_pt.norm();
hitinfo[y*img_width + x].normal = (*cb).normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade = lighting((*cb).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].shade += lighting((*cb).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src2, light_col);
hitinfo[y*img_width + x].rgb = hitinfo[y*img_width + x].shade.get_int();
hitinfo[y*img_width + x].ref_ray = reflect(hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal);


}
}
}

void next_depth(int x, int y){
for(int i = 0; i < n_sphere; i++){
std::vector<Sphere>::iterator sp;
std::vector<Cube>::iterator cb;
Comment on lines +170 to +171
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here. Use auto.

for(sp = hitable_sphere.begin(); sp != hitable_sphere.end(); ++sp){
if(hitinfo[y*img_width + x].ishitting){
Intersection i_;
bool hits = i_.hit(hitable_sphere[i], hitinfo[y*img_width + x].ref_ray);
if (hitinfo[y*img_width + x].ishitting && hits){
bool hits = i_.hit(*sp, hitinfo[y*img_width + x].ref_ray);
if (hits){
if (hitinfo[y*img_width + x].dist > i_.dist_1()){
hitinfo[y*img_width + x].dist = i_.dist_1();
hitinfo[y*img_width + x].intersection_pt = hitinfo[y*img_width + x].ref_ray.fetch(hitinfo[y*img_width + x].dist);
hitinfo[y*img_width + x].normal = hitable_sphere[i].normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade_new = lighting(hitable_sphere[i].mat(), hitinfo[y*img_width + x].ref_ray, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].normal = (*sp).normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade_new = lighting((*sp).mat(), hitinfo[y*img_width + x].ref_ray, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].shade_new = lighting((*sp).mat(), hitinfo[y*img_width + x].ref_ray, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src2, light_col);
hitinfo[y*img_width + x].ref_ray = reflect(hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal);
}
}
}
}

for(cb = hitable_cube.begin(); cb != hitable_cube.end(); ++cb){
if(hitinfo[y*img_width + x].ishitting){
bool hits = (*cb).hit(hitinfo[y*img_width + x].ray_);
if (hits){
float d = (*cb).get_int_pt().norm();
if (hitinfo[y*img_width + x].dist>d){
hitinfo[y*img_width + x].intersection_pt = (*cb).get_int_pt();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More walls of text. Please change this.

hitinfo[y*img_width + x].dist = d;
hitinfo[y*img_width + x].normal = (*cb).normal(hitinfo[y*img_width + x].intersection_pt);
hitinfo[y*img_width + x].shade_new = lighting((*cb).mat(), hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal, hitinfo[y*img_width + x].intersection_pt, light_src, light_col);
hitinfo[y*img_width + x].ref_ray = reflect(hitinfo[y*img_width + x].ray_, hitinfo[y*img_width + x].normal);
}
}

}
}
}

void render(){
for(int x=0; x<img_width; x++){
for(int y=0; y<img_height; y++){
hit_object(x,y);
// hitinfo[y*img_width + x].ishitting = false;
next_depth(x,y);
hitinfo[y*img_width + x].shade += hitinfo[y*img_width + x].shade_new;
hitinfo[y*img_width + x].shade_new = {0,0,0};
hitinfo[y*img_width + x].rgb = hitinfo[y*img_width + x].shade.get_int();
// next_depth(x,y);
next_depth(x,y);
hitinfo[y*img_width + x].shade += hitinfo[y*img_width + x].shade_new;
hitinfo[y*img_width + x].shade_new = {0,0,0};
Expand Down
6 changes: 3 additions & 3 deletions Rendera/include/sphere.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
#include "color.hpp"
#include "material.hpp"

class sphere{
class Sphere{
vec3 center;
float radius;
Material material;

public:
sphere(){}
sphere(vec3 Center, float Radius, Material mat): center {Center}, radius {Radius}, material {mat} {}
Sphere(){}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set the constructor equal to default. Don't make it have an empty body.

Sphere(vec3 Center, float Radius, Material mat): center {Center}, radius {Radius}, material {mat} {}

//surface normal function, returns ray along outward normal
ray normal(vec3 point){
Expand Down
Loading