Featured image of post 3D Graphics: RayTracing Intro

3D Graphics: RayTracing Intro

A quick intro on raytracing

Raytracing is a form of light reflection calculation that allows shadows to be calculated and recieve more exact versions of light intensities

Basic Raytracing

We care about the rays of light that the sun emits and bounce around before hitting our eye. The sun emits millions of rays of light that never hit our eye so if we calculated all the rays of the sun, we would be wasting many computing cycles

What is actually done in basic raytracing is to actually emit from the target (our vew/camera) and see which ray actually reaches the sun. We can set a limit on the number of reflections until we want to drop a ray and this let’s us calculate only the rays we care about

trace

Shadows

In terms of shadows, there are two different types of shadows: hard shadow & soft shadow

  • Hard Shadow: No light ever hits the particular spot
  • Soft Shadow: Some light hits the spot but not all

shadow

Raytracing PsuedoCode

# Calculating all the rays
function traceRay(point, direction, scene)
	# find intersection
	(intersectPoint, normal, material) = scene.intersect(point, direction)
	
	# using the halfway point to calculate the reflection
	# (a + b)/2 = c && -(c * 2) + a = b
	reflection = -2 * (math.dot(direction, normal)) + d 

	#calculate the rotation of the current ray for the internal boucing of the object (ie: Figure out refraction ray)
	internalRay = SnellLaw(point, direction, scene) 
	
	# Get light intensity (light model: Specular + Diffuse + Ambience )
	intensity = shade(intersectPoint, normal, material, direction, scene)
	# reflection ray
	+ material.specularColor * traceRay(intersectPoint, reflection, scene)
	# refraction ray
	+ material.trasnmissive * traceRay(intersectPoint, inernalRay, scene)
	return intensity
	
# performing ray tracing on the image
function traceImage()
	for each pixel
		pixelWorld = translateFromProjectionToWorld(pixel)
		direction = (pixelWorld - camera)/ mag(pixelWorld - camera)
		traceRay(pixel world positiion, direction, scene)

# finding the intersection of a ray
function intersect(point, distance)
	x = point.x + t * direction.x
	y = point.y + t * direction.y
	z = point.z + t * direction.z
	// Example with sphere
	if object[0].radius^2 == x^2 + y^2 + z^2
		INTERSECTION CONFIRMED

function shade(intersectionPoint, normal, material, direction, scene)
	# Grab the color of the object
	intensity = material.diffuseColor

	# Go for every light hitting this object
	for each scene.lights
		# calculate the attenuation of this point (both by distance and shadow)
		attenuation = 
light.distanceAtten(intersectionPoint) * light.shadowAtten(intersectionPoint)
		# get the direcetion of the light to the point
		L = light.getDirection(intersectionPoint)
		# Do diffusion, specular, and ambient lighting
		intensity = intensity + light.ambient + attenuation*(diffuse(L, normal) + specular(L, normal))
	# Return the final light intensity
	return intensity
	

Detecting Intersection

A current point on a ray can be represented using the function $$R(t) = P_0 + t\vec{d}$$ This is a function that will produce a point for us that we can immediately use to verify for intersection. Now we need a primitive to verify against. A simple example is using a sphere!

Sphere

We can represent a sphere using the equation: $$x^2+y^2+z^2=r^2$$ This equation does two things, tells us the radius if we know a point on the sphere, but it also tells us whether something is on the same sphere if we only know the radius and need to confirm the points

Using both equations, we can rewrite it into a solving for zero problem:

$$x^2+y^2+z^2-r^2=0$$ Since we can produce the x,y, and z with our ray problem, we can turn it into a problem involving only one unknown variable, t! $$(P_0x + t\vec{d_x})^2 + (P_0y + t\vec{d_y})^2 + (P_0z + t\vec{d_z})^2 - r^2 = 0 $$ Now before we call this good, we have to note, this equation will only tell us if a point lies exactly on the sphere. We want to also be able to tell if point is inside the sphere. We call solve this by turning this into an inequality

$$(P_0x + t\vec{d_x})^2 + (P_0y + t\vec{d_y})^2 + (P_0z + t\vec{d_z})^2 - r^2 \leq 0 $$ Disclaimer: This assumes the sphere starts at the origin (0,0,0), you will have to take that into account when using with a sphere not at the origin: $$(x-a)^2+(y-b)^2+(z-c)^2=r^2$$ $a$,$b$,$c$ = sphere origin position

Plane

Unlike spheres, we don’t have a nice clean equation to verify our points, we need to do vector maths

We know that all points on a plane have the same normal, this means any vector we make using two points on the plane should be perpendicular to the normal!

We can represent our verification fuction as:

with Q being the point generated from $R(t)$ and P being a point on the plane

$$\vec{N} \cdot (Q - P)=0$$

0 represents the normal and the vector derived with two points being perpendicular, anything else means it does not lie on the plane. Note: Any point on the plane can be used to generate the $(Q-P)$ vector, as long as it’s normalized.

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy