using UnityEngine;
using UnityEngine.Rendering;
​
namespace Study
{
    public class ColorAndDepthPipeline : RenderPipeline
    {
        private static readonly int ColorAttachmentId = Shader.PropertyToID("_CameraColorAttachment");
        private static readonly int DepthAttachmentId = Shader.PropertyToID("_CameraDepthAttachment");
        private static UnityEngine.Experimental.Rendering.GraphicsFormat ColorFormat = SystemInfo.GetGraphicsFormat(UnityEngine.Experimental.Rendering.DefaultFormat.LDR);
        private int depthBufferBits = 24;
        
        protected override void Render(ScriptableRenderContext context, Camera[] cameras)
        {
            BeginFrameRendering(context,cameras);
            
            foreach (var camera in cameras)
            {
                BeginCameraRendering(context,camera);
             
                // カリングの計算
                ScriptableCullingParameters cullingParams;
                if (!camera.TryGetCullingParameters(out cullingParams))
                    continue;
                CullingResults cull = context.Cull(ref cullingParams);
​
                context.SetupCameraProperties(camera); // シェーダーのカメラパラメータを計算 (unity_MatrixVP や unity_MatrixVP をシェーダーへ送信する)
                
                //Color Texture Descriptor
                RenderTextureDescriptor colorRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight);
                colorRTDesc.graphicsFormat = ColorFormat;
                colorRTDesc.depthBufferBits = depthBufferBits;
                colorRTDesc.sRGB = (QualitySettings.activeColorSpace == ColorSpace.Linear);
                colorRTDesc.msaaSamples = 1;
                colorRTDesc.enableRandomWrite = true; //For compute
​
                //Depth Texture Descriptor
                RenderTextureDescriptor depthRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight);
                depthRTDesc.colorFormat = RenderTextureFormat.Depth;
                depthRTDesc.depthBufferBits = depthBufferBits;
​
                // テクスチャ確保・レンダーターゲット指定
                {
                    var cmd = new CommandBuffer();
                    cmd.GetTemporaryRT(ColorAttachmentId, colorRTDesc, FilterMode.Bilinear);
                    cmd.GetTemporaryRT(DepthAttachmentId, depthRTDesc, FilterMode.Bilinear);
​
                    // レンダーターゲットの指定 (カラー・デプス)
                    cmd.SetRenderTarget((RenderTargetIdentifier)ColorAttachmentId, (RenderTargetIdentifier)DepthAttachmentId);
                    context.ExecuteCommandBuffer(cmd);
                    cmd.Release();
                }
​
                // 描画設定の作成
                var passName = new ShaderTagId("ExampleLightModeTag"); // 描画対象のShaderTag
                var sortingSettings = new SortingSettings(camera); // ソート設定
                var drawingSettings = new DrawingSettings(passName, sortingSettings); // 描画設定
                var filteringSettings = new FilteringSettings(RenderQueueRange.all); // フィルタリングなし
                
                // Rendererを実行し、カラー・デプスの描画を行う
                {
                    var cmd = new CommandBuffer();
                    // cmd.SetRenderTarget((RenderTargetIdentifier)ColorAttachmentId, (RenderTargetIdentifier)DepthAttachmentId);
                    context.ExecuteCommandBuffer(cmd); // コマンドバッファ実行をスケジューリング
                    context.DrawRenderers(cull, ref drawingSettings, ref filteringSettings);
                    cmd.Release();
                }
                
                // バックバッファを画面へコピー・テクスチャ解放
                {
                    var cmd = new CommandBuffer();
                    
                    // バックバッファを画面へコピー
                    cmd.Blit(DepthAttachmentId, BuiltinRenderTextureType.CameraTarget);
                
                    // テクスチャ解放
                    cmd.ReleaseTemporaryRT(ColorAttachmentId);
                    cmd.ReleaseTemporaryRT(DepthAttachmentId);
                    context.ExecuteCommandBuffer(cmd); // コマンドバッファ実行をスケジューリング
                
                    cmd.Release();
                }
                
                // contextにスケジューリングされたコマンドをすべて実行
                context.Submit();
                
                EndCameraRendering(context, camera);
            }
            
            EndFrameRendering(context,cameras);
        }
    }
}