private void RenderCascades() { SunshineMath.BoundingSphere boundingSphere = default(SunshineMath.BoundingSphere); if (Sunshine.Instance.UsingCustomBounds) { boundingSphere = Sunshine.Instance.CustomBounds; } else { boundingSphere = SunshineMath.FrustumBoundingSphereBinarySearch(this.AttachedCamera, this.AttachedCamera.nearClipPlane, Sunshine.Instance.LightDistance, true, this.BoundsPadding, 0.01f, 20); } if (!this.NeedsRefresh(boundingSphere.origin)) { return; } bool flag = Sunshine.Instance.TerrainLODTweak > 0f; if (flag) { this.tempTerrainList.Clear(); this.tempTerrainPixelError.Clear(); Terrain[] activeTerrains = Terrain.activeTerrains; for (int i = 0; i < activeTerrains.Length; i++) { Terrain terrain = activeTerrains[i]; if (terrain) { this.tempTerrainList.Add(terrain); this.tempTerrainPixelError.Add(terrain.heightmapPixelError); terrain.heightmapPixelError *= 1f - Sunshine.Instance.TerrainLODTweak; } } } for (int j = 0; j < Sunshine.Instance.CascadeCount; j++) { Camera camera = Sunshine.Instance.SunLightCameras[j]; camera.cullingMask = Sunshine.Instance.GetCascadeOccluders(j); SunshineMath.SetupShadowCamera(Sunshine.Instance.SunLight, camera, this.AttachedCamera, Sunshine.Instance.CascadeNearClip(j), Sunshine.Instance.CascadeFarClip(j), Sunshine.Instance.LightPaddingZ, this.BoundsPadding, Sunshine.Instance.CascadeMapResolution, ref boundingSphere, ref this.cascadeTemporalData[j]); Shader.SetGlobalVector("sunshine_DepthBiases", new Vector2(Sunshine.Instance.ShadowBias, Sunshine.Instance.ShadowSlopeBias(j))); camera.rect = Sunshine.Instance.CascadeRects[j]; camera.targetTexture = Sunshine.Instance.Lightmap; camera.useOcclusionCulling = Sunshine.Instance.UseOcclusionCulling; camera.RenderWithShader(Sunshine.Instance.OccluderShader, "RenderType"); } if (flag) { for (int k = this.tempTerrainList.Count - 1; k >= 0; k--) { Terrain terrain2 = this.tempTerrainList[k]; terrain2.heightmapPixelError = this.tempTerrainPixelError[k]; } this.tempTerrainList.Clear(); this.tempTerrainPixelError.Clear(); } this.refreshRequested = false; }
private void SetShadowCamera() { if (this.eyeCamera.renderingPath == RenderingPath.DeferredShading && this.enableFarShadows) { Shader.EnableKeyword("_USING_DEFERREDSHADING"); this.shadowCameraGO.transform.rotation = Quaternion.LookRotation(Sunshine.Instance.SunLight.transform.forward); Transform transform = this.shadowCameraGO.transform; SunshineMath.BoundingSphere boundingSphere = default(SunshineMath.BoundingSphere); boundingSphere = SunshineMath.FrustumBoundingSphereBinarySearch(this.eyeCamera, this.eyeCamera.nearClipPlane, this.FarCascadeDistance, true, 0f, 0.01f, 20); float num = SunshineMath.QuantizeValueWithoutFlicker(boundingSphere.radius, 100, this.last_boundingRadius); this.last_boundingRadius = num; float num2 = num * 2f; transform.position = boundingSphere.origin; transform.position = this.eyeCamera.transform.position - Sunshine.Instance.SunLight.transform.forward * this.FarCascadeDistance * 0.5f; Vector3 vector = transform.InverseTransformPoint(Vector3.zero); float step = num2 / (float)this.shadowMapSize; vector.x = SunshineMath.QuantizeValueWithoutFlicker(vector.x, step, this.last_lightWorldOrigin.x); vector.y = SunshineMath.QuantizeValueWithoutFlicker(vector.y, step, this.last_lightWorldOrigin.y); this.last_lightWorldOrigin = vector; transform.position -= transform.TransformPoint(vector); Vector3 vector2 = transform.InverseTransformPoint(boundingSphere.origin); transform.position += transform.forward * (vector2.z - (boundingSphere.radius + this.lightCamera.nearClipPlane)); this.lightCamera.orthographicSize = num2 * 0.5f; this.lightCamera.nearClipPlane = this.eyeCamera.nearClipPlane; this.lightCamera.farClipPlane = (boundingSphere.radius + this.lightCamera.nearClipPlane) * 2f; this.lightCamera.cullingMask = this.CullingMask; this.bb_quad = Vector3.Dot(-Sunshine.Instance.SunLight.transform.forward, Vector3.up); this.biasLerp = Mathf.Abs(this.bb_quad); this.bb_quad = Mathf.Clamp01(Mathf.Clamp01(this.bb_quad + 0.0001f) - 0.75f) * 4f; this.bb_billboard = 1f - this.bb_quad; Shader.SetGlobalVector(this.billboardShadeFadeFactorsProp, new Vector4(this.bb_billboard, this.bb_quad, 0f, 0f)); this.biasLerp = Mathf.Clamp01(Mathf.Abs(0.7071f - this.biasLerp) * 4f); this.FarCascadeDepthBias = Mathf.Lerp(this.MaxFarCascadeDepthBias, this.MinFarCascadeDepthBias, this.biasLerp); this.SetFarShadowMatrix(boundingSphere.radius, this.FarCascadeDistance); Component[] componentsInChildren = this.parent.GetComponentsInChildren(typeof(MeshFilter)); int num3 = componentsInChildren.Length; GL.PushMatrix(); Graphics.SetRenderTarget(this.m_shadowTexture); GL.LoadProjectionMatrix(this.lightCamera.projectionMatrix); GL.Clear(true, false, Color.black, 6000f); this.mat.SetPass(0); foreach (MeshFilter meshFilter in componentsInChildren) { Graphics.DrawMeshNow(meshFilter.mesh, this.matrix); } GL.PopMatrix(); } else { Shader.DisableKeyword("_USING_DEFERREDSHADING"); } float num4 = QualitySettings.shadowDistance * 0.125f; Shader.SetGlobalVector(this.farCascadeBlendValuesProps, new Vector4(QualitySettings.shadowDistance - num4 * 2f, num4, this.FarCascadeDistance - this.FarCascadeDistance * 0.275f)); }
private void SetShadowCamera() { if (this.eyeCamera.renderingPath == RenderingPath.DeferredShading && this.enableFarShadows) { Shader.EnableKeyword("_USING_DEFERREDSHADING"); if (this.shadowCameraGO == null || Sunshine.Instance == null) { return; } this.shadowCameraGO.transform.rotation = Quaternion.LookRotation(Sunshine.Instance.SunLight.transform.forward); Transform transform = this.shadowCameraGO.transform; SunshineMath.BoundingSphere boundingSphere = default(SunshineMath.BoundingSphere); boundingSphere = SunshineMath.FrustumBoundingSphereBinarySearch(this.eyeCamera, this.eyeCamera.nearClipPlane, this.FarCascadeDistance, true, 0f, 0.01f, 20); float num = SunshineMath.QuantizeValueWithoutFlicker(boundingSphere.radius, 100, this.last_boundingRadius); this.last_boundingRadius = num; float num2 = num * 2f; transform.position = boundingSphere.origin; transform.position = this.eyeCamera.transform.position - Sunshine.Instance.SunLight.transform.forward * this.FarCascadeDistance * 0.5f; Vector3 vector = transform.InverseTransformPoint(Vector3.zero); float step = num2 / (float)this.shadowMapSize; vector.x = SunshineMath.QuantizeValueWithoutFlicker(vector.x, step, this.last_lightWorldOrigin.x); vector.y = SunshineMath.QuantizeValueWithoutFlicker(vector.y, step, this.last_lightWorldOrigin.y); this.last_lightWorldOrigin = vector; transform.position -= transform.TransformPoint(vector); Vector3 vector2 = transform.InverseTransformPoint(boundingSphere.origin); transform.position += transform.forward * (vector2.z - (boundingSphere.radius + this.lightCamera.nearClipPlane)); this.lightCamera.orthographicSize = num2 * 0.5f; this.lightCamera.nearClipPlane = this.eyeCamera.nearClipPlane; this.lightCamera.farClipPlane = (boundingSphere.radius + this.lightCamera.nearClipPlane) * 2f; this.lightCamera.cullingMask = this.CullingMask; this.bb_quad = Vector3.Dot(-Sunshine.Instance.SunLight.transform.forward, Vector3.up); this.biasLerp = Mathf.Abs(this.bb_quad); this.bb_quad = Mathf.Clamp01(Mathf.Clamp01(this.bb_quad + 0.0001f) - 0.75f) * 4f; this.bb_billboard = 1f - this.bb_quad; Shader.SetGlobalVector(this.billboardShadeFadeFactorsProp, new Vector4(this.bb_billboard, this.bb_quad, 0f, 0f)); this.biasLerp = Mathf.Clamp01(Mathf.Abs(0.7071f - this.biasLerp) * 4f); this.FarCascadeDepthBias = Mathf.Lerp(this.MaxFarCascadeDepthBias, this.MinFarCascadeDepthBias, this.biasLerp); this.SetFarShadowMatrix(boundingSphere.radius, this.FarCascadeDistance); float shadowDistance = QualitySettings.shadowDistance; QualitySettings.shadowDistance = 0f; this.lightCamera.Render(); QualitySettings.shadowDistance = shadowDistance; Shader.SetGlobalTexture(this.farCascadeProp, this.m_shadowTexture); Shader.SetGlobalMatrix(this.farCascadeMatrixProp, this.m_shadowMatrix); } else { Shader.DisableKeyword("_USING_DEFERREDSHADING"); } float num3 = QualitySettings.shadowDistance * 0.125f; Shader.SetGlobalVector(this.farCascadeBlendValuesProps, new Vector4(QualitySettings.shadowDistance - num3 * 2f, num3, this.FarCascadeDistance - this.FarCascadeDistance * 0.275f)); }
public static void SetupShadowCamera(Light light, Camera lightCamera, Camera eyeCamera, float eyeNearClip, float eyeFarClip, float paddingZ, float paddingRadius, int snapResolution, ref SunshineMath.BoundingSphere totalShadowBounds, ref SunshineMath.ShadowCameraTemporalData temporalData) { Transform transform = lightCamera.transform; SunshineMath.BoundingSphere boundingSphere = default(SunshineMath.BoundingSphere); if (Sunshine.Instance.UsingCustomBounds) { boundingSphere = Sunshine.Instance.CustomBounds; } else { boundingSphere = SunshineMath.FrustumBoundingSphereBinarySearch(eyeCamera, eyeNearClip, eyeFarClip, true, paddingRadius, 0.01f, 20); } float num = SunshineMath.QuantizeValueWithoutFlicker(boundingSphere.radius, 100, temporalData.boundingRadius); temporalData.boundingRadius = num; float num2 = num * 2f; lightCamera.aspect = 1f; lightCamera.orthographic = true; lightCamera.nearClipPlane = eyeCamera.nearClipPlane; lightCamera.farClipPlane = (totalShadowBounds.radius + paddingZ + lightCamera.nearClipPlane) * 2f; lightCamera.orthographicSize = num2 * 0.5f; transform.rotation = Quaternion.LookRotation(light.transform.forward); transform.position = boundingSphere.origin; Vector3 vector = transform.InverseTransformPoint(Vector3.zero); float step = num2 / (float)snapResolution; vector.x = SunshineMath.QuantizeValueWithoutFlicker(vector.x, step, temporalData.lightWorldOrigin.x); vector.y = SunshineMath.QuantizeValueWithoutFlicker(vector.y, step, temporalData.lightWorldOrigin.y); temporalData.lightWorldOrigin = vector; transform.position -= transform.TransformPoint(vector); Vector3 vector2 = transform.InverseTransformPoint(totalShadowBounds.origin); transform.position += transform.forward * (vector2.z - (totalShadowBounds.radius + lightCamera.nearClipPlane + paddingZ)); }
/// <summary> /// Renders the cascades. /// </summary> void RenderCascades() { SunshineMath.BoundingSphere shadowBoundingSphere = new SunshineMath.BoundingSphere(); if(Sunshine.Instance.UsingCustomBounds) shadowBoundingSphere = Sunshine.Instance.CustomBounds; else shadowBoundingSphere = SunshineMath.FrustumBoundingSphereBinarySearch(AttachedCamera, AttachedCamera.nearClipPlane, Sunshine.Instance.LightDistance, true, BoundsPadding, 0.01f, 20); if(!NeedsRefresh(shadowBoundingSphere.origin)) return; bool tweakTerrain = (ShadowsActive && Sunshine.Instance.TerrainLODTweak > 0f); if(tweakTerrain) { tempTerrainList.Clear(); tempTerrainPixelError.Clear(); foreach(var t in Terrain.activeTerrains) { if(t) { tempTerrainList.Add(t); tempTerrainPixelError.Add(t.heightmapPixelError); t.heightmapPixelError *= (1.0f - Sunshine.Instance.TerrainLODTweak); //t.detailObjectDistance; //t.treeDistance; //t.treeBillboardDistance; } } } for(int cID = 0; cID < Sunshine.Instance.CascadeCount; cID++) { Camera cascadeCamera = Sunshine.Instance.SunLightCameras[cID]; cascadeCamera.cullingMask = Sunshine.Instance.GetCascadeOccluders(cID); SunshineMath.SetupShadowCamera(Sunshine.Instance.SunLight, cascadeCamera, AttachedCamera, Sunshine.Instance.CascadeNearClip(cID), Sunshine.Instance.CascadeFarClip(cID), Sunshine.Instance.LightPaddingZ, BoundsPadding, Sunshine.Instance.CascadeMapResolution, ref shadowBoundingSphere, ref cascadeTemporalData[cID]); //float cascadeScale = SunshineMath.ShadowTexelWorldSize(Sunshine.Configuration.CascadeMapResolution, cascadeCamera.orthographicSize) / cascade0TexelSize; //Shader.SetGlobalFloat("sunshine_DepthBias", Sunshine.Configuration.SunLight.shadowBias * cascadeScale); Shader.SetGlobalVector("sunshine_DepthBiases", new Vector2(Sunshine.Instance.ShadowBias(cID), Sunshine.Instance.ShadowSlopeBias(cID))); cascadeCamera.rect = Sunshine.Instance.CascadeRects[cID]; cascadeCamera.targetTexture = Sunshine.Instance.Lightmap; cascadeCamera.useOcclusionCulling = Sunshine.Instance.UseOcclusionCulling; //Reset camera "time" somehow?.... Grass has different wind time on different cascades!? // New LOD and Visibility Hack... // Positions camera to match EyeCamera... // Tweaks Matrices to render correctly... if(Sunshine.Instance.UseLODFix) { var worldToCameraMatrix = cascadeCamera.worldToCameraMatrix; var projectionMatrix = cascadeCamera.projectionMatrix; var position = cascadeCamera.transform.position; var rotation = cascadeCamera.transform.rotation; var aspect = cascadeCamera.aspect; var fieldOfView = cascadeCamera.fieldOfView; var orthographic = cascadeCamera.orthographic; var orthographicSize = cascadeCamera.orthographicSize; //var nearClipPlane = cascadeCamera.nearClipPlane; //var farClipPlane = cascadeCamera.farClipPlane; cascadeCamera.transform.position = transform.position; //float resolutionScale = (float)cascadeCamera.pixelHeight / (float)AttachedCamera.pixelHeight; // This causes Billboards to be oriented improperly... // However, billboards are already problematic, so go for it... cascadeCamera.transform.rotation = transform.rotation; cascadeCamera.aspect = AttachedCamera.aspect; cascadeCamera.fieldOfView = AttachedCamera.fieldOfView;// * resolutionScale; cascadeCamera.orthographic = AttachedCamera.orthographic; if(cascadeCamera.orthographic) cascadeCamera.orthographicSize = AttachedCamera.orthographicSize;// * resolutionScale cascadeCamera.worldToCameraMatrix = worldToCameraMatrix; cascadeCamera.projectionMatrix = projectionMatrix; cascadeCamera.layerCullDistances = GetCachedCullDistances(AttachedCamera); cascadeCamera.layerCullSpherical = AttachedCamera.layerCullSpherical; cascadeCamera.RenderWithShader(Sunshine.Instance.OccluderShader, "RenderType"); cascadeCamera.transform.position = position; cascadeCamera.transform.rotation = rotation; cascadeCamera.aspect = aspect; cascadeCamera.fieldOfView = fieldOfView; cascadeCamera.orthographic = orthographic; cascadeCamera.orthographicSize = orthographicSize; cascadeCamera.ResetWorldToCameraMatrix(); cascadeCamera.ResetProjectionMatrix(); } else cascadeCamera.RenderWithShader(Sunshine.Instance.OccluderShader, "RenderType"); } if(tweakTerrain) { for(int i=tempTerrainList.Count-1; i>=0; i--) { var t = tempTerrainList[i]; t.heightmapPixelError = tempTerrainPixelError[i]; } tempTerrainList.Clear(); tempTerrainPixelError.Clear(); } refreshRequested = false; }