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

📄 globalphotonmap.java

📁 Sunflow是一个照片级的渲染系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
            return (dx * dx) + (dy * dy) + (dz * dz);
        }
    }

    public void init() {
        UI.printInfo(Module.LIGHT, "Balancing global photon map ...");
        UI.taskStart("Balancing global photon map", 0, 1);
        Timer t = new Timer();
        t.start();
        balance();
        t.end();
        UI.taskStop();
        UI.printInfo(Module.LIGHT, "Global photon map:");
        UI.printInfo(Module.LIGHT, "  * Photons stored:   %d", storedPhotons);
        UI.printInfo(Module.LIGHT, "  * Photons/estimate: %d", numGather);
        UI.printInfo(Module.LIGHT, "  * Estimate radius:  %.3f", gatherRadius);
        maxRadius = 1.4f * (float) Math.sqrt(maxPower * numGather);
        UI.printInfo(Module.LIGHT, "  * Maximum radius:   %.3f", maxRadius);
        UI.printInfo(Module.LIGHT, "  * Balancing time:   %s", t.toString());
        if (gatherRadius > maxRadius)
            gatherRadius = maxRadius;
        t.start();
        precomputeRadiance();
        t.end();
        UI.printInfo(Module.LIGHT, "  * Precompute time:  %s", t.toString());
        UI.printInfo(Module.LIGHT, "  * Radiance photons: %d", storedPhotons);
        UI.printInfo(Module.LIGHT, "  * Search radius:    %.3f", gatherRadius);
    }

    public void precomputeRadiance() {
        if (storedPhotons == 0)
            return;
        // precompute the radiance for all photons that are neither
        // leaves nor parents of leaves in the tree.
        int quadStoredPhotons = halfStoredPhotons / 2;
        Point3 p = new Point3();
        Vector3 n = new Vector3();
        Point3 ppos = new Point3();
        Vector3 pdir = new Vector3();
        Vector3 pvec = new Vector3();
        Color irr = new Color();
        Color pow = new Color();
        float maxDist2 = gatherRadius * gatherRadius;
        NearestPhotons np = new NearestPhotons(p, numGather, maxDist2);
        Photon[] temp = new Photon[quadStoredPhotons + 1];
        UI.taskStart("Precomputing radiance", 1, quadStoredPhotons);
        for (int i = 1; i <= quadStoredPhotons; i++) {
            UI.taskUpdate(i);
            Photon curr = photons[i];
            p.set(curr.x, curr.y, curr.z);
            Vector3.decode(curr.normal, n);
            irr.set(Color.BLACK);
            np.reset(p, maxDist2);
            locatePhotons(np);
            if (np.found < 8) {
                curr.data = 0;
                temp[i] = curr;
                continue;
            }
            float invArea = 1.0f / ((float) Math.PI * np.dist2[0]);
            float maxNDist = np.dist2[0] * 0.05f;
            for (int j = 1; j <= np.found; j++) {
                Photon phot = np.index[j];
                Vector3.decode(phot.dir, pdir);
                float cos = -Vector3.dot(pdir, n);
                if (cos > 0.01f) {
                    ppos.set(phot.x, phot.y, phot.z);
                    Point3.sub(ppos, p, pvec);
                    float pcos = Vector3.dot(pvec, n);
                    if ((pcos < maxNDist) && (pcos > -maxNDist))
                        irr.add(pow.setRGBE(phot.power));
                }
            }
            irr.mul(invArea);
            // compute radiance
            irr.mul(new Color(curr.data)).mul(1.0f / (float) Math.PI);
            curr.data = irr.toRGBE();
            temp[i] = curr;
        }
        UI.taskStop();

        // resize photon map to only include irradiance photons
        numGather /= 4;
        maxRadius = 1.4f * (float) Math.sqrt(maxPower * numGather);
        if (gatherRadius > maxRadius)
            gatherRadius = maxRadius;
        storedPhotons = quadStoredPhotons;
        halfStoredPhotons = storedPhotons / 2;
        log2n = (int) Math.ceil(Math.log(storedPhotons) / Math.log(2.0));
        photons = temp;
        hasRadiance = true;
    }

    public Color getRadiance(Point3 p, Vector3 n) {
        if (!hasRadiance || (storedPhotons == 0))
            return Color.BLACK;
        float px = p.x;
        float py = p.y;
        float pz = p.z;
        int i = 1;
        int level = 0;
        int cameFrom;
        float dist2;
        float maxDist2 = gatherRadius * gatherRadius;
        Photon nearest = null;
        Photon curr;
        Vector3 photN = new Vector3();
        float[] dist1d2 = new float[log2n];
        int[] chosen = new int[log2n];
        while (true) {
            while (i < halfStoredPhotons) {
                float dist1d = photons[i].getDist1(px, py, pz);
                dist1d2[level] = dist1d * dist1d;
                i += i;
                if (dist1d > 0)
                    i++;
                chosen[level++] = i;
            }
            curr = photons[i];
            dist2 = curr.getDist2(px, py, pz);
            if (dist2 < maxDist2) {
                Vector3.decode(curr.normal, photN);
                float currentDotN = Vector3.dot(photN, n);
                if (currentDotN > 0.9f) {
                    nearest = curr;
                    maxDist2 = dist2;
                }
            }
            do {
                cameFrom = i;
                i >>= 1;
                level--;
                if (i == 0)
                    return (nearest == null) ? Color.BLACK : new Color().setRGBE(nearest.data);
            } while ((dist1d2[level] >= maxDist2) || (cameFrom != chosen[level]));
            curr = photons[i];
            dist2 = curr.getDist2(px, py, pz);
            if (dist2 < maxDist2) {
                Vector3.decode(curr.normal, photN);
                float currentDotN = Vector3.dot(photN, n);
                if (currentDotN > 0.9f) {
                    nearest = curr;
                    maxDist2 = dist2;
                }
            }
            i = chosen[level++] ^ 1;
        }
    }

    private static class NearestPhotons {
        int found;
        float px, py, pz;
        private int max;
        private boolean gotHeap;
        protected float[] dist2;
        protected Photon[] index;

        NearestPhotons(Point3 p, int n, float maxDist2) {
            max = n;
            found = 0;
            gotHeap = false;
            px = p.x;
            py = p.y;
            pz = p.z;
            dist2 = new float[n + 1];
            index = new Photon[n + 1];
            dist2[0] = maxDist2;
        }

        void reset(Point3 p, float maxDist2) {
            found = 0;
            gotHeap = false;
            px = p.x;
            py = p.y;
            pz = p.z;
            dist2[0] = maxDist2;
        }

        void checkAddNearest(Photon p) {
            float fdist2 = p.getDist2(px, py, pz);
            if (fdist2 < dist2[0]) {
                if (found < max) {
                    found++;
                    dist2[found] = fdist2;
                    index[found] = p;
                } else {
                    int j;
                    int parent;
                    if (!gotHeap) {
                        float dst2;
                        Photon phot;
                        int halfFound = found >> 1;
                        for (int k = halfFound; k >= 1; k--) {
                            parent = k;
                            phot = index[k];
                            dst2 = dist2[k];
                            while (parent <= halfFound) {
                                j = parent + parent;
                                if ((j < found) && (dist2[j] < dist2[j + 1]))
                                    j++;
                                if (dst2 >= dist2[j])
                                    break;
                                dist2[parent] = dist2[j];
                                index[parent] = index[j];
                                parent = j;
                            }
                            dist2[parent] = dst2;
                            index[parent] = phot;
                        }
                        gotHeap = true;
                    }
                    parent = 1;
                    j = 2;
                    while (j <= found) {
                        if ((j < found) && (dist2[j] < dist2[j + 1]))
                            j++;
                        if (fdist2 > dist2[j])
                            break;
                        dist2[parent] = dist2[j];
                        index[parent] = index[j];
                        parent = j;
                        j += j;
                    }
                    dist2[parent] = fdist2;
                    index[parent] = p;
                    dist2[0] = dist2[1];
                }
            }
        }
    }

    public boolean allowDiffuseBounced() {
        return true;
    }

    public boolean allowReflectionBounced() {
        return true;
    }

    public boolean allowRefractionBounced() {
        return true;
    }

    public int numEmit() {
        return numEmit;
    }
}

⌨️ 快捷键说明

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