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

📄 sunskylight.java

📁 Sunflow是一个照片级的渲染系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                float u = (x + 0.5f) * du;
                float v = (y + 0.5f) * dv;
                Color c = getSkyRGB(getDirection(u, v));
                imageHistogram[x][y] = c.getLuminance() * (float) Math.sin(Math.PI * v);
                if (y > 0)
                    imageHistogram[x][y] += imageHistogram[x][y - 1];
            }
            colHistogram[x] = imageHistogram[x][h - 1];
            if (x > 0)
                colHistogram[x] += colHistogram[x - 1];
            for (int y = 0; y < h; y++)
                imageHistogram[x][y] /= imageHistogram[x][h - 1];
        }
        for (int x = 0; x < w; x++)
            colHistogram[x] /= colHistogram[w - 1];
        jacobian = (float) (2 * Math.PI * Math.PI) / (w * h);
    }

    public boolean update(ParameterList pl, SunflowAPI api) {
        Vector3 up = pl.getVector("up", null);
        Vector3 east = pl.getVector("east", null);
        if (up != null && east != null)
            basis = OrthoNormalBasis.makeFromWV(up, east);
        else if (up != null)
            basis = OrthoNormalBasis.makeFromW(up);
        numSkySamples = pl.getInt("samples", numSkySamples);
        sunDirWorld = pl.getVector("sundir", sunDirWorld);
        turbidity = pl.getFloat("turbidity", turbidity);
        // recompute model
        initSunSky();
        return true;
    }

    public void init(String name, SunflowAPI api) {
        // register this object with the api properly
        api.geometry(name, this);
        api.shader(name + ".shader", this);
        api.parameter("shaders", name + ".shader");
        api.instance(name + ".instance", name);
        api.light(name + ".light", this);
    }

    private Color getSkyRGB(Vector3 dir) {
        if (dir.z < 0)
            return Color.BLACK;
        if (dir.z < 0.001f)
            dir.z = 0.001f;
        dir.normalize();
        double theta = Math.acos(MathUtils.clamp(dir.z, -1, 1));
        double gamma = Math.acos(MathUtils.clamp(Vector3.dot(dir, sunDir), -1, 1));
        double x = perezFunction(perezx, theta, gamma, zenithx);
        double y = perezFunction(perezy, theta, gamma, zenithy);
        double Y = perezFunction(perezY, theta, gamma, zenithY) * 1e-4;
        XYZColor c = ChromaticitySpectrum.get((float) x, (float) y);
        // XYZColor c = new ChromaticitySpectrum((float) x, (float) y).toXYZ();
        float X = (float) (c.getX() * Y / c.getY());
        float Z = (float) (c.getZ() * Y / c.getY());
        return RGBSpace.SRGB.convertXYZtoRGB(X, (float) Y, Z);
    }

    public int getNumSamples() {
        return 1 + numSkySamples;
    }

    public void getPhoton(double randX1, double randY1, double randX2, double randY2, Point3 p, Vector3 dir, Color power) {
        // FIXME: not implemented
    }

    public float getPower() {
        return 0;
    }

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

    public PrimitiveList getBakingPrimitives() {
        return null;
    }

    public int getNumPrimitives() {
        return 1;
    }

    public float getPrimitiveBound(int primID, int i) {
        return 0;
    }

    public BoundingBox getWorldBounds(Matrix4 o2w) {
        return null;
    }

    public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
        if (r.getMax() == Float.POSITIVE_INFINITY)
            state.setIntersection(0, 0, 0);
    }

    public void prepareShadingState(ShadingState state) {
        if (state.includeLights())
            state.setShader(this);
    }

    public Color getRadiance(ShadingState state) {
        return getSkyRGB(basis.untransform(state.getRay().getDirection())).constrainRGB();
    }

    public void scatterPhoton(ShadingState state, Color power) {
        // let photon escape
    }

    private Vector3 getDirection(float u, float v) {
        Vector3 dest = new Vector3();
        double phi = 0, theta = 0;
        theta = u * 2 * Math.PI;
        phi = v * Math.PI;
        double sin_phi = Math.sin(phi);
        dest.x = (float) (-sin_phi * Math.cos(theta));
        dest.y = (float) Math.cos(phi);
        dest.z = (float) (sin_phi * Math.sin(theta));
        return dest;
    }
}

⌨️ 快捷键说明

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