Ejemplo n.º 1
0
	void test01_shRotation() {
		/* Generate a random SH expansion, rotate it and 
		   spot-check 100 times against the original evaluated
		   at appropriately rotated positions */

		ref<Random> random = new Random();
		int bands = 8;

		SHVector vec1(bands);
		for (int l=0; l<bands; ++l)
			for (int m=-l; m<=l; ++m)
				vec1(l, m) = random->nextFloat();

		Vector axis(squareToSphere(Point2(random->nextFloat(), random->nextFloat())));
		Transform trafo = Transform::rotate(axis, random->nextFloat()*360);
		Transform inv = trafo.inverse();
		SHRotation rot(vec1.getBands());

		SHVector::rotation(trafo, rot);
		SHVector vec2(bands);

		rot(vec1, vec2);

		for (int i=0; i<100; ++i) {
			Vector dir1(squareToSphere(Point2(random->nextFloat(), random->nextFloat()))), dir2;
			trafo(dir1, dir2);

			Float value1 = vec1.eval(dir2);
			Float value2 = vec2.eval(dir1);
			assertEqualsEpsilon(value1, value2, Epsilon);
		}
	}
Ejemplo n.º 2
0
	Vector sampleDirection(Point2 sample, Float &pdf, Spectrum &value) const {
#if defined(SAMPLE_UNIFORMLY)
		pdf = 1.0f / (4*M_PI);
		Vector d = squareToSphere(sample);
		value = Le(-d);
		return d;
#endif
	}
Ejemplo n.º 3
0
	void sampleEmission(EmissionRecord &eRec, 
		const Point2 &sample1, const Point2 &sample2) const {
		eRec.sRec.p = m_position;
		eRec.d = squareToSphere(sample2);
		eRec.pdfDir = 1.0f / (4 * M_PI);
		eRec.pdfArea = 1;
		eRec.value = m_intensity;
	}
Ejemplo n.º 4
0
	void sampleEmissionArea(EmissionRecord &eRec, const Point2 &sample) const {
		if (eRec.type == EmissionRecord::ENormal) {
			Vector d = squareToSphere(sample);
			eRec.sRec.p = m_bsphere.center + d * m_bsphere.radius;
			eRec.sRec.n = Normal(-d);
			eRec.pdfArea = 1.0f / (4 * M_PI * m_bsphere.radius * m_bsphere.radius);
			eRec.value = Spectrum(M_PI);
		} else {
			/* Preview mode, which is more suitable for VPL-based rendering: approximate 
			   the infinitely far-away source with set of diffuse point sources */
			const Float radius = m_bsphere.radius * 1.5f;
			Vector d = squareToSphere(sample);
			eRec.sRec.p = m_bsphere.center + d * radius;
			eRec.sRec.n = Normal(-d);
			eRec.pdfArea = 1.0f / (4 * M_PI * radius * radius);
			eRec.value = Le(d) * M_PI;
		}
	}
Ejemplo n.º 5
0
	void sampleEmissionArea(EmissionRecord &eRec, const Point2 &sample) const {
		Float radius = m_bsphere.radius;
		if (eRec.type == EmissionRecord::EPreview) {
			/* This is more suitable for VPL-based rendering */
			radius *= 1.5;
		}
		Vector d = squareToSphere(sample);
		eRec.sRec.p = m_bsphere.center + d * radius;
		eRec.sRec.n = Normal(-d);
		eRec.pdfArea = 1.0f / (4 * M_PI * radius * radius);
		eRec.value = m_intensity * M_PI;
	}
Ejemplo n.º 6
0
	/**
	 * This is the tricky bit - we want to sample a ray that
	 * has uniform density over the set of all rays passing
	 * through the scene.
	 * For more detail, see "Using low-discrepancy sequences and 
	 * the Crofton formula to compute surface areas of geometric models"
	 * by Li, X. and Wang, W. and Martin, R.R. and Bowyer, A. 
	 * (Computer-Aided Design vol 35, #9, pp. 771--782)
	 */
	void sampleEmission(EmissionRecord &eRec, 
		const Point2 &sample1, const Point2 &sample2) const {
		Assert(eRec.type == EmissionRecord::ENormal);
		/* Chord model - generate the ray passing through two uniformly
		   distributed points on a sphere containing the scene */
		Vector d = squareToSphere(sample1);
		eRec.sRec.p = m_bsphere.center + d * m_bsphere.radius;
		eRec.sRec.n = Normal(-d);
		Point p2 = m_bsphere.center + squareToSphere(sample2) * m_bsphere.radius;
		eRec.d = p2 - eRec.sRec.p;
		Float length = eRec.d.length();

		if (length == 0) {
			eRec.value = Spectrum(0.0f);
			eRec.pdfArea = eRec.pdfDir = 1.0f;
			return;
		}

		eRec.d /= length;
		eRec.pdfArea = 1.0f / (4 * M_PI * m_bsphere.radius * m_bsphere.radius);
		eRec.pdfDir = INV_PI * dot(eRec.sRec.n, eRec.d);
		eRec.value = Le(-eRec.d);
	}
Ejemplo n.º 7
0
	void sample(const Point &p, LuminaireSamplingRecord &lRec,
		const Point2 &sample) const {
		Vector d = squareToSphere(sample);
	
		Float nearHit, farHit;
		if (m_bsphere.contains(p) && m_bsphere.rayIntersect(Ray(p, d, 0.0f), nearHit, farHit)) {
			lRec.sRec.p = p + d * nearHit;
			lRec.pdf = 1.0f / (4*M_PI);
			lRec.sRec.n = normalize(m_bsphere.center - lRec.sRec.p);
			lRec.d = -d;
			lRec.value = m_intensity;
		} else {
			lRec.pdf = 0.0f;
		}
	}
Ejemplo n.º 8
0
	Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
		Float radius = m_bsphere.radius;
		if (eRec.type == EmissionRecord::EPreview) 
			radius *= 1.5f;
		Point p2 = m_bsphere.center + squareToSphere(sample) * radius;
		eRec.d = p2 - eRec.sRec.p;
		Float length = eRec.d.length();

		if (length == 0.0f) {
			eRec.pdfDir = 1.0f;
			return Spectrum(0.0f);
		}
		
		eRec.d /= length;
		eRec.pdfDir = INV_PI * dot(eRec.sRec.n, eRec.d);
		return Spectrum(INV_PI);
	}
Ejemplo n.º 9
0
void VPLShaderManager::setVPL(const VPL &vpl) {
	Point p = vpl.its.p + vpl.its.shFrame.n * 0.01;
	Intersection its;

	/* Estimate good near and far plane locations by tracing some rays */
	Float nearClip =  std::numeric_limits<Float>::infinity(),
		  farClip  = -std::numeric_limits<Float>::infinity();
	Ray ray;
	ray.o = p;

	if (m_shadowMap == NULL || m_shadowMapResolution != m_shadowMap->getSize().x) {
		m_shadowMap = m_renderer->createGPUTexture("Shadow cube map", NULL);
		m_shadowMap->setSize(Point3i(m_shadowMapResolution, m_shadowMapResolution, 1));
		m_shadowMap->setFrameBufferType(GPUTexture::EDepthBuffer);
		m_shadowMap->setType(GPUTexture::ETextureCubeMap);
		m_shadowMap->setWrapType(GPUTexture::EClampToEdge);
		m_shadowMap->setFilterType(GPUTexture::ENearest);
		m_shadowMap->setDepthMode(GPUTexture::ENormal);
		m_shadowMap->init();
	}

	const int sampleCount = 200;
	const Float invSampleCount = 1.0f/sampleCount;

	for (int i=1; i<=sampleCount; ++i) {
		Vector dir;
		Point2 seed(i*invSampleCount, radicalInverse(2, i)); // Hammersley seq.
		if (vpl.type == ESurfaceVPL || vpl.luminaire->getType() & Luminaire::EOnSurface)
			dir = vpl.its.shFrame.toWorld(squareToHemispherePSA(seed));
		else
			dir = squareToSphere(seed);
		ray.setDirection(dir);
		if (m_scene->rayIntersect(ray, its)) {
			nearClip = std::min(nearClip, its.t);
			farClip = std::max(farClip, its.t);
		}
	}

	m_minDist = nearClip + (farClip - nearClip) * m_clamping;

	nearClip = std::min(nearClip, (Float) 0.001f);
	farClip = std::min(farClip * 1.5f, m_maxClipDist);

	if (farClip < 0 || nearClip >= farClip) {
		/* Unable to find any surface - just default values based on the scene size */
		nearClip = 1e-3f * m_scene->getBSphere().radius;
		farClip = 2 * m_scene->getBSphere().radius;
		m_minDist = 0;
	}
	farClip = std::min(farClip, 5.0f*m_scene->getBSphere().radius);

	m_nearClip = nearClip;
	m_invClipRange = 1/(farClip-nearClip);
	Transform lightViewTrafo, lightProjTrafo = Transform::glPerspective(90.0f, nearClip, farClip);
	Matrix4x4 identity;
	identity.setIdentity();
	m_renderer->setCamera(identity, identity);

	m_shadowMap->activateTarget();
	if (m_singlePass && m_shadowProgram != NULL) {
		/* "Fancy": render the whole cube map in a single pass using 
		   a geometry program. On anything but brand-new hardware, this 
		   is actually slower. */

		m_shadowMap->activateSide(-1);
		m_shadowMap->clear();
		m_shadowProgram->bind();
		try {
			for (int i=0; i<6; ++i) {
				switch (i) {
					case 0: lightViewTrafo = Transform::lookAt(p, p + Vector(1, 0, 0), Vector(0, 1, 0)).inverse(); break;
					case 1: lightViewTrafo = Transform::lookAt(p, p + Vector(-1, 0, 0), Vector(0, 1, 0)).inverse(); break;
					case 2: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 1, 0), Vector(0, 0, -1)).inverse(); break;
					case 3: lightViewTrafo = Transform::lookAt(p, p + Vector(0, -1, 0), Vector(0, 0, 1)).inverse(); break;
					case 4: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, 1), Vector(0, 1, 0)).inverse(); break;
					case 5: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, -1), Vector(0, 1, 0)).inverse(); break;
				}
				lightViewTrafo = Transform::scale(Vector(-1, 1, 1)) * lightViewTrafo;
				const Matrix4x4 &viewMatrix = lightViewTrafo.getMatrix();
				m_shadowProgram->setParameter(m_shadowProgramParam_cubeMapTransform[i], lightProjTrafo * lightViewTrafo);
				m_shadowProgram->setParameter(m_shadowProgramParam_depthVec[i], Vector4(
					-viewMatrix.m[2][0] * m_invClipRange,
					-viewMatrix.m[2][1] * m_invClipRange,
					-viewMatrix.m[2][2] * m_invClipRange,
					(-viewMatrix.m[2][3] - m_nearClip) * m_invClipRange
				));
			}
			m_renderer->drawAll(m_drawList);
		} catch (const std::exception &ex) {
			m_shadowProgram->unbind();
			throw ex;
		}
		m_shadowProgram->unbind();
	} else {
		/* Old-fashioned: render 6 times, once for each cube map face */
		m_altShadowProgram->bind();
		try {
			for (int i=0; i<6; ++i) {
				switch (i) {
					case 0: lightViewTrafo = Transform::lookAt(p, p + Vector(1, 0, 0), Vector(0, 1, 0)).inverse(); break;
					case 1: lightViewTrafo = Transform::lookAt(p, p + Vector(-1, 0, 0), Vector(0, 1, 0)).inverse(); break;
					case 2: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 1, 0), Vector(0, 0, -1)).inverse(); break;
					case 3: lightViewTrafo = Transform::lookAt(p, p + Vector(0, -1, 0), Vector(0, 0, 1)).inverse(); break;
					case 4: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, 1), Vector(0, 1, 0)).inverse(); break;
					case 5: lightViewTrafo = Transform::lookAt(p, p + Vector(0, 0, -1), Vector(0, 1, 0)).inverse(); break;
				}
				lightViewTrafo = Transform::scale(Vector(-1, 1, 1)) * lightViewTrafo;
				const Matrix4x4 &viewMatrix = lightViewTrafo.getMatrix();

				m_altShadowProgram->setParameter(m_altShadowProgramParam_cubeMapTransform, lightProjTrafo * lightViewTrafo);
				m_altShadowProgram->setParameter(m_altShadowProgramParam_depthVec, Vector4(
					-viewMatrix.m[2][0] * m_invClipRange,
					-viewMatrix.m[2][1] * m_invClipRange,
					-viewMatrix.m[2][2] * m_invClipRange,
					(-viewMatrix.m[2][3] - m_nearClip) * m_invClipRange
				));

				m_shadowMap->activateSide(i);
				m_shadowMap->clear();
				m_renderer->drawAll(m_drawList);
			}
		} catch (std::exception &ex) {
			m_altShadowProgram->unbind();
			throw ex;
		}

		m_altShadowProgram->unbind();
	}
	m_shadowMap->releaseTarget();
}
Ejemplo n.º 10
0
 Float sample(PhaseFunctionQueryRecord &pRec,
              Float &pdf, Sampler *sampler) const {
     pRec.wo = squareToSphere(sampler->next2D());
     pdf = 1/(4 * M_PI);
     return f(pRec);
 }
Ejemplo n.º 11
0
	Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
		eRec.d = squareToSphere(sample);
		eRec.pdfDir = 1.0f / (4 * M_PI);
		return Spectrum(1.0f / (4*M_PI));
	}