public void PreRenderFrame(Camera camera, Camera lastNormalCamera, CommandBuffer commandBuffer) { if (TemporalReprojectionMaterial == null) { return; } WeatherMakerCameraType cameraType = WeatherMakerScript.GetCameraType(camera); if (cameraType == WeatherMakerCameraType.Other) { return; } lastNormalCamera = (cameraType == WeatherMakerCameraType.Normal ? camera : (lastNormalCamera ?? camera)); // assign current matrixes, only normal stereo cameras use the stereo methods // reflection cameras are rendered one eye at a time without stereo if (camera.stereoEnabled) { view[0] = camera.GetStereoViewMatrix(Camera.StereoscopicEye.Left); view[1] = camera.GetStereoViewMatrix(Camera.StereoscopicEye.Right); projection[0] = lastNormalCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left); projection[1] = lastNormalCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right); inverseView[0] = view[0].inverse; inverseView[1] = view[1].inverse; inverseProjection[0] = projection[0].inverse; inverseProjection[1] = projection[1].inverse; inverseProjectionView[0] = inverseProjection[0] * inverseView[0]; inverseProjectionView[1] = inverseProjection[1] * inverseView[1]; prevViewProjection[0] = (projection[0] * prevView[0]); prevViewProjection[1] = (projection[1] * prevView[1]); ipivpvp[0] = projection[0] * prevView[0] * inverseView[0] * inverseProjection[0]; ipivpvp[1] = projection[1] * prevView[1] * inverseView[1] * inverseProjection[1]; } else { view[0] = view[1] = camera.worldToCameraMatrix; inverseView[0] = inverseView[1] = camera.cameraToWorldMatrix; projection[0] = projection[1] = lastNormalCamera.projectionMatrix; inverseProjection[0] = inverseProjection[1] = lastNormalCamera.projectionMatrix.inverse; inverseProjectionView[0] = inverseProjectionView[1] = inverseView[0] * inverseProjection[0]; prevViewProjection[0] = prevViewProjection[1] = (projection[0] * prevView[0]); ipivpvp[0] = ipivpvp[1] = projection[0] * prevView[0] * inverseView[0] * inverseProjection[0]; } commandBuffer.SetGlobalTexture(WMS._TemporalReprojection_SubFrame, SubFrameTexture); commandBuffer.SetGlobalTexture(WMS._TemporalReprojection_PrevFrame, PrevFrameTexture); commandBuffer.SetGlobalFloat(WMS._TemporalReprojection_BlendMode, (float)BlendMode); commandBuffer.SetGlobalFloat(WMS._TemporalReprojection_SubPixelSize, ReprojectionSize); commandBuffer.SetGlobalFloat(WMS._TemporalReprojection_SubFrameNumber, SubFrameNumber); commandBuffer.SetGlobalFloat(WMS._TemporalReprojection_SimilarityMax, TemporalReprojectionMaterial.GetFloat(WMS._TemporalReprojection_SimilarityMax)); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_PreviousView, prevView); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_View, view); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_InverseView, inverseView); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_Projection, projection); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_InverseProjection, inverseProjection); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_InverseProjectionView, inverseProjectionView); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_PreviousViewProjection, prevViewProjection); commandBuffer.SetGlobalMatrixArray(WMS._TemporalReprojection_ipivpvp, ipivpvp); }
public void PostRenderFrame(Camera camera) { if (TemporalReprojectionMaterial == null) { return; } WeatherMakerCameraType cameraType = WeatherMakerScript.GetCameraType(camera); if (cameraType == WeatherMakerCameraType.Other) { return; } // turn off first frame handling NeedsFirstFrameHandling = false; prevView[0] = view[0]; prevView[1] = view[1]; // move to next temporal reprojection frame unchecked { //if (++debugCount % 60 == 0) { if (++frameIndex == frameNumbers.Length) { frameIndex = 0; } SubFrameNumber = frameNumbers[frameIndex]; } } }
private void SetupCommandBufferForCamera(Camera camera) { if (camera == null) { return; } WeatherMakerCameraType cameraType = WeatherMakerScript.GetCameraType(camera); Camera baseCamera = WeatherMakerCommandBufferManagerScript.BaseCamera; UpdateDeferredShadingKeyword(camera); CalculateMatrixes(camera, baseCamera); CalculateFrustumCorners(camera); Shader.SetGlobalMatrixArray(WMS._WeatherMakerInverseView, inverseView); Shader.SetGlobalMatrixArray(WMS._WeatherMakerInverseProj, inverseProj); Shader.SetGlobalMatrixArray(WMS._WeatherMakerView, view); Shader.SetGlobalVectorArray(WMS._WeatherMakerCameraFrustumCorners, cameraFrustumCorners); Shader.SetGlobalVector(WMS._WeatherMakerCameraPos, camera.transform.position); if (cameraType == WeatherMakerCameraType.CubeMap || camera == WeatherMakerCommandBufferManagerScript.CubemapCamera) { Shader.SetGlobalFloat(WMS._WeatherMakerCameraRenderMode, 2.0f); } else if (cameraType == WeatherMakerCameraType.Reflection) { Shader.SetGlobalFloat(WMS._WeatherMakerCameraRenderMode, 1.0f); } else { Shader.SetGlobalFloat(WMS._WeatherMakerCameraRenderMode, 0.0f); } }
private void SetupCommandBufferForCamera(Camera camera) { #if !UNITY_SERVER if (camera == null) { return; } WeatherMakerCameraProperties props = GetCameraProperties(camera); WeatherMakerCameraType cameraType = WeatherMakerScript.GetCameraType(camera); Camera baseCamera = WeatherMakerCommandBufferManagerScript.BaseCamera; UpdateDeferredShadingKeyword(camera); CalculateMatrixes(camera, baseCamera); CalculateFrustumCorners(camera); Shader.SetGlobalMatrixArray(WMS._WeatherMakerInverseView, inverseView); Shader.SetGlobalMatrixArray(WMS._WeatherMakerInverseProj, inverseProj); Shader.SetGlobalMatrixArray(WMS._WeatherMakerView, view); Shader.SetGlobalVectorArray(WMS._WeatherMakerCameraFrustumCorners, cameraFrustumCorners); Shader.SetGlobalVector(WMS._WeatherMakerCameraOriginOffset, props.OriginOffsetCumulative); Shader.SetGlobalVector(WMS._WeatherMakerCameraPosComputeShader, camera.transform.position); if (cameraType == WeatherMakerCameraType.CubeMap) { Shader.SetGlobalFloat(WMS._WeatherMakerCameraRenderMode, 2.0f); } else if (cameraType == WeatherMakerCameraType.Reflection) { Shader.SetGlobalFloat(WMS._WeatherMakerCameraRenderMode, 1.0f); } else { Shader.SetGlobalFloat(WMS._WeatherMakerCameraRenderMode, 0.0f); } #endif }
private void CameraPostRender(Camera camera) { if (WeatherMakerCommandBufferManagerScript.CameraStack == 0 && WeatherMakerScript.GetCameraType(camera) == WeatherMakerCameraType.Normal) { RenderTexture.ReleaseTemporary(tempShadowBuffer); #if UNITY_LWRP if (_commandBufferDepthShadows != null) { camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _commandBufferDepthShadows); } if (_commandBufferScreenSpaceShadows1 != null) { camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _commandBufferScreenSpaceShadows1); } if (_commandBufferScreenSpaceShadows2 != null) { camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _commandBufferScreenSpaceShadows2); } #else RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, ref _commandBufferScreenSpaceShadows1, false); RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, ref _commandBufferScreenSpaceShadows2, false); #endif } }
private void CameraPreCull(Camera camera) { if (WeatherMakerCommandBufferManagerScript.CameraStack == 1 && WeatherMakerScript.GetCameraType(camera) == WeatherMakerCameraType.Normal) { // render cloud shadows at half scale for large screens int scale = (WeatherMakerScript.Instance == null || WeatherMakerScript.Instance.PerformanceProfile == null ? (UnityEngine.XR.XRDevice.isPresent || Screen.width > 2000 ? 4 : 2) : (int)WeatherMakerScript.Instance.PerformanceProfile.VolumetricCloudShadowDownsampleScale); tempShadowBuffer = RenderTexture.GetTemporary(WeatherMakerFullScreenEffect.GetRenderTextureDescriptor(scale, 0, 1, RenderTextureFormat.ARGB32, 0, camera)); tempShadowBuffer.wrapMode = TextureWrapMode.Clamp; tempShadowBuffer.filterMode = FilterMode.Bilinear; AddScreenSpaceShadowsCommandBuffer(camera); // ensure that the any shader using cloud shadows knows the correct cloud shadow parameters if (CloudShadowMaterial != null) { Shader.SetGlobalFloat(WMS._CloudShadowMapAdder, CloudShadowMaterial.GetFloat(WMS._CloudShadowMapAdder)); Shader.SetGlobalFloat(WMS._CloudShadowMapMultiplier, CloudShadowMaterial.GetFloat(WMS._CloudShadowMapMultiplier)); Shader.SetGlobalFloat(WMS._CloudShadowMapPower, CloudShadowMaterial.GetFloat(WMS._CloudShadowMapPower)); Shader.SetGlobalFloat(WMS._WeatherMakerCloudVolumetricShadowDither, CloudShadowMaterial.GetFloat(WMS._WeatherMakerCloudVolumetricShadowDither)); Shader.SetGlobalTexture(WMS._WeatherMakerCloudShadowDetailTexture, CloudShadowMaterial.GetTexture(WMS._WeatherMakerCloudShadowDetailTexture)); Shader.SetGlobalFloat(WMS._WeatherMakerCloudShadowDetailScale, CloudShadowMaterial.GetFloat(WMS._WeatherMakerCloudShadowDetailScale)); Shader.SetGlobalFloat(WMS._WeatherMakerCloudShadowDetailIntensity, CloudShadowMaterial.GetFloat(WMS._WeatherMakerCloudShadowDetailIntensity)); Shader.SetGlobalFloat(WMS._WeatherMakerCloudShadowDetailFalloff, CloudShadowMaterial.GetFloat(WMS._WeatherMakerCloudShadowDetailFalloff)); Shader.SetGlobalFloat(WMS._WeatherMakerCloudShadowDistanceFade, CloudShadowMaterial.GetFloat(WMS._WeatherMakerCloudShadowDistanceFade)); } } }
private void CameraPostRender(Camera camera) { if (WeatherMakerScript.Instance == null || WeatherMakerScript.Instance.PerformanceProfile == null) { return; } WeatherMakerCameraType cameraType = WeatherMakerScript.GetCameraType(camera); if ((WeatherMakerCommandBufferManagerScript.CameraStack == 0 && cameraType == WeatherMakerCameraType.Normal) || (cameraType == WeatherMakerCameraType.Reflection && WeatherMakerScript.Instance.PerformanceProfile.VolumetricCloudReflectionShadows)) { RenderTexture.ReleaseTemporary(tempShadowBuffer); #if UNITY_URP if (_commandBufferDepthShadows != null) { camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _commandBufferDepthShadows); } if (_commandBufferScreenSpaceShadows1 != null) { camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _commandBufferScreenSpaceShadows1); } if (_commandBufferScreenSpaceShadows2 != null) { camera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _commandBufferScreenSpaceShadows2); } #else RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, ref _commandBufferScreenSpaceShadows1, false); RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, ref _commandBufferScreenSpaceShadows2, false); #endif } }
public void PreCullFrame(Camera camera, WeatherMakerDownsampleScale scale, WeatherMakerTemporalReprojectionSize projSize) { if (TemporalReprojectionMaterial == null) { return; } WeatherMakerCameraType cameraType = WeatherMakerScript.GetCameraType(camera); if (cameraType == WeatherMakerCameraType.Other) { return; } int projSizeInt = (int)projSize; int downsampling = (int)scale; int frameWidth = camera.pixelWidth / downsampling; int frameHeight = camera.pixelHeight / downsampling; // ensure reprojection fits cleanly into frame while (frameWidth % projSizeInt != 0) { frameWidth++; } while (frameHeight % projSizeInt != 0) { frameHeight++; } if (frameWidth != FrameWidth || frameHeight != FrameHeight || ReprojectionSize != projSizeInt) { DisposeRenderTextures(); ReprojectionSize = projSizeInt; ReprojectionSizeSquared = ReprojectionSize * ReprojectionSize; CreateFrameNumbers(); FrameWidth = frameWidth; FrameHeight = frameHeight; SubFrameWidth = frameWidth / projSizeInt; SubFrameHeight = frameHeight / projSizeInt; RenderTextureFormat format = camera.allowHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default; RenderTextureDescriptor descSubFrame = WeatherMakerFullScreenEffect.GetRenderTextureDescriptor(downsampling, projSizeInt, projSizeInt, format, 0, camera); subFrameCurrent = WeatherMakerFullScreenEffect.CreateRenderTexture(descSubFrame, FilterMode.Bilinear, TextureWrapMode.Clamp); subFrameCurrent.name = "WeatherMakerTemporalReprojectionSubFrame"; RenderTextureDescriptor descPrevFrame = WeatherMakerFullScreenEffect.GetRenderTextureDescriptor(downsampling, projSizeInt, 1, format, 0, camera); prevFrameCurrent = WeatherMakerFullScreenEffect.CreateRenderTexture(descPrevFrame, FilterMode.Bilinear, TextureWrapMode.Clamp); prevFrameCurrent.name = "WeatherMakerTemporalReprojectionPrevFrame"; OffsetXConstant = (1.0f / (float)frameWidth); OffsetYConstant = (1.0f / (float)frameHeight); OffsetXConstant2 = (-0.5f * (float)(ReprojectionSize - 1) * OffsetXConstant); OffsetYConstant2 = (-0.5f * (float)(ReprojectionSize - 1) * OffsetYConstant); NeedsFirstFrameHandling = true; } ComputeTemporalOffsets(); }
/// <summary> /// Camera pre cull event /// </summary> /// <param name="camera">Camera</param> protected override void OnCameraPreCull(Camera camera) { if (!IsFirstPerson || Intensity == 0.0f || (WeatherMakerPrecipitationManagerScript.Instance != null && WeatherMakerScript.GetCameraType(camera) != WeatherMakerCameraType.Normal && !WeatherMakerPrecipitationManagerScript.Instance.FollowNonNormalCameras)) { return; } #if UNITY_EDITOR else if (camera.cameraType != CameraType.SceneView && camera.name.IndexOf("scenecamera", System.StringComparison.OrdinalIgnoreCase) < 0 && camera.name.IndexOf("prerender", System.StringComparison.OrdinalIgnoreCase) < 0) { #endif // put particle system on the new camera PositionAllElements(camera.transform); // if switching to a new camera, re-emit particles as they need to render around the new camera if (Intensity > 0.0f && Time.timeScale > 0.0f && (lastCamera == null || lastCamera != camera)) { // TODO: Give each camera it's own precipitation // spawn new particles, Unity does not auto-update particle system when it moves, it waits until next frame if (ParticleSystem.isPlaying) { ParticleSystem.Emit((int)Mathf.Round(ParticleSystem.emission.rateOverTime.constant * Time.deltaTime)); ParticleSystem.Simulate(Time.timeScale / 1000.0f, true, false, false); ParticleSystem.Play(true); } if (MistParticleSystem != null && MistParticleSystem.isPlaying && Intensity >= MistThreshold) { MistParticleSystem.Emit((int)Mathf.Round(MistParticleSystem.emission.rateOverTime.constant * Time.deltaTime)); MistParticleSystem.Simulate(Time.timeScale / 1000.0f, true, false, false); MistParticleSystem.Play(true); } if (ParticleSystemSecondary != null && ParticleSystemSecondary.isPlaying && Intensity >= SecondaryThreshold) { ParticleSystemSecondary.Emit((int)Mathf.Round(ParticleSystemSecondary.emission.rateOverTime.constant * Time.deltaTime)); ParticleSystemSecondary.Simulate(Time.timeScale / 1000.0f, true, false, false); ParticleSystemSecondary.Play(true); } } lastCamera = camera; #if UNITY_EDITOR } #endif }
private void CheckOriginOffset(Camera camera) { if (!Application.isPlaying || camera.cameraType != CameraType.Game || WeatherMakerScript.GetCameraType(camera) != WeatherMakerCameraType.Normal || OriginOffsetDistance <= 0.0f || WeatherMakerScript.Instance == null) { return; } // check for a camera too far away from origin, when this happens adjust the camera close to the origin and // move the root transform that contains the camera by the same offset WeatherMakerCameraProperties props = GetCameraProperties(camera); Vector3 pos = camera.transform.position; Vector3 originOffset = Vector3.zero; if (Mathf.Abs(pos.x) > OriginOffsetDistance || Mathf.Abs(pos.y) > OriginOffsetDistance || Mathf.Abs(pos.z) > OriginOffsetDistance) { originOffset -= pos; } if (originOffset != Vector3.zero) { // temporal reprojections don't do well with a large jump in camera position, I think it is something with the change in view or projection // matrix, more research and debugging is needed, for now we force the next frame to do a full re-render foreach (WeatherMakerCommandBuffer buf in commandBuffers) { if (buf.ReprojectionState != null) { buf.ReprojectionState.NeedsFirstFrameHandling = true; } } props.OriginOffsetCumulative += originOffset; props.OriginOffsetCurrent = originOffset; OriginOffsetChanged.Invoke(props); if (OriginOffsetAutoAdjustAll) { for (int i = 0; i < UnityEngine.SceneManagement.SceneManager.sceneCount; i++) { UnityEngine.SceneManagement.SceneManager.GetSceneAt(i).GetRootGameObjects(rootObjects); foreach (GameObject obj in rootObjects) { Transform t = obj.transform; if (t.transform != WeatherMakerScript.Instance.transform && t.GetComponentInChildren <Canvas>() == null) { t.position += originOffset; } } rootObjects.Clear(); } } UnityEngine.Debug.LogFormat("Adjusted origin offset, current: {0}, cumulative: {1}.", props.OriginOffsetCurrent, props.OriginOffsetCumulative); } }
/// <summary> /// Determine if a camera should be rendered in weather maker /// </summary> /// <param name="script">Script</param> /// <param name="camera">Camera</param> /// <param name="ignoreReflections">Whether to ignore reflection cameras (i.e. water reflection or mirror)</param> /// <returns>True to ignore, false to render</returns> public static bool ShouldIgnoreCamera(MonoBehaviour script, Camera camera, bool ignoreReflections = true) { if (camera == null || Instance == null || script == null || !script.enabled || !script.gameObject.activeInHierarchy || camera.cameraType == UnityEngine.CameraType.Preview || (Instance.AllowCameras.Count == 0 && Instance.AllowCamerasNames.Count == 0 && Instance.AllowCamerasNamesPartial.Count == 0) || (camera.CachedName().IndexOf("depth", System.StringComparison.OrdinalIgnoreCase) >= 0)) { return(true); } #if UNITY_EDITOR else if (camera.cameraType == UnityEngine.CameraType.SceneView) { return(WeatherMakerScript.Instance == null || !WeatherMakerScript.Instance.AllowSceneCamera); } #endif WeatherMakerCameraType type = WeatherMakerScript.GetCameraType(camera); // if camera is not in allow list and // camera is not an allowed reflection camera and // camera is not an allowed reflection probe camera // then ignore it bool notInAllowList = !Instance.AllowCameras.Contains(camera); bool notInAllowNameList = true; foreach (string s in Instance.AllowCamerasNames) { if (camera.CachedName() == s) { notInAllowNameList = false; break; } } if (notInAllowNameList) { foreach (string s in Instance.AllowCamerasNamesPartial) { if (camera.CachedName().IndexOf(s, System.StringComparison.OrdinalIgnoreCase) >= 0) { notInAllowNameList = false; break; } } } bool ignoreReflection = (ignoreReflections || type != WeatherMakerCameraType.Reflection); bool ignoreProbe = (Instance.PerformanceProfile.IgnoreReflectionProbes || type != WeatherMakerCameraType.CubeMap); bool ignore = notInAllowList && notInAllowNameList && ignoreReflection && ignoreProbe; return(ignore); }
private void CameraPreCull(Camera camera) { if (Profile != null && WeatherMakerScript.GetCameraType(camera) == WeatherMakerCameraType.Normal) { if (radius == 0.0f) { var shape = meteorParticles.shape; shape.radius = radius * camera.farClipPlane; shape.arc = arc; } var mn = meteorParticles.main; var speed = mn.startSpeed; speed.constantMin = this.speed.x * camera.farClipPlane; speed.constantMax = this.speed.y * camera.farClipPlane; mn.startSpeed = speed; transform.position = camera.transform.position + (offset * camera.farClipPlane); } }
private WeatherMakerCommandBuffer GetOrCreateWeatherMakerCommandBuffer(Camera camera) { foreach (KeyValuePair <Camera, WeatherMakerCommandBuffer> kv in weatherMakerCommandBuffers) { if (kv.Key == camera) { return(kv.Value); } } WeatherMakerCommandBuffer cmd = new WeatherMakerCommandBuffer { Camera = camera, CameraType = WeatherMakerScript.GetCameraType(camera), CommandBuffer = new CommandBuffer { name = CommandBufferName } }; weatherMakerCommandBuffers.Add(new KeyValuePair <Camera, WeatherMakerCommandBuffer>(camera, cmd)); return(cmd); }
/// <summary> /// Camera pre cull event /// </summary> /// <param name="camera">Camera</param> protected virtual void CameraPreCull(Camera camera) { if (Effect != null && Effect.Enabled && !WeatherMakerScript.ShouldIgnoreCamera(this, camera, !AllowReflections)) { if ((camera.actualRenderingPath == RenderingPath.Forward || camera.actualRenderingPath == RenderingPath.VertexLit)) { #if UNITY_EDITOR if (WeatherMakerScript.GetCameraType(camera) == WeatherMakerCameraType.Normal) { Debug.LogWarning("Full screen overlay works best with deferred shading"); } #endif camera.depthTextureMode |= DepthTextureMode.DepthNormals; } else { camera.depthTextureMode &= (~DepthTextureMode.DepthNormals); } Effect.PreCullCamera(camera, true); } }
/// <summary> /// Update the full screen effect, usually called from OnPreRender or OnPreCull /// </summary> /// <param name="camera">Camera</param> /// <param name="integratedTemporalReprojection">Whether to use integrated temporal reprojection (if temporal reprojection is enabled)</param> public void PreCullCamera(Camera camera, bool integratedTemporalReprojection = true) { //integratedTemporalReprojection = false; if (WeatherMakerScript.Instance != null && WeatherMakerScript.Instance.CommandBufferManager != null && (Enabled || preSetupCommandBuffer != null) && Material != null && clonedMaterial != null && camera != null) { WeatherMakerCameraType cameraType = WeatherMakerScript.GetCameraType(camera); if (cameraType == WeatherMakerCameraType.Other) { return; } WeatherMakerTemporalReprojectionState reprojState = null; WeatherMakerDownsampleScale downsampleScale = DownsampleScale; if (cameraType != WeatherMakerCameraType.Normal) { if (camera.pixelWidth > 2000) { downsampleScale = WeatherMakerDownsampleScale.QuarterResolution; } else if (camera.pixelWidth > 1000) { downsampleScale = WeatherMakerDownsampleScale.HalfResolution; } } if (Enabled) { // setup temporal reprojection state reprojState = temporalStates.Find(b => b.Camera == camera); if (reprojState == null) { // temporal reprojection is not currently possible with cubemap if (TemporalReprojection != WeatherMakerTemporalReprojectionSize.None && TemporalReprojectionMaterial != null && (cameraType == WeatherMakerCameraType.Normal || cameraType == WeatherMakerCameraType.Reflection)) { reprojState = new WeatherMakerTemporalReprojectionState(camera, TemporalReprojectionMaterial, integratedTemporalReprojection); temporalStates.Add(reprojState); } } else if (TemporalReprojection == WeatherMakerTemporalReprojectionSize.None || TemporalReprojectionMaterial == null) { reprojState.Dispose(); temporalStates.Remove(reprojState); reprojState = null; } if (reprojState != null) { WeatherMakerTemporalReprojectionSize reprojSize = (cameraType == WeatherMakerCameraType.Normal ? TemporalReprojection : WeatherMakerTemporalReprojectionSize.FourByFour); reprojState.PreCullFrame(camera, downsampleScale, reprojSize); } } WeatherMakerCommandBuffer cmdBuffer = CreateCommandBuffer(camera, reprojState, downsampleScale, preSetupCommandBuffer); if (reprojState != null) { reprojState.CommandBuffer = cmdBuffer; } } }