/// <summary> /// Cleanup all resources and set Enabled to false /// </summary> public void Dispose() { lastDownSampleScale = -1.0f; lastDownsampleRenderBufferScale = -1.0f; lastBlurShaderType = (BlurShaderType)0x7FFFFFFF; foreach (Camera c in cameras) { if (c != null) { WeatherMakerScript.Instance.CommandBufferManagerScript.RemoveCommandBuffer(c, CommandBufferName); } } cameras.Clear(); Enabled = false; }
/// <summary> /// Call from LateUpdate in script /// </summary> public void LateUpdate() { if (Enabled) { needsToBeRecreated = lastDownSampleScale != DownsampleScale || lastDownsampleRenderBufferScale != DownsampleRenderBufferScale || lastBlurShaderType != BlurShaderType; lastDownSampleScale = DownsampleScale; lastDownsampleRenderBufferScale = DownsampleRenderBufferScale; lastBlurShaderType = BlurShaderType; } else { Dispose(); } }
/// <summary> /// Call from LateUpdate in script /// </summary> public void SetupEffect(Material material, Material blitMaterial, Material blurMaterial, BlurShaderType blurShaderType, float downSampleScale, float downsampleRenderBufferScale, System.Action <WeatherMakerCommandBuffer> updateMaterialProperties, bool enabled) { Enabled = enabled; if (Enabled) { if (material != Material) { Material = material; } if (BlitMaterial != blitMaterial) { BlitMaterial = blitMaterial; } if (BlurMaterial != blurMaterial) { BlurMaterial = blurMaterial; } BlurShaderType = blurShaderType; DownsampleScale = downSampleScale; DownsampleRenderBufferScale = downsampleRenderBufferScale; if (UpdateMaterialProperties != updateMaterialProperties) { UpdateMaterialProperties = updateMaterialProperties; } needsToBeRecreated = lastDownSampleScale != DownsampleScale || lastDownsampleRenderBufferScale != DownsampleRenderBufferScale || lastBlurShaderType != BlurShaderType; lastDownSampleScale = DownsampleScale; lastDownsampleRenderBufferScale = DownsampleRenderBufferScale; lastBlurShaderType = BlurShaderType; } else { Dispose(); } }
/// <summary> /// Call from LateUpdate in script /// </summary> public void SetupEffect ( Material material, Material blitMaterial, Material blurMaterial, BlurShaderType blurShaderType, WeatherMakerDownsampleScale downSampleScale, WeatherMakerDownsampleScale downsampleRenderBufferScale, WeatherMakerDownsampleScale downsampleScalePostProcess, Material temporalReprojectionMaterial, WeatherMakerTemporalReprojectionSize temporalReprojection, System.Action <WeatherMakerCommandBuffer> updateMaterialProperties, bool enabled, WeatherMakerTemporalReprojectionState.TemporalReprojectionBlendMode temporalReprojectionBlendMode = WeatherMakerTemporalReprojectionState.TemporalReprojectionBlendMode.Blur, System.Action <WeatherMakerCommandBuffer> preSetupCommandBuffer = null ) { Enabled = enabled; if (Enabled || preSetupCommandBuffer != null) { // setup material, if playing we want to clone it to avoid modifying the material if (Material != material || (Application.isPlaying && clonedMaterial == null)) { Material = material; if (Application.isPlaying) { if (clonedMaterial != null) { GameObject.DestroyImmediate(clonedMaterial); } clonedMaterial = new Material(Material); clonedMaterial.name += " (Clone)"; } else { clonedMaterial = Material; } } BlitMaterial = blitMaterial; BlurMaterial = blurMaterial; TemporalReprojectionMaterial = temporalReprojectionMaterial; DownsampleScalePostProcess = downsampleScalePostProcess; BlurShaderType = blurShaderType; DownsampleScale = (downSampleScale == WeatherMakerDownsampleScale.Disabled ? WeatherMakerDownsampleScale.FullResolution : downSampleScale); DownsampleRenderBufferScale = downsampleRenderBufferScale; TemporalReprojection = temporalReprojection; UpdateMaterialProperties = updateMaterialProperties; this.preSetupCommandBuffer = preSetupCommandBuffer; foreach (WeatherMakerTemporalReprojectionState state in temporalStates) { state.BlendMode = temporalReprojectionBlendMode; } // cleanup dead cameras for (int i = weatherMakerCommandBuffers.Count - 1; i >= 0; i--) { if (weatherMakerCommandBuffers[i].Key == null) { if (weatherMakerCommandBuffers[i].Value.CommandBuffer != null) { weatherMakerCommandBuffers[i].Value.CommandBuffer.Clear(); weatherMakerCommandBuffers[i].Value.CommandBuffer.Release(); } weatherMakerCommandBuffers.RemoveAt(i); } } } else { Dispose(); } }
private WeatherMakerCommandBuffer CreateCommandBuffer(Camera camera, WeatherMakerTemporalReprojectionState reprojState, WeatherMakerDownsampleScale downsampleScale, System.Action <WeatherMakerCommandBuffer> preSetupCommandBuffer) { if (WeatherMakerScript.Instance == null) { Debug.LogError("Cannot create command buffer, WeatherMakerScript.Instance is null"); return(null); } // Debug.Log("Creating command buffer " + CommandBufferName); WeatherMakerCommandBuffer weatherMakerCommandBuffer = GetOrCreateWeatherMakerCommandBuffer(camera); // multi-pass vr uses one command buffer for each eye if (camera.stereoTargetEye == StereoTargetEyeMask.Right) { weatherMakerCommandBuffer.Camera = camera; return(weatherMakerCommandBuffer); } else if (weatherMakerCommandBuffer != null && weatherMakerCommandBuffer.CommandBuffer != null) { camera.RemoveCommandBuffer(RenderQueue, weatherMakerCommandBuffer.CommandBuffer); weatherMakerCommandBuffer.CommandBuffer.Clear(); } RenderTextureFormat defaultFormat = (camera.allowHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default); CommandBuffer commandBuffer = weatherMakerCommandBuffer.CommandBuffer; int postSourceId = -1; RenderTargetIdentifier postSource = postSourceId; WeatherMakerCameraType cameraType = weatherMakerCommandBuffer.CameraType; // setup reprojection state if (reprojState != null) { reprojState.PreRenderFrame(camera, WeatherMakerCommandBufferManagerScript.BaseCamera, commandBuffer); if (!reprojState.NeedsFirstFrameHandling && reprojState.BlendMode == WeatherMakerTemporalReprojectionState.TemporalReprojectionBlendMode.Sharp) { float xo = reprojState.TemporalOffsetX; float yo = reprojState.TemporalOffsetY; commandBuffer.SetGlobalVector(WMS._WeatherMakerTemporalUV, new Vector4(xo, yo, 1.0f, 1.0f)); } else { commandBuffer.SetGlobalVector(WMS._WeatherMakerTemporalUV, Vector4.zero); } } int scale = (int)downsampleScale; if (reprojState != null && reprojState.BlendMode == WeatherMakerTemporalReprojectionState.TemporalReprojectionBlendMode.Blur) { int totalDownScale = (scale * reprojState.ReprojectionSize); switch (totalDownScale) { case 0: case 1: totalDownScale = 1; break; case 2: case 3: totalDownScale = 2; break; case 4: case 5: totalDownScale = 4; break; case 6: case 7: case 8: case 9: case 10: case 11: totalDownScale = 8; break; default: totalDownScale = 16; break; } //Debug.LogFormat("Total down scale: {0}, {1}, {2}", totalDownScale, scale, reprojState.ReprojectionSize); commandBuffer.SetGlobalFloat(WMS._WeatherMakerDownsampleScale, (float)totalDownScale); } else { commandBuffer.SetGlobalFloat(WMS._WeatherMakerDownsampleScale, scale); } if (preSetupCommandBuffer != null) { preSetupCommandBuffer.Invoke(weatherMakerCommandBuffer); } if (Enabled) { commandBuffer.SetGlobalFloat(WMS._WeatherMakerTemporalReprojectionEnabled, 0.0f); commandBuffer.SetGlobalVector(WMS._WeatherMakerTemporalUV_VertexShaderProjection, Vector4.zero); commandBuffer.SetGlobalVector(WMS._WeatherMakerTemporalUV_FragmentShader, Vector4.zero); if (DownsampleRenderBufferScale != WeatherMakerDownsampleScale.Disabled) { // render camera target to texture, performing separate down-sampling commandBuffer.GetTemporaryRT(WMS._MainTex5, GetRenderTextureDescriptor((int)DownsampleRenderBufferScale, 0, 1, defaultFormat, 0, camera), FilterMode.Bilinear); commandBuffer.Blit(CameraTargetIdentifier(), WMS._MainTex5); } commandBuffer.SetGlobalFloat(WMS._ZTest, (float)ZTest); // if no blur, no downsample, no temporal reprojection and no post processing (pass count > 2) then we can just draw directly to camera target if (BlurShaderType == BlurShaderType.None && DownsampleScale == WeatherMakerDownsampleScale.FullResolution && reprojState == null && clonedMaterial.passCount < 3) { // set blend mode for blitting to camera target commandBuffer.SetGlobalFloat(WMS._SrcBlendMode, (float)SourceBlendMode); commandBuffer.SetGlobalFloat(WMS._DstBlendMode, (float)DestBlendMode); commandBuffer.Blit(CameraTargetIdentifier(), CameraTargetIdentifier(), clonedMaterial, 0); } else { // render to texture, using current image target as input _MainTex, no blend // alpha or blue will use _MainTex to render the final result int renderTargetRenderedImageId = WMS._MainTex3; int renderTargetDepthTextureId = WMS._WeatherMakerTemporaryDepthTexture; RenderTargetIdentifier renderTargetRenderedImage = new RenderTargetIdentifier(renderTargetRenderedImageId); RenderTargetIdentifier renderTargetDepthTexture = new RenderTargetIdentifier(renderTargetDepthTextureId); BlurShaderType blur = BlurShaderType; if (cameraType != WeatherMakerCameraType.Normal) { if (BlurMaterial.passCount > 3) { blur = BlurShaderType.Bilateral; } else { blur = BlurShaderType.GaussianBlur17; } } int mod = (reprojState == null ? 0 : reprojState.ReprojectionSize); commandBuffer.GetTemporaryRT(renderTargetRenderedImageId, GetRenderTextureDescriptor(scale, mod, 1, defaultFormat, 0, camera), FilterMode.Bilinear); commandBuffer.GetTemporaryRT(renderTargetDepthTextureId, GetRenderTextureDescriptor(scale, mod, 1, RenderTextureFormat.RFloat, 0, camera), FilterMode.Point); // set blend mode for blitting to render texture commandBuffer.SetGlobalFloat(WMS._SrcBlendMode, (float)BlendMode.One); commandBuffer.SetGlobalFloat(WMS._DstBlendMode, (float)BlendMode.Zero); if (reprojState == null || reprojState.TemporalReprojectionMaterial == null) { // render to final destination commandBuffer.Blit(renderTargetDepthTextureId, renderTargetRenderedImage, clonedMaterial, 0); } else { AttachTemporalReprojection(commandBuffer, reprojState, renderTargetDepthTextureId, renderTargetRenderedImage, clonedMaterial, scale, defaultFormat); } if (cameraType == WeatherMakerCameraType.Normal && DownsampleScalePostProcess != WeatherMakerDownsampleScale.Disabled) { AttachPostProcessing(commandBuffer, clonedMaterial, 0, 0, defaultFormat, renderTargetRenderedImage, reprojState, camera, ref postSourceId, ref postSource); //AttachPostProcessing(commandBuffer, material, w, h, defaultFormat, renderTargetRenderedImageId, reprojState, ref postSourceId, ref postSource); } AttachBlurBlit(commandBuffer, renderTargetRenderedImage, renderTargetDepthTexture, CameraTargetIdentifier(), clonedMaterial, blur, defaultFormat, camera); // cleanup commandBuffer.ReleaseTemporaryRT(renderTargetRenderedImageId); commandBuffer.ReleaseTemporaryRT(renderTargetDepthTextureId); commandBuffer.SetGlobalTexture(WMS._MainTex2, new RenderTargetIdentifier(BuiltinRenderTextureType.None)); } if (DownsampleRenderBufferScale != WeatherMakerDownsampleScale.Disabled) { // cleanup commandBuffer.ReleaseTemporaryRT(WMS._MainTex5); } } weatherMakerCommandBuffer.Material = clonedMaterial; weatherMakerCommandBuffer.ReprojectionState = reprojState; weatherMakerCommandBuffer.RenderQueue = RenderQueue; camera.AddCommandBuffer(RenderQueue, commandBuffer); if (WeatherMakerCommandBufferManagerScript.Instance != null) { WeatherMakerCommandBufferManagerScript.Instance.AddCommandBuffer(weatherMakerCommandBuffer); } return(weatherMakerCommandBuffer); }
internal void AttachBlurBlit(CommandBuffer commandBuffer, RenderTargetIdentifier renderedImageId, RenderTargetIdentifier depthTextureId, RenderTargetIdentifier finalTargetId, Material material, BlurShaderType blur, RenderTextureFormat defaultFormat, Camera camera) { if (material != null && material.passCount > 1) { // assume second pass is a depth writer pass, just writes the chosen depth pixel to a new texture // TODO: Would be nice to just use the depth buffer of the render texture to do this in one pass, // but Unity does not appear to expose pulling out the depth buffer of a temporary render texture using command buffers commandBuffer.Blit(renderedImageId, depthTextureId, material, 1); } // set blend mode for blitting to camera target commandBuffer.SetGlobalFloat(WMS._SrcBlendMode, (float)SourceBlendMode); commandBuffer.SetGlobalFloat(WMS._DstBlendMode, (float)DestBlendMode); // blur if requested if (blur == BlurShaderType.None) { // blit texture directly on top of camera without blur, depth aware alpha blend commandBuffer.Blit(renderedImageId, finalTargetId, BlitMaterial); } else { // blur texture directly on to camera target, depth and alpha aware blur, alpha blend if (blur == BlurShaderType.GaussianBlur7) { commandBuffer.SetGlobalFloat(WMS._Blur7, 1.0f); commandBuffer.Blit(renderedImageId, finalTargetId, BlurMaterial); } else if (blur == BlurShaderType.GaussianBlur17 || BlurMaterial.passCount < 4) { commandBuffer.SetGlobalFloat(WMS._Blur7, 0.0f); commandBuffer.Blit(renderedImageId, finalTargetId, BlurMaterial); } else { AttachBilateralBlur(commandBuffer, BlurMaterial, renderedImageId, finalTargetId, defaultFormat, DownsampleScale, camera); } } }