Exemplo n.º 1
0
RGBColor Transmittance::SampleF(const Vector& wi, Vector& wo, const Normal& n) const
{
	float eta = ior;

	Normal ns = n;
	float nDotWi = Dot(wo, ns);
	if (nDotWi > 0.0f) //Uhel je tupy (jdeme zevnitr ven)
	{
		eta = 1.f / ior;
		ns = -ns;
	}

	float w = -(nDotWi) / (wi.Length() * n.Length());
	float r = eta;
	float k = sqrtf(1 + (w - r)*(w + r));

	wo = r*wi + (w - k)*n;

	return c;
}
Exemplo n.º 2
0
// Function for the upper bound on error
Spectrum ErrorBound(Point p, Normal n, Point bb_low, Point bb_high, Point l, Spectrum brdf, Spectrum intensities) {
    double err = 1;
    bool inf = false;
    int i;
    double dist = 0;
    // Calculate minimum distance from bounding box
    for(i = 0; i < 3; i++) {
        if(p[i] < bb_low[i])
            dist += (p[i] - bb_low[i])*(p[i] - bb_low[i]);
        else if(p[i] > bb_high[i])
            dist += (p[i] - bb_high[i])*(p[i] - bb_high[i]);
        else {
            inf = true;
            break;
        }
    }
    // Infinite error bound if p is inside the bounding box
    if(inf || dist < 0.001) {
        return -1 * intensities;
    }
    // Bound of the geometric term
    err *= 1.0 / dist;
    n /= n.Length();
    // To bound the cosine term, align normal to the z-axis 
    // and take maximum z-coordinate and minimum absolute values of x and y coordinates.
    float M[3][3]; //Rotation matrix from normal to z-axis
    float v[3][3];
    float vsq[3][3];
    int j;
    for(i = 0; i < 3; i++) {
        for(j = 0; j < 3; j++) {
            if(i == j)
                M[i][j] = 1;
            else
                M[i][j] = 0;
            v[i][j] = 0;
            vsq[i][j] = 0;
        }
    }
    float vx = n[1];
    float vy = -(n[0]);
    float s = sqrtf(vx*vx + vy*vy);
    float c = n[2];
    Point bb_low2, bb_high2;
    for(i = 0; i < 3; i++) {
        bb_low2[i] = bb_low[i] - p[i];
        bb_high2[i] = bb_high[i] - p[i];
    }
    int k;
    if(fabsf(s) < 0.001) {
        if(c < 0) {
            M[2][2] = -1;
        }
    }
    else {
        v[0][2] = vy;
        M[0][2] += vy;
        v[1][2] = -vx;
        M[1][2] += -vx;
        v[2][0] = -vy;
        M[2][0] += -vy;
        v[2][1] = vx;
        M[2][1] += vx;
        float temp = (1 - c) / (s * s);
        for(i = 0; i < 3; i++) {
            for(j = 0; j < 3; j++) {
                for(k = 0; k < 3; k++) {
                    vsq[i][j] += v[i][k] * v[k][j];
                }
                M[i][j] += vsq[i][j] * temp;
            }
        }
    }
    // Rotation Matrix computed
    Point bb_low3, bb_high3;
    // Transform and align normal to the z-axis
    // Apply the transform to the bounding box points
    for(i = 0; i < 3; i++) {
        for(k = 0; k < 3; k++) {
            bb_low3[i] += M[i][k]*bb_low2[k];
            bb_high3[i] += M[i][k]*bb_high2[k];
        }
    }
    // For cos theta bound, use maximum z and minimum absolute x and y
    float max_z = bb_high3[2];
    if(bb_low3[2] > max_z)
        max_z = bb_low3[2];
    // Negative maximum z means that none of the light sources are in the reflection hemisphere. Bound is 0.
    if(max_z < 0.001)
        return 0 * intensities;
    float min_x, min_y;
    if((bb_low3[0] < 0 && bb_high3[0] > 0) || (bb_high3[0] < 0 && bb_low3[0] > 0))
        min_x = 0;
    else
        min_x = min(fabsf(bb_low3[0]), fabsf(bb_high3[0]));
    if((bb_low3[1] < 0 && bb_high3[1] > 0) || (bb_high3[1] < 0 && bb_low3[1] > 0))
        min_y = 0;
    else
        min_y = min(fabsf(bb_low3[1]), fabsf(bb_high3[1]));
    err *= max_z / sqrtf((max_z * max_z) + (min_y * min_y) + (min_x * min_x)); // Multiply by the cosine bound
    return err * brdf * intensities; // Multiply by the constant lambertian brdf and the sum of light intensities
}
Exemplo n.º 3
0
void MeshBaryTriangle::GetShadingGeometry(const Transform &obj2world,
	const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const
{
	if (!mesh->n) {
		*dgShading = dg;
		return;
	}

	// Use _n_ to compute shading tangents for triangle, _ss_ and _ts_
	const Normal nsi = dg.iData.baryTriangle.coords[0] * mesh->n[v[0]] +
		dg.iData.baryTriangle.coords[1] * mesh->n[v[1]] + dg.iData.baryTriangle.coords[2] * mesh->n[v[2]];
	const Normal ns = Normalize(nsi);

	Vector ss, ts;
	Vector tangent, bitangent;
	float btsign;
	// if we got a generated tangent space, use that
	if (mesh->t) {
		// length of these vectors is essential for sampled normal mapping
		// they should be normalized at vertex level, and NOT normalized after interpolation
		tangent = dg.iData.baryTriangle.coords[0] * mesh->t[v[0]] +
			dg.iData.baryTriangle.coords[1] * mesh->t[v[1]] + dg.iData.baryTriangle.coords[2] * mesh->t[v[2]];
		// only degenerate triangles will have different vertex signs
		bitangent = Cross(nsi, tangent);
		// store sign, and also magnitude of interpolated normal so we can recover it
		btsign = (mesh->btsign[v[0]] ? 1.f : -1.f) * nsi.Length();

		ss = Normalize(tangent);
		ts = Normalize(bitangent);
	} else {
		ts = Normalize(Cross(ns, dg.dpdu));
		ss = Cross(ts, ns);

		ts *= Dot(dg.dpdv, ts) > 0.f ? 1.f : -1.f;

		tangent = ss;
		bitangent = ts;

		btsign = (Dot(ts, ns) > 0.f ? 1.f : -1.f);
	}

	// the length of dpdu/dpdv can be important for bumpmapping
	ss *= dg.dpdu.Length();
	ts *= dg.dpdv.Length();

	Normal dndu, dndv;
	// Compute \dndu and \dndv for triangle shading geometry
	float uvs[3][2];
	GetUVs(uvs);

	// Compute deltas for triangle partial derivatives of normal
	const float du1 = uvs[0][0] - uvs[2][0];
	const float du2 = uvs[1][0] - uvs[2][0];
	const float dv1 = uvs[0][1] - uvs[2][1];
	const float dv2 = uvs[1][1] - uvs[2][1];
	const Normal dn1 = mesh->n[v[0]] - mesh->n[v[2]];
	const Normal dn2 = mesh->n[v[1]] - mesh->n[v[2]];
	const float determinant = du1 * dv2 - dv1 * du2;

	if (determinant == 0.f)
		dndu = dndv = Normal(0, 0, 0);
	else {
		const float invdet = 1.f / determinant;
		dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
		dndv = (-du2 * dn1 + du1 * dn2) * invdet;
	}

	*dgShading = DifferentialGeometry(dg.p, ns, ss, ts,
		dndu, dndv, tangent, bitangent, btsign, dg.u, dg.v, this);
	dgShading->iData = dg.iData;
}