0

I've sucessfully implemented a ray tracer from scratch in C and it's marvelous: sphere1

The surface normal on this sphere is taken by computing the intersection point, A, and treating this as a euclidean vector with origin, B, the center of the sphere. To normalize it, I first subtracted A with B, yielding C:

C = (Ax-Bx,Ay-By)

From this, it's divided by the magnitude:

N = C/|C|

The illumination is calculated by taking the dot product of N and LIGHT_SOURCE and multiplying it with 255:

if (dot_product<0.0) dot_product = 0.0;
illumination = (unsigned char)(dot_product*255.0);

When I tried setting the light source to (0.0, 0.0, -1.0), it produce something like this: sphere2

I expected the shade to be something like it's brighter on the middle and becoming more dimmer on the side.

Anyone know what's causing the problem?

Source code: https://gist.github.com/harieamjari/6297a35400460edbabbd8e39720ed0f5

This can be compiled if you already have libpng16.

Spade 000
  • 43
  • 4

2 Answers2

1

It turns out, the problem was because the sphere was placed very far away and the radius is too big. This produces a normal with a high value z.

A solution for me was to place the sphere very close to the origin—about z=0.25, and set the radius of the sphere less than z— about r=0.125.

light_source (-1,0,0) -1,0,0 light_source (0,0,-1) 0,0,-1

Spade 000
  • 43
  • 4
0

I think there is a problem with your ray-sphere intersection.

It should go like this

sphere_normal = ray.origin - sphere_center;
b = dot(sphere_normal , ray.normalized_dir);
c = dot(sphere_normal , sphere_normal ) - sphere_radius*spheres_radius;
float disc = b * b - c;

float t = -1.0f; if(disc >= 0.0f) t = -b +- sqrt(disc);

if(t >= 0) // means ray intersects...

Check out scratchapixel to understand how I got this. https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection

gallickgunner
  • 2,438
  • 1
  • 12
  • 34