Post by madox on Aug 20, 2019 17:38:43 GMT
I noticed one thing not covered in the book is rendering proper looking shadows for transparent objects. A transparent object should still let light through and not make a solid shadow. Also light gets refracted distorting shadows. Well, using what I learned so far from the book, I tried to make the shadows look more proper. After a few days trying things, here is a result I got, which I think is pretty good:
There are 2 lights here, one above and one down low to make shadows. The middle ball is a glass ball with a hollow core. This scene takes pretty long to render: about 8s, which is long compared 0.4s using the old shadow code.
To do this, I first added a new value to material: "transmit" which is how much light gets transmitted through the object. I separated this from the transparency value just in case it helps to be separated.
Then I altered the end of the is_shadowed() function to look like:
...
first part unchanged
...
if h is present and h.t < distance
if hit.object.material.transmit
comp <- prepare_computations(r, intersections)
r2 <- { compute the refracted ray same as refracted_color() does }
intersections2 <- intersect_world(world, r2)
hit2 <- hit(intersections2)
if (hit2)
comp2 <- prepare_computations(r2, intersections2)
return is_shadowed(world, comp2.over_point) * (1 - hit.object.material.transmit)
end if
return 1
end if
else
return 0
endif
Finally, in the lighting function, multiply the diffuse and specular values by this shadow value.
I hope this is close to correct and welcome and feedback on this!
Update: I should add what I did in english! If the point is in shadow, take the ray from the point to the light and refract it with our existing code. Cast that new ray and if it hits something, recursively get the shadow of that new point.
There are 2 lights here, one above and one down low to make shadows. The middle ball is a glass ball with a hollow core. This scene takes pretty long to render: about 8s, which is long compared 0.4s using the old shadow code.
To do this, I first added a new value to material: "transmit" which is how much light gets transmitted through the object. I separated this from the transparency value just in case it helps to be separated.
Then I altered the end of the is_shadowed() function to look like:
...
first part unchanged
...
if h is present and h.t < distance
if hit.object.material.transmit
comp <- prepare_computations(r, intersections)
r2 <- { compute the refracted ray same as refracted_color() does }
intersections2 <- intersect_world(world, r2)
hit2 <- hit(intersections2)
if (hit2)
comp2 <- prepare_computations(r2, intersections2)
return is_shadowed(world, comp2.over_point) * (1 - hit.object.material.transmit)
end if
return 1
end if
else
return 0
endif
Finally, in the lighting function, multiply the diffuse and specular values by this shadow value.
I hope this is close to correct and welcome and feedback on this!
Update: I should add what I did in english! If the point is in shadow, take the ray from the point to the light and refract it with our existing code. Cast that new ray and if it hits something, recursively get the shadow of that new point.