private void Update(Scene scene, Camera camera)
        {
            // set GL state for depth map
            GL.ClearColor(1, 1, 1, 1);
            GL.Disable(EnableCap.Blend);
            GL.Enable(EnableCap.CullFace);
            GL.FrontFace(FrontFaceDirection.Ccw);

            GL.CullFace(renderer.shadowMapCullFace);

            renderer.DepthTest = true;
            var lights = new List <Light>();

            // preprocess lights
            //  - skip lights that are not casting shadows
            //	- create virtual lights for cascaded shadow maps
            foreach (var light in scene.lights)
            {
                if (!light.DoesCastShadow)
                {
                    continue;
                }

                var shadowLight = light as HasShadow;
                if (shadowLight != null && shadowLight.ShadowCascade)
                {
                    for (var n = 0; n < shadowLight.ShadowCascadeCount; n++)
                    {
                        VirtualLight virtualLight;

                        if (shadowLight.ShadowCascadeArray[n] == null)
                        {
                            virtualLight = CreateVirtualLight(light, n);
                            virtualLight.OriginalCamera = camera;

                            var gyro = new Gyroscope();
                            gyro.Position = shadowLight.ShadowCascadeOffset;

                            gyro.Add(virtualLight);
                            //gyro.Add(virtualLight.Target);
                            camera.Add(gyro);

                            shadowLight.ShadowCascadeArray[n] = virtualLight;
                            Debug.WriteLine("Created virtualLight {0}", virtualLight);
                        }
                        else
                        {
                            virtualLight = shadowLight.ShadowCascadeArray[n];
                        }

                        UpdateVirtualLight(light, n);
                        lights.Add(virtualLight);
                    }
                }
                else
                {
                    lights.Add(light);
                }
            }

            // render depth map
            foreach (var light in lights)
            {
                var hasShadow = light as HasShadow;
                if (hasShadow.shadowMap == null)
                {
                    var isSoftShadow = renderer.shadowMapType == ShadowType.PCFSoftShadowMap;
                    hasShadow.shadowMap           = new RenderTarget(hasShadow.ShadowMapWidth, hasShadow.ShadowMapHeight);
                    hasShadow.shadowMap.MinFilter = isSoftShadow ? TextureMinFilter.Nearest : TextureMinFilter.Linear;
                    hasShadow.shadowMap.MagFilter = isSoftShadow ? TextureMagFilter.Nearest : TextureMagFilter.Linear;;
                    hasShadow.shadowMap.Format    = Three.Net.Renderers.PixelFormat.RGBA;

                    hasShadow.ShadowMapSize = new Vector2(hasShadow.ShadowMapWidth, hasShadow.ShadowMapHeight);
                    hasShadow.ShadowMatrix  = Matrix4.Identity;
                }

                if (hasShadow.ShadowCamera == null)
                {
                    if (hasShadow is SpotLight)
                    {
                        hasShadow.ShadowCamera = new PerspectiveCamera(renderer, hasShadow.ShadowCameraFov, hasShadow.ShadowCameraNear, hasShadow.ShadowCameraFar);
                    }
                    else if (hasShadow is DirectionalLight)
                    {
                        hasShadow.ShadowCamera = new OrthographicCamera(hasShadow.ShadowCameraLeft, hasShadow.ShadowCameraRight, hasShadow.ShadowCameraTop, hasShadow.ShadowCameraBottom, hasShadow.ShadowCameraNear, hasShadow.ShadowCameraFar);
                    }
                    else
                    {
                        throw new Exception("Unsupported light type for shadow");
                    }

                    scene.Add(hasShadow.ShadowCamera);
                    if (scene.AutoUpdate)
                    {
                        scene.UpdateMatrixWorld();
                    }
                }

                if (hasShadow.ShadowCameraVisible /* && light.CameraHelper == null*/)
                {
                    throw new NotImplementedException();
                    //light.CameraHelper = new CameraHelper( hasShadow.ShadowCamera );
                    //hasShadow.ShadowCamera.Add( light.CameraHelper );
                }

                var virtualLight = light as VirtualLight;
                if (virtualLight != null && virtualLight.OriginalCamera == camera)
                {
                    UpdateShadowCamera(camera, light);
                }

                var shadowMap    = hasShadow.shadowMap;
                var shadowMatrix = hasShadow.ShadowMatrix;
                var shadowCamera = hasShadow.ShadowCamera;

                shadowCamera.Position = Vector3.FromPosition(light.matrixWorld);
                matrixPosition        = (light as HasTarget).Target;
                shadowCamera.LookAt(matrixPosition);
                shadowCamera.UpdateMatrixWorld();

                shadowCamera.matrixWorldInverse = Matrix4.GetInverse(shadowCamera.matrixWorld);

                //TODO : Creating helpers if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
                //if (hasShadow.ShadowCameraVisible) light.cameraHelper.update();

                // compute shadow matrix

                shadowMatrix = new Matrix4(0.5f, 0.0f, 0.0f, 0.5f,
                                           0.0f, 0.5f, 0.0f, 0.5f,
                                           0.0f, 0.0f, 0.5f, 0.5f,
                                           0.0f, 0.0f, 0.0f, 1.0f);

                shadowMatrix.Multiply(shadowCamera.projectionMatrix);
                shadowMatrix.Multiply(shadowCamera.matrixWorldInverse);

                // update camera matrices and frustum
                projectionScreenMatrix.MultiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
                frustum = Frustum.FromMatrix(projectionScreenMatrix);

                // render shadow map
                renderer.SetRenderTarget(shadowMap);
                renderer.Clear();

                // set object matrices & frustum culling

                renderList.Clear();
                ProjectObject(scene, scene, shadowCamera);

                // render regular objects
                foreach (var glObject in renderList)
                {
                    var o      = glObject.Object;
                    var buffer = glObject.Buffer;

                    throw new NotImplementedException();
                }
            }

            // restore GL state
            var clearColor = renderer.ClearColor;

            GL.ClearColor(clearColor.R, clearColor.G, clearColor.B, 1);
            GL.Enable(EnableCap.Blend);

            if (renderer.shadowMapCullFace == CullFaceMode.Front)
            {
                GL.CullFace(CullFaceMode.Back);
            }
        }