void RayTracer::traceOnePhoton(int ignoreX, int ignoreY, int threadID) { ThreadData& threadData(m_threadData[threadID]); Photon photon; emitPhoton(*threadData.rnd, photon); const float MIN_POWER_THRESHOLD = 0.001f / m_settings.photon.numEmitted; float probabilityHint = 1.0; for (int numBounces = 0; (numBounces < m_settings.photon.numBounces) && (photon.power.sum() > MIN_POWER_THRESHOLD); ++numBounces) { // Find the first surface float distance = finf(); const shared_ptr<Surfel>& surfel = castRay(photon.position, -photon.wi, distance, false); if (isNull(surfel)) { return; } // Store the photon (if this is not the first bounce and it is // not a purely specular surface) if ((numBounces > 0) && surfel->nonZeroFiniteScattering()) { photon.effectRadius = photonEffectRadius(probabilityHint); // Update photon position. Store it slightly before it hit the surface // to improve filtering later. photon.position = surfel->position + photon.wi * min(photon.effectRadius, distance) / 4; // Store a copy of this photon m_photonList[threadID].append(photon); } // Scatter Color3 weight; Vector3 wo; float probabilityScale; surfel->scatter(PathDirection::SOURCE_TO_EYE, photon.wi, true, *threadData.rnd, weight, wo, probabilityScale); probabilityHint *= probabilityScale; // Update photon power and direction photon.power *= weight; photon.wi = -wo; photon.position = bump(surfel, wo); } }
// Populate the data set based on the values given for bounding void MandelSet::calculateSet(double xmin, double xmax, double ymin, double ymax){ pixelData.clear(); pixelData.reserve(width*height); // set up pixeldat item std::vector<std::thread> threads; threads.reserve(concurentThreadsSupported); // reserve space for the threads to use std::vector<int> partitions; partitions.reserve(concurentThreadsSupported + 1); // reserve space for the partiion for (unsigned int i = 0; i < concurentThreadsSupported + 1; i++){ partitions.push_back(i*((width * height) / concurentThreadsSupported)); // calculate and push on the next partition reference } std::vector<threadData> tdata; double xdist = (xmax - xmin); double ydist = (ymax - ymin); // initialize used vars double x_scale = xdist / width; // determine pixel scale double y_scale = ydist / height; for (unsigned int i = 0; i < (partitions.size() - 1); i++){ int istart = partitions[i] % width; int jstart = partitions[i] / height; int iend = partitions[i + 1] % width; int jend = partitions[i + 1] / height; tdata.push_back(threadData(istart, iend, jstart, jend, x_scale, y_scale, xmin, ymin,this)); } for (unsigned int i = 0; i < (partitions.size() - 1); i++){ threads.push_back(std::thread(&mandelThread, std::ref(tdata[i]))); } for (unsigned int i = 0; i < threads.size(); i++){ threads[i].join(); } for (unsigned int i = 0; i < tdata.size(); i++){ for (unsigned int j = 0; j < tdata[i].out.size(); j++){ pixelData.push_back(tdata[i].out[j]); } } }
void RayTracer::traceOnePixel(int x, int y, int threadID) { ThreadData& threadData(m_threadData[threadID]); Radiance3 L; if (m_settings.sqrtNumPrimaryRays == 1) { // Through pixel center L = traceOnePrimaryRay(float(x) + 0.5f, float(y) + 0.5f, threadData); } else { const float denom = 1.0f / m_settings.sqrtNumPrimaryRays; for (int i = 0; i < m_settings.sqrtNumPrimaryRays; ++i) { for (int j = 0; j < m_settings.sqrtNumPrimaryRays; ++j) { // Place the sample taps in a centered regular grid L += traceOnePrimaryRay(float(x) + (i + 0.5f) * denom, float(y) + (j + 0.5f) * denom, threadData); } } L /= square((float)m_settings.sqrtNumPrimaryRays); } m_image->set(x, y, L); }
waitAny::waitAny() : td(*threadData()), readyState(nullptr) {}