⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bucketrenderer.java

📁 Sunflow是一个照片级的渲染系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
            for (int x = 0; x < sbw; x++, index++) {
                int sx = sx0 + x;
                int sy = sy0 + y;
                int j = sx & (sigma.length - 1);
                int k = sy & (sigma.length - 1);
                int i = j * sigma.length + sigma[k];
                float dx = useJitter ? (float) sigma[k] / (float) sigma.length : 0.5f;
                float dy = useJitter ? (float) sigma[j] / (float) sigma.length : 0.5f;
                float rx = (sx + dx) * invSubPixelSize;
                float ry = (sy + dy) * invSubPixelSize;
                ry = imageHeight - ry - 1;
                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(Module.BCKT, "Dumping bucket [%d, %d] to file ...", bx, by);
            Bitmap bitmap = new Bitmap(sbw, sbh, true);
            for (int y = sbh - 1, index = 0; y >= 0; y--)
                for (int x = 0; x < sbw; x++, index++)
                    bitmap.setPixel(x, y, samples[index].c.copy().toNonLinear());
            bitmap.save(String.format("bucket_%04d_%04d.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);
                }
            }
        } else {
            // filter samples into pixels
            float cy = imageHeight - 1 - (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 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);
                            weight += f;
                        }
                    }
                    c.mul(1.0f / weight);
                    bucketRGB[index] = c;
                }
            }
        }
        // update pixels
        display.imageUpdate(x0, y0, bw, bh, bucketRGB);
    }

    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 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);
    }

    private static final class ImageSample {
        float rx, ry;
        int i, n;
        Color c;
        Instance instance;
        Shader shader;
        float nx, ny, nz;

        ImageSample(float rx, float ry, int i) {
            this.rx = rx;
            this.ry = ry;
            this.i = i;
            n = 0;
            c = null;
            instance = null;
            shader = null;
            nx = ny = nz = 1;
        }

        final void set(ShadingState state) {
            if (state == null)
                c = Color.BLACK;
            else {
                c = state.getResult();
                checkNanInf();
                shader = state.getShader();
                instance = state.getInstance();
                if (state.getNormal() != null) {
                    nx = state.getNormal().x;
                    ny = state.getNormal().y;
                    nz = state.getNormal().z;
                }
            }
            n = 1;
        }

        final void add(ShadingState state) {
            if (n == 0)
                c = Color.black();
            if (state != null) {
                c.add(state.getResult());
                checkNanInf();
            }
            n++;
        }

        final void checkNanInf() {
            if (c.isNan())
                UI.printError(Module.BCKT, "NaN shading sample!");
            else if (c.isInf())
                UI.printError(Module.BCKT, "Inf shading sample!");

        }

        final void scale(float s) {
            c.mul(s);
        }

        final boolean processed() {
            return c != null;
        }
        
        final boolean sampled() {
            return n > 0;
        }

        final boolean 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;
            // 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;
        }

        static final 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;
            return result;
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -