private void computeSubPixel(ImageSample sample, IntersectionState istate) { float x = sample.rx; float y = sample.ry; double q0 = QMC.halton(1, sample.i); double q1 = QMC.halton(2, sample.i); double q2 = QMC.halton(3, sample.i); if (superSampling > 1) { // multiple sampling sample.add(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i)); for (int i = 1; i < superSampling; i++) { double time = QMC.mod1(q0 + i * invSuperSampling); double lensU = QMC.mod1(q1 + QMC.halton(0, i)); double lensV = QMC.mod1(q2 + QMC.halton(1, i)); sample.add(scene.getRadiance(istate, x, y, lensU, lensV, time, sample.i + i)); } sample.scale((float)invSuperSampling); } else { // single sample sample.set(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i)); } }
private void renderBucket(IDisplay display, int bx, int by, int threadID, IntersectionState istate, ShadingCache cache) { // pixel sized extents int x0 = bx * bucketSize; int y0 = by * bucketSize; int bw = Math.Min(bucketSize, imageWidth - x0); int bh = Math.Min(bucketSize, imageHeight - y0); // prepare bucket display.imagePrepare(x0, y0, bw, bh, threadID); Color[] bucketRGB = new Color[bw * bh]; float[] bucketAlpha = new float[bw * bh]; for (int y = 0, i = 0, cy = imageHeight - 1 - y0; y < bh; y++, cy--) { for (int x = 0, cx = x0; x < bw; x++, i++, cx++) { // sample pixel Color c = Color.black(); float a = 0; int instance = ((cx & ((1 << QMC.MAX_SIGMA_ORDER) - 1)) << QMC.MAX_SIGMA_ORDER) + QMC.sigma(cy & ((1 << QMC.MAX_SIGMA_ORDER) - 1), QMC.MAX_SIGMA_ORDER); double jitterX = QMC.halton(0, instance); double jitterY = QMC.halton(1, instance); double jitterT = QMC.halton(2, instance); double jitterU = QMC.halton(3, instance); double jitterV = QMC.halton(4, instance); for (int s = 0; s < numSamples; s++) { float rx = cx + 0.5f + (float)warpCubic(QMC.mod1(jitterX + s * invNumSamples)); float ry = cy + 0.5f + (float)warpCubic(QMC.mod1(jitterY + QMC.halton(0, s))); double time = QMC.mod1(jitterT + QMC.halton(1, s)); double lensU = QMC.mod1(jitterU + QMC.halton(2, s)); double lensV = QMC.mod1(jitterV + QMC.halton(3, s)); ShadingState state = scene.getRadiance(istate, rx, ry, lensU, lensV, time, instance + s, 5, cache); if (state != null) { c.add(state.getResult()); a++; } } bucketRGB[i] = c.mul(invNumSamples); bucketAlpha[i] = a * invNumSamples; if (cache != null) { cache.reset(); } } } // update pixels display.imageUpdate(x0, y0, bw, bh, bucketRGB, bucketAlpha); }
/** * Get a QMC sample from a finite sequence of n elements. This provides * better stratification than the infinite version, but does not allow for * adaptive sampling. * * @param j sample number (starts from 0) * @param dim dimension to sample * @param n number of samples * @return pseudo-random value in [0,1) */ public double getRandom(int j, int dim, int n) { switch (dim) { case 0: return(QMC.mod1(qmcD0I + (double)j / (double)n)); case 1: return(QMC.mod1(qmcD1I + QMC.halton(0, j))); default: return(QMC.mod1(QMC.halton(d + dim, i) + QMC.halton(dim - 1, j))); } }