Search in sources :

Example 1 with Color

use of org.sunflow.image.Color in project joons-renderer by joonhyublee.

the class GridPhotonMap method getRadiance.

@Override
public synchronized Color getRadiance(Point3 p, Vector3 n) {
    if (!bounds.contains(p)) {
        return Color.BLACK;
    }
    Vector3 ext = bounds.getExtents();
    int ix = (int) (((p.x - bounds.getMinimum().x) * nx) / ext.x);
    int iy = (int) (((p.y - bounds.getMinimum().y) * ny) / ext.y);
    int iz = (int) (((p.z - bounds.getMinimum().z) * nz) / ext.z);
    ix = MathUtils.clamp(ix, 0, nx - 1);
    iy = MathUtils.clamp(iy, 0, ny - 1);
    iz = MathUtils.clamp(iz, 0, nz - 1);
    int id = ix + iy * nx + iz * nx * ny;
    rwl.readLock().lock();
    PhotonGroup center = null;
    for (PhotonGroup g = get(ix, iy, iz); g != null; g = g.next) {
        if (g.id == id && Vector3.dot(n, g.normal) > NORMAL_THRESHOLD) {
            if (g.radiance == null) {
                center = g;
                break;
            }
            Color r = g.radiance.copy();
            rwl.readLock().unlock();
            return r;
        }
    }
    int vol = 1;
    while (true) {
        int numPhotons = 0;
        int ndiff = 0;
        Color irr = Color.black();
        Color diff = (center == null) ? Color.black() : null;
        for (int z = iz - (vol - 1); z <= iz + (vol - 1); z++) {
            for (int y = iy - (vol - 1); y <= iy + (vol - 1); y++) {
                for (int x = ix - (vol - 1); x <= ix + (vol - 1); x++) {
                    int vid = x + y * nx + z * nx * ny;
                    for (PhotonGroup g = get(x, y, z); g != null; g = g.next) {
                        if (g.id == vid && Vector3.dot(n, g.normal) > NORMAL_THRESHOLD) {
                            numPhotons += g.count;
                            irr.add(g.flux);
                            if (diff != null) {
                                diff.add(g.diffuse);
                                ndiff++;
                            }
                            // only one valid group can be found,
                            break;
                        // skip the others
                        }
                    }
                }
            }
        }
        if (numPhotons >= numGather || vol >= 3) {
            // we have found enough photons
            // cache irradiance and return
            float area = (2 * vol - 1) / 3.0f * ((ext.x / nx) + (ext.y / ny) + (ext.z / nz));
            area *= area;
            area *= Math.PI;
            irr.mul(1.0f / area);
            // upgrade lock manually
            rwl.readLock().unlock();
            rwl.writeLock().lock();
            try {
                if (center == null) {
                    if (ndiff > 0) {
                        diff.mul(1.0f / ndiff);
                    }
                    center = new PhotonGroup(id, n);
                    center.diffuse.set(diff);
                    center.next = cellHash[id % cellHash.length];
                    cellHash[id % cellHash.length] = center;
                }
                irr.mul(center.diffuse);
                center.radiance = irr.copy();
            } finally {
                rwl.writeLock().unlock();
            }
            return irr;
        }
        vol++;
    }
}
Also used : Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3)

Example 2 with Color

use of org.sunflow.image.Color in project joons-renderer by joonhyublee.

the class SCParser method parseColor.

private Color parseColor() throws IOException, ParserException, ColorSpecificationException {
    if (p.peekNextToken("{")) {
        String space = p.getNextToken();
        int req = ColorFactory.getRequiredDataValues(space);
        if (req == -2) {
            UI.printWarning(Module.API, "Unrecognized color space: %s", space);
            return null;
        } else if (req == -1) {
            // array required, parse how many values are required
            req = p.getNextInt();
        }
        Color c = ColorFactory.createColor(space, parseFloatArray(req));
        p.checkNextToken("}");
        return c;
    } else {
        float r = p.getNextFloat();
        float g = p.getNextFloat();
        float b = p.getNextFloat();
        return ColorFactory.createColor(null, r, g, b);
    }
}
Also used : Color(org.sunflow.image.Color)

Example 3 with Color

use of org.sunflow.image.Color in project joons-renderer by joonhyublee.

the class GlobalPhotonMap method precomputeRadiance.

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;
}
Also used : Point3(org.sunflow.math.Point3) Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3)

Example 4 with Color

use of org.sunflow.image.Color in project joons-renderer by joonhyublee.

the class GlobalPhotonMap method getRadiance.

@Override
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;
    }
}
Also used : Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3)

Example 5 with Color

use of org.sunflow.image.Color in project joons-renderer by joonhyublee.

the class SunSkyLight method getSamples.

public void getSamples(ShadingState state) {
    if (Vector3.dot(sunDirWorld, state.getGeoNormal()) > 0 && Vector3.dot(sunDirWorld, state.getNormal()) > 0) {
        LightSample dest = new LightSample();
        dest.setShadowRay(new Ray(state.getPoint(), sunDirWorld));
        dest.getShadowRay().setMax(Float.MAX_VALUE);
        dest.setRadiance(sunColor, sunColor);
        dest.traceShadow(state);
        state.addSample(dest);
    }
    int n = state.getDiffuseDepth() > 0 ? 1 : numSkySamples;
    for (int i = 0; i < n; i++) {
        // random offset on unit square, we use the infinite version of
        // getRandom because the light sampling is adaptive
        double randX = state.getRandom(i, 0, n);
        double randY = state.getRandom(i, 1, n);
        int x = 0;
        while (randX >= colHistogram[x] && x < colHistogram.length - 1) {
            x++;
        }
        float[] rowHistogram = imageHistogram[x];
        int y = 0;
        while (randY >= rowHistogram[y] && y < rowHistogram.length - 1) {
            y++;
        }
        // sample from (x, y)
        float u = (float) ((x == 0) ? (randX / colHistogram[0]) : ((randX - colHistogram[x - 1]) / (colHistogram[x] - colHistogram[x - 1])));
        float v = (float) ((y == 0) ? (randY / rowHistogram[0]) : ((randY - rowHistogram[y - 1]) / (rowHistogram[y] - rowHistogram[y - 1])));
        float px = ((x == 0) ? colHistogram[0] : (colHistogram[x] - colHistogram[x - 1]));
        float py = ((y == 0) ? rowHistogram[0] : (rowHistogram[y] - rowHistogram[y - 1]));
        float su = (x + u) / colHistogram.length;
        float sv = (y + v) / rowHistogram.length;
        float invP = (float) Math.sin(sv * Math.PI) * jacobian / (n * px * py);
        Vector3 localDir = getDirection(su, sv);
        Vector3 dir = basis.transform(localDir, new Vector3());
        if (Vector3.dot(dir, state.getGeoNormal()) > 0 && Vector3.dot(dir, state.getNormal()) > 0) {
            LightSample dest = new LightSample();
            dest.setShadowRay(new Ray(state.getPoint(), dir));
            dest.getShadowRay().setMax(Float.MAX_VALUE);
            Color radiance = getSkyRGB(localDir);
            dest.setRadiance(radiance, radiance);
            dest.getDiffuseRadiance().mul(invP);
            dest.getSpecularRadiance().mul(invP);
            dest.traceShadow(state);
            state.addSample(dest);
        }
    }
}
Also used : LightSample(org.sunflow.core.LightSample) Color(org.sunflow.image.Color) XYZColor(org.sunflow.image.XYZColor) Vector3(org.sunflow.math.Vector3) Ray(org.sunflow.core.Ray)

Aggregations

Color (org.sunflow.image.Color)48 Vector3 (org.sunflow.math.Vector3)34 Ray (org.sunflow.core.Ray)22 OrthoNormalBasis (org.sunflow.math.OrthoNormalBasis)15 LightSample (org.sunflow.core.LightSample)8 Point3 (org.sunflow.math.Point3)7 ShadingState (org.sunflow.core.ShadingState)6 Bitmap (org.sunflow.image.Bitmap)2 XYZColor (org.sunflow.image.XYZColor)2 Timer (org.sunflow.system.Timer)2 FileWriter (java.io.FileWriter)1 IOException (java.io.IOException)1 ConstantSpectralCurve (org.sunflow.image.ConstantSpectralCurve)1 GenericBitmap (org.sunflow.image.formats.GenericBitmap)1 BoundingBox (org.sunflow.math.BoundingBox)1 IntArray (org.sunflow.util.IntArray)1