Beispiel #1
0
 public void AddSample(ImageSample sample)
 {
     int previousCount = Samples.Count;
     Samples.Add(sample);
     int diff = Samples.Count - previousCount;
     if (diff > 0)
     {
         // add sample only if it is not a duplicate
         SampleMap.Add(sample.Y * Width + sample.X, sample);
     }
 }
Beispiel #2
0
            public static ImageSample bilerp(ImageSample result, ImageSample i00, ImageSample i01, ImageSample i10, ImageSample i11, float dx, float dy)
            {
                float k00 = (1.0f - dx) * (1.0f - dy);
                float k01 = (1.0f - dx) * dy;
                float k10 = dx * (1.0f - dy);
                float k11 = dx * dy;
                Color c00 = i00.c;
                Color c01 = i01.c;
                Color c10 = i10.c;
                Color c11 = i11.c;
                Color c = Color.mul(k00, c00);
                c.madd(k01, c01);
                c.madd(k10, c10);
                c.madd(k11, c11);
                result.c = c;
				result.alpha = k00 * i00.alpha + k01 * i01.alpha + k10 * i10.alpha + k11 * i11.alpha;
                return result;
            }
Beispiel #3
0
            public bool isDifferent(ImageSample sample, float thresh)
            {
                if (instance != sample.instance)
                    return true;
                if (shader != sample.shader)
                    return true;
                if (Color.hasContrast(c, sample.c, thresh))
                    return true;
				if (Math.Abs(alpha - sample.alpha) / (alpha + sample.alpha) > thresh)
					return true;
                // only compare normals if this pixel has not been averaged
                float dot = (nx * sample.nx + ny * sample.ny + nz * sample.nz);
                return dot < 0.9f;
            }
Beispiel #4
0
        private void refineSamples(ImageSample[] samples, int sbw, int x, int y, int stepSize, float thresh, IntersectionState istate)
        {
            int dx = stepSize;
            int dy = stepSize * sbw;
            int i00 = x + y * sbw;
            ImageSample s00 = samples[i00];
            ImageSample s01 = samples[i00 + dy];
            ImageSample s10 = samples[i00 + dx];
            ImageSample s11 = samples[i00 + dx + dy];
            if (!s00.sampled())
                computeSubPixel(s00, istate);
            if (!s01.sampled())
                computeSubPixel(s01, istate);
            if (!s10.sampled())
                computeSubPixel(s10, istate);
            if (!s11.sampled())
                computeSubPixel(s11, istate);
            if (stepSize > minStepSize)
            {
                if (s00.isDifferent(s01, thresh) || s00.isDifferent(s10, thresh) || s00.isDifferent(s11, thresh) || s01.isDifferent(s11, thresh) || s10.isDifferent(s11, thresh) || s01.isDifferent(s10, thresh))
                {
                    stepSize >>= 1;
                    thresh *= 2;
                    refineSamples(samples, sbw, x, y, stepSize, thresh, istate);
                    refineSamples(samples, sbw, x + stepSize, y, stepSize, thresh, istate);
                    refineSamples(samples, sbw, x, y + stepSize, stepSize, thresh, istate);
                    refineSamples(samples, sbw, x + stepSize, y + stepSize, stepSize, thresh, istate);
                    return;
                }
            }

            // interpolate remaining samples
            float ds = 1.0f / stepSize;
            for (int i = 0; i <= stepSize; i++)
                for (int j = 0; j <= stepSize; j++)
                    if (!samples[x + i + (y + j) * sbw].processed())
                        ImageSample.bilerp(samples[x + i + (y + j) * sbw], s00, s01, s10, s11, i * ds, j * ds);
        }
Beispiel #5
0
 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, 4, null));
         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, 4, null));
         }
         sample.scale((float)invSuperSampling);
     }
     else
     {
         // single sample
         sample.set(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i, 4, null));
     }
 }
Beispiel #6
0
        private void renderBucket(IDisplay display, int bx, int by, int threadID, IntersectionState istate)
        {
            // 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];

            // subpixel extents
            int sx0 = x0 * subPixelSize - fs;
            int sy0 = y0 * subPixelSize - fs;
            int sbw = bw * subPixelSize + fs * 2;
            int sbh = bh * subPixelSize + fs * 2;

            // round up to align with maximum step size
            sbw = (sbw + (maxStepSize - 1)) & (~(maxStepSize - 1));
            sbh = (sbh + (maxStepSize - 1)) & (~(maxStepSize - 1));
            // extra padding as needed
            if (maxStepSize > 1)
            {
                sbw++;
                sbh++;
            }
            // allocate bucket memory
            ImageSample[] samples = new ImageSample[sbw * sbh];
            // allocate samples and compute jitter offsets
            float invSubPixelSize = 1.0f / subPixelSize;
            for (int y = 0, index = 0; y < sbh; y++)
            {
                for (int x = 0; x < sbw; x++, index++)
                {
                    int sx = sx0 + x;
                    int sy = sy0 + y;
					int j = sx & (sigmaLength - 1);
					int k = sy & (sigmaLength - 1);
					int i = (j << sigmaOrder) + QMC.sigma(k, sigmaOrder);
					float dx = useJitter ? (float) QMC.halton(0, k) : 0.5f;
					float dy = useJitter ? (float) QMC.halton(0, j) : 0.5f;
                    float rx = (sx + dx) * invSubPixelSize;
                    float ry = (sy + dy) * invSubPixelSize;
                    ry = imageHeight - ry;
                    samples[index] = new ImageSample(rx, ry, i);
                }
            }
            for (int x = 0; x < sbw - 1; x += maxStepSize)
                for (int y = 0; y < sbh - 1; y += maxStepSize)
                    refineSamples(samples, sbw, x, y, maxStepSize, thresh, istate);
            if (dumpBuckets)
            {
                UI.printInfo(UI.Module.BCKT, "Dumping bucket [{0}, {1}] to file ...", bx, by);
				GenericBitmap bitmap = new GenericBitmap(sbw, sbh);
				for (int y = sbh - 1, index = 0; y >= 0; y--)
                    for (int x = 0; x < sbw; x++, index++)
						bitmap.writePixel(x, y, samples[index].c, samples[index].alpha);
                bitmap.save(string.Format("bucket_{0}_{1}.png", bx, by));
            }
            if (displayAA)
            {
                // color coded image of what is visible
                float invArea = invSubPixelSize * invSubPixelSize;
                for (int y = 0, index = 0; y < bh; y++)
                {
                    for (int x = 0; x < bw; x++, index++)
                    {
                        int sampled = 0;
                        for (int i = 0; i < subPixelSize; i++)
                        {
                            for (int j = 0; j < subPixelSize; j++)
                            {
                                int sx = x * subPixelSize + fs + i;
                                int sy = y * subPixelSize + fs + j;
                                int s = sx + sy * sbw;
                                sampled += samples[s].sampled() ? 1 : 0;
                            }
                        }
                        bucketRGB[index] = new Color(sampled * invArea);
						bucketAlpha[index] = 1.0f;
                    }
                }
            }
            else
            {
                // filter samples into pixels
                float cy = imageHeight - (y0 + 0.5f);
                for (int y = 0, index = 0; y < bh; y++, cy--)
                {
                    float cx = x0 + 0.5f;
                    for (int x = 0; x < bw; x++, index++, cx++)
                    {
                        Color c = Color.black();
						float a = 0.0f;
                        float weight = 0.0f;
                        for (int j = -fs, sy = y * subPixelSize; j <= fs; j++, sy++)
                        {
                            for (int i = -fs, sx = x * subPixelSize, s = sx + sy * sbw; i <= fs; i++, sx++, s++)
                            {
                                float dx = samples[s].rx - cx;
                                if (Math.Abs(dx) > fhs)
                                    continue;
                                float dy = samples[s].ry - cy;
                                if (Math.Abs(dy) > fhs)
                                    continue;
                                float f = filter.get(dx, dy);
                                c.madd(f, samples[s].c);
								a += f * samples[s].alpha;
                                weight += f;
                            }
                        }
						float invWeight = 1.0f / weight;
						c.mul(invWeight);
						a *= invWeight;
                        bucketRGB[index] = c;
						bucketAlpha[index] = a;
					}
                }
            }
            // update pixels
            display.imageUpdate(x0, y0, bw, bh, bucketRGB, bucketAlpha);
        }