Exemplo n.º 1
0
	ustring sample(const Vec3 &Ng,
	               const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
	               float randu, float randv,
	               Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
	               float &pdf, Color3 &eval) const
	{
		// we are viewing the surface from the right side - send a ray out with cosine
		// distribution over the hemisphere
		sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
		if (Ng.dot(omega_in) > 0) {
			// TODO: account for sheen when sampling
			float cosNO = m_N.dot(omega_out);
			float sinNO2 = 1 - cosNO * cosNO;
			float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0;
			eval.setValue(westin, westin, westin);
			// TODO: find a better approximation for the diffuse bounce
			domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
			domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
			domega_in_dx *= 125;
			domega_in_dy *= 125;
		}
		else {
			pdf = 0;
		}
		return Labels::REFLECT;
	}
Exemplo n.º 2
0
    ustring sample (const Vec3 &Ng,
                 const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
                 float randu, float randv,
                 Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
                 float &pdf, Color3 &eval) const
    {
        Vec3 R, dRdx, dRdy;
        Vec3 T, dTdx, dTdy;
        bool inside;

        fresnel_dielectric(m_eta, m_N,
                           omega_out, domega_out_dx, domega_out_dy,
                           R, dRdx, dRdy,
                           T, dTdx, dTdy,
                           inside);

        if (!inside) {
            pdf = 1;
            eval.setValue(1.0f, 1.0f, 1.0f);
            omega_in = T;
            domega_in_dx = dTdx;
            domega_in_dy = dTdy;
        }

        return Labels::TRANSMIT;
    }
Exemplo n.º 3
0
 ustring sample (const Vec3 &Ng,
              const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
              float randu, float randv,
              Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
              float &pdf, Color3 &eval) const
 {
     // we are viewing the surface from the right side - send a ray out with cosine
     // distribution over the hemisphere
     sample_cos_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
     if (Ng.dot(omega_in) > 0) {
         eval.setValue(pdf, pdf, pdf);
         // TODO: find a better approximation for the diffuse bounce
         domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
         domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
         domega_in_dx *= 125;
         domega_in_dy *= 125;
     } else
         pdf = 0;
     return Labels::REFLECT;
 }
Exemplo n.º 4
0
	ustring sample(const Vec3 &Ng,
	               const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
	               float randu, float randv,
	               Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
	               float &pdf, Color3 &eval) const
	{
		float cosNO = m_N.dot(omega_out);
		if (cosNO > 0) {
			domega_in_dx = domega_out_dx;
			domega_in_dy = domega_out_dy;
			Vec3 T, B;
			make_orthonormals(omega_out, T, B);
			float phi = 2 * (float) M_PI * randu;
			float cosTheta = powf(randv, 1 / (m_invroughness + 1));
			float sinTheta2 = 1 - cosTheta * cosTheta;
			float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
			omega_in = (cosf(phi) * sinTheta) * T +
			           (sinf(phi) * sinTheta) * B +
			           (cosTheta) * omega_out;
			if (Ng.dot(omega_in) > 0)
			{
				// common terms for pdf and eval
				float cosNI = m_N.dot(omega_in);
				// make sure the direction we chose is still in the right hemisphere
				if (cosNI > 0)
				{
					pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness);
					pdf = (m_invroughness + 1) * pdf;
					eval.setValue(pdf, pdf, pdf);
					// Since there is some blur to this reflection, make the
					// derivatives a bit bigger. In theory this varies with the
					// exponent but the exact relationship is complex and
					// requires more ops than are practical.
					domega_in_dx *= 10;
					domega_in_dy *= 10;
				}
			}
		}
		return Labels::REFLECT;
	}
Exemplo n.º 5
0
	ustring sample(const Vec3 &Ng,
	               const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
	               float randu, float randv,
	               Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
	               float &pdf, Color3 &eval) const
	{
		float cosNO = m_N.dot(omega_out);
		if (cosNO > 0) {
			Vec3 X, Y, Z = m_N;
			make_orthonormals(Z, X, Y);
			// generate a random microfacet normal m
			// eq. 35,36:
			// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
			//                  and sin(atan(x)) == x/sqrt(1+x^2)
			float alpha2 = m_ab * m_ab;
			float tanThetaM = sqrtf(-alpha2 * logf(1 - randu));
			float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM);
			float sinThetaM = cosThetaM * tanThetaM;
			float phiM = 2 * float(M_PI) * randv;
			Vec3 m = (cosf(phiM) * sinThetaM) * X +
			         (sinf(phiM) * sinThetaM) * Y +
			         cosThetaM  * Z;
			if (Refractive == 0) {
				float cosMO = m.dot(omega_out);
				if (cosMO > 0) {
					// eq. 39 - compute actual reflected direction
					omega_in = 2 * cosMO * m - omega_out;
					if (Ng.dot(omega_in) > 0) {
						// microfacet normal is visible to this ray
						// eq. 25
						float cosThetaM2 = cosThetaM * cosThetaM;
						float tanThetaM2 = tanThetaM * tanThetaM;
						float cosThetaM4 = cosThetaM2 * cosThetaM2;
						float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 *  cosThetaM4);
						// eq. 24
						float pm = D * cosThetaM;
						// convert into pdf of the sampled direction
						// eq. 38 - but see also:
						// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
						pdf = pm * 0.25f / cosMO;
						// Eval BRDF*cosNI
						float cosNI = m_N.dot(omega_in);
						// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
						float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
						float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
						float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
						float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
						float G = G1o * G1i;
						// eq. 20: (F*G*D)/(4*in*on)
						float out = (G * D) * 0.25f / cosNO;
						eval.setValue(out, out, out);
						domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx;
						domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy;

						/* disabled for now - gives texture filtering problems */
#if 0
						// Since there is some blur to this reflection, make the
						// derivatives a bit bigger. In theory this varies with the
						// roughness but the exact relationship is complex and
						// requires more ops than are practical.
						domega_in_dx *= 10;
						domega_in_dy *= 10;
#endif
					}
				}
			}
			else {
				// CAUTION: the i and o variables are inverted relative to the paper
				// eq. 39 - compute actual refractive direction
				Vec3 R, dRdx, dRdy;
				Vec3 T, dTdx, dTdy;
				bool inside;
				fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
				                   R, dRdx, dRdy,
				                   T, dTdx, dTdy,
				                   inside);
				if (!inside) {
					omega_in = T;
					domega_in_dx = dTdx;
					domega_in_dy = dTdy;
					// eq. 33
					float cosThetaM2 = cosThetaM * cosThetaM;
					float tanThetaM2 = tanThetaM * tanThetaM;
					float cosThetaM4 = cosThetaM2 * cosThetaM2;
					float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 *  cosThetaM4);
					// eq. 24
					float pm = D * cosThetaM;
					// eval BRDF*cosNI
					float cosNI = m_N.dot(omega_in);
					// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
					float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
					float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
					float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
					float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
					float G = G1o * G1i;
					// eq. 21
					float cosHI = m.dot(omega_in);
					float cosHO = m.dot(omega_out);
					float Ht2 = m_eta * cosHI + cosHO;
					Ht2 *= Ht2;
					float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
					// eq. 38 and eq. 17
					pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
					eval.setValue(out, out, out);

					/* disabled for now - gives texture filtering problems */
#if 0
					// Since there is some blur to this refraction, make the
					// derivatives a bit bigger. In theory this varies with the
					// roughness but the exact relationship is complex and
					// requires more ops than are practical.
					domega_in_dx *= 10;
					domega_in_dy *= 10;
#endif
				}
			}
		}
		return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
	}