Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        private int progressiveRenderNext(IntersectionState istate)
        {
            int         TASK_SIZE = 16;
            SmallBucket first     = smallBucketQueue.Count > 0 ? smallBucketQueue.Dequeue() : null;

            if (first == null)
            {
                return(0);
            }
            int  ds      = first.size / TASK_SIZE;
            bool useMask = smallBucketQueue.Count != 0;
            int  mask    = 2 * first.size / TASK_SIZE - 1;
            int  pixels  = 0;

            for (int i = 0, y = first.y; i < TASK_SIZE && y < imageHeight; i++, y += ds)
            {
                for (int j = 0, x = first.x; j < TASK_SIZE && x < imageWidth; j++, x += ds)
                {
                    // check to see if this is a pixel from a higher level tile
                    if (useMask && (x & mask) == 0 && (y & mask) == 0)
                    {
                        continue;
                    }
                    int          instance = ((x & ((1 << QMC.MAX_SIGMA_ORDER) - 1)) << QMC.MAX_SIGMA_ORDER) + QMC.sigma(y & ((1 << QMC.MAX_SIGMA_ORDER) - 1), QMC.MAX_SIGMA_ORDER);
                    double       time     = QMC.halton(1, instance);
                    double       lensU    = QMC.halton(2, instance);
                    double       lensV    = QMC.halton(3, instance);
                    ShadingState state    = scene.getRadiance(istate, x, imageHeight - 1 - y, lensU, lensV, time, instance, 4, null);
                    Color        c        = state != null?state.getResult() : Color.BLACK;

                    pixels++;
                    // fill region
                    display.imageFill(x, y, Math.Min(ds, imageWidth - x), Math.Min(ds, imageHeight - y), c, state == null ? 0 : 1);
                }
            }
            if (first.size >= 2 * TASK_SIZE)
            {
                // generate child buckets
                int size = (int)((uint)first.size >> 1);//>>>
                for (int i = 0; i < 2; i++)
                {
                    if (first.y + i * size < imageHeight)
                    {
                        for (int j = 0; j < 2; j++)
                        {
                            if (first.x + j * size < imageWidth)
                            {
                                SmallBucket b = new SmallBucket();
                                b.x         = first.x + j * size;
                                b.y         = first.y + i * size;
                                b.size      = size;
                                b.constrast = 1.0f / size;
                                smallBucketQueue.Enqueue(b);
                            }
                        }
                    }
                }
            }
            return(pixels);
        }