public Color3 getRadiance(RayContext rayContext)
        {
            Vector3 d = new Vector3();
            d.set( rayContext.ray.dir );

            double len = System.Math.Sqrt(d.x*d.x + d.y*d.y);
            double r = (len<0.0001) ? 0.0f : System.Math.Acos(-d.z)/(2.0f*System.Math.PI*len);
            double u = r*d.x + 0.5f;
            double v = 0.5f - r*d.y;

            int w = m_skyTexture.getWidth(), h = m_skyTexture.getHeight();

            double x = System.Math.Min(System.Math.Max(u, 0), 1);
            double y = System.Math.Min(System.Math.Max(v, 0), 1);

            Color3 c = new Color3();//m_skyTexture.evalColor(x, y);

            //System.Diagnostics.Debug.WriteLine(x.ToString()+" "+y.ToString());
            return c;
        }
        public Color3 getColor()
        {
            Color3 sumCol = new Color3();

            if (null == m_samples)
                return sumCol;

            if (m_samples.Count<1)
                return sumCol;

            foreach (ImageSample sample in m_samples)
            {
                sumCol += sample.color;
            }

            sumCol *= 1.0 / (double)m_samples.Count;

            //if (Double.IsNaN(sumCol.getIntensity()))
            //    return new Color3();

            return sumCol;
        }
        public Color3 illuminate(RayContext rayContext, BRDF brdf)
        {
            Color3 finalColor = new Color3();

            BRDFTypes brdfType = brdf.getType();

            if (brdf.matchTypes(BRDFTypes.Diffuse) || brdf.matchTypes(BRDFTypes.Glossy))
            {
                if (null != m_directLightIntegrator)
                    finalColor += m_directLightIntegrator.illuminate(rayContext, brdf);

                if (brdf.matchTypes(BRDFTypes.Diffuse) && null != m_diffuseIntegrator)
                    finalColor += m_diffuseIntegrator.illuminate(rayContext, brdf);
            }

            if (brdf.matchTypes(BRDFTypes.Specular))
            {
                if (rayContext.traceLevel < m_maxTraceLevel)
                    if (null != m_specularIntegrator)
                        finalColor += m_specularIntegrator.illuminate(rayContext, brdf);
            }

            return finalColor;
        }
 public ConstantShader()
 {
     //Default Implementation
     color = new Color3(0.8, 0.3, 0);
 }
 public void setColor(int x, int y, Color3 col)
 {
     lock (thisLock) {
         m_color[x + y * m_width] = col;
     }
 }
 public BRDF()
 {
     filterColor = new Color3();
     filterTexture = null;
 }
 public Color3( Color3 color )
 {
     this.r = color.r;
     this.g = color.g;
     this.b = color.b;
 }
 public void set( Color3 color )
 {
     this.r = color.r;
     this.g = color.g;
     this.b = color.b;
 }
        public Color3 illuminate(RayContext rayContext, BRDF brdf)
        {
            Ray newRay = new Ray();

            double invPdf = 0;

            //във finalColor ще сумираме резултатния цвят
            Color3 finalColor = new Color3();

            //задаваме максималната бройка лъчи
            //с които ще проследяваме грапави отражения
            int numSamples = 10;
            int curSample = 0;  //номер на текущ лъч

            for (curSample = 0; curSample < numSamples; curSample++)
            {
                //генерирме двойка случайни числа (ru, rv)
                double ru = rayContext.getRandom(0, curSample);
                double rv = rayContext.getRandom(1, curSample);

                //искаме brdf да конструира лъч използвайки (ru, rv)
                bool isValidSample = brdf.getSample(rayContext, ru, rv, out newRay.dir, out invPdf);

                if (!isValidSample)
                    continue;

                //конструираме нов лъч от текущата точка
                //и го обвиваме във собствен контекст
                newRay.p = rayContext.hitData.hitPos;
                RayContext newContext = RayContext.createNewContext(rayContext, newRay);
                //извикваме функцията shade, която проследява
                //лъча в сцената и го осветява
                rayContext.scene.shade(newContext);

                double cosT = rayContext.hitData.hitNormal * (newRay.dir);
                if (cosT < 0.0) cosT *= -1.0;

                double pdf;

                Color3 w = new Color3(1, 1, 1);
                //пресмятаме, каква част от светлината ще отрази BRFD-a
                w = brdf.eval(rayContext, newRay.dir, out pdf);

                if (!brdf.isSingular())
                {
                    w *= cosT * invPdf;
                }
                //добавяме енергията на новия лъч
                finalColor += newContext.resultColor * w;

                //if (Double.IsNaN(finalColor.getIntensity()))
                //    break;

                if (brdf.isSingular())
                    break;
            }

            //сумираме енергията от всички лъчи
            if (curSample > 0)
                finalColor *= 1.0 / (double)curSample;

            return finalColor;
        }
        public Color3 illuminate(RayContext rayContext, BRDF brdf)
        {
            //вземаме списък с всички светлини в сцената
            List<Light> lights = rayContext.scene.getLights();
            //в sumColor ще сумираме тяхната енергия
            Color3 sumColor = new Color3();
            foreach (Light light in lights)
            {
                Color3 color = new Color3();
                //задаваме максималната бройка лъчи
                //с които ще проследяваме към всяка светлина
                int numSamples = 25;
                int curSample = 0; //номер на текущ лъч
                LightSample lightSample;

                rayContext.randomIndex = 0;

                do
                {
                    curSample++;
                    //генерирме двойка случайни числа (ru, rv)
                    double ru = rayContext.getRandom(0, curSample);
                    double rv = rayContext.getRandom(1, curSample);
                    //искаме от светлината да върне сонда за сянка
                    lightSample = light.getSample(rayContext, ru, rv);

                    rayContext.randomIndex++;

                    if (null == lightSample)
                        continue;
                    //пресмятаме косинуса между нормалата на повърхността и лъча към лампата
                    double cosT = rayContext.hitData.hitNormal * (lightSample.shadowRay.dir);
                    if (cosT < 0.00001) cosT = 0.0;

                    //проверяваме за засенчване
                    if (rayContext.scene.traceShadowRay(lightSample.shadowRay, rayContext))
                        continue;

                    double pdf = 1.0;
                    //пресмятаме, каква част от светлината ще отрази BRFD-a
                    Color3 brdfCol = brdf.eval(rayContext, lightSample.shadowRay.dir, out pdf);

                    color += brdfCol * pdf * lightSample.color * cosT;

                    //ако светлината е точкова ни е нужен само един лъч
                    if (light.isSingular())
                        break;

                } while (curSample < numSamples);

                if (curSample < 1)
                    curSample = 1;

                //сумираме резултата от всички сампъли
                color *= 1.0 / (double)curSample;
                sumColor += color;
            }

            int lightsCount = lights.Count;
            if (lightsCount < 1)
                lightsCount = 1;

            //сумираме енергията от всички светлини
            sumColor *= 1.0 / (double)lightsCount;
            return sumColor;
        }
 public void setBackgroundColor(Color3 bgColor)
 {
     backgroundColor.set(bgColor);
 }
 public Scene()
 {
     primitives = new List<GeomPrimitive>();
     backgroundColor = new Color3(0, 0, 0);
     lights = new List<Light>();
 }
 public LightSample()
 {
     color = new Color3();
     shadowRay = new Ray();
 }
 public OmniLight()
 {
     pos = new Vector3();
     color = new Color3();
     power = 1.0;
 }