Ejemplo n.º 1
0
//http://cse.csusb.edu/tong/courses/cs621/notes/ray.php
Vector3 SimpleMaterial::getReflectionDirection(const ONB& normal, const Vector3& in_dir) {
    Vector3 reflection = normal.w();
    reflection *= -2.0 * dot(in_dir, normal.w());
    reflection += in_dir;
    reflection.normalize();
    return reflection;
}
Ejemplo n.º 2
0
bool DSphere::randomPoint(const Vector3 &viewpoint, const Vector2 &seed, float time, Vector3 &light_point, Vector3 &N, float &pdf, Color &radiance) const {
    float d = (viewpoint - getCenter(0)).magnitude();
    if (d < radius) {return false;}
    float r = radius;
    //internal angle of cone surrounding light seen from viewpoint
    float sin_alpha_max = r / d;
    float cos_alpha_max = sqrt(1 - sin_alpha_max * sin_alpha_max);
    float q = 1.0 / (2*M_PI*(1 - cos_alpha_max));
    float cos_alpha = 1 + seed.x() * (cos_alpha_max - 1);
    float sin_alpha = sqrt(1 - cos_alpha * cos_alpha);
    float phi = 2*M_PI*seed.y();
    float cos_phi = cos(phi);
    float sin_phi = sin(phi);
    Vector3 k_i(cos_phi * sin_alpha, sin_phi * sin_alpha, cos_alpha);
    //construct local coordinate system UVW where viewpoint at origin and sphere at (0,0,d) in UVW
    ONB UVW;
    UVW.initFromW(getCenter(0) - viewpoint);
    Ray to_light(viewpoint, k_i.x() * UVW.u() + k_i.y() * UVW.v() + k_i.z() * UVW.w());
    
    IntersectRecord rec;
    if (this -> intersect(to_light, 0.00001, FLT_MAX, time, rec)) {
        light_point = rec.intersection;
        float cos_theta_prime = -dot(rec.uvw.w(), to_light.direction());
        pdf = q * cos_theta_prime / (light_point - viewpoint).squaredMagnitude();
        N = rec.uvw.w();
        radiance = mptr -> emittedRadiance(rec.uvw, -to_light.direction(), light_point, rec.uv);
        return true;
    }
    return false;
}
Ejemplo n.º 3
0
bool PhongMetalMaterial::specularDirection(const ONB& uvw, const Vector3D& v_in, const Vector3D& p, const Vector2D& uv,
        Vector2D& seed, ColorRGB& color, Vector3D& v_out)
{
    float phi = 2* PI* seed.getX();
    //the phong exponent is stored in the red value for the texture at that point
    float exponent = phong_exp->value(uv, p).getRed();
    float cosTheta = pow(1-seed.getY(), 1.0/(exponent+1));
    float sinTheta = sqrt(1-cosTheta*cosTheta);
    float x = cos(phi) * sinTheta;
    float y = sin(phi) * sinTheta;
    float z = cosTheta;


    ONB basis;
    Vector3D w = v_in - 2*dotProduct(v_in, uvw.w())*uvw.w();
    basis.initFromW(w);

    //color = R->value(uv, p);
    ColorRGB r = R->value(uv, p);
    float c = 1 - (dotProduct(v_in, uvw.w()));
    color = r + (ColorRGB(1, 1, 1) + (-r))*(c*c*c*c*c);
    v_out = x*basis.u() + y*basis.v() + z*basis.w();

    if(exponent <10000) seed.scramble();
    return (dotProduct(v_out, uvw.w()) >0 );

}
Ejemplo n.º 4
0
bool SimpleMaterial::getTransmissionDirection(const ONB &uvw, const Vector3 &in_dir, Color& _extinction, float &fresnel_scale, Vector3& transmission) {
    
    Vector3 normal = uvw.w();
    
    //printf("COS = %f \n", dot(in_dir, normal));
    float cosine = dot(in_dir, normal);
    if (cosine < 0.0f) {//incoming ray
        float temp1 = 1.0f / n;
        cosine = -cosine;
        float root = 1.0f - (temp1 * temp1) * (1.0f - cosine * cosine);
        //assume dielectrics embedded in air dont check for total internal refelction, yay physics
        transmission = in_dir * temp1 + normal * (temp1 * cosine - sqrt(root));
        _extinction = Color(1.0f, 1.0f, 1.0f);
    }
    else { //(cosine > 0.0f) ray outgoing
        float temp2 = (dot(in_dir, normal));
        float root = 1.0f - (n*n) * (1.0f - temp2 * temp2);
        if (root < 0.0f) {return false;} //total internal reflection
        else {transmission = in_dir * n + -normal * (n * temp2 - sqrt(root));}
        _extinction = transmissive;
    }
    
    //printf("COS = %f", cosine);
    //printf("R = %f", R0);
    //printf("%f", 1.0f - (R0 + (1.0f - R0) * pow(1.0f - cosine, 5)));
    fresnel_scale = 1.0f - (R0 + (1.0f - R0) * pow(1.0f - cosine, 5));
    
    return true;
}
Ejemplo n.º 5
0
Color SimpleMaterial::specularResponse(const ONB& normal, const Vector3& light_vector, const Vector3& eye_vector) {
    Vector3 bisector = normalize(light_vector + eye_vector);
    float specular_term = dot(normal.w(), bisector);
    if (specular_term < 0.0) specular_term = 0.0;
    if (specular_term > 1.0) specular_term = 1.0;
    float phong_constant = pow(specular_term, phong_exp);
    return specular * phong_constant;
}
Ejemplo n.º 6
0
ColorRGB DiffSpecMaterial::ambientResponse(const ONB& uvw, const Vector3D& v_in, const Vector3D& p, const Vector2D& uv)
{
	float cosine = dotProduct(v_in, uvw.w());
	if (cosine < 0.0f) cosine = -cosine;
	float temp1 = 1.0f - cosine;
	float R = R0 + (1.0f - R0) *temp1*temp1*temp1*temp1*temp1;
	float P = (R + 0.5f) / 2.0f;
	if(rng() <= P)
		return spec_mat->ambientResponse(uvw, v_in, p, uv);
	else
		return diff_mat->ambientResponse(uvw, v_in, p, uv);
}
int TexturedLambertianShader::getBRDFSampledRays(Object3d* p_object, Vector3d p_point, Vector3d p_normal, UVMap p_uv, Vector3d p_viewVec, Vector3d p_inVec, Ray* p_specularRays, RGB* p_values) {

	const float PI = 3.14159265358979323846f;
	//Malley's method. find a sample in the unit disk (r,theta) = (sqrt(rand1), 2pi*rand2)

	float r = sqrt(((float)(rand() % 1000)) / 1000.0f);
	float theta = (((float)(rand() % 1000)) / 1000.0f) * 2 * PI;

	float x = r * cos(theta);
	float y = r * sin(theta);
	float z = sqrt(1 - x*x - y*y);

	ONB onb;
	onb.initFromU(p_normal);
	Vector3d outVec = onb.v * x + onb.w * y + onb.u * z;
	p_specularRays[0].setPoint(p_point);
	p_specularRays[0].setDir(outVec);
	p_specularRays[0].setDiffuse(true);
	
	RGB c = (map != NULL)? map->getTexel(p_uv.u, p_uv.v) : color;
	p_values[0] = c;

	return 1;
}
Ejemplo n.º 8
0
bool PhongMetalMaterial::specularDirection(const ONB& uvw, const Vector3& v_in, const Vector3& p, const Vector2& uv, Vector2& seed, Color& color, Vector3& v_out) {
    float phi = 2 * M_PI * seed.x();
    float exponent = phong_exp -> value(uv, p).getRed();
    float cosTheta = pow(1 - seed.y(), 1.0 / (exponent + 1));
    float sinTheta = sqrt(1 - cosTheta*cosTheta);
    float x = cos(phi) * sinTheta;
    float y = sin(phi) * sinTheta;
    float z = cosTheta;
    
    ONB basis;
    Vector3 w = v_in - 2*dot(v_in, uvw.w()) * uvw.w();
    basis.initFromW(w);
    
    color = tex -> value(uv, p);
    v_out = x*basis.u() + y*basis.v() + z*basis.w();
    
    if (exponent < 10000) {/*seed.scramble();*/}
    return dot(v_out, uvw.w()) > 0;
}
Ejemplo n.º 9
0
Color SimpleMaterial::diffuseResponse(const ONB& normal, const Vector3& light_vector) {
    float diffuse_term = dot(normal.w(), normalize(light_vector));
    if (diffuse_term < 0.0) diffuse_term = 0.0;
    if (diffuse_term > 1.0) diffuse_term = 1.0;
    return diffuse * diffuse_term;
}