pythonpython-3.xraytracing

Render only the front faces of 3D objects in a raytracer


I'm working on a raytracer implementation in Python, and I want to ensure that only the front faces of 3D objects are rendered. Currently, the raytracer renders both the front and back faces, and I would like to modify the code to only accumulate color for the front faces.

Here's the relevant portion of my code:

def extract(cond, x):
    if isinstance(x, (int, float, complex)):
        return x
    return np.extract(cond, x)
class Ray:
    def __init__(self,origin, dir, depth, n, reflections, transmissions, diffuse_reflections):
        self.origin  = origin   
        self.dir = dir
        self.depth = depth     
        self.n = n
        self.reflections = reflections
        self.transmissions = transmissions
        self.diffuse_reflections = diffuse_reflections
    def extract(self,hit_check):
        return Ray(self.origin.extract(hit_check), self.dir.extract(hit_check), self.depth,  self.n.extract(hit_check), self.reflections, self.transmissions,self.diffuse_reflections)
class Hit:
    def __init__(self, distance, orientation, material, collider,surface):
        self.distance = distance
        self.orientation = orientation
        self.material = material
        self.collider = collider
        self.surface = surface
        self.u = None
        self.v = None
        self.N = None
        self.point = None
    def get_uv(self):
        if self.u is None:
            return self.collider.assigned_primitive.get_uv(self)
        return self.u, self.v
    def get_normal(self):
        if self.N is None:
            return self.collider.get_N(self)
        return self.N
def get_raycolor(ray, scene):
    distances, hit_orientation = zip(*[s.intersect(ray.origin, ray.dir) for s in scene.collider_list])
    nearest = np.minimum.reduce(distances)
    color = vec3(0., 0., 0.)
    for (coll, dis , orient) in zip(scene.collider_list, distances, hit_orientation):
        hit_check = (nearest != FARAWAY) & (dis == nearest)
        if np.any(hit_check):
            color += coll.assigned_primitive.material.get_color(scene,  ray.extract(hit_check), Hit(extract(hit_check,dis) , extract(hit_check,orient), coll.assigned_primitive.material, coll, coll.assigned_primitive)).place(hit_check)
    return color

Solution

  • Your code already has this feature.

    if you do this you will find out your code gets slower.

    From:

    def get_raycolor(ray, scene):
        distances, hit_orientation = zip(*[s.intersect(ray.origin, ray.dir) for s in scene.collider_list])
        nearest = np.minimum.reduce(distances)
        color = vec3(0., 0., 0.)
        for (coll, dis , orient) in zip(scene.collider_list, distances, hit_orientation):
            hit_check = (nearest != FARAWAY) & (dis == nearest)
            if np.any(hit_check):
                color += coll.assigned_primitive.material.get_color(scene,  ray.extract(hit_check), Hit(extract(hit_check,dis) , extract(hit_check,orient), coll.assigned_primitive.material, coll, coll.assigned_primitive)).place(hit_check)
        return color
    

    To:

    def get_raycolor(ray, scene):
        distances, hit_orientation = zip(*[s.intersect(ray.origin, ray.dir) for s in scene.collider_list])
        nearest = np.minimum.reduce(distances)
        color = vec3(0., 0., 0.)
        for (coll, dis , orient) in zip(scene.collider_list, distances, hit_orientation):
            hit_check = (nearest != FARAWAY) & (dis == nearest)
            color += coll.assigned_primitive.material.get_color(scene,  ray.extract(hit_check), Hit(extract(hit_check,dis) , extract(hit_check,orient), coll.assigned_primitive.material, coll, coll.assigned_primitive)).place(hit_check)
        return color