如何在Python光线追踪器中仅渲染3D物体的正面
仅渲染3D物体正面的光线追踪器修改方案
问题说明
我用Python实现的光线追踪器目前会同时渲染3D物体的正面和背面,需要修改代码,让它仅对正面累积颜色。相关代码片段如下:
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
修改方案
核心是在击中判断逻辑里加入仅保留正面击中的过滤条件。假设你的hit_orientation中1代表正面(即光线从物体外部击中表面,法线与光线方向夹角为钝角),修改get_raycolor函数里的hit_check即可:
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): # 新增正面过滤:仅保留orient为正面的击中 hit_check = (nearest != FARAWAY) & (dis == nearest) & (orient == 1) 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
关键说明
- 如果你的代码中用其他值表示正面(比如
-1),把orient == 1替换成对应的判断即可。 - 修改后,光线只有击中物体正面时才会累积颜色,背面的击中会被直接忽略,不参与颜色计算。
内容的提问来源于stack exchange,提问作者FrostDream
相关产品推荐
相关产品推荐

