Beispiel #1
0
        public Color GetRadiance(ShadingState state)
        {
            // make sure we are on the right side of the material
            state.faceforward();
            // direct lighting
            state.initLightSamples();
            state.initCausticSamples();
            Color d = getDiffuse(state);
            Color lr = state.diffuse(d);
            if (!state.includeSpecular)
                return lr;
            if (glossyness == 0)
            {
                float cos = state.getCosND();
                float dn = 2 * cos;
                Vector3 refDir = new Vector3();
                refDir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
                refDir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
                refDir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
                Ray refRay = new Ray(state.getPoint(), refDir);
                // compute Fresnel term
                cos = 1 - cos;
                float cos2 = cos * cos;
                float cos5 = cos2 * cos2 * cos;

                Color spec = getSpecular(state);
                Color ret = Color.white();
                ret.sub(spec);
                ret.mul(cos5);
                ret.add(spec);
                return lr.add(ret.mul(state.traceReflection(refRay, 0)));
            }
            else
                return lr.add(state.specularPhong(getSpecular(state), 2 / glossyness, numSamples));
        }
Beispiel #2
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     // intersect in local space
     float rd2x = r.dx * r.dx;
     float rd2y = r.dy * r.dy;
     float rd2z = r.dz * r.dz;
     float ro2x = r.ox * r.ox;
     float ro2y = r.oy * r.oy;
     float ro2z = r.oz * r.oz;
     // setup the quartic coefficients
     // some common terms could probably be shared across these
     double A = (rd2y * rd2y + rd2z * rd2z + rd2x * rd2x);
     double B = 4 * (r.oy * rd2y * r.dy + r.oz * r.dz * rd2z + r.ox * r.dx * rd2x);
     double C = (-rd2x - rd2y - rd2z + 6 * (ro2y * rd2y + ro2z * rd2z + ro2x * rd2x));
     double D = 2 * (2 * ro2z * r.oz * r.dz - r.oz * r.dz + 2 * ro2x * r.ox * r.dx + 2 * ro2y * r.oy * r.dy - r.ox * r.dx - r.oy * r.dy);
     double E = 3.0f / 8.0f + (-ro2z + ro2z * ro2z - ro2y + ro2y * ro2y - ro2x + ro2x * ro2x);
     // solve equation
     double[] t = Solvers.solveQuartic(A, B, C, D, E);
     if (t != null)
     {
         // early rejection
         if (t[0] >= r.getMax() || t[t.Length - 1] <= r.getMin())
             return;
         // find first intersection in front of the ray
         for (int i = 0; i < t.Length; i++)
         {
             if (t[i] > r.getMin())
             {
                 r.setMax((float)t[i]);
                 state.setIntersection(0, 0, 0);
                 return;
             }
         }
     }
 }
Beispiel #3
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     if (primID < instances.Length)
         instances[primID].intersect(r, state);
     else
         lights[primID - instances.Length].intersect(r, state);
 }
Beispiel #4
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     // intersect in local space
     float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz;
     float qb = 2 * ((r.dx * r.ox) + (r.dy * r.oy) + (r.dz * r.oz));
     float qc = ((r.ox * r.ox) + (r.oy * r.oy) + (r.oz * r.oz)) - 1;
     double[] t = Solvers.solveQuadric(qa, qb, qc);
     if (t != null)
     {
         // early rejection
         if (t[0] >= r.getMax() || t[1] <= r.getMin())
             return;
         if (t[0] > r.getMin())
             r.setMax((float)t[0]);
         else
             r.setMax((float)t[1]);
         state.setIntersection(0, 0, 0);
     }
 }
Beispiel #5
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     int i3 = primID * 3;
     float ocx = r.ox - particles[i3 + 0];
     float ocy = r.oy - particles[i3 + 1];
     float ocz = r.oz - particles[i3 + 2];
     float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz;
     float qb = 2 * ((r.dx * ocx) + (r.dy * ocy) + (r.dz * ocz));
     float qc = ((ocx * ocx) + (ocy * ocy) + (ocz * ocz)) - r2;
     double[] t = Solvers.solveQuadric(qa, qb, qc);
     if (t != null)
     {
         // early rejection
         if (t[0] >= r.getMax() || t[1] <= r.getMin())
             return;
         if (t[0] > r.getMin())
             r.setMax((float)t[0]);
         else
             r.setMax((float)t[1]);
         state.setIntersection(primID);
     }
 }
Beispiel #6
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     // intersect in local space
     float rd2x = r.dx * r.dx;
     float rd2y = r.dy * r.dy;
     float rd2z = r.dz * r.dz;
     float ro2x = r.ox * r.ox;
     float ro2y = r.oy * r.oy;
     float ro2z = r.oz * r.oz;
     // compute some common factors
     double alpha = rd2x + rd2y + rd2z;
     double beta = 2 * (r.ox * r.dx + r.oy * r.dy + r.oz * r.dz);
     double gamma = (ro2x + ro2y + ro2z) - ri2 - ro2;
     // setup quartic coefficients
     double A = alpha * alpha;
     double B = 2 * alpha * beta;
     double C = beta * beta + 2 * alpha * gamma + 4 * ro2 * rd2z;
     double D = 2 * beta * gamma + 8 * ro2 * r.oz * r.dz;
     double E = gamma * gamma + 4 * ro2 * ro2z - 4 * ro2 * ri2;
     // solve equation
     double[] t = Solvers.solveQuartic(A, B, C, D, E);
     if (t != null)
     {
         // early rejection
         if (t[0] >= r.getMax() || t[t.Length - 1] <= r.getMin())
             return;
         // find first intersection in front of the ray
         for (int i = 0; i < t.Length; i++)
         {
             if (t[i] > r.getMin())
             {
                 r.setMax((float)t[i]);
                 state.setIntersection(0, 0, 0);
                 return;
             }
         }
     }
 }
Beispiel #7
0
        public Color GetRadiance(ShadingState state)
        {
            if (!state.includeSpecular)
                return Color.BLACK;
            state.faceforward();
            float cos = state.getCosND();
            float dn = 2 * cos;
            Vector3 refDir = new Vector3();
            refDir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
            refDir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
            refDir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
            Ray refRay = new Ray(state.getPoint(), refDir);

            // compute Fresnel term
            cos = 1 - cos;
            float cos2 = cos * cos;
            float cos5 = cos2 * cos2 * cos;
            Color ret = Color.white();
            ret.sub(color);
            ret.mul(cos5);
            ret.add(color);
            return ret.mul(state.traceReflection(refRay, 0));
        }
 public Color getIrradiance(ShadingState state, Color diffuseReflectance)
 {
     OrthoNormalBasis onb = state.getBasis();
     Vector3 w = new Vector3();
     Color result = Color.black();
     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)(2 * Math.PI * xi);
         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(maxDist);
         result.add(Color.blend(bright, dark, state.traceShadow(r)));
     }
     return result.mul((float)Math.PI / samples);
 }
Beispiel #9
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     float intervalMin = r.getMin();
     float intervalMax = r.getMax();
     float orgX = r.ox;
     float orgY = r.oy;
     float orgZ = r.oz;
     float dirX = r.dx, invDirX = 1 / dirX;
     float dirY = r.dy, invDirY = 1 / dirY;
     float dirZ = r.dz, invDirZ = 1 / dirZ;
     float t1, t2;
     t1 = (-1 - orgX) * invDirX;
     t2 = (+1 - orgX) * invDirX;
     int curr = -1;
     if (invDirX > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             curr = 0;
         }
         if (t2 < intervalMax)
             intervalMax = t2;
         if (intervalMin > intervalMax)
             return;
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             curr = 1;
         }
         if (t1 < intervalMax)
             intervalMax = t1;
         if (intervalMin > intervalMax)
             return;
     }
     t1 = (-1 - orgY) * invDirY;
     t2 = (+1 - orgY) * invDirY;
     if (invDirY > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             curr = 2;
         }
         if (t2 < intervalMax)
             intervalMax = t2;
         if (intervalMin > intervalMax)
             return;
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             curr = 3;
         }
         if (t1 < intervalMax)
             intervalMax = t1;
         if (intervalMin > intervalMax)
             return;
     }
     t1 = (-1 - orgZ) * invDirZ;
     t2 = (+1 - orgZ) * invDirZ;
     if (invDirZ > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             curr = 4;
         }
         if (t2 < intervalMax)
             intervalMax = t2;
         if (intervalMin > intervalMax)
             return;
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             curr = 5;
         }
         if (t1 < intervalMax)
             intervalMax = t1;
         if (intervalMin > intervalMax)
             return;
     }
     // box is hit at [intervalMin, intervalMax]
     orgX += intervalMin * dirX;
     orgY += intervalMin * dirY;
     orgZ += intervalMin * dirZ;
     // locate starting point inside the grid
     // and set up 3D-DDA vars
     int indxX, indxY, indxZ;
     int stepX, stepY, stepZ;
     int stopX, stopY, stopZ;
     float deltaX, deltaY, deltaZ;
     float tnextX, tnextY, tnextZ;
     // stepping factors along X
     indxX = (int)((orgX + 1) * invVoxelwx);
     if (indxX < 0)
         indxX = 0;
     else if (indxX >= nx)
         indxX = nx - 1;
     if (Math.Abs(dirX) < 1e-6f)
     {
         stepX = 0;
         stopX = indxX;
         deltaX = 0;
         tnextX = float.PositiveInfinity;
     }
     else if (dirX > 0)
     {
         stepX = 1;
         stopX = nx;
         deltaX = voxelwx * invDirX;
         tnextX = intervalMin + ((indxX + 1) * voxelwx - 1 - orgX) * invDirX;
     }
     else
     {
         stepX = -1;
         stopX = -1;
         deltaX = -voxelwx * invDirX;
         tnextX = intervalMin + (indxX * voxelwx - 1 - orgX) * invDirX;
     }
     // stepping factors along Y
     indxY = (int)((orgY + 1) * invVoxelwy);
     if (indxY < 0)
         indxY = 0;
     else if (indxY >= ny)
         indxY = ny - 1;
     if (Math.Abs(dirY) < 1e-6f)
     {
         stepY = 0;
         stopY = indxY;
         deltaY = 0;
         tnextY = float.PositiveInfinity;
     }
     else if (dirY > 0)
     {
         stepY = 1;
         stopY = ny;
         deltaY = voxelwy * invDirY;
         tnextY = intervalMin + ((indxY + 1) * voxelwy - 1 - orgY) * invDirY;
     }
     else
     {
         stepY = -1;
         stopY = -1;
         deltaY = -voxelwy * invDirY;
         tnextY = intervalMin + (indxY * voxelwy - 1 - orgY) * invDirY;
     }
     // stepping factors along Z
     indxZ = (int)((orgZ + 1) * invVoxelwz);
     if (indxZ < 0)
         indxZ = 0;
     else if (indxZ >= nz)
         indxZ = nz - 1;
     if (Math.Abs(dirZ) < 1e-6f)
     {
         stepZ = 0;
         stopZ = indxZ;
         deltaZ = 0;
         tnextZ = float.PositiveInfinity;
     }
     else if (dirZ > 0)
     {
         stepZ = 1;
         stopZ = nz;
         deltaZ = voxelwz * invDirZ;
         tnextZ = intervalMin + ((indxZ + 1) * voxelwz - 1 - orgZ) * invDirZ;
     }
     else
     {
         stepZ = -1;
         stopZ = -1;
         deltaZ = -voxelwz * invDirZ;
         tnextZ = intervalMin + (indxZ * voxelwz - 1 - orgZ) * invDirZ;
     }
     // are we starting inside the cube
     bool isInside = inside(indxX, indxY, indxZ) && bounds.contains(r.ox, r.oy, r.oz);
     // trace through the grid
     for (; ; )
     {
         if (inside(indxX, indxY, indxZ) != isInside)
         {
             // we hit a boundary
             r.setMax(intervalMin);
             // if we are inside, the last bit needs to be flipped
             if (isInside)
                 curr ^= 1;
             state.setIntersection(curr);
             return;
         }
         if (tnextX < tnextY && tnextX < tnextZ)
         {
             curr = dirX > 0 ? 0 : 1;
             intervalMin = tnextX;
             if (intervalMin > intervalMax)
                 return;
             indxX += stepX;
             if (indxX == stopX)
                 return;
             tnextX += deltaX;
         }
         else if (tnextY < tnextZ)
         {
             curr = dirY > 0 ? 2 : 3;
             intervalMin = tnextY;
             if (intervalMin > intervalMax)
                 return;
             indxY += stepY;
             if (indxY == stopY)
                 return;
             tnextY += deltaY;
         }
         else
         {
             curr = dirZ > 0 ? 4 : 5;
             intervalMin = tnextZ;
             if (intervalMin > intervalMax)
                 return;
             indxZ += stepZ;
             if (indxZ == stopZ)
                 return;
             tnextZ += deltaZ;
         }
     }
 }
Beispiel #10
0
 public void intersect(Ray r, IntersectionState state)
 {
     if (builtTess == 0)
         tesselate();
     if (builtAccel == 0)
         build();
     accel.intersect(r, state);
 }
Beispiel #11
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     instances[primID].intersect(r, state);
 }
 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().lockwoot();//fixme
     Color irr;
     lock(lockObj)
         irr = getIrradiance(state.getPoint(), state.getNormal());
     //rwl.readLock().unlock();
     if (irr == null)
     {
         // compute new sample
         irr = Color.black();
         OrthoNormalBasis onb = state.getBasis();
         float invR = 0;
         float minR = float.PositiveInfinity;
         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().lockwoot();//fixme
         lock(lockObj)
             insert(state.getPoint(), state.getNormal(), invR, irr);
         //rwl.writeLock().unlock();
         // view irr-cache points
         // irr = Color.YELLOW.copy().mul(1e6f);
     }
     return irr;
 }
        public Color getRadiance(ShadingState state)
        {
            // make sure we are on the right side of the material
            state.faceforward();
            OrthoNormalBasis onb = state.getBasis();
            // direct lighting and caustics
            state.initLightSamples();
            state.initCausticSamples();
            Color lr = Color.black();
            // compute specular contribution
            if (state.includeSpecular)
            {
                Vector3 inv = state.getRay().getDirection().negate(new Vector3());
                foreach (LightSample sample in state)
                {
                    float cosNL = sample.dot(state.getNormal());
                    float fr = brdf(inv, sample.getShadowRay().getDirection(), onb);
                    lr.madd(cosNL * fr, sample.getSpecularRadiance());
                }

                // indirect lighting - specular
                if (numRays > 0)
                {
                    int n = state.getDepth() == 0 ? numRays : 1;
                    for (int i = 0; i < n; i++)
                    {
                        // specular indirect lighting
                        double r1 = state.getRandom(i, 0, n);
                        double r2 = state.getRandom(i, 1, n);

                        float alphaRatio = alphaY / alphaX;
                        float phi = 0;
                        if (r1 < 0.25)
                        {
                            double val = 4 * r1;
                            phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                        }
                        else if (r1 < 0.5)
                        {
                            double val = 1 - 4 * (0.5 - r1);
                            phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                            phi = (float)Math.PI - phi;
                        }
                        else if (r1 < 0.75)
                        {
                            double val = 4 * (r1 - 0.5);
                            phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                            phi += (float)Math.PI;
                        }
                        else
                        {
                            double val = 1 - 4 * (1 - r1);
                            phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                            phi = 2 * (float)Math.PI - phi;
                        }

                        float cosPhi = (float)Math.Cos(phi);
                        float sinPhi = (float)Math.Sin(phi);

                        float denom = (cosPhi * cosPhi) / (alphaX * alphaX) + (sinPhi * sinPhi) / (alphaY * alphaY);
                        float theta = (float)Math.Atan(Math.Sqrt(-Math.Log(1 - r2) / denom));

                        float sinTheta = (float)Math.Sin(theta);
                        float cosTheta = (float)Math.Cos(theta);

                        Vector3 h = new Vector3();
                        h.x = sinTheta * cosPhi;
                        h.y = sinTheta * sinPhi;
                        h.z = cosTheta;
                        onb.transform(h);

                        Vector3 o = new Vector3();
                        float ih = Vector3.dot(h, inv);
                        o.x = 2 * ih * h.x - inv.x;
                        o.y = 2 * ih * h.y - inv.y;
                        o.z = 2 * ih * h.z - inv.z;

                        float no = onb.untransformZ(o);
                        float ni = onb.untransformZ(inv);
                        float w = ih * cosTheta * cosTheta * cosTheta * (float)Math.Sqrt(Math.Abs(no / ni));

                        Ray r = new Ray(state.getPoint(), o);
                        lr.madd(w / n, state.traceGlossy(r, i));
                    }
                }
                lr.mul(rhoS);
            }
            // add diffuse contribution
            lr.add(state.diffuse(getDiffuse(state)));
            return lr;
        }
        public void scatterPhoton(ShadingState state, Color power)
        {
            // make sure we are on the right side of the material
            state.faceforward();
            Color d = getDiffuse(state);
            state.storePhoton(state.getRay().getDirection(), power, d);
            float avgD = d.getAverage();
            float avgS = rhoS.getAverage();
            double rnd = state.getRandom(0, 0, 1);
            if (rnd < avgD)
            {
                // photon is scattered diffusely
                power.mul(d).mul(1.0f / avgD);
                OrthoNormalBasis onb = state.getBasis();
                double u = 2 * Math.PI * rnd / avgD;
                double v = state.getRandom(0, 1, 1);
                float s = (float)Math.Sqrt(v);
                float s1 = (float)Math.Sqrt(1.0f - v);
                Vector3 w = new Vector3((float)Math.Cos(u) * s, (float)Math.Sin(u) * s, s1);
                w = onb.transform(w, new Vector3());
                state.traceDiffusePhoton(new Ray(state.getPoint(), w), power);
            }
            else if (rnd < avgD + avgS)
            {
                // photon is scattered specularly
                power.mul(rhoS).mul(1 / avgS);
                OrthoNormalBasis basis = state.getBasis();
                Vector3 inv = state.getRay().getDirection().negate(new Vector3());
                double r1 = rnd / avgS;
                double r2 = state.getRandom(0, 1, 1);

                float alphaRatio = alphaY / alphaX;
                float phi = 0;
                if (r1 < 0.25)
                {
                    double val = 4 * r1;
                    phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                }
                else if (r1 < 0.5)
                {
                    double val = 1 - 4 * (0.5 - r1);
                    phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                    phi = (float)Math.PI - phi;
                }
                else if (r1 < 0.75)
                {
                    double val = 4 * (r1 - 0.5);
                    phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                    phi += (float)Math.PI;
                }
                else
                {
                    double val = 1 - 4 * (1 - r1);
                    phi = (float)Math.Atan(alphaRatio * Math.Tan(Math.PI / 2 * val));
                    phi = 2 * (float)Math.PI - phi;
                }

                float cosPhi = (float)Math.Cos(phi);
                float sinPhi = (float)Math.Sin(phi);

                float denom = (cosPhi * cosPhi) / (alphaX * alphaX) + (sinPhi * sinPhi) / (alphaY * alphaY);
                float theta = (float)Math.Atan(Math.Sqrt(-Math.Log(1 - r2) / denom));

                float sinTheta = (float)Math.Sin(theta);
                float cosTheta = (float)Math.Cos(theta);

                Vector3 h = new Vector3();
                h.x = sinTheta * cosPhi;
                h.y = sinTheta * sinPhi;
                h.z = cosTheta;
                basis.transform(h);

                Vector3 o = new Vector3();
                float ih = Vector3.dot(h, inv);
                o.x = 2 * ih * h.x - inv.x;
                o.y = 2 * ih * h.y - inv.y;
                o.z = 2 * ih * h.z - inv.z;

                Ray r = new Ray(state.getPoint(), o);
                state.traceReflectionPhoton(r, power);
            }
        }
Beispiel #15
0
 public void intersect(Ray r, IntersectionState state)
 {
     float intervalMin = r.getMin();
     float intervalMax = r.getMax();
     float orgX = r.ox;
     float dirX = r.dx, invDirX = 1 / dirX;
     float t1, t2;
     t1 = (bounds.getMinimum().x - orgX) * invDirX;
     t2 = (bounds.getMaximum().x - orgX) * invDirX;
     if (invDirX > 0)
     {
         if (t1 > intervalMin)
             intervalMin = t1;
         if (t2 < intervalMax)
             intervalMax = t2;
     }
     else
     {
         if (t2 > intervalMin)
             intervalMin = t2;
         if (t1 < intervalMax)
             intervalMax = t1;
     }
     if (intervalMin > intervalMax)
         return;
     float orgY = r.oy;
     float dirY = r.dy, invDirY = 1 / dirY;
     t1 = (bounds.getMinimum().y - orgY) * invDirY;
     t2 = (bounds.getMaximum().y - orgY) * invDirY;
     if (invDirY > 0)
     {
         if (t1 > intervalMin)
             intervalMin = t1;
         if (t2 < intervalMax)
             intervalMax = t2;
     }
     else
     {
         if (t2 > intervalMin)
             intervalMin = t2;
         if (t1 < intervalMax)
             intervalMax = t1;
     }
     if (intervalMin > intervalMax)
         return;
     float orgZ = r.oz;
     float dirZ = r.dz, invDirZ = 1 / dirZ;
     t1 = (bounds.getMinimum().z - orgZ) * invDirZ;
     t2 = (bounds.getMaximum().z - orgZ) * invDirZ;
     if (invDirZ > 0)
     {
         if (t1 > intervalMin)
             intervalMin = t1;
         if (t2 < intervalMax)
             intervalMax = t2;
     }
     else
     {
         if (t2 > intervalMin)
             intervalMin = t2;
         if (t1 < intervalMax)
             intervalMax = t1;
     }
     if (intervalMin > intervalMax)
         return;
     // box is hit at [intervalMin, intervalMax]
     orgX += intervalMin * dirX;
     orgY += intervalMin * dirY;
     orgZ += intervalMin * dirZ;
     // locate starting point inside the grid
     // and set up 3D-DDA vars
     int indxX, indxY, indxZ;
     int stepX, stepY, stepZ;
     int stopX, stopY, stopZ;
     float deltaX, deltaY, deltaZ;
     float tnextX, tnextY, tnextZ;
     // stepping factors along X
     indxX = (int)((orgX - bounds.getMinimum().x) * invVoxelwx);
     if (indxX < 0)
         indxX = 0;
     else if (indxX >= nx)
         indxX = nx - 1;
     if (Math.Abs(dirX) < 1e-6f)
     {
         stepX = 0;
         stopX = indxX;
         deltaX = 0;
         tnextX = float.PositiveInfinity;
     }
     else if (dirX > 0)
     {
         stepX = 1;
         stopX = nx;
         deltaX = voxelwx * invDirX;
         tnextX = intervalMin + ((indxX + 1) * voxelwx + bounds.getMinimum().x - orgX) * invDirX;
     }
     else
     {
         stepX = -1;
         stopX = -1;
         deltaX = -voxelwx * invDirX;
         tnextX = intervalMin + (indxX * voxelwx + bounds.getMinimum().x - orgX) * invDirX;
     }
     // stepping factors along Y
     indxY = (int)((orgY - bounds.getMinimum().y) * invVoxelwy);
     if (indxY < 0)
         indxY = 0;
     else if (indxY >= ny)
         indxY = ny - 1;
     if (Math.Abs(dirY) < 1e-6f)
     {
         stepY = 0;
         stopY = indxY;
         deltaY = 0;
         tnextY = float.PositiveInfinity;
     }
     else if (dirY > 0)
     {
         stepY = 1;
         stopY = ny;
         deltaY = voxelwy * invDirY;
         tnextY = intervalMin + ((indxY + 1) * voxelwy + bounds.getMinimum().y - orgY) * invDirY;
     }
     else
     {
         stepY = -1;
         stopY = -1;
         deltaY = -voxelwy * invDirY;
         tnextY = intervalMin + (indxY * voxelwy + bounds.getMinimum().y - orgY) * invDirY;
     }
     // stepping factors along Z
     indxZ = (int)((orgZ - bounds.getMinimum().z) * invVoxelwz);
     if (indxZ < 0)
         indxZ = 0;
     else if (indxZ >= nz)
         indxZ = nz - 1;
     if (Math.Abs(dirZ) < 1e-6f)
     {
         stepZ = 0;
         stopZ = indxZ;
         deltaZ = 0;
         tnextZ = float.PositiveInfinity;
     }
     else if (dirZ > 0)
     {
         stepZ = 1;
         stopZ = nz;
         deltaZ = voxelwz * invDirZ;
         tnextZ = intervalMin + ((indxZ + 1) * voxelwz + bounds.getMinimum().z - orgZ) * invDirZ;
     }
     else
     {
         stepZ = -1;
         stopZ = -1;
         deltaZ = -voxelwz * invDirZ;
         tnextZ = intervalMin + (indxZ * voxelwz + bounds.getMinimum().z - orgZ) * invDirZ;
     }
     int cellstepX = stepX;
     int cellstepY = stepY * nx;
     int cellstepZ = stepZ * ny * nx;
     int cell = indxX + indxY * nx + indxZ * ny * nx;
     // trace through the grid
     for (; ; )
     {
         if (tnextX < tnextY && tnextX < tnextZ)
         {
             if (cells[cell] != null)
             {
                 foreach (int i in cells[cell])
                     primitives.intersectPrimitive(r, i, state);
                 if (state.hit() && (r.getMax() < tnextX && r.getMax() < intervalMax))
                     return;
             }
             intervalMin = tnextX;
             if (intervalMin > intervalMax)
                 return;
             indxX += stepX;
             if (indxX == stopX)
                 return;
             tnextX += deltaX;
             cell += cellstepX;
         }
         else if (tnextY < tnextZ)
         {
             if (cells[cell] != null)
             {
                 foreach (int i in cells[cell])
                     primitives.intersectPrimitive(r, i, state);
                 if (state.hit() && (r.getMax() < tnextY && r.getMax() < intervalMax))
                     return;
             }
             intervalMin = tnextY;
             if (intervalMin > intervalMax)
                 return;
             indxY += stepY;
             if (indxY == stopY)
                 return;
             tnextY += deltaY;
             cell += cellstepY;
         }
         else
         {
             if (cells[cell] != null)
             {
                 foreach (int i in cells[cell])
                     primitives.intersectPrimitive(r, i, state);
                 if (state.hit() && (r.getMax() < tnextZ && r.getMax() < intervalMax))
                     return;
             }
             intervalMin = tnextZ;
             if (intervalMin > intervalMax)
                 return;
             indxZ += stepZ;
             if (indxZ == stopZ)
                 return;
             tnextZ += deltaZ;
             cell += cellstepZ;
         }
     }
 }
Beispiel #16
0
 public void traceRefractionPhoton(ShadingState previous, Ray r, Color power)
 {
     if (previous.getRefractionDepth() >= maxRefractionDepth)
         return;
     IntersectionState istate = previous.getIntersectionState();
     scene.trace(r, istate);
     if (previous.getIntersectionState().hit())
     {
         // create a new shading context
         ShadingState state = ShadingState.createRefractionBounceState(previous, r, 0);
         shadePhoton(state, power);
     }
 }
Beispiel #17
0
 public ShadingState traceFinalGather(ShadingState previous, Ray r, int i)
 {
     if (previous.getDiffuseDepth() >= maxDiffuseDepth)
         return null;
     IntersectionState istate = previous.getIntersectionState();
     scene.trace(r, istate);
     return istate.hit() ? ShadingState.createFinalGatherState(previous, r, i) : null;
 }
Beispiel #18
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     if (r.getMax() == float.PositiveInfinity)
         state.setIntersection(0, 0, 0);
 }
Beispiel #19
0
 /**
  * Create a new ray by transforming the supplied one by the given matrix. If
  * the matrix is <code>null</code>, the original ray is returned.
  *
  * @param m matrix to transform the ray by
  */
 public Ray transform(Matrix4 m)
 {
     if (m == null)
         return this;
     Ray r = new Ray();
     r.ox = m.transformPX(ox, oy, oz);
     r.oy = m.transformPY(ox, oy, oz);
     r.oz = m.transformPZ(ox, oy, oz);
     r.dx = m.transformVX(dx, dy, dz);
     r.dy = m.transformVY(dx, dy, dz);
     r.dz = m.transformVZ(dx, dy, dz);
     r.tMin = tMin;
     r.tMax = tMax;
     return r;
 }
Beispiel #20
0
 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);
     foreach (PointLight vpl in 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;
 }
Beispiel #21
0
 public void intersect(Ray r, IntersectionState state)
 {
     for (int i = 0; i < n; i++)
         primitives.intersectPrimitive(r, i, state);
 }
Beispiel #22
0
 public ShadingState getRadiance(float rx, float ry, int i, Ray r, IntersectionState istate)
 {
     lock (lockObj)
     {
         scene.trace(r, istate);
         if (istate.hit())
         {
             ShadingState state = ShadingState.createState(istate, rx, ry, r, i, this);
             state.getInstance().prepareShadingState(state);
             IShader shader = getShader(state);
             if (shader == null)
             {
                 state.setResult(Color.BLACK);
                 return state;
             }
             if (_shadingCache != null)
             {
                 Color c = lookupShadingCache(state, shader);
                 if (c != null)
                 {
                     state.setResult(c);
                     return state;
                 }
             }
             state.setResult(shader.getRadiance(state));
             if (_shadingCache != null)
                 addShadingCache(state, shader, state.getResult());
             return state;
         }
         else
             return null;
     }
 }
Beispiel #23
0
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     float intervalMin = float.NegativeInfinity;
     float intervalMax = float.PositiveInfinity;
     float orgX = r.ox;
     float invDirX = 1 / r.dx;
     float t1, t2;
     t1 = (minX - orgX) * invDirX;
     t2 = (maxX - orgX) * invDirX;
     int sideIn = -1, sideOut = -1;
     if (invDirX > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             sideIn = 0;
         }
         if (t2 < intervalMax)
         {
             intervalMax = t2;
             sideOut = 1;
         }
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             sideIn = 1;
         }
         if (t1 < intervalMax)
         {
             intervalMax = t1;
             sideOut = 0;
         }
     }
     if (intervalMin > intervalMax)
         return;
     float orgY = r.oy;
     float invDirY = 1 / r.dy;
     t1 = (minY - orgY) * invDirY;
     t2 = (maxY - orgY) * invDirY;
     if (invDirY > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             sideIn = 2;
         }
         if (t2 < intervalMax)
         {
             intervalMax = t2;
             sideOut = 3;
         }
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             sideIn = 3;
         }
         if (t1 < intervalMax)
         {
             intervalMax = t1;
             sideOut = 2;
         }
     }
     if (intervalMin > intervalMax)
         return;
     float orgZ = r.oz;
     float invDirZ = 1 / r.dz;
     t1 = (minZ - orgZ) * invDirZ; // no front wall
     t2 = (maxZ - orgZ) * invDirZ;
     if (invDirZ > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             sideIn = 4;
         }
         if (t2 < intervalMax)
         {
             intervalMax = t2;
             sideOut = 5;
         }
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             sideIn = 5;
         }
         if (t1 < intervalMax)
         {
             intervalMax = t1;
             sideOut = 4;
         }
     }
     if (intervalMin > intervalMax)
         return;
     if (r.isInside(intervalMin))
     {
         r.setMax(intervalMin);
         state.setIntersection(sideIn, 0, 0);
     }
     else if (r.isInside(intervalMax))
     {
         r.setMax(intervalMax);
         state.setIntersection(sideOut, 0, 0);
     }
 }
Beispiel #24
0
        public void intersect(Ray r, IntersectionState state)
        {
            float intervalMin = r.getMin();
            float intervalMax = r.getMax();
            float orgX = r.ox;
            float dirX = r.dx, invDirX = 1 / dirX;
            float t1, t2;

                t1 = (bounds.getMinimum ().x - orgX) * invDirX;
                t2 = (bounds.getMaximum ().x - orgX) * invDirX;
                if (invDirX > 0) {
                    if (t1 > intervalMin)
                        intervalMin = t1;
                    if (t2 < intervalMax)
                        intervalMax = t2;
                } else {
                    if (t2 > intervalMin)
                        intervalMin = t2;
                    if (t1 < intervalMax)
                        intervalMax = t1;
                }
                if (intervalMin > intervalMax)
                    return;
                float orgY = r.oy;
                float dirY = r.dy, invDirY = 1 / dirY;
                t1 = (bounds.getMinimum ().y - orgY) * invDirY;
                t2 = (bounds.getMaximum ().y - orgY) * invDirY;
                if (invDirY > 0) {
                    if (t1 > intervalMin)
                        intervalMin = t1;
                    if (t2 < intervalMax)
                        intervalMax = t2;
                } else {
                    if (t2 > intervalMin)
                        intervalMin = t2;
                    if (t1 < intervalMax)
                        intervalMax = t1;
                }
                if (intervalMin > intervalMax)
                    return;
                float orgZ = r.oz;
                float dirZ = r.dz, invDirZ = 1 / dirZ;
                t1 = (bounds.getMinimum ().z - orgZ) * invDirZ;
                t2 = (bounds.getMaximum ().z - orgZ) * invDirZ;
                if (invDirZ > 0) {
                    if (t1 > intervalMin)
                        intervalMin = t1;
                    if (t2 < intervalMax)
                        intervalMax = t2;
                } else {
                    if (t2 > intervalMin)
                        intervalMin = t2;
                    if (t1 < intervalMax)
                        intervalMax = t1;
                }
                if (intervalMin > intervalMax)
                    return;

                // compute custom offsets from direction sign bit
                int offsetXFront = (int)((uint)(ByteUtil.floatToRawIntBits (dirX) & (1 << 31)) >> 30);//>>>
                int offsetYFront = (int)((uint)(ByteUtil.floatToRawIntBits (dirY) & (1 << 31)) >> 30);//>>>
                int offsetZFront = (int)((uint)(ByteUtil.floatToRawIntBits (dirZ) & (1 << 31)) >> 30);//>>>

                int offsetXBack = offsetXFront ^ 2;
                int offsetYBack = offsetYFront ^ 2;
                int offsetZBack = offsetZFront ^ 2;

                IntersectionState.StackNode[] stack = state.getStack ();
                int stackPos = 0;
                int node = 0;

                while (true) {
                    int tn = tree [node];
                    int axis = tn & (3 << 30);
                    int offset = tn & ~(3 << 30);
                    switch (axis) {
                    case 0:
                        {
                            float d = (ByteUtil.intBitsToFloat (tree [node + 1]) - orgX) * invDirX;
                            int back = offset + offsetXBack;
                            node = back;
                            if (d < intervalMin)
                                continue;
                            node = offset + offsetXFront; // front
                            if (d > intervalMax)
                                continue;
                            // push back node
                            stack [stackPos].node = back;
                            stack [stackPos].near = (d >= intervalMin) ? d : intervalMin;
                            stack [stackPos].far = intervalMax;
                            stackPos++;
                            // update ray interval for front node
                            intervalMax = (d <= intervalMax) ? d : intervalMax;
                            continue;
                        }
                    case 1 << 30:
                        {
                            // y axis
                            float d = (ByteUtil.intBitsToFloat (tree [node + 1]) - orgY) * invDirY;
                            int back = offset + offsetYBack;
                            node = back;
                            if (d < intervalMin)
                                continue;
                            node = offset + offsetYFront; // front
                            if (d > intervalMax)
                                continue;
                            // push back node
                            stack [stackPos].node = back;
                            stack [stackPos].near = (d >= intervalMin) ? d : intervalMin;
                            stack [stackPos].far = intervalMax;
                            stackPos++;
                            // update ray interval for front node
                            intervalMax = (d <= intervalMax) ? d : intervalMax;
                            continue;
                        }
                    case 2 << 30:
                        {
                            // z axis
                            float d = (ByteUtil.intBitsToFloat (tree [node + 1]) - orgZ) * invDirZ;
                            int back = offset + offsetZBack;
                            node = back;
                            if (d < intervalMin)
                                continue;
                            node = offset + offsetZFront; // front
                            if (d > intervalMax)
                                continue;
                            // push back node
                            stack [stackPos].node = back;
                            stack [stackPos].near = (d >= intervalMin) ? d : intervalMin;
                            stack [stackPos].far = intervalMax;
                            stackPos++;
                            // update ray interval for front node
                            intervalMax = (d <= intervalMax) ? d : intervalMax;
                            continue;
                        }
                    default:
                        {
                            // leaf - test some objects
                            int n = tree [node + 1];
                            while (n > 0) {
                                primitiveList.intersectPrimitive (r, primitives [offset], state);
                                n--;
                                offset++;
                            }
                            if (r.getMax () < intervalMax)
                                return;
                            do {
                                // stack is empty?
                                if (stackPos == 0)
                                    return;
                                // move back up the stack
                                stackPos--;
                                intervalMin = stack [stackPos].near;
                                if (r.getMax () < intervalMin)
                                    continue;
                                node = stack [stackPos].node;
                                intervalMax = stack [stackPos].far;
                                break;
                            } while (true);
                            break;
                        }
                    } // switch
                } // traversal loop
        }
Beispiel #25
0
 public ShadingState getRadiance(float rx, float ry, float time, int i, int d, Ray r, IntersectionState istate, ShadingCache cache)
 {
     istate.time = time;
     scene.trace(r, istate);
     if (istate.hit()) {
         ShadingState state = ShadingState.createState(istate, rx, ry, time, r, i, d, this);
         state.getInstance().prepareShadingState(state);
         IShader shader = getShader(state);
         if (shader == null) {
             state.setResult(Color.BLACK);
             return state;
         }
         if (cache != null) {
             Color c = cache.lookup(state, shader);
             if (c != null) {
                 state.setResult(c);
                 return state;
             }
         }
         state.setResult(shader.GetRadiance(state));
         if (cache != null)
             cache.add(state, shader, state.getResult());
         checkNanInf(state.getResult());
         return state;
     } else
         return null;
 }
Beispiel #26
0
 public void intersect(Ray r, IntersectionState state)
 {
     Ray localRay = r.transform(w2o.sample(state.time));
     state.current = this;
     geometry.intersect(localRay, state);
     // FIXME: transfer max distance to current ray
     r.setMax(localRay.getMax());
 }
Beispiel #27
0
 public Color traceRefraction(ShadingState previous, Ray r, int i)
 {
     // limit path depth and disable caustic paths
     if (previous.getRefractionDepth() >= maxRefractionDepth || previous.getDiffuseDepth() > 0)
         return Color.BLACK;
     IntersectionState istate = previous.getIntersectionState();
     istate.numRefractionRays++;
     scene.trace(r, istate);
     return istate.hit() ? shadeHit(ShadingState.createRefractionBounceState(previous, r, i)) : Color.BLACK;
 }
Beispiel #28
0
            public void getSamples(ShadingState state)
            {
                if (meshlight.numSamples == 0)
                    return;
                Vector3 n = state.getNormal();
                Point3 p = state.getPoint();
                // vector towards each vertex of the light source
                Vector3 p0 = Point3.sub(meshlight.getPoint(meshlight.triangles[tri3 + 0]), p, new Vector3());
                // cull triangle if it is facing the wrong way
                if (Vector3.dot(p0, ng) >= 0)
                    return;
                Vector3 p1 = Point3.sub(meshlight.getPoint(meshlight.triangles[tri3 + 1]), p, new Vector3());
                Vector3 p2 = Point3.sub(meshlight.getPoint(meshlight.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)
                    return;
                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
                    return;
                Vector3 n0 = Vector3.cross(p0, p1, new Vector3());
                float len0 = n0.Length();
                if (len0 > 1e-6f)
                    n0.div(len0);
                else
                    return;
                Vector3 n1 = Vector3.cross(p1, p2, new Vector3());
                float len1 = n1.Length();
                if (len1 > 1e-6f)
                    n1.div(len1);
                else
                    return;
                Vector3 n2 = Vector3.cross(p2, p0, new Vector3());
                float len2 = n2.Length();
                if (len2 > 1e-6f)
                    n2.div(len2);
                else
                    return;

                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 : meshlight.numSamples;
                Color c = Color.mul(area / samples, meshlight.radiance);
                for (int i = 0; i < samples; i++)
                {
                    // random offset on unit square
                    double randX = state.getRandom(i, 0, samples);
                    double randY = state.getRandom(i, 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;

                    // make sure the sample is in the right hemisphere - facing in
                    // the right direction
                    if (Vector3.dot(result, n) > 0 && Vector3.dot(result, state.getGeoNormal()) > 0 && Vector3.dot(result, ng) < 0)
                    {
                        // compute intersection with triangle (if any)
                        Ray shadowRay = new Ray(state.getPoint(), result);
                        if (!intersectTriangleKensler(shadowRay))
                            continue;
                        LightSample dest = new LightSample();
                        dest.setShadowRay(shadowRay);
                        // prepare sample
                        dest.setRadiance(c, c);
                        dest.traceShadow(state);
                        state.addSample(dest);
                    }
                }
            }
Beispiel #29
0
            public void Run()
            {
                ByteUtil.InitByteUtil();
                IntersectionState istate = new IntersectionState();
                for (int i = start; i < end; i++)
                {
                    lock (lockObj)
                    {
                        UI.taskUpdate(server.photonCounter);
                        server.photonCounter++;
                        if (UI.taskCanceled())
                            return;
                    }

                    int qmcI = i + seed;

                    double rand = QMC.halton(0, qmcI) * histogram[histogram.Length - 1];
                    int j = 0;
                    while (rand >= histogram[j] && j < histogram.Length)
                        j++;
                    // make sure we didn't pick a zero-probability light
                    if (j == histogram.Length)
                        continue;

                    double randX1 = (j == 0) ? rand / histogram[0] : (rand - histogram[j]) / (histogram[j] - histogram[j - 1]);
                    double randY1 = QMC.halton(1, qmcI);
                    double randX2 = QMC.halton(2, qmcI);
                    double randY2 = QMC.halton(3, qmcI);
                    Point3 pt = new Point3();
                    Vector3 dir = new Vector3();
                    Color power = new Color();
                    server.lights[j].getPhoton(randX1, randY1, randX2, randY2, pt, dir, power);
                    power.mul(scale);
                    Ray r = new Ray(pt, dir);
                    server.scene.trace(r, istate);
                    if (istate.hit())
                        server.shadePhoton(ShadingState.createPhotonState(r, istate, qmcI, map, server), power);
                }
            }
Beispiel #30
0
 private bool intersectTriangleKensler(Ray r)
 {
     int a = 3 * meshlight.triangles[tri3 + 0];
     int b = 3 * meshlight.triangles[tri3 + 1];
     int c = 3 * meshlight.triangles[tri3 + 2];
     float edge0x = meshlight.points[b + 0] - meshlight.points[a + 0];
     float edge0y = meshlight.points[b + 1] - meshlight.points[a + 1];
     float edge0z = meshlight.points[b + 2] - meshlight.points[a + 2];
     float edge1x = meshlight.points[a + 0] - meshlight.points[c + 0];
     float edge1y = meshlight.points[a + 1] - meshlight.points[c + 1];
     float edge1z = meshlight.points[a + 2] - meshlight.points[c + 2];
     float nx = edge0y * edge1z - edge0z * edge1y;
     float ny = edge0z * edge1x - edge0x * edge1z;
     float nz = edge0x * edge1y - edge0y * edge1x;
     float v = r.dot(nx, ny, nz);
     float iv = 1 / v;
     float edge2x = meshlight.points[a + 0] - r.ox;
     float edge2y = meshlight.points[a + 1] - r.oy;
     float edge2z = meshlight.points[a + 2] - r.oz;
     float va = nx * edge2x + ny * edge2y + nz * edge2z;
     float t = iv * va;
     if (t <= 0)
         return false;
     float ix = edge2y * r.dz - edge2z * r.dy;
     float iy = edge2z * r.dx - edge2x * r.dz;
     float iz = edge2x * r.dy - edge2y * r.dx;
     float v1 = ix * edge1x + iy * edge1y + iz * edge1z;
     float beta = iv * v1;
     if (beta < 0)
         return false;
     float v2 = ix * edge0x + iy * edge0y + iz * edge0z;
     if ((v1 + v2) * v > v * v)
         return false;
     float gamma = iv * v2;
     if (gamma < 0)
         return false;
     // FIXME: arbitrary bias, should handle as in other places
     r.setMax(t - 1e-3f);
     return true;
 }