Beispiel #1
0
    def f(self, wo: 'geo.Vector', wi: 'geo.Vector') -> 'Spectrum':
        diffuse = (28. / (23. * PI)) * self.Rd * \
                  (Spectrum(1.) - self.Rs) * \
                  (1. - np.power(1. - .5 * abs_cos_theta(wi), 5)) * \
                  (1. - np.power(1. - .5 * abs_cos_theta(wo), 5))

        wh = geo.normalize(wi + wo)

        specular = self.distribution.D(wh) / \
                   (4. * wi.abs_dot(wh) * max(abs_cos_theta(wi), abs_cos_theta(wo))) * \
                   self.schlick(wi.dot(wh))

        return diffuse + specular
Beispiel #2
0
    def sample_f(self, wo: 'geo.Vector', u1: FLOAT,
                 u2: FLOAT) -> [FLOAT, 'geo.Vector', 'Spectrum']:
        # find direction
        wi = geo.Vector(-wo.x, -wo.y, wo.z)

        return [
            1., wi,
            self.fresnel(cos_theta(wo)) * self.R / abs_cos_theta(wi)
        ]  # 1. suggests no MC samples needed
Beispiel #3
0
    def pdf(self, wo: 'geo.Vector', wi: 'geo.Vector') -> FLOAT:
        wh = geo.normalize(wo + wi)
        ct = abs_cos_theta(wh)

        if wo.dot(wh) <= 0.:
            return 0.

        return (
            (self.e + 1.) * np.power(ct, self.e)) / (2. * PI * 4. * wo.dot(wh))
Beispiel #4
0
    def pdf(self, wo: 'geo.Vector', wi: 'geo.Vector') -> FLOAT:
        """
		pdf()

		Returns pdf of given direction
		"""
        if wo.z * wi.z > 0.:
            # same hemisphere
            return abs_cos_theta(wi) * INV_PI
        return 0.
Beispiel #5
0
    def f(self, wo: 'geo.Vector', wi: 'geo.Vector') -> 'Spectrum':
        st_i = sin_theta(wi)
        st_o = sin_theta(wo)

        # \cos(\phi_i - \phi_o)
        mc = 0.
        if st_i > EPS and st_o > EPS:
            dcos = cos_phi(wi) * cos_phi(wo) + sin_phi(wi) * sin_phi(wo)
            mc = max(0., dcos)

        # \sin \alpah \tan \beta
        if abs_cos_theta(wi) > abs_cos_theta(wo):
            sa = st_o
            tb = st_i / abs_cos_theta(wi)
        else:
            sa = st_i
            tb = st_o / abs_cos_theta(wo)

        return self.R * INV_PI * (self.A + self.B * mc * sa * tb)
Beispiel #6
0
    def D(self, wh: 'geo.Vector') -> FLOAT:
        cth = abs_cos_theta(wh)
        d = 1. - cth * cth

        if d == 0.:
            return 0.

        e = (self.ex * wh.x * wh.x + self.ey * wh.y * wh.y) / d
        return np.sqrt(
            (self.ex + 2.) * (self.ey + 2.)) * INV_2PI * np.power(cth, e)
Beispiel #7
0
 def pdf(self, wo: 'geo.Vector', wi: 'geo.Vector') -> FLOAT:
     wh = geo.normalize(wo + wi)
     ct = abs_cos_theta(wh)
     ds = 1. - ct * ct
     if ds > 0. and wo.dot(wh) > 0.:
         return (np.sqrt((self.ex + 1.) * (self.ey + 1.)) * INV_2PI * np.power(ct,
                                                                               (
                                                                               self.ex * wh.x * wh.x + self.ey * wh.y * wh.y) / ds)) / \
                (4. * wo.dot(wh))
     else:
         return 0.
Beispiel #8
0
    def rho_hh(self, nSamples: INT, samples_1: [FLOAT],
               samples_2: [FLOAT]) -> 'Spectrum':
        """
		Computs hemispherical-hemispherical reflectance function.

		- samples_1, samples_2
			2d np array
		"""
        r = Spectrum(0.)
        for i in range(nSamples):
            wo = mc.uniform_sample_hemisphere(samples_1[i][0], samples_1[i][1])
            pdf_o = INV_2PI

            pdf_i, wi, f = self.sample_f(wo, samples_2[i][0], samples_2[i][1])

            if pdf_i > 0.:
                r += f * abs_cos_theta(wi) * abs_cos_theta(wo) / (pdf_o *
                                                                  pdf_i)

        r /= (PI * nSamples)
        return r
Beispiel #9
0
    def rho_hd(self, w: 'geo.Vector', samples: [FLOAT]) -> 'Spectrum':
        """
		Computes hemispherical-directional reflectance function.

		- w
			Incoming 'geo.Vector'
		- samples
			2d np array
		"""
        r = Spectrum(0.)
        for smp in samples:
            pdf, wi, f = self.sample_f(w, smp[0], smp[1])
            if pdf > 0.:
                r += f * abs_cos_theta(wi) / pdf

        r /= len(samples)
        return r
Beispiel #10
0
    def sample_f(self, wo: 'geo.Vector', u1: FLOAT,
                 u2: FLOAT) -> [FLOAT, 'geo.Vector', 'Spectrum']:
        # find eta pair
        ei, et = self.ei, self.et
        if cos_theta(wo) > 0.:
            ei, et = et, ei

        # compute transmited ray direction
        si_sq = sin_theta_sq(wo)
        eta = ei / et
        st_sq = eta * eta * si_sq

        if st_sq >= 1.:
            return [0., None, None]

        ct = np.sqrt(max(0., 1. - st_sq))
        if cos_theta(wo) > 0.:
            ct = -ct
        wi = geo.Vector(eta * (-wo.x), eta * (-wo.y), ct)

        F = self.fresnel(cos_theta(wo))

        return [1., wi, (et * et) / (ei * ei) * (Spectrum(1.) - F) * \
                self.T / abs_cos_theta(wi)]  # 1. suggests no MC samples needed
Beispiel #11
0
    def sample_f(self, wo: 'geo.Vector', u1: FLOAT,
                 u2: FLOAT) -> [FLOAT, 'geo.Vector']:
        # sample from first quadrant and remap to hemisphere to sample w_h
        if u1 < .25:
            phi, ct = self.__sample_first_quad(4. * u1, u2)
        elif u1 < .5:
            u1 = 4. * (.5 - u1)
            phi, ct = self.__sample_first_quad(u1, u2)
            phi = PI - phi
        elif u1 < .75:
            u1 = 4. * (u1 - .5)
            phi, ct = self.__sample_first_quad(u1, u2)
            phi += PI
        else:
            u1 = 4. * (1. - u1)
            phi, ct = self.__sample_first_quad(u1, u2)
            phi = 2. * PI - phi

        st = np.sqrt(max(0., 1. - ct * ct))
        wh = geo.spherical_direction(st, ct, phi)
        if wo.z * wh.z <= 0.:
            wh *= -1.

        # incident direction by reflection
        wi = -wo + 2. * wo.dot(wh) * wh

        # compute pdf for w_i
        ct = abs_cos_theta(wh)
        ds = 1. - ct * ct
        if ds > 0. and wo.dot(wh) > 0.:
            return [(np.sqrt((self.ex + 1.) * (self.ey + 1.)) * INV_2PI * np.power(ct,
                                                                                   (
                                                                                   self.ex * wh.x * wh.x + self.ey * wh.y * wh.y) / ds)) / \
                    (4. * wo.dot(wh)), wi]
        else:
            return [0., wi]
Beispiel #12
0
 def pdf(self, wo: 'geo.Vector', wi: 'geo.Vector') -> FLOAT:
     if wo.z * wi.z <= 0.:
         return 0.
     return .5 * (abs_cos_theta(wi) * INV_PI +
                  self.distribution.pdf(wo, wi))
Beispiel #13
0
 def D(self, wh: 'geo.Vector') -> FLOAT:
     return (self.e + 2) * INV_2PI * np.power(abs_cos_theta(wh), self.e)
Beispiel #14
0
 def G(self, wo: 'geo.Vector', wi: 'geo.Vector', wh: 'geo.Vector') -> FLOAT:
     return min(
         1.,
         min((2. * abs_cos_theta(wh) * abs_cos_theta(wo) / wo.abs_dot(wh)),
             (2. * abs_cos_theta(wh) * abs_cos_theta(wi) / wo.abs_dot(wh))))