private void Update(Scene scene, Camera camera) { // set GL state for depth map GL.ClearColor( 1, 1, 1, 1 ); GL.Disable( EnableCap.Blend); renderer.DepthTest = true; // update scene if ( scene.AutoUpdate) scene.UpdateMatrixWorld(); // update camera matrices and frustum camera.matrixWorldInverse = Matrix4.GetInverse(camera.matrixWorld); projectionScreenMatrix.MultiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); frustum = Frustum.FromMatrix( projectionScreenMatrix ); // render depth map renderer.SetRenderTarget(renderTarget ); renderer.Clear(); // set object matrices & frustum culling renderList.Clear(); ProjectObject(scene,scene,camera); // render regular objects foreach(var glObject in renderList) { var o = glObject.Object; var buffer = glObject.Buffer; // TODO: create proper depth material for particles if(o is PointCloud /*&& !o.customDepthMaterial*/) continue; // var useMorphing = o.geometry.MorphTargets != null && o.geometry.MorphTargets.Count > 0; /* TODO IAN, need this for skinning? && object.Material.morphTargets */ // var useSkinning = o is SkinnedMesh; /* TODO IAN, need this for skinning? && object.Material.skinning */ Material material; if (o.customDepthMaterial != null) material = o.customDepthMaterial; //else if ( useSkinning ) material = useMorphing ? depthMaterialMorphSkin : depthMaterialSkin; //else if ( useMorphing ) material = depthMaterialMorph; else material = depthMaterial; renderer.RenderBuffer( camera, scene.lights, null, material, buffer, o ); } // restore GL state var clearColor = renderer.ClearColor; GL.ClearColor(clearColor.R, clearColor.G, clearColor.B, 1 ); GL.Enable( EnableCap.Blend); }
public static Frustum FromMatrix(Matrix4 projectionScreen) { var me = projectionScreen.elements; float me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3]; float me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7]; float me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11]; float me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15]; var f = new Frustum( new Plane(me3 - me0, me7 - me4, me11 - me8, me15 - me12), new Plane(me3 + me0, me7 + me4, me11 + me8, me15 + me12), new Plane(me3 + me1, me7 + me5, me11 + me9, me15 + me13), new Plane(me3 - me1, me7 - me5, me11 - me9, me15 - me13), new Plane(me3 - me2, me7 - me6, me11 - me10, me15 - me14), new Plane(me3 + me2, me7 + me6, me11 + me10, me15 + me14)); foreach(var p in f.planes) p.Normalize(); return f; }
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); }