//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; }
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 ); }
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; }
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; }
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; }
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; }
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); }
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; }