void Display::keyUp(SDLKey key) { Vector3 velocity = app->getVelocity(); Vector3 angularVelocity = app->getAngularVelocity(); switch(key) { case SDLK_a: if(velocity.x < 0) velocity.x = 0; break; case SDLK_d: if(velocity.x > 0) velocity.x = 0; break; case SDLK_w: if(velocity.z > 0) velocity.z = 0; break; case SDLK_s: if(velocity.z < 0) velocity.z = 0; break; case SDLK_LCTRL: if(velocity.y < 0) velocity.y = 0; break; case SDLK_SPACE: if(velocity.y > 0) velocity.y = 0; break; case SDLK_LEFT: if(angularVelocity.y > 0) angularVelocity.y = 0; break; case SDLK_RIGHT: if(angularVelocity.y < 0) angularVelocity.y = 0; break; case SDLK_UP: if(angularVelocity.x > 0) angularVelocity.x = 0; break; case SDLK_DOWN: if(angularVelocity.x < 0) angularVelocity.x = 0; break; default: break; } if(velocity.length2() > 0.1) velocity = velocity.normalized(); if(angularVelocity.length2() > 0.01) angularVelocity = angularVelocity.normalized(); app->setVelocity(velocity*Speed); app->setAngularVelocity(angularVelocity*AngularSpeed); }
void Display::keyDown(SDLKey key) { Vector3 velocity = app->getVelocity(); Vector3 angularVelocity = app->getAngularVelocity(); switch(key) { case SDLK_a: velocity.x = -1; break; case SDLK_d: velocity.x = 1; break; case SDLK_w: velocity.z = 1; break; case SDLK_s: velocity.z = -1; break; case SDLK_LCTRL: velocity.y = -1; break; case SDLK_SPACE: velocity.y = 1; break; case SDLK_ESCAPE: quit = true; break; case SDLK_LEFT: angularVelocity.y = 1; break; case SDLK_RIGHT: angularVelocity.y = -1; break; case SDLK_UP: angularVelocity.x = 1; break; case SDLK_DOWN: angularVelocity.x = -1; break; default: break; } if(velocity.length2() > 0.01) velocity = velocity.normalized(); if(angularVelocity.length2() > 0.01) angularVelocity = angularVelocity.normalized(); app->setVelocity(velocity*Speed); app->setAngularVelocity(angularVelocity*AngularSpeed); }
void WFace::computeNormal() { WEdge *u,*v,*start; Vector3 uvect,vvect; Vector3 n; start=edge(); u=edge(); if (u->left()==this) uvect=u->direction(); else uvect=-u->direction(); do { if (u->left()==this) { v=u->succLeft(); } else { v=u->succRight(); } vvect=v->direction(); if (v->right()==this) vvect=-vvect; n=uvect.cross(vvect); u=v; uvect=vvect; } while (n.length2()<0.000000001 && (u!=start)); if (u==start) { normal(Vector3(0,0,0)); // cas particulier : face aplatie } else { n.normalize(); normal(n); } }
Vector3 Lambert::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the irradiance Vector3 irradiance = (pLight->color() * pLight->wattage()) * std::max(0.0f, dot(hit.N, l)) / (4.0 * PI * falloff); L += irradiance * (m_kd / PI); } return L; }
bool within(const Scatter& pos, Vector3 r, double rMax, const Grid& g) { const int n = pos.length(); double r2 = rMax*rMax; for (int p = 0; p < n; p++) { Vector3 d = g.wrapDiff(pos.get(p) - r); if (d.length2() < r2) return true; } return false; }
int Object::createPlane( Material* mat , float w , float h , float* color , float xTile , float yTile , Vector3 const& normal , Vector3 const& alignDir , Vector3 const& offset , bool invYDir ) { Vector3 yLen = normal.cross( alignDir ); assert( yLen.length2() > 1e-4 ); yLen.normalize(); Vector3 xLen = yLen.cross( normal ); xLen *= 0.5f * w; yLen *= 0.5f * h; if ( invYDir ) yLen = -yLen; Vector3 n = normal; n.normalize(); int texLen = 2; VertexType type = ( color ) ? CFVT_XYZ_N_CF1 : CFVT_XYZ_N; //VertexType type = ( color ) ? CFVT_XYZ_CF1 : CFVT_XYZ; MeshBuilder builder = MeshBuilder( type | CFVF_TEX1( 2 ) ); if ( color ) builder.setColor( color ); builder.setNormal( n ); builder.reserveVexterBuffer( 4 ); builder.reserveIndexBuffer( 12 ); builder.setPosition( offset - xLen - yLen ); builder.setTexCoord( 0 , 0 , 0 ); builder.addVertex(); builder.setPosition( offset + xLen - yLen ); builder.setTexCoord( 0 ,xTile, 0 ); builder.addVertex(); builder.setPosition( offset + xLen + yLen ); builder.setTexCoord( 0 , xTile , yTile ); builder.addVertex(); builder.setPosition( offset - xLen + yLen ); builder.setTexCoord( 0 , 0 , yTile ); builder.addVertex(); builder.addQuad( 0 , 1 , 2 , 3 ); return builder.createIndexTrangle( this , mat ); }
bool Sphere::intersect(HitInfo& result, const Ray& ray, float tMin, float tMax) { const Vector3 toO = ray.o - m_center; const float a = ray.d.length2(); const float b = dot(2*ray.d, toO); const float c = toO.length2() - m_radius*m_radius; const float discrim = b*b-4.0f*a*c; if (discrim < 0) return false; // quadratic equation would yield imaginary numbers const float sqrt_discrim = sqrt(discrim); // solve the quadratic equation const float t[2] = {(-b-sqrt_discrim)/(2.0f*a), (-b+sqrt_discrim)/(2.0f*a)}; // since we know that discrim >= 0, t[0] < t{1] // return the t closest to us that is within range if ((t[0] > tMin) && (t[0] < tMax)) { result.t = t[0]; } else if((t[1] > tMin) && (t[1] < tMax)) { result.t = t[1]; } else { // neither of the solutions are in the required range return false; } if (result.t < 0.0001f) { return false; } result.P = ray.o + result.t*ray.d; result.N = (result.P-m_center); result.N.normalize(); result.material = this->m_material; return true; }
inline Vector3 pointOnSphere(float sx, float sy) { #if 0 // Rejection sampling Vector3 v; do { v.x = randomFloat() * 2.0f - 1.0f; v.y = randomFloat() * 2.0f - 1.0f; v.z = randomFloat() * 2.0f - 1.0f; } while (v.length2() > 1.0f); return v; #else sx = sx * 3.14159265f * 2.0f; sy = sy * 2.0f - 1.0f; float r = sqrtf(1.0f - sy * sy); return Vector3(cosf(sx) * r, sy, sinf(sx) * r); #endif }
Vector3 SpecularRefractionShading::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component float nDotL = dot(hit.N, l); Vector3 result = pLight->color(); result *= m_kd; L += std::max(0.0f, nDotL / falloff * pLight->wattage() / PI) * result; Vector3 r = (-l + 2 * dot(l, hit.N) * hit.N).normalized(); float eDotR = dot(viewDir, r); eDotR = 0.0f > eDotR ? 0.0f : 1.0f < eDotR ? 1.0f : eDotR; // clamp it to [0..1] eDotR = pow(eDotR, 3); L += std::max(0.0f, eDotR * falloff * pLight->wattage()); } // add the ambient component L += m_ka; return L; }
Vector3 Lambert::shade(const Ray& ray, const HitInfo& hit, const Scene& scene, int bounce) { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const PointLights *lightlist = scene.lights(); // loop over all of the lights PointLights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component float nDotL = dot(hit.N, l); Vector3 result = pLight->color(); result *= m_kd; L += std::max(0.0f, nDotL/falloff * pLight->wattage() / PI) * result; } // add the ambient component L += m_ka; return L; }
VOID Quaternion::setRotate( const Vector3& from, const Vector3& to ) { // This routine takes any vector as argument but normalized // vectors are necessary, if only for computing the dot product. // Too bad the API is that generic, it leads to performance loss. // Even in the case the 2 vectors are not normalized but same length, // the sqrt could be shared, but we have no way to know beforehand // at this point, while the caller may know. // So, we have to test... in the hope of saving at least a sqrt Vector3 sourceVector = from; Vector3 targetVector = to; F32 fromLen2 = from.length2(); F32 fromLen; // normalize only when necessary, epsilon test if ((fromLen2 < 1.0-1e-7) || (fromLen2 > 1.0+1e-7)) { fromLen = ::sqrtf(fromLen2); sourceVector /= fromLen; } else fromLen = 1.0; F32 toLen2 = to.length2(); // normalize only when necessary, epsilon test if ((toLen2 < 1.0-1e-7) || (toLen2 > 1.0+1e-7)) { F32 toLen; // re-use fromLen for case of mapping 2 vectors of the same length if ((toLen2 > fromLen2-1e-7) && (toLen2 < fromLen2+1e-7)) { toLen = fromLen; } else toLen = ::sqrtf(toLen2); targetVector /= toLen; } // Now let's get into the real stuff // Use "dot product plus one" as test as it can be re-used later on F32 dotProdPlus1 = 1.0f + sourceVector * targetVector; // Check for degenerate case of full u-turn. Use epsilon for detection if (dotProdPlus1 < 1e-7) { // Get an orthogonal vector of the given vector // in a plane with maximum vector coordinates. // Then use it as quaternion axis with pi angle // Trick is to realize one value at least is >0.6 for a normalized vector. if (::fabs(sourceVector.x()) < 0.6f) { const F32 norm = ::sqrtf(1.0f - sourceVector.x() * sourceVector.x()); _v[0] = 0.0f; _v[1] = sourceVector.z() / norm; _v[2] = -sourceVector.y() / norm; _v[3] = 0.0f; } else if (::fabs(sourceVector.y()) < 0.6f) { const F32 norm = ::sqrtf(1.0f - sourceVector.y() * sourceVector.y()); _v[0] = -sourceVector.z() / norm; _v[1] = 0.0f; _v[2] = sourceVector.x() / norm; _v[3] = 0.0f; } else { const F32 norm = ::sqrtf(1.0f - sourceVector.z() * sourceVector.z()); _v[0] = sourceVector.y() / norm; _v[1] = -sourceVector.x() / norm; _v[2] = 0.0f; _v[3] = 0.0f; } } else { // Find the shortest angle quaternion that transforms normalized vectors // into one other. Formula is still valid when vectors are colinear const F32 s = ::sqrtf(0.5f * dotProdPlus1); const Vector3 tmp = sourceVector ^ targetVector / (2.0f*s); _v[0] = tmp.x(); _v[1] = tmp.y(); _v[2] = tmp.z(); _v[3] = s; } }
Vector3 Lambert::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); // reflectance if (m_ks != 0 && ray.times <3) { Vector3 Wr = -2 * dot(ray.d, hit.N) * hit.N + ray.d; Wr.normalize(); Ray r(hit.P + (EPSILON * Wr), Wr); HitInfo hi; r.times = ray.times + 1; if(scene.trace(hi, r)) L += m_spec * m_ks * hi.material->shade(r, hi, scene); } // cellular noise texture if(m_noisiness > 0) { float at[3] = { hit.P.x, hit.P.y, hit.P.z }; const long mO = 3; float F[mO]; float delta[mO][3]; unsigned long *ID = new unsigned long(); WorleyNoise::noise3D(at, mO, F, delta, ID); L += m_noisiness * (0.5f * (F[2] - F[1]));// + PerlinNoise::noise(at[0], at[1], at[2])); } // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component float nDotL = dot(hit.N, l); Vector3 result = pLight->color(); result *= f_diff * m_kd; L += std::max(0.0f, nDotL/falloff * pLight->wattage() / PI) * result; // highlights //if (m_ks != 0) L += m_spec * pLight->color() * m_ks * max(0.f, pow(dot(viewDir, l), SPECULAR_CONST)); // / dot(hit.N, l); } // refraction if (m_trans != 0 && ray.times <3) { float n = (ray.times % 2 == 0) ? (ENV_INDEX / m_refInd) : (m_refInd / ENV_INDEX); float wn = dot(viewDir, hit.N); if (wn < 0) wn = -wn; Vector3 Wt = -1 * n * (viewDir - wn * hit.N) - sqrtf(1 - (n * n) * (1 - wn * wn)) * hit.N; Wt.normalize(); Ray r(hit.P + (EPSILON * Wt), Wt); r.times = ray.times + 1; HitInfo hi; if (scene.trace(hi, r)) L += m_trans * m_kt * hi.material->shade(r, hi, scene); } // add the ambient component L += m_ka; if(DO_BOUNCE && ray.times < BOUNCES) { float v = rand() / (float)RAND_MAX; float u = rand() / (float)RAND_MAX; Vector3 coord = hemisphereSample_cos(u,v); Vector3 unv = Vector3(rand() / (float)RAND_MAX, rand() / (float)RAND_MAX, rand() / (float)RAND_MAX); Vector3 v1 = cross(hit.N, unv); Vector3 v2 = cross(v1, hit.N); Vector3 dir = coord.x * v1 + coord.z * hit.N + coord.y * v2; dir.normalize(); Ray r(hit.P, dir); r.times = ray.times + 1; HitInfo hi; if(scene.trace(hi, r)) L+= m_kd * dot(r.d, hit.N) * hit.material->shade(r, hi, scene); } return L; }
Vector3 Specular::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { printf("Shading specular\n"); Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); Vector3 color = Vector3(m_kd); if (hit.material->hasTexture()) { Vector3 c = Vector3(hit.P); color = m_texture->getColor(c); } // loop over all of the lights HitInfo lightHitReflect = HitInfo(hit); HitInfo lightHitRefract = HitInfo(hit); lightHitReflect.hitNum = hit.hitNum; lightHitRefract.hitNum = hit.hitNum; Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Ray lightRay; Vector3 l = pLight->position() - hit.P; float falloff = l.length2(); l /= sqrt(falloff); /* Calculate the diffuse component - From Labertian Shading Model */ float nDotL = dot(hit.N, l); Vector3 diffuseResult = pLight->color(); diffuseResult *= color; L += std::max(0.0f, nDotL/falloff * pLight->wattage() / PI) * diffuseResult; /* Calculate the specular highlight - From Phong Shading Model */ Vector3 h = (viewDir + l).normalize(); float nDotH = dot(hit.N, h); Vector3 specResult = pLight->color(); specResult *= m_ks; L += pow(std::max(0.0f, nDotH/falloff * pLight->wattage() / PI), m_p) * specResult; /* Calculate the specular reflectance */ if(lightHitReflect.hitNum < 1){ Vector3 r = reflect(hit.N, ray.d); lightRay.d = r.normalize(); lightRay.o = hit.P; if(scene.trace(lightHitReflect, lightRay, 0.0001, r.length())){ lightHitReflect.hitNum = lightHitReflect.hitNum+1; L += lightHitReflect.material->shade(lightRay, lightHitReflect, scene)*m_rl; } } /* Calculate the specular refractance */ // Vector3 incident = viewDir - hit.P; if(lightHitRefract.hitNum < 1 && m_rf > 0.0f ){ Vector3 t = refract(hit.N, ray.d, hit.material->n(), m_n); if(t != Vector3(0.0f)) lightRay.d = t.normalize(); else lightRay.d = t; lightRay.o = hit.P; if(scene.trace(lightHitRefract, lightRay, 0.0001, t.length())){ lightHitRefract.hitNum = lightHitRefract.hitNum+1; L+=lightHitRefract.material->shade(lightRay, lightHitRefract, scene)*m_rf; } else { L+=scene.getBGColor()*m_rf; } } } return L; }
void Quaternion::setRotation(const Vector3 &v1,const Vector3 &v2) { Quaternion q; Vector3 a = v1.cross(v2); this->set(sqrt(v1.length2() * v2.length2()) + v1.dot(v2),a); this->normalize(); }
//Blinn-Phong shading model Vector3 Specular::shade(Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 reflected = Vector3(0.0f, 0.0f, 0.0f); Vector3 L = Vector3(0.0f, 0.0f, 0.0f); //scale down intensity of light in proportion to num of ray bounces Vector3 attenuation = k_s * ( 1 / (ray.numBounces+1)); const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { //find reflected vector, given normal and incident light direction PointLight* pLight = *lightIter; //light vector points from hit point to light Vector3 l = pLight->position() - hit.P; //why did we use ray.d here instead of l? Would just need to change calculation a bit //to use l reflected = ray.d - 2.0f * (dot(hit.N, ray.d)) * hit.N; if (ray.numBounces < maxBounces) { //trace from reflected vector now Ray reflect(ray.numBounces + 1); reflect.o = hit.P; reflect.d = reflected; HitInfo hitReflect; if (scene.trace(hitReflect, reflect, 0.008f)) { //get color from object hit //printf("Bounced reflected ray hit something!\n"); L += attenuation * hitReflect.material->shade(reflect, hitReflect, scene); } else { //get color from background L += Vector3(0,0,0.5f);//bgColor; } } //Get halfway vector Vector3 h = (L + -1 * ray.d).normalize(); Ray shadow_ray(0); HitInfo hi; shadow_ray.o = hit.P; shadow_ray.d = l; //std::cout<<"M = "<<M<< " hit.N = "<<hit.N<<std::endl; if (scene.trace(hi, shadow_ray, 0.001f, sqrt(l.length2()))) { // We are in shadow } else { //get color of light Vector3 color = pLight->color(); //flip vector from eye so points from hit point back to eye //L += k_s * color * pow(std::max(0.0f, dot(h, hit.N)), shinyExp); //L += attenuation * color * pow(std::max(0.0f, dot(reflected, -ray.d)), shinyExp); //Specular Highlights //This is separate from the reflection calculation because it //needs to be dependent on just the shinyExp //https://en.wikipedia.org/wiki/Specular_highlight //Specular calculation for ABSORBED light L += attenuation * pow(std::max(0.0f, dot(h, hit.N)), 50* shinyExp); //check entering or exiting and change n1/n2 n2/n1 //dot product ray.dot.normal //Specular Refraction //L += attenuation * color * pow(std::max(0.0f, dot(wt, -ray.d)), shinyExp); //std::cout<<"Final Refraction vector = "<<(k_s * color * pow(std::max(0.0f, //dot(wt,ray.d)), shinyExp))<<std::endl; } } return L; }
Vector3 PencilShader::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { int m = 0; int totalRays = 0; float step = (float)RAD_H/SAMPLES; std::vector<Vector3> normals; std::vector<HitInfo> hits; for(float r = step; r <= RAD_H; r+=step){ float theta_step = (2.0*M_PI)/(pow(2, r+2)); for(float theta = 0; theta <= 2.0*M_PI; theta += theta_step){ totalRays++; float x = r*cos(theta); float y = r*sin(theta); Ray stencilRay; Vector3 dir = Vector3(ray.d); dir.x += x; dir.y += y; stencilRay.o = ray.o; stencilRay.d = dir; HitInfo h; if(scene.trace(h, stencilRay)){ if(h.objId != hit.objId){ m++; } else{ normals.push_back(Vector3(h.N)); hits.push_back(h); } } else m++; } } //Hit other geometry, outline edge if(m > 0){ return Vector3(0.0f); } float gradient = 0.0; //Check for creases or silhouettes for(int i = 0; i <= normals.size(); i++){ gradient += (dot(normals[i], hit.N))/normals.size(); if(gradient < 0.01) return Vector3(0.0f); } Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Lights *lightlist = scene.lights(); Ray shadow; shadow.o = hit.P - ray.o; Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component shadow.d = l; float nDotL = dot(hit.N, l); //Map into color location L += getTextureColor(nDotL, hit); } return L; }
bool within(Vector3 p, Vector3 r, double rMax, const Grid& g) { double r2 = rMax*rMax; Vector3 d = g.wrapDiff(p - r); return (d.length2() < r2); }
const Vector3 RectangleLight::sampleLight(const unsigned int threadID, const Vector3 &from, const Vector3 &normal, const float time, const Scene &scene, const Vector3 &rVec, float &outSpec, bool isSecondary) const { Ray sampleRay(threadID); HitInfo sampleHit; Vector3 randDir = 0, tmpResult = 0; float e1, e2, tmpSpec = 0; bool cutOff = false; int samplesDone = 0; float samplesDoneRecip = 1.0f; ALIGN_SSE float falloff = 1.0f; do { // Get a random vector into the light e1 = Scene::getRand(threadID); e2 = Scene::getRand(threadID); e2 = (e2 > 0.99) ? 0.99 : e2; randDir = ((m_v1 + e1*(m_v2-m_v1) + e2*(m_v3-m_v1)) - from); float nDotL = dot(normal, randDir); Vector3 E = 0; float attenuate = 1.0f; if (nDotL > epsilon) // Only do work if light can be hit { // the inverse-squared falloff falloff = randDir.length2(); ALIGN_SSE float distanceRecip, distance; #ifndef NO_SSE fastrsqrtss(setSSE(falloff), distanceRecip); recipss(setSSE(falloff), falloff); recipss(setSSE(distanceRecip), distance); #else distance = sqrtf(falloff); distanceRecip = 1.0f / distance; falloff = 1.0f / falloff; #endif randDir *= distanceRecip; nDotL *= distanceRecip; if (m_castShadows) { sampleHit.t = distance - epsilon; // We need this to account for the fact that we CAN hit geometry, to avoid false positives. if (m_fastShadows) { sampleRay.set(threadID, from, randDir, time, 1.001f, 0, 0, IS_SHADOW_RAY); // Create shadow ray if (scene.trace(threadID, sampleHit, sampleRay, epsilon)) // Quick method, returns any hit { attenuate = 0.0f; } } else // Full method, accounts for transparency effects { float distanceTraversed = 0.0f; sampleRay.set(threadID, from, randDir, time, 1.001f, 0, 0, IS_PRIMARY_RAY); // Create primary ray while (distanceTraversed < distance && attenuate > epsilon) { if (scene.trace(threadID, sampleHit, sampleRay, epsilon)) { Vector3 hitN; sampleHit.getInterpolatedNormal(hitN); float nDL = dot(hitN, -randDir); if (nDL > 0.0) // Only attenuate on incoming direction { attenuate *= sampleHit.obj->m_material->refractAmt(); } Vector3 newP = Vector3(sampleRay.o[0], sampleRay.o[1], sampleRay.o[2]) + sampleHit.t * randDir; sampleRay.set(threadID, newP, randDir, time, 1.001f, 0, 0, IS_PRIMARY_RAY); distanceTraversed += sampleHit.t; } else { distanceTraversed = distance; } } } } } else { attenuate = 0.0f; } E = m_power * falloff * _1_4PI; // Light irradiance for this sample samplesDone++; samplesDoneRecip = 1.0f / (float)samplesDone; cutOff = (E * samplesDoneRecip).average() < m_noiseThreshold; // Stop sampling if contribution is below the noise threshold tmpResult += E * attenuate; tmpSpec += max(0.f, dot(rVec, randDir)) * attenuate; } while (samplesDone < m_numSamples && !cutOff); outSpec = tmpSpec * samplesDoneRecip; return tmpResult * samplesDoneRecip; }
Vector3 RefractiveInterface::shade(const Ray& ray, const HitInfo& hit, const Scene& scene, const bool& isFront) const { Ray rayLight; HitInfo hitLight; Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const PointLights *plightlist = scene.pointLights(); // loop over all of the POINT lights PointLights::const_iterator plightIter; for (plightIter = plightlist->begin(); plightIter != plightlist->end(); plightIter++) { PointLight* pLight = *plightIter; Vector3 l = pLight->position() - hit.P; rayLight.o = hit.P; rayLight.d = l.normalized(); Vector3 brdf = BRDF(rayLight.d, hit.N, -ray.d, isFront); if (brdf == 0) continue; if (scene.trace(hitLight, rayLight, 0.0001, l.length())) continue; // the inverse-squared falloff float falloff = l.length2(); float nDotL = fabs(dot(hit.N, l)); Vector3 result = pLight->color(); L += nDotL / falloff * pLight->wattage() *brdf * result; } const AreaLights *alightlist = scene.areaLights(); // loop over all of the lights AreaLights::const_iterator alightIter; for (alightIter = alightlist->begin(); alightIter != alightlist->end(); alightIter++) { AreaLight* aLight = *alightIter; vec3pdf vp = aLight->randPt(); Vector3 l = vp.v - hit.P; // shoot a shadow ray to a random point on the area light rayLight.o = hit.P; rayLight.d = l.normalized(); Vector3 brdf = BRDF(rayLight.d, hit.N, -ray.d, isFront); if (brdf == 0) continue; // if the shadow ray hits the "backside of the light" continue to the next area light if (!aLight->intersect(hitLight, rayLight)){ continue; } // if the shadow ray is occluded by another (hence the "skip") object continue the next light if (scene.trace(hitLight, rayLight, aLight, 0.0001, l.length())){ continue; } // the inverse-squared falloff float falloff = l.length2(); float nDotL = fabs(dot(hit.N, l)); Vector3 result = aLight->color(); L += std::max(0.0f, dot(hitLight.N, -l))* 0.0f, nDotL / falloff* aLight->wattage() / aLight->area() *brdf * result / (vp.p); } // add the ambient component L += m_ka; return L; }
Vector3 CoolWarmShader::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { if(m_edges){ Vector3 hitPoint = hit.P - ray.o; int m = 0; int totalRays = 0; float step = (float)RAD_H/SAMPLES; std::vector<Vector3> normals; for(float r = step; r <= RAD_H; r+=step){ float theta_step = (2.0*M_PI)/(pow(2, r+2)); for(float theta = 0; theta <= 2.0*M_PI; theta += theta_step){ totalRays++; float x = r*cos(theta); float y = r*sin(theta); Ray stencilRay; Vector3 dir = Vector3(ray.d); dir.x += x; dir.y += y; stencilRay.o = ray.o; stencilRay.d = dir; HitInfo h; if(scene.trace(h, stencilRay)){ if(h.objId != hit.objId){ m++; } else{ normals.push_back(h.N); } } else m++; } } } Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); Vector3 color = Vector3(m_kd); if (hit.material->hasTexture()) { Vector3 c = Vector3(hit.P); color = m_texture->getColor(c); } // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component float nDotL = dot(hit.N, l); //Map into color location L += getCellColor(nDotL); } return L; }