// TODO: implement adaptive supersampling RGBColour World::colourForPixelAt(int i, int j) { double d = viewport.getViewingDistance(); if (ss_level == 1) { // no super-sampling double uValue = viewport.uAmount(i, 1, 0, false); double vValue = viewport.vAmount(j, 1, 0, false); vec3 direction = wAxis.scaled(-d) + uAxis.scaled(uValue) + vAxis.scaled(vValue); Ray theRay(cameraPosition, direction); return RGBColour(traceRay(theRay, 0.0, 0)); } // 0.01 => x16, 1.2 => x64 double thresholds[2] = {0.01, 1.2}; double var = 0.0; int lvl_log = 2; RGBVec pixelColour; while (lvl_log <= ss_level) { pixelColour = RGBVec(0.0,0.0,0.0); int lvl = int_pow(2, lvl_log - 1); double scale_factor = 1.0 / static_cast<double>(lvl*lvl); vec3 sum_x_sq(0.0,0.0,0.0); for (int a = 0; a < lvl; a++) { for (int b = 0; b < lvl; b++) { double uValue = viewport.uAmount(i, ss_level, a, lvl_log > 2); double vValue = viewport.vAmount(j, ss_level, b, lvl_log > 2); vec3 direction = wAxis.scaled(-d) + uAxis.scaled(uValue) + vAxis.scaled(vValue); Ray theRay(cameraPosition, direction); RGBVec sample = traceRay(theRay, 0.0, 0).scaled(scale_factor); pixelColour += sample; if (ss_level > 2) sum_x_sq += sample.getVector().pointwise(sample.getVector()); } } if (lvl_log == 2 && ss_level > 2) { vec3 varvec = sum_x_sq.scaled(scale_factor) - pixelColour.getVector().pointwise(pixelColour.getVector()); var = varvec.magnitude(); if (i % 100 == 0 && j % 100 == 0) std::cout << "var: " << var << std::endl; } if (var < thresholds[lvl_log - 2] || lvl_log == ss_level) break; lvl_log++; } if (lvl_log == 2) renderStats.ss_x4++; else if (lvl_log == 3) renderStats.ss_x16++; else if (lvl_log == 4) renderStats.ss_x64++; return RGBColour(pixelColour); }
Ray ray_for_pixel (int x_, int y_) const { float delta_x = float((x_ + 0.5f) - m_x_res * 0.5f) / (m_x_res * 0.5f); float delta_y = float((y_ + 0.5f) - m_y_res * 0.5f) / (m_y_res * 0.5f); // initialize ray diffferentials Vector3D d = m_z + (m_x * delta_x) + (m_y * delta_y); Vector3D dPdx, dPdy, dDdx, dDdy; dDdx = (( (m_x * d.dot(d)) - (d * d.dot(m_x)) )*(1.f/std::pow(d.dot(d), 1.5))) * (1.f/((float)m_x_res*0.5f)); dDdy = (( (m_y * d.dot(d)) - (d * d.dot(m_y)) )*(1.f/std::pow(d.dot(d), 1.5))) * (1.f/((float)m_y_res*0.5f)); Ray theRay(m_pos, d.normalize()); theRay.setdDdx(dDdx); theRay.setdDdy(dDdy); theRay.setdPdx(dPdx); theRay.setdPdy(dPdy); return theRay; }