Search in sources :

Example 31 with Point3

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

the class WireframeShader method getRadiance.

public Color getRadiance(ShadingState state) {
    Point3[] p = new Point3[3];
    if (!state.getTrianglePoints(p)) {
        return getFillColor(state);
    }
    // transform points into camera space
    Point3 center = state.getPoint();
    Matrix4 w2c = state.getWorldToCamera();
    center = w2c.transformP(center);
    for (int i = 0; i < 3; i++) {
        p[i] = w2c.transformP(state.transformObjectToWorld(p[i]));
    }
    float cn = 1.0f / (float) Math.sqrt(center.x * center.x + center.y * center.y + center.z * center.z);
    for (int i = 0, i2 = 2; i < 3; i2 = i, i++) {
        // compute orthogonal projection of the shading point onto each
        // triangle edge as in:
        // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
        float t = (center.x - p[i].x) * (p[i2].x - p[i].x);
        t += (center.y - p[i].y) * (p[i2].y - p[i].y);
        t += (center.z - p[i].z) * (p[i2].z - p[i].z);
        t /= p[i].distanceToSquared(p[i2]);
        float projx = (1 - t) * p[i].x + t * p[i2].x;
        float projy = (1 - t) * p[i].y + t * p[i2].y;
        float projz = (1 - t) * p[i].z + t * p[i2].z;
        float n = 1.0f / (float) Math.sqrt(projx * projx + projy * projy + projz * projz);
        // check angular width
        float dot = projx * center.x + projy * center.y + projz * center.z;
        if (dot * n * cn >= cosWidth) {
            return getLineColor(state);
        }
    }
    return getFillColor(state);
}
Also used : Point3(org.sunflow.math.Point3) Matrix4(org.sunflow.math.Matrix4)

Example 32 with Point3

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

the class BezierMesh method tesselate.

public PrimitiveList tesselate() {
    float[] vertices = new float[patches.length * (subdivs + 1) * (subdivs + 1) * 3];
    float[] normals = smooth ? new float[patches.length * (subdivs + 1) * (subdivs + 1) * 3] : null;
    float[] uvs = new float[patches.length * (subdivs + 1) * (subdivs + 1) * 2];
    int[] indices = new int[patches.length * subdivs * subdivs * (quads ? 4 : (2 * 3))];
    int vidx = 0, pidx = 0;
    float step = 1.0f / subdivs;
    int vstride = subdivs + 1;
    Point3 p = new Point3();
    Vector3 n = smooth ? new Vector3() : null;
    for (float[] patch : patches) {
        // create patch vertices
        for (int i = 0, voff = 0; i <= subdivs; i++) {
            float u = i * step;
            float[] bu = bernstein(u);
            float[] bdu = bernsteinDeriv(u);
            for (int j = 0; j <= subdivs; j++, voff += 3) {
                float v = j * step;
                float[] bv = bernstein(v);
                float[] bdv = bernsteinDeriv(v);
                getPatchPoint(u, v, patch, bu, bv, bdu, bdv, p, n);
                vertices[vidx + voff + 0] = p.x;
                vertices[vidx + voff + 1] = p.y;
                vertices[vidx + voff + 2] = p.z;
                if (smooth) {
                    normals[vidx + voff + 0] = n.x;
                    normals[vidx + voff + 1] = n.y;
                    normals[vidx + voff + 2] = n.z;
                }
                uvs[(vidx + voff) / 3 * 2 + 0] = u;
                uvs[(vidx + voff) / 3 * 2 + 1] = v;
            }
        }
        // generate patch triangles
        for (int i = 0, vbase = vidx / 3; i < subdivs; i++) {
            for (int j = 0; j < subdivs; j++) {
                int v00 = (i + 0) * vstride + (j + 0);
                int v10 = (i + 1) * vstride + (j + 0);
                int v01 = (i + 0) * vstride + (j + 1);
                int v11 = (i + 1) * vstride + (j + 1);
                if (quads) {
                    indices[pidx + 0] = vbase + v01;
                    indices[pidx + 1] = vbase + v00;
                    indices[pidx + 2] = vbase + v10;
                    indices[pidx + 3] = vbase + v11;
                    pidx += 4;
                } else {
                    // add 2 triangles
                    indices[pidx + 0] = vbase + v00;
                    indices[pidx + 1] = vbase + v10;
                    indices[pidx + 2] = vbase + v01;
                    indices[pidx + 3] = vbase + v10;
                    indices[pidx + 4] = vbase + v11;
                    indices[pidx + 5] = vbase + v01;
                    pidx += 6;
                }
            }
        }
        vidx += vstride * vstride * 3;
    }
    ParameterList pl = new ParameterList();
    pl.addPoints("points", InterpolationType.VERTEX, vertices);
    if (quads) {
        pl.addIntegerArray("quads", indices);
    } else {
        pl.addIntegerArray("triangles", indices);
    }
    pl.addTexCoords("uvs", InterpolationType.VERTEX, uvs);
    if (smooth) {
        pl.addVectors("normals", InterpolationType.VERTEX, normals);
    }
    PrimitiveList m = quads ? new QuadMesh() : new TriangleMesh();
    m.update(pl, null);
    pl.clear(true);
    return m;
}
Also used : QuadMesh(org.sunflow.core.primitive.QuadMesh) Point3(org.sunflow.math.Point3) PrimitiveList(org.sunflow.core.PrimitiveList) TriangleMesh(org.sunflow.core.primitive.TriangleMesh) ParameterList(org.sunflow.core.ParameterList) Vector3(org.sunflow.math.Vector3)

Example 33 with Point3

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

the class InstantGI method getGlobalRadiance.

@Override
public Color getGlobalRadiance(ShadingState state) {
    Point3 p = state.getPoint();
    Vector3 n = state.getNormal();
    int set = (int) (state.getRandom(0, 1, 1) * numSets);
    float maxAvgPow = 0;
    float minDist = 1;
    Color pow = null;
    for (PointLight vpl : virtualLights[set]) {
        maxAvgPow = Math.max(maxAvgPow, vpl.power.getAverage());
        if (Vector3.dot(n, vpl.n) > 0.9f) {
            float d = vpl.p.distanceToSquared(p);
            if (d < minDist) {
                pow = vpl.power;
                minDist = d;
            }
        }
    }
    return pow == null ? Color.BLACK : pow.copy().mul(1.0f / maxAvgPow);
}
Also used : Point3(org.sunflow.math.Point3) Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3)

Example 34 with Point3

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

the class InstantGI method getIrradiance.

@Override
public Color getIrradiance(ShadingState state, Color diffuseReflectance) {
    float b = (float) Math.PI * c / diffuseReflectance.getMax();
    Color irr = Color.black();
    Point3 p = state.getPoint();
    Vector3 n = state.getNormal();
    int set = (int) (state.getRandom(0, 1, 1) * numSets);
    for (PointLight vpl : virtualLights[set]) {
        Ray r = new Ray(p, vpl.p);
        float dotNlD = -(r.dx * vpl.n.x + r.dy * vpl.n.y + r.dz * vpl.n.z);
        float dotND = r.dx * n.x + r.dy * n.y + r.dz * n.z;
        if (dotNlD > 0 && dotND > 0) {
            float r2 = r.getMax() * r.getMax();
            Color opacity = state.traceShadow(r);
            Color power = Color.blend(vpl.power, Color.BLACK, opacity);
            float g = (dotND * dotNlD) / r2;
            irr.madd(0.25f * Math.min(g, b), power);
        }
    }
    // bias compensation
    int nb = (state.getDiffuseDepth() == 0 || numBias <= 0) ? numBias : 1;
    if (nb <= 0) {
        return irr;
    }
    OrthoNormalBasis onb = state.getBasis();
    Vector3 w = new Vector3();
    float scale = (float) Math.PI / nb;
    for (int i = 0; i < nb; i++) {
        float xi = (float) state.getRandom(i, 0, nb);
        float xj = (float) state.getRandom(i, 1, nb);
        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);
        r.setMax((float) Math.sqrt(cosTheta / b));
        ShadingState temp = state.traceFinalGather(r, i);
        if (temp != null) {
            temp.getInstance().prepareShadingState(temp);
            if (temp.getShader() != null) {
                float dist = temp.getRay().getMax();
                float r2 = dist * dist;
                float cosThetaY = -Vector3.dot(w, temp.getNormal());
                if (cosThetaY > 0) {
                    float g = (cosTheta * cosThetaY) / r2;
                    // was this path accounted for yet?
                    if (g > b) {
                        irr.madd(scale * (g - b) / g, temp.getShader().getRadiance(temp));
                    }
                }
            }
        }
    }
    return irr;
}
Also used : Point3(org.sunflow.math.Point3) 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)

Example 35 with Point3

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

the class TriangleMeshLight method getSamples.

public void getSamples(ShadingState state) {
    if (numSamples == 0) {
        return;
    }
    Vector3 n = state.getNormal();
    Point3 p = state.getPoint();
    for (int tri3 = 0, i = 0; tri3 < triangles.length; tri3 += 3, i++) {
        // vector towards each vertex of the light source
        Vector3 p0 = Point3.sub(getPoint(triangles[tri3 + 0]), p, new Vector3());
        // cull triangle if it is facing the wrong way
        if (Vector3.dot(p0, ngs[i]) >= 0) {
            continue;
        }
        Vector3 p1 = Point3.sub(getPoint(triangles[tri3 + 1]), p, new Vector3());
        Vector3 p2 = Point3.sub(getPoint(triangles[tri3 + 2]), p, new Vector3());
        // if all three vertices are below the hemisphere, stop
        if (Vector3.dot(p0, n) <= 0 && Vector3.dot(p1, n) <= 0 && Vector3.dot(p2, n) <= 0) {
            continue;
        }
        p0.normalize();
        p1.normalize();
        p2.normalize();
        float dot = Vector3.dot(p2, p0);
        Vector3 h = new Vector3();
        h.x = p2.x - dot * p0.x;
        h.y = p2.y - dot * p0.y;
        h.z = p2.z - dot * p0.z;
        float hlen = h.length();
        if (hlen > 1e-6f) {
            h.div(hlen);
        } else {
            continue;
        }
        Vector3 n0 = Vector3.cross(p0, p1, new Vector3());
        float len0 = n0.length();
        if (len0 > 1e-6f) {
            n0.div(len0);
        } else {
            continue;
        }
        Vector3 n1 = Vector3.cross(p1, p2, new Vector3());
        float len1 = n1.length();
        if (len1 > 1e-6f) {
            n1.div(len1);
        } else {
            continue;
        }
        Vector3 n2 = Vector3.cross(p2, p0, new Vector3());
        float len2 = n2.length();
        if (len2 > 1e-6f) {
            n2.div(len2);
        } else {
            continue;
        }
        float cosAlpha = MathUtils.clamp(-Vector3.dot(n2, n0), -1.0f, 1.0f);
        float cosBeta = MathUtils.clamp(-Vector3.dot(n0, n1), -1.0f, 1.0f);
        float cosGamma = MathUtils.clamp(-Vector3.dot(n1, n2), -1.0f, 1.0f);
        float alpha = (float) Math.acos(cosAlpha);
        float beta = (float) Math.acos(cosBeta);
        float gamma = (float) Math.acos(cosGamma);
        float area = alpha + beta + gamma - (float) Math.PI;
        float cosC = MathUtils.clamp(Vector3.dot(p0, p1), -1.0f, 1.0f);
        float salpha = (float) Math.sin(alpha);
        float product = salpha * cosC;
        // use lower sampling depth for diffuse bounces
        int samples = state.getDiffuseDepth() > 0 ? 1 : numSamples;
        Color c = Color.mul(area / samples, radiance);
        for (int j = 0; j < samples; j++) {
            // random offset on unit square
            double randX = state.getRandom(j, 0, samples);
            double randY = state.getRandom(j, 1, samples);
            float phi = (float) randX * area - alpha + (float) Math.PI;
            float sinPhi = (float) Math.sin(phi);
            float cosPhi = (float) Math.cos(phi);
            float u = cosPhi + cosAlpha;
            float v = sinPhi - product;
            float q = (-v + cosAlpha * (cosPhi * -v + sinPhi * u)) / (salpha * (sinPhi * -v - cosPhi * u));
            float q1 = 1.0f - q * q;
            if (q1 < 0.0f) {
                q1 = 0.0f;
            }
            float sqrtq1 = (float) Math.sqrt(q1);
            float ncx = q * p0.x + sqrtq1 * h.x;
            float ncy = q * p0.y + sqrtq1 * h.y;
            float ncz = q * p0.z + sqrtq1 * h.z;
            dot = p1.dot(ncx, ncy, ncz);
            float z = 1.0f - (float) randY * (1.0f - dot);
            float z1 = 1.0f - z * z;
            if (z1 < 0.0f) {
                z1 = 0.0f;
            }
            Vector3 nd = new Vector3();
            nd.x = ncx - dot * p1.x;
            nd.y = ncy - dot * p1.y;
            nd.z = ncz - dot * p1.z;
            nd.normalize();
            float sqrtz1 = (float) Math.sqrt(z1);
            Vector3 result = new Vector3();
            result.x = z * p1.x + sqrtz1 * nd.x;
            result.y = z * p1.y + sqrtz1 * nd.y;
            result.z = z * p1.z + sqrtz1 * nd.z;
            // the right direction
            if (Vector3.dot(result, n) > 0 && Vector3.dot(result, state.getGeoNormal()) > 0 && Vector3.dot(result, ngs[i]) < 0) {
                // compute intersection with triangle (if any)
                Ray shadowRay = new Ray(state.getPoint(), result);
                if (!intersectTriangleKensler(tri3, shadowRay)) {
                    continue;
                }
                LightSample dest = new LightSample();
                dest.setShadowRay(shadowRay);
                // prepare sample
                dest.setRadiance(c, c);
                dest.traceShadow(state);
                state.addSample(dest);
            }
        }
    }
}
Also used : Point3(org.sunflow.math.Point3) LightSample(org.sunflow.core.LightSample) Color(org.sunflow.image.Color) Vector3(org.sunflow.math.Vector3) Ray(org.sunflow.core.Ray)

Aggregations

Point3 (org.sunflow.math.Point3)39 Vector3 (org.sunflow.math.Vector3)27 Instance (org.sunflow.core.Instance)9 Color (org.sunflow.image.Color)7 Ray (org.sunflow.core.Ray)5 LightSample (org.sunflow.core.LightSample)4 TriangleMesh (org.sunflow.core.primitive.TriangleMesh)3 ParameterList (org.sunflow.core.ParameterList)2 Matrix4 (org.sunflow.math.Matrix4)2 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 FloatBuffer (java.nio.FloatBuffer)1 MappedByteBuffer (java.nio.MappedByteBuffer)1 PrimitiveList (org.sunflow.core.PrimitiveList)1 SceneParser (org.sunflow.core.SceneParser)1 ShadingState (org.sunflow.core.ShadingState)1 QuadMesh (org.sunflow.core.primitive.QuadMesh)1 BoundingBox (org.sunflow.math.BoundingBox)1