inline bool Triangle::intersect(Ray& ray, Intersection& intersection) { vec3 pvec = cross(ray.direction, edge2); float det = dot(edge1, pvec); if(det <= 0.0) return false; vec3 tvec = ray.origin - vert0; float u = dot(tvec, pvec); if(u < 0.0f || u > det) return false; vec3 qvec = cross(tvec, edge1); float v = dot(ray.direction, qvec); if(v < 0.0f || u + v > det) return false; float t = dot(edge2, qvec); float inv_det = 1.0f / det; t *= inv_det; //u *= inv_det; //v *= inv_det; if(t >= intersection.getT()) return false; intersection.set(t, ray.getPosition(t), cross(edge1, edge2), edge1, this); return true; }
Color AtmospherePathTracingIntegrator::transmittance( SceneCPtr scene, const Ray &r, bool debug )const { Atmosphere::LUTParameters &parms = scene->m_atmosphere->m_parameters; const Real heightOffset = (Real)parms.R_e+0.1f; // move to correct height Ray ray = r; ray.o += Vector( 0.0f, heightOffset, 0.0f ); // find intersection with outer atmosphere Real t0,t1; if (!math::intersectionRaySphere<Real>( ray, (Real)parms.R_a, t0, t1)) return math::Vec3f(1.0f); if( t1 > ray.tmax ) t1 = ray.tmax; unsigned numSamples = parms.viewRaySamples*m_numStepsMultiplier; Real segmentLength = t1 / numSamples; //Real segmentLength = 200.0f; //unsigned numSamples = int(t1 / segmentLength); //Real tCurrent = 0.0; //math::Vec3f sumR(0.0f), sumM(0.0f); Real densityR = Real(0.0); Real densityM = Real(0.0); for (unsigned i = 0; i < numSamples; ++i) { Vector samplePosition = ray.getPosition(i*segmentLength); Real height = samplePosition.getLength() - (Real)parms.R_e; Real currentDensityR = exp(-height / parms.h_r)*segmentLength; Real currentDensityM = exp(-height / parms.h_m)*segmentLength; densityR += (Real)currentDensityR; densityM += (Real)currentDensityM; } Vector opticalDepth = (Vector)parms.beta_r*densityR + (Vector)parms.beta_m*Real(1.1)*densityM; return Vector( exp(-opticalDepth.x), exp(-opticalDepth.y), exp(-opticalDepth.z) ); }
// inter_point : Poistion where ray intersected with geometry. VolumeTracer::Interval VolumeTracer::getInterval(Ray ray, IVolume* volume, vec3 inter_point) { OBB::IntervalData intersect = volume->getInterval(ray); if(!intersect.intersected) return Interval(); vec3 min = intersect.min; vec3 max = intersect.max; if(intersect.inside) // If we're inside the box, we have no min, put ray position to min. min = ray.getPosition(); float dist = glm::distance(min, max); // If inter_point is within the volume, move it to max if(glm::distance(min, inter_point) < dist) max = inter_point; return Interval(true, min, max); }
IAccDataStruct::IntersectionData Heightmap::triangleIntersection(Ray ray, Triangle* triangle1, Triangle* triangle2) { vec3 o = ray.getPosition(); vec3 d = ray.getDirection(); Triangle* closest_tri = NULL; //float closest_dist = -1; vec3 closest_pos; float closest_t = numeric_limits<float>::infinity( ); for(int i = 0; i < 2; i++) { Triangle* cur_triangle; switch (i) { case 0: cur_triangle = triangle1; break; case 1: cur_triangle = triangle2; break; default: cur_triangle = triangle1; break; } const vector<vec3*> vertices = cur_triangle->getVertices(); vec3 v0 = *(vertices[0]); vec3 v1 = *(vertices[1]); vec3 v2 = *(vertices[2]); vec3 e1 = v1 - v0; vec3 e2 = v2 - v0; vec3 s = o - v0; vec3 dxe2 = cross(d, e2); vec3 sxe1 = cross(s, e1); vec3 res = ( 1.0f / dot(dxe2, e1) ) * vec3( dot(sxe1, e2), dot(dxe2, s), dot(sxe1, d) ); float t = res.x; float u = res.y; float v = res.z; float dist = glm::distance(o, closest_pos); if(u >= 0 && v >= 0 && u + v <= 1) { // Intersection! if(t > 0 && t < closest_t) { closest_tri = cur_triangle; closest_pos = o + t * d; //closest_dist = dist; closest_t = t; } } } if(closest_t == numeric_limits<float>::infinity( )) { return IAccDataStruct::IntersectionData::miss(); } vec3 v1v0 = *(closest_tri->getVertices()[1]) - *(closest_tri->getVertices()[0]); vec3 v2v1 = *(closest_tri->getVertices()[2]) - *(closest_tri->getVertices()[1]); vec3 v2v0 = *(closest_tri->getVertices()[2]) - *(closest_tri->getVertices()[0]); vec3 pv0 = closest_pos - *(closest_tri->getVertices()[0]); vec3 pv1 = closest_pos - *(closest_tri->getVertices()[1]); float a = length(cross(v1v0, v2v0)); float a0 = length(cross(v2v1, pv1))/a; float a1 = length(cross(v2v0, pv0))/a; float a2 = length(cross(v1v0, pv0))/a; vec3 inter_normal = a0 * *(closest_tri->getNormals()[0]) + a1 * *(closest_tri->getNormals()[1]) + a2 * *(closest_tri->getNormals()[2]); vec3 v1 = v1v0; vec3 v2 = v2v1; if(v1.length() > v2.length()) { v1 = v2v1; v1 = v1v0; } if(v2.length() > v2v0.length()) { v2 = v2v0; } return IAccDataStruct::IntersectionData(NULL, 0, closest_pos, glm::normalize(inter_normal), vec2(0,0)); }
Color AtmospherePathTracingIntegrator::Li( SceneCPtr scene, RendererCPtr renderer, const Ray &r, Color &transmittance, bool debug) const { Debug dd; Atmosphere::LUTParameters &parms = scene->m_atmosphere->m_parameters; const Real heightOffset = (Real)parms.R_e+0.1f; // move to correct height Ray ray = r; ray.o += Vector( 0.0f, heightOffset, 0.0f ); // find intersection with outer atmosphere Real t0,t1; if (!math::intersectionRaySphere<Real>( ray, (Real)parms.R_a, t0, t1)) return math::Vec3f(1.0f); if( t1 > ray.tmax ) t1 = ray.tmax; if( t0 < ray.tmin ) t0 = ray.tmin; ///* Real maxDist = t1-t0; //Real stepSize = maxDist/(parms.viewRaySamples); Real stepSize = 1.0f; //Real stepSize = m_stepSize; Vector step = ray.d*stepSize; Real tend; Real volSamplePDF; Vector x; ///* // uniform sampling --------------- tend = t0 + math::g_randomNumber.randomFloat()*maxDist; volSamplePDF = 1.0f/maxDist; // raymarch to tend and compute transmittance Real t = t0;// + math::g_randomNumber.randomFloat()*stepSize; x = ray.getPosition( t ); Real densityR = 0.0f; Real densityM = 0.0f; while( t<tend ) { Real height = x.getLength() - (Real)parms.R_e; Real currentDensityR = exp(-height / parms.h_r)*stepSize; Real currentDensityM = exp(-height / parms.h_m)*stepSize; densityR += currentDensityR; densityM += currentDensityM; t += stepSize; x += step; }; Vector opticalDepth = (Vector)parms.beta_r*densityR + (Vector)parms.beta_m*Real(1.1)*densityM; Vector transmittanceView = Vector( exp(-opticalDepth.x), exp(-opticalDepth.y), exp(-opticalDepth.z) ); //*/ /* // woodcock tracking Real maxDensity = 6.0f; Real densityEnd = -log( math::g_randomNumber.randomFloat() ) / maxDensity; // raymarch to tend and compute transmittance Real densityR = 0.0f; Real densityM = 0.0f; tend = t0; x = ray.getPosition(tend); while( (densityR+densityM<maxDensity)&&(tend<t1) ) { Real height = x.getLength() - (Real)parms.R_e; Real currentDensityR = exp(-height / parms.h_r)*stepSize; Real currentDensityM = exp(-height / parms.h_m)*stepSize; densityR += currentDensityR; densityM += currentDensityM; tend += stepSize; x += step; }; Vector opticalDepth = (Vector)parms.beta_r*densityR + (Vector)parms.beta_m*Real(1.1)*densityM; Vector transmittanceView = Vector( exp(-opticalDepth.x), exp(-opticalDepth.y), exp(-opticalDepth.z) ); volSamplePDF = exp(-(densityR+densityM))*maxDensity; */ /* // woodcock tracking2 Real maxDensity = 2.0f; Real densityEnd = -log( math::g_randomNumber.randomFloat() ) / maxDensity; // raymarch to tend and compute transmittance Real densityR = 0.0f; Real densityM = 0.0f; tend = t0; while(tend < t1) { tend += -log( math::g_randomNumber.randomFloat() ) / maxDensity; x = ray.getPosition(tend); Real height = x.getLength() - (Real)parms.R_e; Real currentDensityR = exp(-height / parms.h_r); Real currentDensityM = exp(-height / parms.h_m); densityR += currentDensityR; densityM += currentDensityM; if( math::g_randomNumber.randomFloat() < (currentDensityR+currentDensityM)/maxDensity ) break; }; Vector opticalDepth = (Vector)parms.beta_r*densityR + (Vector)parms.beta_m*Real(1.1)*densityM; Vector transmittanceView = Vector( exp(-opticalDepth.x), exp(-opticalDepth.y), exp(-opticalDepth.z) ); volSamplePDF = exp(-(densityR+densityM))*maxDensity; */ // --- Real nu = math::dot( ray.d, (Vector)scene->m_atmosphere->m_sunDirection ); Real phaseR = (Real)(3.0f / (16.0f * Real(MATH_PIf))) * (1.0f + nu * nu); Real g = (Real)parms.mie_phase_g; Real phaseM = (3 / (8 * Real(MATH_PI))) * (((1 - g * g) * (1 + nu * nu))/((2 + g * g) * pow(1 + g * g - 2 * g * nu, Real(1.5)))); Color Ls(0.0f); // single scattering { LightCPtr light = scene->m_lights[0]; Vector lx = x - Vector( 0.0f, heightOffset, 0.0f ); Vector wi; Real pdf; Ray vis; // visibility ray Color Li = light->sample_L( lx, wi, pdf, vis ); Color transmittanceLight = renderer->transmittance( scene, vis ); Real height = x.getLength() - (Real)parms.R_e; Real currentDensityR = exp(-height / parms.h_r)*stepSize; Real currentDensityM = exp(-height / parms.h_m)*stepSize; Color tt = transmittanceView*transmittanceLight; Color sum_r = tt*phaseR*currentDensityR*parms.beta_r; Color sum_m = tt*phaseM*currentDensityM*parms.beta_m*Real(1.1f); Ls += Li*(sum_r + sum_m)/pdf; ///* if( debug ) { Debug dd; dd.tend = tend; dd.transmittance = transmittanceLight; dd.Li = Ls; debugData.push_back(dd); } //*/ } transmittance = this->transmittance(scene, r); return Ls/volSamplePDF; }
Ray Transform::transform( const Ray &i_ray, const glm::mat4 &i_transform ) { glm::vec3 position = Transform::transform( i_ray.getPosition(), i_transform ); glm::vec3 direction = Transform::transform( i_ray.getDirection(), i_transform, false ); return Ray( position, direction ); }