Пример #1
0
/**
*  @brief
*    Get index of color
*/
int ImagePalette::GetColorIndex(const Color3 &cColor) const
{
	// Do we need to build the color index?
	if (m_mapColors.GetNumOfElements() == 0) {
		// Build color index
		for (uint32 i=0; i<m_nColors; i++) {
			// Map color to index
			const uint32 nColorInt = cColor.ToUInt32();
			m_mapColors.Add(nColorInt, i);
		}
	}

	// Look up color index
	const uint32 nColorInt = cColor.ToUInt32();
	int nIndex = m_mapColors.Get(nColorInt);

	// If nIndex is 0, it can be either invalid or really index 0, so check if the colors are equal
	if (nIndex == 0) {
		// Check if color is valid
		const Color3 cColorLookup = GetColor(0);
		if (cColorLookup != cColor || cColorLookup == Color3::Null) {
			// Invalid index
			nIndex = -1;
		}
	}

	// Return color index
	return nIndex;
}
/**
*  @brief
*    Called when the scene node modifier needs to be updated
*/
void SNMLightRandomAnimation::OnUpdate()
{
	// Update timer
	m_fTimer += Timing::GetInstance()->GetTimeDifference()*Speed;

	// Set current scene node scale
	SNLight &cLight = static_cast<SNLight&>(GetSceneNode());

	// Animate color
		  Color3 cColor  = cLight.Color.Get();
	const Color3 cColorT = Color.Get()*((Math::Cos(m_fTimer)+1)/2)*Radius;
	if (GetFlags() & Multiply) {
		// Red
		cColor.r = (GetFlags() & NR) ? FixColor.Get().r : FixColor.Get().r*cColorT.r;
		// Green
		cColor.g = (GetFlags() & NG) ? FixColor.Get().g : FixColor.Get().g*cColorT.g;
		// Blue
		cColor.b = (GetFlags() & NB) ? FixColor.Get().b : FixColor.Get().b*cColorT.b;
	} else {
		// Red
		cColor.r = (GetFlags() & NR) ? FixColor.Get().r : FixColor.Get().r+cColorT.r;
		// Green
		cColor.g = (GetFlags() & NG) ? FixColor.Get().g : FixColor.Get().g+cColorT.g;
		// Blue
		cColor.b = (GetFlags() & NB) ? FixColor.Get().b : FixColor.Get().b+cColorT.b;
	}

	// Clamp the color values between 0.0 and 1.0
	cColor.Saturate();

	// Finally, set the new color of the light
	cLight.Color.Set(cColor);
}
Пример #3
0
static Color3 finalGathering(KdTree<Photon> *map , Scene& scene , 
							 Intersection& inter , RNG& rng , const Vector3& wo ,
                             int gatherSamples , int knn , Real maxSqrDis)
{
    Color3 res = Color3(0.0 , 0.0 , 0.0);
    for (int i = 0; i < gatherSamples; i++)
    {
		Real pdf;
        Vector3 wi = sampleCosHemisphere(rng.randVector3() , &pdf);
        Ray ray = Ray(inter.p + wi * EPS , wi);

        Intersection _inter;
        
        Geometry *_g = scene.intersect(ray , _inter);

        if (_g == NULL)
            continue;
        
        Color3 tmp = estimate(map , 0 , knn , scene , _inter , -wi , maxSqrDis);

		BSDF bsdf(wi , _inter , scene);
		Real cosine , bsdfPdf;
        Color3 brdf = bsdf.f(scene , wo , cosine , &bsdfPdf);
		if (brdf.isBlack())
			continue;
		pdf *= bsdfPdf;
        res = res + (tmp | brdf) * (cosine / pdf);
    }
    res = res / gatherSamples;
    return res;
}
Color3 BidirPathTracing::getLightRadiance(AbstractLight *light , 
	BidirPathState& cameraState , const Vector3& hitPos , 
	const Vector3& rayDir)
{
	int lightCount = scene.lights.size();
	Real lightPickProb = 1.f / lightCount;

	Real directPdfArea , emissionPdf;
	Color3 radiance = light->getRadiance(scene.sceneSphere ,
		rayDir , hitPos , &directPdfArea , &emissionPdf);

	Color3 res(0);

	if (radiance.isBlack())
		return res;

	if (cameraState.pathLength == 1)
		return radiance;

	directPdfArea *= lightPickProb;
	emissionPdf *= lightPickProb;

 	Real wCamera = mis(directPdfArea) * cameraState.dVCM + 
 		mis(emissionPdf) * cameraState.dVC;

	Real weight = 1.f / (1.f + wCamera);

	return radiance * weight;
}
Пример #5
0
Color3 getDiffuse(const Vector3& lightDir , const Vector3& normal , 
	const Color3& lightIntensity , const Color3& diffuse)
{
	Real coe = std::max(0.0 , lightDir ^ normal);
	Color3 res = (lightIntensity | diffuse) * coe;
	res.clamp();
	return res;
}
Пример #6
0
Color3 getSpecular(const Vector3& reflecDir , const Vector3& visionDir , 
	const Color3& lightIntensity , const Color3& specular)
{
	Real coe = std::max(0.0 , reflecDir ^ visionDir);
	coe = pow(coe , specularCoefficient);
	Color3 res = (lightIntensity | specular) * coe;
	res.clamp();
	return res;
}
Color3 BidirPathTracing::connectToCamera(BidirPathState& lightState , 
	const Vector3& hitPos , BSDF& bsdf)
{
	Color3 res(0);

	Camera& camera = scene.camera;
	Vector3 dirToCamera = camera.pos - hitPos;

	if (((-dirToCamera) ^ camera.forward) <= 0)
		return res;

	Real distEye2 = dirToCamera.sqrLength();
	Real dist = std::sqrt(distEye2);
	dirToCamera = dirToCamera / dist;

	Real cosToCamera , bsdfDirPdf , bsdfRevPdf;

	Color3 bsdfFactor = bsdf.f(scene , dirToCamera , cosToCamera ,
		&bsdfDirPdf , &bsdfRevPdf);

	if (bsdfFactor.isBlack())
		return res;

	bsdfRevPdf *= bsdf.continueProb;

	Real cosAtCamera = ((-dirToCamera) ^ camera.forward);
	Real imagePointToCameraDist = camera.imagePlaneDist / cosAtCamera;
	Real imageToSolidAngleFactor = SQR(imagePointToCameraDist) / cosAtCamera;
	Real imageToSurfaceFactor = imageToSolidAngleFactor * std::abs(cosToCamera) / distEye2;

	Real cameraPdfA = imageToSurfaceFactor /* * 1.f */; // pixel area is 1
	
	Real surfaceToImageFactor = 1.f / imageToSurfaceFactor;

	// We divide the contribution by surfaceToImageFactor to convert the (already
	// divided) pdf from surface area to image plane area, w.r.t. which the
	// pixel integral is actually defined. We also divide by the number of samples
	// this technique makes
	res = (lightState.throughput | bsdfFactor) /
		(lightPathNum * surfaceToImageFactor);
    
    if (res.isBlack())
		return res;

	if (scene.occluded(hitPos , dirToCamera , camera.pos))
		return Color3(0);

	Real wLight = mis(cameraPdfA / lightPathNum) * (lightState.dVCM + 
		mis(bsdfRevPdf) * lightState.dVC);

	Real weight = 1.f / (wLight + 1.f);

	//fprintf(fp , "weight = %.6f\n" , weight);

	return res * weight;
}
// we force to connect eye path to light path 
Color3 BidirPathTracing::connectVertices(BidirPathState& lightState , 
	BSDF& cameraBsdf , const Vector3& hitPos , 
	BidirPathState& cameraState)
{
	Vector3 dir = lightState.pos - hitPos;
	Real dist2 = dir.sqrLength();
	Real dist = std::sqrt(dist2);
	dir = dir / dist;

	Color3 res(0);

	Real cosAtCamera , cameraBsdfDirPdf , cameraBsdfRevPdf;
	Color3 cameraBsdfFactor = cameraBsdf.f(scene , dir , cosAtCamera ,
		&cameraBsdfDirPdf , &cameraBsdfRevPdf);

	if (cameraBsdfFactor.isBlack())
		return res;

	Real cameraContProb = cameraBsdf.continueProb;
	cameraBsdfDirPdf *= cameraContProb;
	cameraBsdfRevPdf *= cameraContProb;

	Real cosAtLight , lightBsdfDirPdf , lightBsdfRevPdf;
	Color3 lightBsdfFactor = lightState.bsdf.f(scene , -dir , cosAtLight ,
		&lightBsdfDirPdf , &lightBsdfRevPdf);

	if (lightBsdfFactor.isBlack())
		return res;

	Real lightContProb = lightState.bsdf.continueProb;
	lightBsdfDirPdf *= lightContProb;
	lightBsdfRevPdf *= lightContProb;

	Real geometryTerm = cosAtLight * cosAtCamera / dist2;

	if (cmp(geometryTerm) < 0)
		return res;

	Real cameraBsdfDirPdfArea = pdfWtoA(cameraBsdfDirPdf , dist , cosAtLight);
	Real lightBsdfDirPdfArea = pdfWtoA(lightBsdfDirPdf , dist , cosAtCamera);

	res = (cameraBsdfFactor | lightBsdfFactor) * geometryTerm;

	if (res.isBlack() || scene.occluded(hitPos , dir , 
		hitPos + dir * dist))
		return Color3(0);

	Real wLight = mis(cameraBsdfDirPdfArea) * 
		(lightState.dVCM + mis(lightBsdfRevPdf) * lightState.dVC);
	Real wCamera = mis(lightBsdfDirPdfArea) *
		(cameraState.dVCM + mis(cameraBsdfRevPdf) * cameraState.dVC);
	Real weight = 1.f / (wLight + 1.f + wCamera);

	return res * weight;
}
Пример #9
0
float Surfel::ExpressiveParameters::boost(const Color3& diffuseReflectivity) const {
    // Avoid computing the HSV transform in the common case
    if (unsaturatedMaterialBoost == saturatedMaterialBoost) {
        return unsaturatedMaterialBoost;
    }

    const float m = diffuseReflectivity.max();
    const float saturation = (m == 0.0f) ? 0.0f : ((m - diffuseReflectivity.min()) / m);

    return lerp(unsaturatedMaterialBoost, saturatedMaterialBoost, saturation);
}
Пример #10
0
/**
 * Raytraces some portion of the scene. Should raytrace for about
 * max_time duration and then return, even if the raytrace is not copmlete.
 * The results should be placed in the given buffer.
 * @param buffer The buffer into which to place the color data. It is
 *  32-bit RGBA (4 bytes per pixel), in row-major order.
 * @param max_time, If non-null, the maximum suggested time this
 *  function raytrace before returning, in seconds. If null, the raytrace
 *  should run to completion.
 * @return true if the raytrace is complete, false if there is more
 *  work to be done.
 */
bool Raytracer::raytrace( unsigned char *buffer, real_t* max_time )
{
    // TODO Add any modifications to this algorithm, if needed.

    static long start_time; // used to show how long time ray tracing cost
    if (0 == current_row)
        start_time = clock();

    static const size_t PRINT_INTERVAL = 64;

    // the time in milliseconds that we should stop
    unsigned int end_time = 0;
    bool is_done = false;

    if ( max_time ) {
        // convert duration to milliseconds
        unsigned int duration = (unsigned int) ( *max_time * 1000 );
        end_time = SDL_GetTicks() + duration;
    }

    // until time is up, run the raytrace. we render an entire row at once
    // for simplicity and efficiency.
    for ( ; !max_time || end_time > SDL_GetTicks(); ++current_row ) {

        if ( current_row % PRINT_INTERVAL == 0 ) {
            printf( "Raytracing (row %u)...\n", current_row );
        }

        // we're done if we finish the last row
        is_done = current_row == height;
        // break if we finish
        if ( is_done )
            break;

        for ( size_t x = 0; x < width; ++x ) {
            // trace a pixel
            Color3 color = trace_pixel( scene, x, current_row, width, height );
            // write the result to the buffer, always use 1.0 as the alpha
            color.to_array( &buffer[4 * ( current_row * width + x )] );
        }
    }

    if ( is_done ) {
        printf( "Done raytracing!\n" );
        printf( "Used %d milliseconds.\n", clock()-start_time );
    }


    return is_done;
}
Пример #11
0
void PS3GCMCGEffect::setUniform(const Color3& uniformData, const char* uniformName) const {
  {
    CGparameter parameter = cellGcmCgGetNamedParameter(vertexProgram_, uniformName);
    if (parameter) {
      cellGcmSetVertexProgramParameter(parameter, uniformData.valuePtr());
    }
  }
  {
    CGparameter parameter = cellGcmCgGetNamedParameter(fragmentProgram_, uniformName);
    if (parameter) {
      cellGcmSetFragmentProgramParameter(fragmentProgram_, parameter, uniformData.valuePtr(), fragmentProgramOffset_);
    }
  }
}
Пример #12
0
bool Raytracer::scatter(const SurfaceSample& s, Photon* p) const
{
	bool scatter = false;
	float t = _random.uniform(0, 1);

	// Check Impulses
	SuperBSDF::Ref bsdf = s.material->bsdf();
	SmallArray<SuperBSDF::Impulse, 3> impulseArray;
	bsdf->getImpulses(s.shadingNormal, s.texCoord, p->direction, impulseArray); // todo: check p.direction

	Color3 impulseSum;

	for (int i = 0; i < impulseArray.size(); ++i)
	{
		if (impulseArray[i].coefficient.average() < 0)
		{
			int sures = 234;
		}
		
		//t -= impulseArray[i].coefficient.average();
		impulseSum += impulseArray[i].coefficient;

		if (t - impulseArray[i].coefficient.average() < 0)
		{
			scatter = true;
			p->direction = impulseArray[i].w;
			p->power = p->power * t / impulseArray[i].coefficient.average();
			check(p->power.average());
			break;
		}
	}

	// Check Diffuse
	if (!scatter)
	{
		const Component4 lambertian = bsdf->lambertian();
		//t - (s.lambertianReflect * (1 - impulseSum.average())).average();

		if (t - (s.lambertianReflect * (1 - impulseSum.average())).average() < 0)
		{
			scatter = true;
			p->direction = Vector3::cosHemiRandom(s.shadingNormal);
			//p->power = p->power * (t / (s.lambertianReflect * (1 - impulseSum.average())).average());
			p->power = p->power * (t / (s.lambertianReflect.average()));// * (1 - impulseSum.average())).average());
			check(p->power.average());
		}
	}

	return scatter;
}
Пример #13
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;
    }
Пример #14
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;
	}
Пример #15
0
/**
*  @brief
*    Set color
*/
void ImagePalette::SetColor(uint32 nIndex, const Color3 &cColor)
{
	// Do we have to resize the palette?
	if (nIndex >= m_nColors)
		Resize(nIndex);

	// Set color
	if (m_pData) {
		m_pData[nIndex*3+0] = cColor.GetRInt();
		m_pData[nIndex*3+1] = cColor.GetGInt();
		m_pData[nIndex*3+2] = cColor.GetBInt();
	}

	// Rebuild color index
	RebuildColorIndex();
}
Пример #16
0
    Material::Ref createMaterial(const ArticulatedModel::Preprocess& preprocess) const {
        debugPrintf("Creating material %s...", name.c_str());
        Material::Specification spec;

        if ((diffuseMap != "") && ! preprocess.stripMaterials) {
            Texture::Specification s;
            s.dimension = Texture::DIM_2D_NPOT;

            // If we turn this off, the BSDF just does it anyway
            s.preprocess.computeMinMaxMean = true;
            s.settings.maxAnisotropy = 2.0f;
            s.filename = diffuseMap;
            spec.setLambertian(s);

        } else {
            spec.setLambertian(diffuseConstant);
        }

        // Assume in air
        spec.setEta(max(1.0f, eta), 1.0f);

        // OBJ models are way too specular and not shiny enough
        spec.setSpecular(specularConstant.pow(9.0f) * 0.4f);
        spec.setGlossyExponentShininess(shininess * 100.0f);

        // spec.setBump(bumpMap);

        Material::Ref m = Material::create(spec);
        debugPrintf("Done\n");
        return m;
    }
bool BidirPathTracing::sampleScattering(BSDF& bsdf , 
	const Vector3& hitPos , BidirPathState& pathState)
{
	Real bsdfDirPdf , cosWo;
	int sampledBSDFType;
	Color3 bsdfFactor = bsdf.sample(scene , rng.randVector3() ,
		pathState.dir , bsdfDirPdf , cosWo , &sampledBSDFType);

	if (bsdfFactor.isBlack())
		return 0;

	Real bsdfRevPdf = bsdfDirPdf;
	if ((sampledBSDFType & BSDF_SPECULAR) == 0)
		bsdfRevPdf = bsdf.pdf(scene , pathState.dir , 1);

	Real contProb = bsdf.continueProb;
	if (rng.randFloat() > contProb)
		return 0;

	bsdfDirPdf *= contProb;
	bsdfRevPdf *= contProb;

	// Partial sub-path MIS quantities
	// the evaluation is completed when the actual hit point is known!
	// i.e. after tracing the ray, out of the procedure
	if (sampledBSDFType & BSDF_SPECULAR)
	{
		pathState.specularVertexNum++;

		pathState.dVCM = 0.f;
		pathState.dVC *= mis(cosWo);
	}
	else
	{
		pathState.specularPath &= 0;

		pathState.dVC = mis(1.f / bsdfDirPdf) * (pathState.dVCM +
			pathState.dVC * mis(bsdfRevPdf));
		pathState.dVCM = mis(1.f / bsdfDirPdf);
	}

	pathState.origin = hitPos;
	pathState.throughput = (pathState.throughput | bsdfFactor) *
		(cosWo / bsdfDirPdf);

	return 1;
}
Пример #18
0
void Raytracer::trace_packet(PacketRegion region, float refractive, unsigned char *buffer)
{
    Int2 ll = region.ll;
    Int2 lr = region.lr;
    Int2 ul = region.ul;
    Int2 ur = region.ur;

    IsectInfo infos[rays_per_packet];
    bool intersected[rays_per_packet];
    Packet packet;
    get_viewing_frustum(ll, lr, ul, ur, packet.frustum);
    Vector3 eye = scene->camera.get_position();
    Int2 pixels[rays_per_packet];
    int r = 0; // counter for rays in packet

    for (int y = ll.y; y <= ul.y; y++)
    {
        for (int x = ll.x; x <= lr.x; x++)
        {
            Int2 pixel(x, y);
            packet.rays[r].eye = eye;
            packet.rays[r].dir = get_viewing_ray(pixel);
            pixels[r] = pixel;
            intersected[r] = false;
            r++;
        }
    }

    for (size_t i = 0; i < scene->num_geometries(); i++)
    {
        scene->get_geometries()[i]->intersect_packet(packet, infos, intersected);
    }

    for (int i = 0; i < rays_per_packet; i++)
    {
        if (intersected[i])
        {
            Color3 color = trace_pixel_end(0, packet.rays[i], refractive, infos[i]);
            color.to_array(&buffer[4 * (pixels[i].y * width + pixels[i].x)]);
        }
        else
        {
            Color3 color = scene->background_color;
            color.to_array(&buffer[4 * (pixels[i].y * width + pixels[i].x)]);
        }
    }
}
Пример #19
0
Color3 getPhong(const Vector3& p , const Vector3& visionDir ,
	const Vector3& normal , const Vector3& lightSourcePos ,
	const Color3& lightIntensity , Geometry* obj , const Real& directCoe)
{
	Vector3 lightDir = lightSourcePos - p;
	lightDir.normalize();
	Vector3 reflecDir = normal * ((normal ^ lightDir) * 2.0) - lightDir;
	reflecDir.normalize();
	Color3 diffuseIntensity = getDiffuse(lightDir , normal , 
		lightIntensity , obj->get_diffuse_color(p));
	Color3 specularIntensity = getSpecular(reflecDir , visionDir , 
		lightIntensity , obj->get_material().specular);
	Color3 ambientIntensity = getAmbient(lightIntensity , obj->get_material().ambient);
	Color3 res = (diffuseIntensity + specularIntensity) * directCoe + ambientIntensity;
	res.clamp();
	return res;
}
Пример #20
0
/**
* @brief get material property to be added to the mesh
*/
Niflib::NiPropertyRef getMatProp(){
	using namespace Niflib;

	NiMaterialPropertyRef matPropRef = new NiMaterialProperty;
	matPropRef->SetName("01 - Default");

	//set base nif colours
	Color3 colour;
	colour.Set(0.588, 0.588, 0.588);
	matPropRef->SetAmbientColor(colour);
	matPropRef->SetDiffuseColor(colour);

	colour.Set(0.9, 0.9, 0.9);
	matPropRef->SetSpecularColor(colour);

	colour.Set(0, 0, 0);
	matPropRef->SetEmissiveColor(colour);

	return DynamicCast<NiProperty>(  matPropRef );
}
Пример #21
0
bool
ShadingSystemImpl::set_colorspace (ustring colorspace)
{
    for (int i = 0;  colorSystems[i].name;  ++i) {
        if (colorspace == colorSystems[i].name) {
            m_Red.setValue (colorSystems[i].xRed, colorSystems[i].yRed, 0.0f);
            m_Green.setValue (colorSystems[i].xGreen, colorSystems[i].yGreen, 0.0f);
            m_Blue.setValue (colorSystems[i].xBlue, colorSystems[i].yBlue, 0.0f);
            m_White.setValue (colorSystems[i].xWhite, colorSystems[i].yWhite, 0.0f);
            // set z values to normalize
            m_Red[2]   = 1.0f - (m_Red[0]   + m_Red[1]);
            m_Green[2] = 1.0f - (m_Green[0] + m_Green[1]);
            m_Blue[2]  = 1.0f - (m_Blue[0]  + m_Blue[1]);
            m_White[2] = 1.0f - (m_White[0] + m_White[1]);

            const Color3 &R(m_Red), &G(m_Green), &B(m_Blue), &W(m_White);
            // xyz -> rgb matrix, before scaling to white.
            Color3 r (G[1]*B[2] - B[1]*G[2], B[0]*G[2] - G[0]*B[2], G[0]*B[1] - B[0]*G[1]);
            Color3 g (B[1]*R[2] - R[1]*B[2], R[0]*B[2] - B[0]*R[2], B[0]*R[1] - R[0]*B[1]);
            Color3 b (R[1]*G[2] - G[1]*R[2], G[0]*R[2] - R[0]*G[2], R[0]*G[1] - G[0]*R[1]);
            Color3 w (r.dot(W), g.dot(W), b.dot(W));  // White scaling factor
            if (W[1] != 0.0f)  // divide by W[1] to scale luminance to 1.0
                w *= 1.0f/W[1];
            // xyz -> rgb matrix, correctly scaled to white.
            r /= w[0];
            g /= w[1];
            b /= w[2];
            m_XYZ2RGB = Matrix33 (r[0], g[0], b[0],
                                  r[1], g[1], b[1],
                                  r[2], g[2], b[2]);
            m_RGB2XYZ = m_XYZ2RGB.inverse();
            m_luminance_scale = Color3 (m_RGB2XYZ[0][1], m_RGB2XYZ[1][1], m_RGB2XYZ[2][1]);

            // Precompute a table of blackbody values
            m_blackbody_table.clear ();
            float lastT = 0;
            for (int i = 0;  lastT <= BB_MAX_TABLE_RANGE;  ++i) {
                float T = powf (float(i), BB_TABLE_XPOWER) * BB_TABLE_SPACING + BB_DRAPER;
                lastT = T;
                bb_spectrum spec (T);
                Color3 rgb = XYZ_to_RGB (spectrum_to_XYZ (spec));
                clamp_zero (rgb);
                rgb = colpow (rgb, 1.0f/BB_TABLE_YPOWER);
                m_blackbody_table.push_back (rgb);
                // std::cout << "Table[" << i << "; T=" << T << "] = " << rgb << "\n";
            }
            // std::cout << "Made " << m_blackbody_table.size() << " table entries for blackbody\n";

#if 0
            // Sanity checks
            std::cout << "m_XYZ2RGB = " << m_XYZ2RGB << "\n";
            std::cout << "m_RGB2XYZ = " << m_RGB2XYZ << "\n";
            std::cout << "m_luminance_scale = " << m_luminance_scale << "\n";
#endif
            return true;
        }
    }
    return false;
}
Пример #22
0
//  Raytraces some portion of the scene
bool Raytracer::raytrace( unsigned char *buffer, real_t* max_time )
{
    static const size_t PRINT_INTERVAL = 64;

    unsigned int end_time = 0;
    bool is_done;

    if ( max_time ) {
        // convert duration to milliseconds
        unsigned int duration = (unsigned int) ( *max_time * 1000 );
        end_time = SDL_GetTicks() + duration;
    }

    // until time is up, run the raytrace. we render an entire row at once
    for ( ; !max_time || end_time > SDL_GetTicks(); ++current_row ) {

        if ( current_row % PRINT_INTERVAL == 0 ) {
            printf( "Raytracing (row %u)...\n", current_row );
        }

        // we're done if we finish the last row
        is_done = current_row == height;
        if ( is_done )
            break;

        for ( size_t x = 0; x < width; ++x ) {
            // trace a pixel
            Color3 color = trace_pixel( scene, x, current_row, width, height );
            color.to_array( &buffer[4 * ( current_row * width + x )] );
        }
    }

    if ( is_done ) {
        printf( "Done raytracing!\n" );
    }

    return is_done;
}
Пример #23
0
static Color3 directIllumination(Scene& scene , Intersection& inter ,
                           RNG& rng , const Vector3& visionDir)
{
    Color3 res = Color3(0.0 , 0.0 , 0.0);
    Vector3 lightDir;
    Real cosine;
    Color3 brdf;
    Ray ray;
    
	BSDF bsdf(visionDir , inter , scene);

	int N = 1;
    for (int i = 0; i < N; i++)
    {
        int k = rand() % scene.lights.size();
		AbstractLight *l = scene.lights[k];
		
		Vector3 dirToLight;
		Real dist , directPdf;

		Color3 illu = l->illuminance(scene.sceneSphere , inter.p , rng.randVector3() ,
			dirToLight , dist , directPdf);

		illu = illu / (directPdf / scene.lights.size());

        if (scene.occluded(inter.p + dirToLight * EPS , dirToLight ,
			inter.p + dirToLight * (inter.t - EPS)))
            continue;
        
		Real bsdfPdf;
        brdf = bsdf.f(scene , dirToLight , cosine , &bsdfPdf);
		if (brdf.isBlack())
			continue;
        res = res + (illu | brdf) * (cosine / bsdfPdf);
    }
    res = res / N;
    return res;
}
Radiance3 RayTracer::L_scatteredDirect(const shared_ptr<Surfel>& surfel, const Vector3& wo, Random& rnd) const {
    
    //Downcast to universalSurfel to allow getting lambertianReflectivity (Not used now)
    const shared_ptr<UniversalSurfel>& u = dynamic_pointer_cast<UniversalSurfel>(surfel);
    debugAssertM(notNull(u), "Encountered a Surfel that was not a UniversalSurfel");
    
    Radiance3 L(0,0,0);

    //For each light, compute the scatteredRadiance and sum them
    for (int i = 0; i < m_lighting->lightArray.size(); ++i){
        const shared_ptr<Light> light(m_lighting->lightArray[i]);
        Vector3 Y = light->position().xyz();
        Vector3 X = u->position;

        //Distance from light source to surface. Compute Birandiance using this.
        Vector3 distance = Y - X;
    
        //Computes stuff necessary for visibility function
        Vector3 wi = distance.direction();
        Vector3 n = u->shadingNormal;

        //Check visibility
        if ((wi.dot(n) > 0) && (wo.dot(n) > 0) && light->inFieldOfView(distance)){
            //Casting shadow ray from light source to surfel. To avoid intersecting the original surfel, bump the light a bit
            Color3 visibility = visiblePercentage(G3D::Ray(Y,-wi), light, distance.magnitude() - 0.1);
                //Add direct ilumination when visible, multiply biranciance by partial coverage
                if (!visibility.isZero()){
                    Biradiance3 Bi = light->bulbPower()/(4.0*G3D::pi()*square(distance.magnitude())); //Unit: W/m^2
                    L += Bi * (u->finiteScatteringDensity(wi,wo)/G3D::pi()) * abs(wi.dot(n)) * visibility;
                //Commented out, used when assuming Lambertian surface
                //L += Bi * (u->lambertianReflectivity/G3D::pi()) * abs(wi.dot(n));
            }
        }   
    }
    //Set the pixel values greater than one to one.
    return L.clamp(0,1);
}
Пример #25
0
void PrimitivesExample::drawEvent() {
    GL::defaultFramebuffer.clear(
        GL::FramebufferClear::Color|GL::FramebufferClear::Depth);

    _shader.setLightPosition({7.0f, 5.0f, 2.5f})
        .setLightColor(Color3{1.0f})
        .setDiffuseColor(_color)
        .setAmbientColor(Color3::fromHsv({_color.hue(), 1.0f, 0.3f}))
        .setTransformationMatrix(_transformation)
        .setNormalMatrix(_transformation.rotationScaling())
        .setProjectionMatrix(_projection);
    _mesh.draw(_shader);

    swapBuffers();
}
Пример #26
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;
 }
Пример #27
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;
	}
Пример #28
0
void PhotonIntegrator::buildPhotonMap(Scene& scene)
{
    if (scene.lights.size() <= 0)
        return;

    causticPhotons.clear();
    indirectPhotons.clear();
    
    bool causticDone = 0 , indirectDone = 0;
    int nShot = 0;

    bool specularPath;
    int nIntersections;
    Intersection inter;
    Real lightPickProb = 1.f / scene.lights.size();

    while (!causticDone || !indirectDone)
    {
        nShot++;

        /* generate initial photon ray */
        int k = (int)(rng.randFloat() * scene.lights.size());

		Vector3 lightPos , lightDir;
		Real emissionPdf , directPdfArea , cosAtLight;
		Color3 alpha;

		AbstractLight *l = scene.lights[k];
		alpha = l->emit(scene.sceneSphere , rng.randVector3() , rng.randVector3() ,
			lightPos , lightDir , emissionPdf , &directPdfArea ,
			&cosAtLight);

		alpha = alpha * cosAtLight / (emissionPdf * lightPickProb);
        
		Ray photonRay(lightPos , lightDir);

        if (!alpha.isBlack())
        {
            specularPath = 1;
            nIntersections = 0;
            Geometry *g = scene.intersect(photonRay , inter);
            while (g != NULL && inter.matId > 0)
            {
				BSDF bsdf(-photonRay.dir , inter , scene);

                nIntersections++;
                bool hasNonSpecular = (cmp(bsdf.componentProb.diffuseProb) > 0 ||
                                      cmp(bsdf.componentProb.glossyProb) > 0);
                if (hasNonSpecular)
                {
                    Photon photon(inter.p , -photonRay.dir , alpha);
                    if (specularPath && nIntersections > 1)
                    {
                        if (!causticDone)
                        {
                            causticPhotons.push_back(photon);
                            if (causticPhotons.size() == nCausticPhotons)
                            {
                                causticDone = 1;
                                nCausticPaths = nShot;
                                causticMap = new KdTree<Photon>(causticPhotons);
                            }
                        }
                    }
                    else
                    {
                        if (nIntersections > 1 && !indirectDone)
                        {
                            indirectPhotons.push_back(photon);
                            if (indirectPhotons.size() == nIndirectPhotons)
                            {
                                indirectDone = 1;
                                nIndirectPaths = nShot;
                                indirectMap = new KdTree<Photon>(indirectPhotons);
                            }
                        }
                    }
                }
                if (nIntersections > maxPathLength)
                    break;

                /* find new photon ray direction */
                /* handle specular reflection and transmission first */
				Real pdf , cosWo;
				int sampledType;

				Color3 bsdfFactor = bsdf.sample(scene , rng.randVector3() ,
					photonRay.dir , pdf , cosWo , &sampledType);

				if (bsdfFactor.isBlack())
					break;

				if (sampledType & BSDF_NON_SPECULAR)
					specularPath = 0;

				// Russian Roulette
				Real contProb = bsdf.continueProb;
				
				if (cmp(contProb - 1.f) < 0)
				{
					if (cmp(rng.randFloat() - contProb) > 0)
						break;
					pdf *= contProb;
				}

				alpha = (alpha | bsdfFactor) * (cosWo / pdf);

				photonRay.origin = inter.p + photonRay.dir * EPS;
				photonRay.tmin = 0.f; photonRay.tmax = INF;

                g = scene.intersect(photonRay , inter);
            }
        }
    }
}
Пример #29
0
Color3 PhotonIntegrator::raytracing(const Ray& ray , int dep)
{
    Color3 res = Color3(0.0 , 0.0 , 0.0);

    if (dep > 2)
        return res;

    Geometry *g = NULL;
	Intersection inter;
    Ray reflectRay , transRay;

    g = scene.intersect(ray , inter);

    if (g == NULL)
        return res;

	if (inter.matId < 0)
	{
		AbstractLight *l = scene.lights[-inter.matId - 1];
		return l->getIntensity() * 100.f;
	}
    
    res = res + directIllumination(scene , inter , rng , -ray.dir);
      
    res = res + estimate(indirectMap , nIndirectPaths , knnPhotons , scene , inter , -ray.dir , maxSqrDis);

	// final gathering is too slow!

    //res = res + finalGathering(indirectMap , scene , inter , rng , -ray.dir , 50 , knnPhotons , maxSqrDis);
    
    res = res + estimate(causticMap , nCausticPaths , knnPhotons , scene , inter , -ray.dir , maxSqrDis);

	BSDF bsdf(-ray.dir , inter , scene);

	Real pdf , cosWo;
	int sampledType;
	Ray newRay;

	Color3 bsdfFactor = bsdf.sample(scene , rng.randVector3() ,
		newRay.dir , pdf , cosWo , &sampledType);

	if (bsdfFactor.isBlack())
		return res;

	// Russian Roulette
	Real contProb = bsdf.continueProb;

	if (cmp(contProb - 1.f) < 0)
	{
		if (cmp(rng.randFloat() - contProb) > 0)
			return res;
		pdf *= contProb;
	}
    
	newRay.origin = inter.p + newRay.dir * EPS;
	newRay.tmin = 0; newRay.tmax = INF;

	Color3 contrib = raytracing(newRay , dep + 1);

	res = res + (contrib | bsdfFactor) * (cosWo / pdf);

    return res;
}
Пример #30
0
static Color3 estimate(KdTree<Photon> *map , int nPaths , int knn ,
                                  Scene& scene , Intersection& inter , 
								  const Vector3& wo , Real maxSqrDis)
{
    Color3 res = Color3(0.0 , 0.0 , 0.0);
    
    if (map == NULL)
        return res;
    
    Photon photon;
    photon.pos = inter.p;

	ClosePhotonQuery query(knn , 0);

    Real searchSqrDis = maxSqrDis;
    Real msd; /* max square distance */
    while (query.kPhotons.size() < knn)
    {
        msd = searchSqrDis;
        query.init(msd);
        map->searchKnn(0 , photon.pos , query);
        searchSqrDis *= 2.0;
    }
    
    int nFoundPhotons = query.kPhotons.size();

    if (nFoundPhotons == 0)
        return res;
    
    Vector3 nv;
    if (cmp(wo ^ inter.n) < 0)
        nv = -inter.n;
    else
        nv = inter.n;

    Real scale = 1.0 / (PI * msd * nFoundPhotons);
    
	BSDF bsdf(wo , inter , scene);
	Real cosTerm , pdf;
    for (int i = 0; i < nFoundPhotons; i++)
    {
        /*
        Real k = kernel(kPhotons[i].photon , p , msd);
        k = 1.0 / PI;
        Real scale = k / (nPaths * msd);
        */
        if (cmp(nv ^ query.kPhotons[i].photon->wi) > 0)
        {
            Color3 brdf = bsdf.f(scene , query.kPhotons[i].photon->wi , 
				cosTerm , &pdf);
			if (brdf.isBlack())
				continue;
            res = res + (brdf | query.kPhotons[i].photon->alpha) * 
				(cosTerm * scale / pdf);
        }
        else
        {
			Vector3 wi(query.kPhotons[i].photon->wi);
			wi.z *= -1.f;
			Color3 brdf = bsdf.f(scene , wi , cosTerm , &pdf);
			if (brdf.isBlack())
				continue;
			res = res + (brdf | query.kPhotons[i].photon->alpha) * 
				(cosTerm * scale / pdf);
        }
    }
    return res;
}