You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:42:12