def G1(N, H, I): HdotI = dot(H, I) if HdotI <= 0.: return 0. NdotH = dot(N, H) NdotI = dot(N, I) return 2. * NdotH * NdotI / HdotI
def intersect(self, ray): t1 = None t2 = None if dot(ray.D, self.lside.N) < 0: # front facing t1 = self.lside.intersect(ray) #print('intersect left face', t1) if dot(ray.D, self.rside.N) < 0: # front facing t2 = self.rside.intersect(ray) #print('intersect right face', t2) tmin = None if t1 is None or t2 is None: if t1 is None: tmin = t2 if t2 is None: tmin = t1 else: tmin = min(t1, t2) hit = None if tmin is not None: p = ray(tmin) if p.z <= 0.: if tmin == t1: #print('hit left side') hit = Hit(p, self.lside.N, 'left') elif tmin == t2: #print('hit right side') hit = Hit(p, self.rside.N, 'right') #print(hit) return hit
def hit_sphere(center, radius, r): oc = r.origin - center a = dot(r.direction, r.direction) b = 2. * dot(oc, r.direction) c = dot(oc, oc) - radius * radius discriminant = b**2 - 4 * a * c return discriminant > 0
def GLambdaWalter(self, w, wh): costhetav = math.fabs(w.z) if costhetav < SMALLFLOAT: return 1 tanthetav = math.sqrt(1.0 - costhetav * costhetav) / costhetav if tanthetav < SMALLFLOAT: return 1.0 a = 1.0 / (self.alpha_x * tanthetav) if (a < 1.6): iG1i = ChiPlus(vec3.dot(w, wh) / w.z) * ( 3.535 * a + 2.181 * a * a) / (1 + 2.276 * a + 2.577 * a * a) else: iG1i = ChiPlus(vec3.dot(w, wh) / w.z) return iG1i
def intersect(self, ray): O = ray.O D = ray.D P = self.P N = self.N # Return the distance from O to the intersection of the ray (O, D) with the # plane (P, N), or +inf if there is no intersection. # O and P are 3D points, D and N (normal) are normalized vectors. denom = dot(D, N) if abs(denom) < 1e-6: return TMAX d = dot(P - O, N) / denom if d < 0: return TMAX return d
def hit(self, ray, t_min, t_max): oc = ray.origin - self.center a = ray.direction.length_squared() half_b = dot(oc, ray.direction) c = oc.length_squared() - (self.radius * self.radius) discriminant = (half_b * half_b) - (a * c) if discriminant > 0: root = math.sqrt(discriminant) temp = (-half_b - root) / a if t_min < temp < t_max: rec = HitRecord() rec.t = temp rec.position = ray.at(rec.t) outwardNormal = (rec.position - self.center) / self.radius rec.setFaceNormal(ray, outwardNormal) rec.material = self.material return True, rec temp = (-half_b + root) / a if t_min < temp < t_max: rec = HitRecord() rec.t = temp rec.position = ray.at(rec.t) outwardNormal = (rec.position - self.center) / self.radius rec.setFaceNormal(ray, outwardNormal) rec.material = self.material return True, rec return False, HitRecord()
def scatter(self, ray_in, rec): attenuation = Vec3(1.0, 1.0, 1.0) if rec.frontFacing: etai_over_etat = 1 / self.refractive_index else: etai_over_etat = self.refractive_index unit_direction = ray_in.direction.norm() cos_theta = min(dot(rec.normal, -unit_direction), 1.0) sin_theta = math.sqrt(1.0 - cos_theta * cos_theta) if etai_over_etat * sin_theta > 1.0: reflected = reflect(unit_direction, rec.normal) scattered = Ray(rec.position, reflected) return True, scattered, attenuation reflection_probability = schlick(cos_theta, etai_over_etat) if random.random() < reflection_probability: reflected = reflect(unit_direction, rec.normal) scattered = Ray(rec.position, reflected) return True, scattered, attenuation refracted = refract(unit_direction, rec.normal, etai_over_etat) scattered = Ray(rec.position, refracted) return True, scattered, attenuation
def fromnormals_faster(n1,n2): axis= vec3.normalize(vec3.cross(n1, n2)) half_n= vec3.normalize(vec3.add(n1, n2)) cos_half_angle= vec3.dot(n1, half_n) sin_half_angle= 1.0 - cos_half_angle**2 return vec3.mulN(axis, sin_half_angle) + (cos_half_angle,)
def fromnormals_faster(n1, n2): axis = vec3.normalize(vec3.cross(n1, n2)) half_n = vec3.normalize(vec3.add(n1, n2)) cos_half_angle = vec3.dot(n1, half_n) sin_half_angle = 1.0 - cos_half_angle ** 2 return vec3.mulN(axis, sin_half_angle) + (cos_half_angle,)
def GB(self, wo, wi, wh): den = vec3.dot(wi, wh) if den < SMALLFLOAT: return 1 nom = 2.0 * wh.z * wi.z if nom > den: return 1 if nom < SMALLFLOAT: return 0 return nom / den
def zipinRatio(self, wo, wh, prob): denom = math.fabs(vec3.dot(wo, wh)) if denom < microfacet.SMALLFLOAT: return 1 nom = math.fabs(wo.z * wh.z * 2.0) if nom < microfacet.SMALLFLOAT: return 0 gr = nom/denom * prob if gr > 1: gr = 1 return gr
def visible(self, theta, n=100000): I = vec3.FromAngle(theta) N = vec3.Z # integrate over the hemisphere dcos = 1 / n dcos_sum = 0.0 for i in range(n + 1): cosh = i / n H = vec3.FromCosAngle(cosh) G = vgroove.G1(N, H, I) # other self-shadowing functions? HdotI = vec3.dot(H, I) dcos_sum += 0.5 * G * self.D(H) * HdotI * dcos return 2 * math.pi * dcos_sum
def scatter(self, ray, record): reflected = vec3.reflect(vec3.normalize(ray.direction), record.normal) outward_normal = (0, 0, 0) idx_ratio = 0 if vec3.dot(ray.direction, record.normal) > 0: outward_normal = vec3.scale(record.normal, -1) idx_ratio = self.ri cos = self.ri * vec3.dot(vec3.normalize(ray.direction), record.normal) else: outward_normal = record.normal idx_ratio = 1.0 / self.ri cos = -vec3.dot(vec3.normalize(ray.direction), record.normal) refracted = vec3.refract(ray.direction, outward_normal, idx_ratio) if refracted: reflect_prob = self.schlick(cos, self.ri) if random.random() < reflect_prob: return Ray(record.p, reflected) return Ray(record.p, refracted) else: return Ray(record.p, reflected)
def hit(self, ray, t_min, t_max): record = HitRecord() oc = vec3.subtract(ray.origin, self.center) a = vec3.squared_length(ray.direction) b = vec3.dot(oc, ray.direction) c = vec3.squared_length(oc) - self.radius**2 discriminant = b**2 - a * c if discriminant > 0: t = (-b - math.sqrt(discriminant)) / a if (t < t_max and t > t_min): record.t = t record.p = ray.point_at_time(t) record.normal = vec3.normalize( vec3.subtract(record.p, self.center)) record.material = self.material return record return None
def Pdf(self, wo, wh): normFactor = 4.0 * vec3.dot(wo, wh) if normFactor < microfacet.SMALLFLOAT: return 0 pdf = self.microfacet.Pdf(wh) return pdf/normFactor
def reflect(wo, n): return -wo + n * vec3.dot(wo, n) * 2.0
def fromnormals(n1, n2): axis, angle = vec3.normalize(vec3.cross(n1, n2)), math.acos(vec3.dot(n1, n2)) return fromaxisangle((axis, angle))
def fromnormals(n1,n2): axis,angle= vec3.normalize(vec3.cross(n1, n2)), math.acos(vec3.dot(n1, n2)) return fromaxisangle((axis,angle))
def transmulvec3(m_trans,v): return tuple([vec3.dot(v, m_c) for m_c in m_trans])
def scatter(self, ray, record): reflected = vec3.reflect(vec3.normalize(ray.direction), record.normal) scattered = Ray(record.p, reflected) return scattered if vec3.dot(scattered.direction, record.normal) > 0 else None
def reflect(N, I): #print('reflect({},{}'.format(N,I)) return I - N * (2 * dot(N, I))
def transmulvec3(m_trans, v): return tuple([vec3.dot(v, m_c) for m_c in m_trans])
def multiply(rotation, w): x = vec3.dot(rotation[0], w) y = vec3.dot(rotation[1], w) z = vec3.dot(rotation[2], w) return vec3.Vec3(x, y, z)