void CAngularSpectralProperties::calculateAngularProperties(
      std::shared_ptr<CSpectralSample> const & t_SpectralSample, MaterialType const t_Type)
    {
        assert(t_SpectralSample != nullptr);

        auto aMeasuredData = t_SpectralSample->getMeasuredData();

        if(m_Angle != 0)
        {
            auto aSourceData = t_SpectralSample->getSourceData();

            auto aWavelengths = aMeasuredData->getWavelengths();
            auto aT = aMeasuredData->properties(SampleData::T);
            assert(aT->size() == aWavelengths.size());

            auto aRf = aMeasuredData->properties(SampleData::Rf);
            assert(aRf->size() == aWavelengths.size());

            auto aRb = aMeasuredData->properties(SampleData::Rb);
            assert(aRb->size() == aWavelengths.size());

            auto lowLambda = 0.3;
            auto highLambda = 2.5;

            // TODO: Only one side is measured and it is considered that front properties are equal
            // to back properties
            auto aTSolNorm =
              t_SpectralSample->getProperty(lowLambda, highLambda, Property::T, Side::Front);

            for(size_t i = 0; i < aWavelengths.size(); ++i)
            {
                auto ww = aWavelengths[i] * 1e-6;
                auto T = (*aT)[i].value();
                auto Rf = (*aRf)[i].value();
                auto Rb = (*aRb)[i].value();

                auto aSurfaceType = coatingType.at(t_Type);

                auto aFrontFactory = CAngularPropertiesFactory(T, Rf, m_Thickness, aTSolNorm);
                auto aBackFactory = CAngularPropertiesFactory(T, Rb, m_Thickness, aTSolNorm);

                auto aFrontProperties = aFrontFactory.getAngularProperties(aSurfaceType);
                auto aBackProperties = aBackFactory.getAngularProperties(aSurfaceType);

                auto Tangle = aFrontProperties->transmittance(m_Angle, ww);
                auto Rfangle = aFrontProperties->reflectance(m_Angle, ww);
                auto Rbangle = aBackProperties->reflectance(m_Angle, ww);

                m_AngularData->addRecord(ww * 1e6, Tangle, Rfangle, Rbangle);
            }
        }
        else
        {
            m_AngularData = aMeasuredData;
        }
    }
Example #2
0
bool Tracer::scatterRefractive(const IntersectDescr& node, Ray& ray) const
{
	// here we throw the dice to dices whether to reflect or to refract
	const double probability = ::uniform_distrib_( ::rand_gen_ );

	// heuristic to determine material transition
	// note, this assumes that only one type of refractive material exists AND
	// that two objects do not intersect, such that an interface within a
	// non-air material exists (well, its not that strict, but simpler to
	// explain this way)
	const double surface_dot = node.normal_.dot( node.incident_ );
	const bool is_entry = ( surface_dot <= 0. );
	// 1.52 is for crown glass
	const double refractive_idx_from = is_entry ? 1.0 : 1.52;
	const double refractive_idx_to = is_entry ? 1.52 : 1.0;

	// The reflectance and refract functions require the normal to point into
	// the direction of the first material. If this is not the case, we invert
	// its direction.
	const Vector corrected_normal = is_entry ? node.normal_ : -1. * node.normal_;
		
	const double reflect = reflectance(
		corrected_normal, node.incident_, refractive_idx_from, refractive_idx_to );

	if( probability <= reflect )
	{
		return scatterSpecular( node, ray );
	}
	else
	{
		Vector refracted_dir = refract( corrected_normal,
										node.incident_,
										refractive_idx_from,
										refractive_idx_to );

		if( refracted_dir.length() > 1e-4 )
		{
			ray = Ray{ node.point_, refracted_dir.normalized() };
			return true;
		}
		else
		{
			return false;
		}
	}

	return false; // should never get here, though
}
Example #3
0
a3Spectrum a3Dieletric::sample(const t3Vector3f& wi, t3Vector3f& wo, float* pdf, const a3Intersection& its) const
{
    static a3Random random;

    t3Vector3f n = its.getNormal();

    // 入射光 / 出射光所在折射率
    float etai = 1.0f, etat = its.shape->refractiveIndex;

    // 光密到光疏
    if(wi.dot(n) > 0)
    {
        t3Math::swap(etai, etat);
        // 翻转法线 保持与入射光线一个平面
        n = -n;
    }

    float eta = etai / etat;

    // 菲涅尔反射(反射的概率)
    //float Fr = a3FresnelDielectric(costhetai, costhetat, etai, etat);
    float Fr = reflectance(n, wi, etai, etat);
    //float P = 0.25 + 0.5 * Fr;

    float r = random.randomFloat();
    if(r > Fr)
    {
        bool TIR = false;
        wo = refract(n, wi, etai, etat, TIR);

        *pdf = 1.0f;

        eta = 1 / eta;
        return getColor(its) * specularTransmittance / t3Math::Abs(wo.dot(n));
    }
    else
    {
        wo = reflect(n, wi);

        *pdf = 1.0f;

        // 镜面反射
        return getColor(its) * specularReflectance / t3Math::Abs(wo.dot(n));
    }
}