예제 #1
0
        public void scatterPhoton(ShadingState state, Color power)
        {
            Color diffuse, specular;

            // make sure we are on the right side of the material
            state.faceforward();
            diffuse  = getDiffuse(state);
            specular = getSpecular(state);
            state.storePhoton(state.getRay().getDirection(), power, diffuse);
            float  d   = diffuse.getAverage();
            float  r   = specular.getAverage();
            double rnd = state.getRandom(0, 0, 1);

            if (rnd < d)
            {
                // photon is scattered
                power.mul(diffuse).mul(1.0f / d);
                OrthoNormalBasis onb = state.getBasis();
                double           u   = 2 * Math.PI * rnd / d;
                double           v   = state.getRandom(0, 1, 1);
                float            s   = (float)Math.Sqrt(v);
                float            s1  = (float)Math.Sqrt(1.0 - 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 < d + r)
            {
                if (glossyness == 0)
                {
                    float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection());
                    power.mul(diffuse).mul(1.0f / d);
                    // photon is reflected
                    float   dn  = 2 * cos;
                    Vector3 dir = new Vector3();
                    dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
                    dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
                    dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
                    state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
                }
                else
                {
                    float dn = 2.0f * state.getCosND();
                    // reflected direction
                    Vector3 refDir = new Vector3();
                    refDir.x = (dn * state.getNormal().x) + state.getRay().dx;
                    refDir.y = (dn * state.getNormal().y) + state.getRay().dy;
                    refDir.z = (dn * state.getNormal().z) + state.getRay().dz;
                    power.mul(spec).mul(1.0f / r);
                    OrthoNormalBasis onb = state.getBasis();
                    double           u   = 2 * Math.PI * (rnd - r) / r;
                    double           v   = state.getRandom(0, 1, 1);
                    float            s   = (float)Math.Pow(v, 1 / ((1.0f / glossyness) + 1));
                    float            s1  = (float)Math.Sqrt(1 - s * s);
                    Vector3          w   = new Vector3((float)Math.Cos(u) * s1, (float)Math.Sin(u) * s1, s);
                    w = onb.transform(w, new Vector3());
                    state.traceReflectionPhoton(new Ray(state.getPoint(), w), power);
                }
            }
        }
예제 #2
0
 public void ScatterPhoton(ShadingState state, Color power)
 {
     float avg = color.getAverage();
     double rnd = state.getRandom(0, 0, 1);
     if (rnd >= avg)
         return;
     state.faceforward();
     float cos = state.getCosND();
     power.mul(color).mul(1.0f / avg);
     // photon is reflected
     float dn = 2 * cos;
     Vector3 dir = new Vector3();
     dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
     dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
     dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
     state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
 }
예제 #3
0
        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 = spec.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
                float dn = 2.0f * state.getCosND();
                // reflected direction
                Vector3 refDir = new Vector3();
                refDir.x = (dn * state.getNormal().x) + state.getRay().dx;
                refDir.y = (dn * state.getNormal().y) + state.getRay().dy;
                refDir.z = (dn * state.getNormal().z) + state.getRay().dz;
                power.mul(spec).mul(1.0f / avgS);
                OrthoNormalBasis onb = state.getBasis();
                double           u   = 2 * Math.PI * (rnd - avgD) / avgS;
                double           v   = state.getRandom(0, 1, 1);
                float            s   = (float)Math.Pow(v, 1 / (this.power + 1));
                float            s1  = (float)Math.Sqrt(1 - s * s);
                Vector3          w   = new Vector3((float)Math.Cos(u) * s1, (float)Math.Sin(u) * s1, s);
                w = onb.transform(w, new Vector3());
                state.traceReflectionPhoton(new Ray(state.getPoint(), w), power);
            }
        }
예제 #4
0
        public void scatterPhoton(ShadingState state, Color power)
        {
            float  avg = color.getAverage();
            double rnd = state.getRandom(0, 0, 1);

            if (rnd >= avg)
            {
                return;
            }
            state.faceforward();
            float cos = state.getCosND();

            power.mul(color).mul(1.0f / avg);
            // photon is reflected
            float   dn  = 2 * cos;
            Vector3 dir = new Vector3();

            dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
            dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
            dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
            state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
        }
예제 #5
0
        public void scatterPhoton(ShadingState state, Color power)
        {
            Color diffuse;

            // make sure we are on the right side of the material
            state.faceforward();
            diffuse = getDiffuse(state);
            state.storePhoton(state.getRay().getDirection(), power, diffuse);
            float  d   = diffuse.getAverage();
            float  r   = d * refl;
            double rnd = state.getRandom(0, 0, 1);

            if (rnd < d)
            {
                // photon is scattered
                power.mul(diffuse).mul(1.0f / d);
                OrthoNormalBasis onb = state.getBasis();
                double           u   = 2 * Math.PI * rnd / d;
                double           v   = state.getRandom(0, 1, 1);
                float            s   = (float)Math.Sqrt(v);
                float            s1  = (float)Math.Sqrt(1.0 - 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 < d + r)
            {
                float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection());
                power.mul(diffuse).mul(1.0f / d);
                // photon is reflected
                float   dn  = 2 * cos;
                Vector3 dir = new Vector3();
                dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
                dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
                dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
                state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
            }
        }
예제 #6
0
 public void ScatterPhoton(ShadingState state, Color power)
 {
     Color diffuse, specular;
     // make sure we are on the right side of the material
     state.faceforward();
     diffuse = getDiffuse(state);
     specular = getSpecular(state);
     state.storePhoton(state.getRay().getDirection(), power, diffuse);
     float d = diffuse.getAverage();
     float r = specular.getAverage();
     double rnd = state.getRandom(0, 0, 1);
     if (rnd < d)
     {
         // photon is scattered
         power.mul(diffuse).mul(1.0f / d);
         OrthoNormalBasis onb = state.getBasis();
         double u = 2 * Math.PI * rnd / d;
         double v = state.getRandom(0, 1, 1);
         float s = (float)Math.Sqrt(v);
         float s1 = (float)Math.Sqrt(1.0 - 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 < d + r)
     {
         if (glossyness == 0)
         {
             float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection());
             power.mul(diffuse).mul(1.0f / d);
             // photon is reflected
             float dn = 2 * cos;
             Vector3 dir = new Vector3();
             dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
             dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
             dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
             state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
         }
         else
         {
             float dn = 2.0f * state.getCosND();
             // reflected direction
             Vector3 refDir = new Vector3();
             refDir.x = (dn * state.getNormal().x) + state.getRay().dx;
             refDir.y = (dn * state.getNormal().y) + state.getRay().dy;
             refDir.z = (dn * state.getNormal().z) + state.getRay().dz;
             power.mul(spec).mul(1.0f / r);
             OrthoNormalBasis onb = state.getBasis();
             double u = 2 * Math.PI * (rnd - r) / r;
             double v = state.getRandom(0, 1, 1);
             float s = (float)Math.Pow(v, 1 / ((1.0f / glossyness) + 1));
             float s1 = (float)Math.Sqrt(1 - s * s);
             Vector3 w = new Vector3((float)Math.Cos(u) * s1, (float)Math.Sin(u) * s1, s);
             w = onb.transform(w, new Vector3());
             state.traceReflectionPhoton(new Ray(state.getPoint(), w), power);
         }
     }
 }
예제 #7
0
        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);
            }
        }
예제 #8
0
 public void ScatterPhoton(ShadingState state, Color power)
 {
     Color diffuse;
     // make sure we are on the right side of the material
     state.faceforward();
     diffuse = getDiffuse(state);
     state.storePhoton(state.getRay().getDirection(), power, diffuse);
     float d = diffuse.getAverage();
     float r = d * refl;
     double rnd = state.getRandom(0, 0, 1);
     if (rnd < d)
     {
         // photon is scattered
         power.mul(diffuse).mul(1.0f / d);
         OrthoNormalBasis onb = state.getBasis();
         double u = 2 * Math.PI * rnd / d;
         double v = state.getRandom(0, 1, 1);
         float s = (float)Math.Sqrt(v);
         float s1 = (float)Math.Sqrt(1.0 - 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 < d + r)
     {
         float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection());
         power.mul(diffuse).mul(1.0f / d);
         // photon is reflected
         float dn = 2 * cos;
         Vector3 dir = new Vector3();
         dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
         dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
         dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
         state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
     }
 }
예제 #9
0
 public void ScatterPhoton(ShadingState state, Color power)
 {
     Color refr = Color.mul(1 - f0, color);
     Color refl = Color.mul(f0, color);
     float avgR = refl.getAverage();
     float avgT = refr.getAverage();
     double rnd = state.getRandom(0, 0, 1);
     if (rnd < avgR)
     {
         state.faceforward();
         // don't reflect internally
         if (state.isBehind())
             return;
         // photon is reflected
         float cos = state.getCosND();
         power.mul(refl).mul(1.0f / avgR);
         float dn = 2 * cos;
         Vector3 dir = new Vector3();
         dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
         dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
         dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
         state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
     }
     else if (rnd < avgR + avgT)
     {
         state.faceforward();
         // photon is refracted
         float cos = state.getCosND();
         float neta = state.isBehind() ? eta : 1.0f / eta;
         power.mul(refr).mul(1.0f / avgT);
         float wK = -neta;
         float arg = 1 - (neta * neta * (1 - (cos * cos)));
         Vector3 dir = new Vector3();
         if (state.isBehind() && absorptionDistance > 0)
         {
             // this ray is inside the object and leaving it
             // compute attenuation that occured along the ray
             power.mul(Color.mul(-state.getRay().getMax() / absorptionDistance, absorptionColor.copy().opposite()).exp());
         }
         if (arg < 0)
         {
             // TIR
             float dn = 2 * cos;
             dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
             dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
             dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
             state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
         }
         else
         {
             float nK = (neta * cos) - (float)Math.Sqrt(arg);
             dir.x = (-wK * state.getRay().dx) + (nK * state.getNormal().x);
             dir.y = (-wK * state.getRay().dy) + (nK * state.getNormal().y);
             dir.z = (-wK * state.getRay().dz) + (nK * state.getNormal().z);
             state.traceRefractionPhoton(new Ray(state.getPoint(), dir), power);
         }
     }
 }
예제 #10
0
        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);
            }
        }
예제 #11
0
 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 = spec.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
         float dn = 2.0f * state.getCosND();
         // reflected direction
         Vector3 refDir = new Vector3();
         refDir.x = (dn * state.getNormal().x) + state.getRay().dx;
         refDir.y = (dn * state.getNormal().y) + state.getRay().dy;
         refDir.z = (dn * state.getNormal().z) + state.getRay().dz;
         power.mul(spec).mul(1.0f / avgS);
         OrthoNormalBasis onb = state.getBasis();
         double u = 2 * Math.PI * (rnd - avgD) / avgS;
         double v = state.getRandom(0, 1, 1);
         float s = (float)Math.Pow(v, 1 / (this.power + 1));
         float s1 = (float)Math.Sqrt(1 - s * s);
         Vector3 w = new Vector3((float)Math.Cos(u) * s1, (float)Math.Sin(u) * s1, s);
         w = onb.transform(w, new Vector3());
         state.traceReflectionPhoton(new Ray(state.getPoint(), w), power);
     }
 }
예제 #12
0
        public void ScatterPhoton(ShadingState state, Color power)
        {
            Color  refr = Color.mul(1 - f0, color);
            Color  refl = Color.mul(f0, color);
            float  avgR = refl.getAverage();
            float  avgT = refr.getAverage();
            double rnd  = state.getRandom(0, 0, 1);

            if (rnd < avgR)
            {
                state.faceforward();
                // don't reflect internally
                if (state.isBehind())
                {
                    return;
                }
                // photon is reflected
                float cos = state.getCosND();
                power.mul(refl).mul(1.0f / avgR);
                float   dn  = 2 * cos;
                Vector3 dir = new Vector3();
                dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
                dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
                dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
                state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
            }
            else if (rnd < avgR + avgT)
            {
                state.faceforward();
                // photon is refracted
                float cos  = state.getCosND();
                float neta = state.isBehind() ? eta : 1.0f / eta;
                power.mul(refr).mul(1.0f / avgT);
                float   wK  = -neta;
                float   arg = 1 - (neta * neta * (1 - (cos * cos)));
                Vector3 dir = new Vector3();
                if (state.isBehind() && absorptionDistance > 0)
                {
                    // this ray is inside the object and leaving it
                    // compute attenuation that occured along the ray
                    power.mul(Color.mul(-state.getRay().getMax() / absorptionDistance, absorptionColor.copy().opposite()).exp());
                }
                if (arg < 0)
                {
                    // TIR
                    float dn = 2 * cos;
                    dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
                    dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
                    dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
                    state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
                }
                else
                {
                    float nK = (neta * cos) - (float)Math.Sqrt(arg);
                    dir.x = (-wK * state.getRay().dx) + (nK * state.getNormal().x);
                    dir.y = (-wK * state.getRay().dy) + (nK * state.getNormal().y);
                    dir.z = (-wK * state.getRay().dz) + (nK * state.getNormal().z);
                    state.traceRefractionPhoton(new Ray(state.getPoint(), dir), power);
                }
            }
        }