Example #1
0
Spectrum MIPMap::getValue(Float u, Float v, 
		Float dudx, Float dudy, Float dvdx, Float dvdy) const {
	if (m_filterType == ETrilinear) {
		++mipmapLookups;
		/* Conservatively estimate a square lookup region */
		Float width = 2.0f * std::max(
			std::max(std::abs(dudx), std::abs(dudy)),
			std::max(std::abs(dvdx), std::abs(dvdy)));
		Float mipmapLevel = m_levels - 1 + 
			log2(std::max(width, (Float) 1e-8f));

		if (mipmapLevel < 0) {
			/* The lookup is smaller than one pixel */
			return triangle(0, u, v);
		} else if (mipmapLevel >= m_levels - 1) {
			/* The lookup is larger than the whole texture */
			return getTexel(m_levels - 1, 0, 0);
		} else {
			/* Tri-linear interpolation */
			int level = (int) mipmapLevel;
			Float delta = mipmapLevel - level;
			return triangle(level, u, v) * (1.0f - delta)
				+ triangle(level, u, v) * delta;
		}
	} else if (m_filterType == EEWA) {
		if (dudx*dudx + dudy*dudy < dvdx*dvdx + dvdy*dvdy) {
			std::swap(dudx, dvdx);
			std::swap(dudy, dvdy);
		}

		Float majorLength = std::sqrt(dudx * dudx + dudy * dudy);
		Float minorLength = std::sqrt(dvdx * dvdx + dvdy * dvdy);

		if (minorLength * m_maxAnisotropy < majorLength && minorLength > 0.0f) {
			Float scale = majorLength / (minorLength * m_maxAnisotropy);
			dvdx *= scale; dvdy *= scale;
			minorLength *= scale;
		}

		if (minorLength == 0)
			return triangle(0, u, v);
	
		// The min() below avoids overflow in the int conversion when lod=inf
		Float lod = 
			std::min(std::max((Float) 0, m_levels - 1 + log2(minorLength)), 
				(Float) (m_levels-1));
		int ilod = floorToInt(lod);
		Float d = lod - ilod;

		return EWA(u, v, dudx, dudy, dvdx, dvdy, ilod)   * (1-d) +
			   EWA(u, v, dudx, dudy, dvdx, dvdy, ilod+1) * d;
	} else {
		int xPos = floorToInt(u*m_levelWidth[0]),
			yPos = floorToInt(v*m_levelHeight[0]);
		return getTexel(0, xPos, yPos);
	}
}
Example #2
0
Spectrum MIPMap::triangle(int level, Float x, Float y) const {
	if (m_filterType == ENone) {
		int xPos = floorToInt(x*m_levelWidth[0]),
			yPos = floorToInt(y*m_levelHeight[0]);
		return getTexel(0, xPos, yPos);
	} else {
		level = clamp(level, 0, m_levels - 1);
		x = x * m_levelWidth[level] - 0.5f;
		y = y * m_levelHeight[level] - 0.5f;
		int xPos = floorToInt(x), yPos = floorToInt(y);
		Float dx = x - xPos, dy = y - yPos;
		return getTexel(level, xPos, yPos) * (1.0f - dx) * (1.0f - dy)
			+ getTexel(level, xPos, yPos + 1) * (1.0f - dx) * dy
			+ getTexel(level, xPos + 1, yPos) * dx * (1.0f - dy)
			+ getTexel(level, xPos + 1, yPos + 1) * dx * dy;
	}	
}
Example #3
0
Spectrum MIPMap::EWA(Float u, Float v, Float dudx, Float dudy, Float dvdx, 
	Float dvdy, int level) const {
	++ewaLookups;
	if (level >= m_levels)
		return getTexel(m_levels-1, 0, 0);

	Spectrum result(0.0f);
	Float denominator = 0.0f;
	u = u * m_levelWidth[level]; v = v * m_levelHeight[level];
	dudx = dudx * m_levelWidth[level]; dudy = dudy * m_levelHeight[level];
	dvdx = dvdx * m_levelWidth[level]; dvdy = dvdy * m_levelHeight[level];

	Float A = dudy * dudy + dvdy * dvdy + 1.0f;
	Float B = -2.0f * (dudx * dudy + dvdx * dvdy);
	Float C = dudx * dudx + dvdx * dvdx + 1.0f;
	Float F = A * C - B * B * 0.25f;
	Float du = std::sqrt(C), dv = std::sqrt(A);
	int u0 = (int) std::ceil(u - du);
	int u1 = (int) std::floor(u + du);
	int v0 = (int) std::ceil(v - dv);
	int v1 = (int) std::floor(v + dv);
	Float invF = 1.0f / F;
	A *= invF; B *= invF; C *= invF;

	for (int ut = u0; ut <= u1; ++ut) {
		const Float uu = ut - u;
		for (int vt = v0; vt <= v1; ++vt) {
			const Float vv = vt - v;
			const Float r2 = A*uu*uu + B*uu*vv + C*vv*vv;
			if (r2 < 1) {
				const Float weight = m_weightLut[
					std::max(0, std::min((int) (r2 * MIPMAP_LUTSIZE), MIPMAP_LUTSIZE - 1))];
				result += getTexel(level, ut, vt) * weight;
				denominator += weight;
			}
		}
	}
	return result / denominator;
}
Example #4
0
	/**
	  * Returns an interpolated texel using bi-linear texture filtering
	  */
	static glm::vec3 readTexture(texture& tex, float s, float t) {

		float xf = std::min(s*tex.width, tex.width-1.0f);
		float yf = std::min(t*tex.height, tex.height-1.0f);

		//// Find the diffrent texture coords.
		float xMin = glm::floor(xf);
		float yMin = glm::floor(yf);
		float xMax = glm::ceil(xf);
		float yMax = glm::ceil(yf);

		////// Find the four nearest texels.
		glm::vec3 A = getTexel(tex, xMin, yMin);
		glm::vec3 B = getTexel(tex, xMax, yMin);
		glm::vec3 C = getTexel(tex, xMax, yMax);
		glm::vec3 D = getTexel(tex, xMin, yMax);
		glm::vec3 xTop;
		glm::vec3 xBot;

		float divx = xMax - xMin;
		float divy = yMax - yMin;

		//horizontal interpolation
		if (divx > 0.0f) {
			xTop = ((xMax-xf)/divx)*A + ((xf-xMin)/divx)*B;
			xBot = ((xMax-xf)/divx)*D + ((xf-xMin)/divx)*C;
		}
		else {
			xTop = 1.0f*A + 0.0f*B;
			xBot = 1.0f*D + 0.0f*C;
		}
		//vertical interpolation
		if (divy > 0.0f) {
			return ((yMax-yf)/divy)*xTop + ((yf-yMin)/divy)*xBot;
		}
		return 1.0f * xTop + 0.0f * xBot;
	}
Example #5
0
/* Isotropic/anisotropic EWA mip-map texture map class based on PBRT */
MIPMap::MIPMap(int width, int height, Spectrum *pixels, 
	EFilterType filterType, EWrapMode wrapMode, Float maxAnisotropy) 
		: m_width(width), m_height(height), m_filterType(filterType), 
		  m_wrapMode(wrapMode), m_maxAnisotropy(maxAnisotropy) {
	Spectrum *texture = pixels;

	if (filterType != ENone && (!isPow2(width) || !isPow2(height))) {
		m_width = (int) roundToPow2((uint32_t) width);
		m_height = (int) roundToPow2((uint32_t) height);

		/* The texture needs to be up-sampled */
		Spectrum *texture1 = new Spectrum[m_width*height];

		/* Re-sample into the X direction */
		ResampleWeight *weights = resampleWeights(width, m_width);
		for (int y=0; y<height; y++) {
			for (int x=0; x<m_width; x++) {
				texture1[x+m_width*y] = Spectrum(0.0f);
				for (int j=0; j<4; j++) {
					int pos = weights[x].firstTexel + j;
					if (pos < 0 || pos >= height) {
						if (wrapMode == ERepeat) 
							pos = modulo(pos, width);
						else if (wrapMode == EClamp)
							pos = clamp(pos, 0, width-1);
					}
					if (pos >= 0 && pos < width)
						texture1[x+m_width*y] += pixels[pos+y*width] 
							* weights[x].weight[j];
				}
			}
		}
		delete[] weights;
		delete[] pixels;

		/* Re-sample into the Y direction */
		texture = new Spectrum[m_width*m_height];
		weights = resampleWeights(height, m_height);
		memset(texture, 0, sizeof(Spectrum)*m_width*m_height);
		for (int x=0; x<m_width; x++) {
			for (int y=0; y<m_height; y++) {
				for (int j=0; j<4; j++) {
					int pos = weights[y].firstTexel + j;
					if (pos < 0 || pos >= height) {
						if (wrapMode == ERepeat) 
							pos = modulo(pos, height);
						else if (wrapMode == EClamp)
							pos = clamp(pos, 0, height-1);
					}
					if (pos >= 0 && pos < height)
						texture[x+m_width*y] += texture1[x+pos*m_width]
							* weights[y].weight[j];
				}
			}
		}
		for (int y=0; y<m_height; y++)
			for (int x=0; x<m_width; x++)
			texture[x+m_width*y].clampNegative();
		delete[] weights;
		delete[] texture1;
	}

	if (m_filterType != ENone)
		m_levels = 1 + log2i((uint32_t) std::max(width, height));
	else
		m_levels = 1;

	m_pyramid = new Spectrum*[m_levels];
	m_pyramid[0] = texture;
	m_levelWidth = new int[m_levels];
	m_levelHeight= new int[m_levels];
	m_levelWidth[0] = m_width;
	m_levelHeight[0] = m_height;

	/* Generate the mip-map hierarchy */
	for (int i=1; i<m_levels; i++) {
		m_levelWidth[i]  = std::max(1, m_levelWidth[i-1]/2);
		m_levelHeight[i] = std::max(1, m_levelHeight[i-1]/2);
		m_pyramid[i] = new Spectrum[m_levelWidth[i] * m_levelHeight[i]];
		for (int y = 0; y < m_levelHeight[i]; y++) {
			for (int x = 0; x < m_levelWidth[i]; x++) {
				m_pyramid[i][x+y*m_levelWidth[i]] = (
					getTexel(i-1, 2*x, 2*y) + 
					getTexel(i-1, 2*x+1, 2*y) + 
					getTexel(i-1, 2*x, 2*y+1) + 
					getTexel(i-1, 2*x+1, 2*y+1)) * 0.25f;
			}
		}
	}

	if (m_filterType == EEWA) {
		m_weightLut = static_cast<Float *>(allocAligned(sizeof(Float)*MIPMAP_LUTSIZE));
		for (int i=0; i<MIPMAP_LUTSIZE; ++i) {
			Float pos = (Float) i / (Float) (MIPMAP_LUTSIZE-1);
			m_weightLut[i] = std::exp(-2.0f * pos) - std::exp(-2.0f);
		}
	}
}
Example #6
0
Color lambertian(Ray normal, const Scene* s, Sphere* sphere, Plane* plane)
{
	Color result;
	result.r = 0;
	result.g = 0;
	result.b = 0;
	bool blocked;

	for(int i = 0; i < s->lights.size(); i++)
	{
		blocked = false;
		Light current_light = s->lights.at(i);
		Ray lightRay;
		lightRay.p0 = current_light.origin;
		lightRay.dir = sub(normal.p0, current_light.origin);
		lightRay.dir = normalize(lightRay.dir);

		// check that point of interest is not shadowed by other objects
		float distFromLight = dist(normal.p0, current_light.origin);
		float distClosestObject = fInfinity; // distance between light and closest object along ray to normal initial point
		for(int k = 0; k < s->planes.size(); k++)
		{
			Plane current_plane = s->planes.at(k);
			if(!areEqual(&current_plane, plane))
			{
				distClosestObject = plane_intersect(&current_plane, &lightRay);

				// check if current object would block the light
				if(distClosestObject < distFromLight)
				{
					blocked = true;
					break;
				}
			}
		}

		for(int k = 0; k < s->spheres.size(); k++)
		{
			Sphere current_sphere = s->spheres.at(k);
			if(!areEqual(&current_sphere, sphere))
			{
				distClosestObject = sphere_intersect(&current_sphere, &lightRay);

				// check if current object would block the light
				if(distClosestObject < distFromLight)
				{
					blocked = true;
					break;
				}
			}
		}

		// check that the light source isn't behind the object
		Vec3 lv = lightRay.dir;
		Vec3 nv = normalize(normal.dir);
		if(dot(lv, nv) > 0.0)
			blocked = true;

		if(!blocked)
		{
			// add this light's contribution to the pixel color
			float coef = abs(dot(lv, nv));

			if(sphere != NULL)
			{
				result.r += (sphere->material.color.r * current_light.color.r) * coef;
				result.g += (sphere->material.color.g * current_light.color.g) * coef;
				result.b += (sphere->material.color.b * current_light.color.b) * coef;
			}
			else if(plane != NULL)
			{
				if(plane->hastexture)
				{
					Color textureColor = getTextureColor(getTexel(normal,plane),plane);

					result.r += textureColor.r * current_light.color.r * coef;
					result.g += textureColor.g * current_light.color.g * coef;
					result.b += textureColor.b * current_light.color.b * coef;
				}
				else 
				{
					result.r += (plane->material.color.r * current_light.color.r) * coef;
					result.g += (plane->material.color.g * current_light.color.g) * coef;
					result.b += (plane->material.color.b * current_light.color.b) * coef;
				}
			}
		}
	}

	return result;
}
Example #7
0
/*
 * @brief integrateTexture Get a texel by computing the mean of the color on a neighborood of size (deltas x deltat)
 * @param pixels    The image to access, organized as a linear array of texel arranged by row
 * @param width     Width of the image
 * @param height    Height of the image
 * @param depth     Depth of the image (number of component by texel)
 * @param s         The column coordinate of the requested texel as a floating point
 * @param t         The row coordinate of the requested texel as a floating point
 * @param deltas    The size, in the column dimension, of the neighborood
 * @param deltat    The size, in the row dimension, of the neighborood
 * @return
 * @todo
 */
Color integrateTexture(unsigned char *pixels, int width, int height, int depth, float s, float t, int deltas, int deltat){
    return getTexel(pixels, width, height, depth, (int)std::floor(s), (int)std::floor(t));
}