Search in sources :

Example 16 with OrthoNormalBasis

use of org.sunflow.math.OrthoNormalBasis in project joons-renderer by joonhyublee.

the class ShadingState method specularPhong.

/**
 * Computes a phong specular response to the current light samples and
 * global illumination.
 *
 * @param spec specular color
 * @param power phong exponent
 * @param numRays number of glossy rays to trace
 * @return shaded color
 */
public final Color specularPhong(Color spec, float power, int numRays) {
    // integrate a phong specular function
    Color lr = Color.black();
    if (!includeSpecular || spec.isBlack()) {
        return lr;
    }
    // reflected direction
    float dn = 2 * cosND;
    Vector3 refDir = new Vector3();
    refDir.x = (dn * n.x) + r.dx;
    refDir.y = (dn * n.y) + r.dy;
    refDir.z = (dn * n.z) + r.dz;
    // direct lighting
    for (LightSample sample : this) {
        float cosNL = sample.dot(n);
        float cosLR = sample.dot(refDir);
        if (cosLR > 0) {
            lr.madd(cosNL * (float) Math.pow(cosLR, power), sample.getSpecularRadiance());
        }
    }
    // indirect lighting
    if (numRays > 0) {
        int numSamples = getDepth() == 0 ? numRays : 1;
        OrthoNormalBasis onb = OrthoNormalBasis.makeFromW(refDir);
        float mul = (2.0f * (float) Math.PI / (power + 1)) / numSamples;
        for (int i = 0; i < numSamples; i++) {
            // specular indirect lighting
            double r1 = getRandom(i, 0, numSamples);
            double r2 = getRandom(i, 1, numSamples);
            double u = 2 * Math.PI * r1;
            double s = (float) Math.pow(r2, 1 / (power + 1));
            double s1 = (float) Math.sqrt(1 - s * s);
            Vector3 w = new Vector3((float) (Math.cos(u) * s1), (float) (Math.sin(u) * s1), (float) s);
            w = onb.transform(w, new Vector3());
            float wn = Vector3.dot(w, n);
            if (wn > 0) {
                lr.madd(wn * mul, traceGlossy(new Ray(p, w), i));
            }
        }
    }
    lr.mul(spec).mul((power + 2) / (2.0f * (float) Math.PI));
    return lr;
}
Also used : Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3) OrthoNormalBasis(org.sunflow.math.OrthoNormalBasis)

Example 17 with OrthoNormalBasis

use of org.sunflow.math.OrthoNormalBasis in project joons-renderer by joonhyublee.

the class IrradianceCacheGIEngine method getIrradiance.

@Override
public Color getIrradiance(ShadingState state, Color diffuseReflectance) {
    if (samples <= 0) {
        return Color.BLACK;
    }
    if (state.getDiffuseDepth() > 0) {
        // do simple path tracing for additional bounces (single ray)
        float xi = (float) state.getRandom(0, 0, 1);
        float xj = (float) state.getRandom(0, 1, 1);
        float phi = (float) (xi * 2 * Math.PI);
        float cosPhi = (float) Math.cos(phi);
        float sinPhi = (float) Math.sin(phi);
        float sinTheta = (float) Math.sqrt(xj);
        float cosTheta = (float) Math.sqrt(1.0f - xj);
        Vector3 w = new Vector3();
        w.x = cosPhi * sinTheta;
        w.y = sinPhi * sinTheta;
        w.z = cosTheta;
        OrthoNormalBasis onb = state.getBasis();
        onb.transform(w);
        Ray r = new Ray(state.getPoint(), w);
        ShadingState temp = state.traceFinalGather(r, 0);
        return temp != null ? getGlobalRadiance(temp).copy().mul((float) Math.PI) : Color.BLACK;
    }
    rwl.readLock().lock();
    Color irr;
    try {
        irr = getIrradiance(state.getPoint(), state.getNormal());
    } finally {
        rwl.readLock().unlock();
    }
    if (irr == null) {
        // compute new sample
        irr = Color.black();
        OrthoNormalBasis onb = state.getBasis();
        float invR = 0;
        float minR = Float.POSITIVE_INFINITY;
        Vector3 w = new Vector3();
        for (int i = 0; i < samples; i++) {
            float xi = (float) state.getRandom(i, 0, samples);
            float xj = (float) state.getRandom(i, 1, samples);
            float phi = (float) (xi * 2 * Math.PI);
            float cosPhi = (float) Math.cos(phi);
            float sinPhi = (float) Math.sin(phi);
            float sinTheta = (float) Math.sqrt(xj);
            float cosTheta = (float) Math.sqrt(1.0f - xj);
            w.x = cosPhi * sinTheta;
            w.y = sinPhi * sinTheta;
            w.z = cosTheta;
            onb.transform(w);
            Ray r = new Ray(state.getPoint(), w);
            ShadingState temp = state.traceFinalGather(r, i);
            if (temp != null) {
                minR = Math.min(r.getMax(), minR);
                invR += 1.0f / r.getMax();
                temp.getInstance().prepareShadingState(temp);
                irr.add(getGlobalRadiance(temp));
            }
        }
        irr.mul((float) Math.PI / samples);
        invR = samples / invR;
        rwl.writeLock().lock();
        try {
            insert(state.getPoint(), state.getNormal(), invR, irr);
        } finally {
            rwl.writeLock().unlock();
        }
    }
    return irr;
}
Also used : ShadingState(org.sunflow.core.ShadingState) Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3) Ray(org.sunflow.core.Ray) OrthoNormalBasis(org.sunflow.math.OrthoNormalBasis)

Aggregations

OrthoNormalBasis (org.sunflow.math.OrthoNormalBasis)17 Vector3 (org.sunflow.math.Vector3)17 Color (org.sunflow.image.Color)15 Ray (org.sunflow.core.Ray)13 ShadingState (org.sunflow.core.ShadingState)3 LightSample (org.sunflow.core.LightSample)2 Point3 (org.sunflow.math.Point3)1