Ejemplo n.º 1
0
MipMap::MipMap(const std::vector<uint8_t> &texels, int width, int height, int ncomp, WRAP_MODE wrap_mode)
	: wrap_mode(wrap_mode), width(width), height(height), ncomp(ncomp)
{
	if (weight_table[0] == -1){
		init_weight_table();
	}
	//We only support power of two textures at the moment
	//Determine if pow2 via http://www.graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
	if (!(width && !(width & (width - 1))) || !(height && !(height & (height - 1)))){
		std::cout << "MipMap Error: Only powers of two are supported at the moment\n";
		assert("Non power of two texture");
	}
	int n_levels = 1 + static_cast<int>(log_2(std::max(width, height)));
	pyramid.reserve(n_levels);
	pyramid.emplace_back(width, height, texels);
	for (int i = 1; i < n_levels; ++i){
		int w = std::max(1, pyramid[i - 1].width / 2);
		int h = std::max(1, pyramid[i - 1].height / 2);
		pyramid.emplace_back(w, h);
		std::vector<uint8_t> &img = pyramid.back().texels;
		img.resize(w * h * ncomp);
		for (int t = 0; t < h; ++t){
			for (int s = 0; s < w; ++s){
				Colorf cf = 0.25 * (texel(i - 1, 2 * s, 2 * t) + texel(i - 1, 2 * s + 1, 2 * t)
					+ texel(i - 1, 2 * s, 2 * t + 1) + texel(i - 1, 2 * s + 1, 2 * t + 1));
				cf.normalize();
				Color24 c{cf};
				//Write the number of components that we have only
				for (int j = 0; j < ncomp; ++j){
					img[t * w * ncomp + s * ncomp + j] = c[j];
				}
			}
		}
	}
}
Ejemplo n.º 2
0
Colorf MipMap::triangle_filter(int lvl, float s, float t) const {
	lvl = clamp(lvl, 0, static_cast<int>(pyramid.size() - 1));
	s = s * pyramid[lvl].width - 0.5f;
	t = t * pyramid[lvl].height - 0.5f;
	int si = static_cast<int>(s);
	int ti = static_cast<int>(t);
	float ds = s - si;
	float dt = t - ti;
	return (1 - ds) * (1 - dt) * texel(lvl, si, ti)
		+ (1 - ds) * dt * texel(lvl, si, ti + 1)
		+ ds * (1 - dt) * texel(lvl, si + 1, ti)
		+ ds * dt * texel(lvl, si + 1, ti + 1);
}
Ejemplo n.º 3
0
Colorf MipMap::sample_ewa(const TextureSample &samp, std::array<float, 2> ds, std::array<float, 2> dt) const {
	//Compute the ellipse's major and minor axes, we pick the major axis to be (ds[0], dt[0]) so
	//swap if this wouldn't be the case
	if (ds[0] * ds[0] + dt[0] * dt[0] < ds[1] * ds[1] + dt[1] * dt[1]){
		std::swap(ds[0], ds[1]);
		std::swap(dt[0], dt[1]);
	}
	float major_len = std::sqrt(ds[0] * ds[0] + dt[0] * dt[0]);
	float minor_len = std::sqrt(ds[1] * ds[1] + dt[1] * dt[1]);

	//Clamp the ellipse eccentricity if it's too anisotropic by increasing the minor axis
	static const float max_anisotropy = 8;
	if (minor_len > 0 && minor_len * max_anisotropy < major_len){
		float s = major_len / (minor_len * max_anisotropy);
		ds[1] *= s;
		dt[1] *= s;
		minor_len *= s;
	}
	if (minor_len == 0){
		return triangle_filter(0, samp.s, samp.t);
	}

	float level = pyramid.size() - 1 + std::log2(minor_len);
	if (level >= pyramid.size()){
		return texel(pyramid.size() - 1, 0, 0);
	}
	int lvl = static_cast<int>(level);
	float d = level - lvl;
	return (1 - d) * ewa_filter(lvl, samp.s, samp.t, ds, dt)
		+ d * ewa_filter(lvl + 1, samp.s, samp.t, ds, dt);
}
Ejemplo n.º 4
0
Colorf MipMap::sample_trilinear(const TextureSample &samp, float w) const {
	float level = pyramid.size() - 1 + std::log2(std::max(w, 1e-8f));
	if (level < 0){
		return triangle_filter(0, samp.s, samp.t);
	}
	if (level >= pyramid.size() - 1){
		return texel(pyramid.size() - 1, 0, 0);
	}
	//Find integer coord of the level and the percentage we're in each
	int lvl = static_cast<int>(level);
	float d = level - lvl;
	return (1 - d) * triangle_filter(lvl, samp.s, samp.t)
		+ d * triangle_filter(lvl + 1, samp.s, samp.t);
}
Ejemplo n.º 5
0
Colorf MipMap::ewa_filter(int lvl, float s, float t, std::array<float, 2> ds, std::array<float, 2> dt) const {
	lvl = clamp(lvl, 0, static_cast<int>(pyramid.size() - 1));
	s = s * pyramid[lvl].width - 0.5f;
	t = t * pyramid[lvl].height - 0.5f;
	for (size_t i = 0; i < ds.size(); ++i){
		ds[i] *= pyramid[lvl].width;
		dt[i] *= pyramid[lvl].height;
	}
	float a = dt[0] * dt[0] + dt[1] * dt[1] + 1;
	float b = -2 * (ds[0] * dt[0] + ds[1] * dt[1]);
	float c = ds[0] * ds[0] + ds[1] * ds[1] + 1;
	float inv_f = 1 / (a * c - b * b * 0.25f);
	a *= inv_f;
	b *= inv_f;
	c *= inv_f;

	//Compute the ellipse's AABB so we can find which texels to loop over and filter
	float det = -b * b + 4 * a * c;
	float inv_det = 1 / det;
	float u_sqrt = std::sqrt(det * c);
	float v_sqrt = std::sqrt(det * a);
	std::array<int, 2> s_bound{
		static_cast<int>(s - 2 * inv_det * u_sqrt),
		static_cast<int>(s + 2 * inv_det * u_sqrt)
	};
	std::array<int, 2> t_bound{
		static_cast<int>(t - 2 * inv_det * v_sqrt),
		static_cast<int>(t + 2 * inv_det * v_sqrt)
	};

	Colorf color;
	float weight_sum = 0;
	for (int it = t_bound[0]; it <= t_bound[1]; ++it){
		float t_pos = it - t;
		for (int is = s_bound[0]; is <= s_bound[1]; ++is){
			float s_pos = is - s;
			//Find the position of this texel relative to the ellipse and see if it's inside
			float r_sqr = a * s_pos * s_pos + b * s_pos * t_pos + c * t_pos * t_pos;
			if (r_sqr < 1){
				float w = weight_table[std::min(static_cast<int>(r_sqr * WEIGHT_LUT_SIZE), WEIGHT_LUT_SIZE - 1)];
				color += texel(lvl, is, it) * w;
				weight_sum += w;
			}
		}
	}
	return color / weight_sum;
}
void DistanceFieldShiftedStyleTextMaterialShader::updateShift(qreal fontScale, const QPointF &shift)
{
    QPointF texel(1.0 / fontScale * shift.x(),
                  1.0 / fontScale * shift.y());
    program()->setUniformValue(m_shift_id, texel);
}
Ejemplo n.º 7
0
static void
renderscanline_uvi_full( mame_bitmap *bitmap, const rectangle *clip, const edge *e1, const edge *e2, int sy )
{
	if( e1->x > e2->x )
	{
		SWAP(e1,e2);
	}

	{
		UINT32 *pDest = (UINT32 *)bitmap->line[sy];
		INT32 *pZBuf = namco_zbuffer + bitmap->width*sy;

		int x0 = (int)e1->x;
		int x1 = (int)e2->x;
		int w = x1-x0;
		if( w )
		{
			float u = e1->u; /* u/z */
			float v = e1->v; /* v/z */
			float i = e1->i; /* i/z */
			float z = e1->z; /* 1/z */
			float oow = 1.0f / w;
			float du = (e2->u - e1->u)*oow;
			float dv = (e2->v - e1->v)*oow;
			float dz = (e2->z - e1->z)*oow;
			float di = (e2->i - e1->i)*oow;
			int x, crop;
			int baseColor = mColor&0x7f00;
			pen_t *pens = &Machine->pens[baseColor];

			crop = clip->min_x - x0;
			if( crop>0 )
			{
				u += crop*du;
				v += crop*dv;
				i += crop*di;
				z += crop*dz;
				x0 = clip->min_x;
			}
			if( x1>clip->max_x )
			{
				x1 = clip->max_x;
			}

			for( x=x0; x<x1; x++ )
			{
				if( mZSort<pZBuf[x] )
				{
					float ooz = 1.0f/z;
					UINT32 color = pens[texel(u * ooz,v * ooz)];
					int shade = i * ooz;
					int r = color>>16;
					int g = (color>>8)&0xff;
					int b = color&0xff;
					r+=shade; if( r<0 ) r = 0; else if( r>0xff ) r = 0xff;
					g+=shade; if( g<0 ) g = 0; else if( g>0xff ) g = 0xff;
					b+=shade; if( b<0 ) b = 0; else if( b>0xff ) b = 0xff;
					pDest[x] = (r<<16)|(g<<8)|b;
					pZBuf[x] = mZSort;
				}
				u += du;
				v += dv;
				i += di;
				z += dz;
			}
		}
	}
Ejemplo n.º 8
0
	Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &r) const {
		/* Find the surface that is visible in the requested direction */
		Intersection its;
		Ray3f ray(r);
		if (!scene->rayIntersect(ray, its))
			return Color3f(0.0f);
		Color3f radiance(0.0f);
		
		bool specularBounce = false;
		Color3f pathThroughput(1.0f);
		for ( int bounces = 0; ; ++bounces ) {
			const Luminaire* luminaire = its.mesh->getLuminaire();
			if ((bounces == 0 || specularBounce) && luminaire != NULL) {
				Vector3f wo = (-ray.d).normalized();
				Color3f emission = luminaire->le(its.p, its.shFrame.n, wo);
				radiance += pathThroughput*emission;
			}
			const Texture* texture = its.mesh->getTexture();
			Color3f texel(1.0f);
			if ( texture ) {
				texel = texture->lookUp(its.uv.x(), its.uv.y());
			}
			const BSDF* bsdf = its.mesh->getBSDF();
			// sample illumination from lights, add to path contribution
			if (!bsdf->isSpecular()){
				radiance += pathThroughput*UniformSampleAllLights(scene, ray, its, sampler, m_samplePolicy)*texel;
			}
			// sample bsdf to get new path direction
			BSDFQueryRecord bRec(its.toLocal((-ray.d)).normalized());
			Color3f f = bsdf->sample(bRec, sampler->next2D() );	
			if (f.isZero() ) { // farther path no contribution
				break;
			}
			specularBounce = bsdf->isSpecular();
			Vector3f d = its.toWorld(bRec.wo);
			f *= texel;
			pathThroughput *= f;
			ray = Ray3f(its.p, d );
			// possibly termination
			if (bounces > kSampleDepth) {
#if 0
				float continueProbability = std::min( 0.5f, pathThroughput.y() );
				if ( sampler->next1D() > continueProbability ) {
					break;
				}
#else
				float continueProbability = std::max(f.x(), 
					std::max(f.y(), f.z()));
				if ( sampler->next1D() > continueProbability ) {
					break;
				}
#endif
				pathThroughput /= continueProbability;
			}
			if (bounces == m_maxDepth) {
				break;
			}
			// find next vertex of path
			if ( !scene->rayIntersect(ray, its) ) {
				break;
			}
		}

		return radiance;
	}