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); } }