public void UpdateDirectionalLights(ref Dictionary <Light, int> light_table, ref ScriptableRenderContext renderContext, List <Light> dirlights, Camera camera, ref CommandBuffer setup_properties)
        {
            if (helper_ == null)
            {
                return;
            }
            light_table.Clear();
            //helper.name = camera.name + "_helper";
            if (dirlights.Count == 0)
            {
                return;
            }
            Transform helper_trans = helper_.transform;
            Matrix4x4 proj_mat     = GL.GetGPUProjectionMatrix(camera.projectionMatrix, false) * camera.worldToCameraMatrix;

            proj_mat = proj_mat.inverse;

            //spilt the view frustrum
            CascadeHelper cascadeHelper = new CascadeHelper(proj_mat, camera.transform.position, m_asset.cascadeNum);

            //setup property
            setup_properties.SetGlobalVector(shaderPropertyID.dirctionalShadowSplitDistance, cascadeHelper.SplitVolum(m_asset.cascadeDistribution, m_asset.shadowDistance));
            setup_properties.SetGlobalInt(shaderPropertyID.maxCascadeNum, m_asset.cascadeNum);
            setup_properties.SetGlobalVector(shaderPropertyID.dirShadowResolution, new Vector4((int)m_asset.directionalShadowResolution, (int)m_asset.directionalShadowResolution,
                                                                                               1f / (float)m_asset.directionalShadowResolution, 1f / (float)m_asset.directionalShadowResolution));

            m_DirShadowArray.TestNeedModify((int)m_asset.directionalShadowResolution, (int)m_asset.directionalShadowResolution, dirlights.Count);
            if (m_DirShadowArray.IsValid())
            {
                setup_properties.SetGlobalTexture(shaderPropertyID.dirShadowArray, m_DirShadowArray.data);
            }
            m_shadowcascade_matrix_vp.TestNeedModify(dirlights.Count);
            if (m_shadowcascade_matrix_vp.IsValid())
            {
                setup_properties.SetGlobalBuffer(shaderPropertyID.shadowcascade_matrix_vp, m_shadowcascade_matrix_vp.data);
            }

            var cb = CommandBufferPool.Get("Directional light shadowmap");
            List <ShadowCascadeMatrix> mts = new List <ShadowCascadeMatrix>();

            for (int i = 0; i < dirlights.Count; i++)
            {
                var light = dirlights[i];
                light_table[light] = i;

                Matrix4x4 l2w = light.transform.localToWorldMatrix;
                Vector4   dir = new Vector4(l2w.m02, l2w.m12, l2w.m22, 0);

                cb.SetRenderTarget(m_DirShadowArray.data, 0, CubemapFace.Unknown, i);
                cb.ClearRenderTarget(false, true, Color.clear);
                renderContext.ExecuteCommandBuffer(cb);
                cb.Clear();
                Matrix4x4[] mats_per_light = new Matrix4x4[4];
                for (int j = 0; j < m_asset.cascadeNum; j++)
                {
                    //correct the forward of the helper camera to light dir
                    helper_trans.forward = dir;

                    float[] bias = cascadeHelper.GetCascadeVolum(helper_trans.worldToLocalMatrix, j);
                    helper_trans.position   = new Vector3(bias[0], bias[1], bias[2]) - helper_trans.forward * m_asset.shadowDistance;
                    helper.orthographicSize = bias[4] / 2;
                    helper.farClipPlane     = bias[5] + m_asset.shadowDistance;
                    helper.aspect           = bias[3] / bias[4];

                    cb.ClearRenderTarget(true, false, Color.clear);
                    mats_per_light[j] = GL.GetGPUProjectionMatrix(helper.projectionMatrix, true) * helper.worldToCameraMatrix;
                    cb.SetGlobalMatrix(shaderPropertyID.shadow_mat, mats_per_light[j]);
                    renderContext.ExecuteCommandBuffer(cb);
                    cb.Clear();
                    var cullResults = new CullResults();
                    CullResults.Cull(helper, renderContext, out cullResults);

                    var filterSetting = new FilterRenderersSettings(true);
                    filterSetting.renderQueueRange = RenderQueueRange.opaque;
                    filterSetting.layerMask        = helper.cullingMask;

                    var renderSetting = new DrawRendererSettings(camera, new ShaderPassName(string.Format("VRP_DS_{0:G}", j)));
                    renderSetting.sorting.flags = SortFlags.None;
                    renderContext.DrawRenderers(cullResults.visibleRenderers, ref renderSetting, filterSetting);
                }
                var mt = new ShadowCascadeMatrix();
                mt.a = mats_per_light[0]; mt.b = mats_per_light[1]; mt.c = mats_per_light[2]; mt.d = mats_per_light[3];
                mts.Add(mt);
            }
            CommandBufferPool.Release(cb);
            m_shadowcascade_matrix_vp.data.SetData(mts);
        }
        public void UpdateLightBuffer(ref Dictionary <Light, int> lights_table, List <VisibleLight> lights, ref CommandBuffer setup_properties, bool isGI)
        {
            if (isGI)
            {
                lightBuffer_GI.TestNeedModify(lights.Count);
            }
            else
            {
                lightBuffer.TestNeedModify(lights.Count);
            }

            BindProperties(lights.Count, ref setup_properties, isGI);
            if (lights.Count == 0)
            {
                return;
            }

            List <LightStruct> lights_ = new List <LightStruct>();

            try
            {
                foreach (var light in lights)
                {
                    LightStruct lightStruct = new LightStruct();
                    Matrix4x4   l2w         = light.localToWorld;
                    lightStruct.others = new Vector4(-1, -1, -1, -1);
                    switch (light.lightType)
                    {
                    case LightType.Directional:
                    {
                        lightStruct.geometry   = new Vector3(l2w.m02, l2w.m12, l2w.m22).normalized;
                        lightStruct.pos_type   = -lightStruct.geometry;
                        lightStruct.geometry.w = float.MaxValue;
                        lightStruct.pos_type.w = 0;
                        if (light.light.shadows != LightShadows.None)
                        {
                            lightStruct.others.x = lights_table[light.light];
                        }
                    }
                    break;

                    case LightType.Point:
                    {
                        lightStruct.pos_type   = new Vector4(l2w.m03, l2w.m13, l2w.m23, 1);
                        lightStruct.geometry   = new Vector3(l2w.m02, l2w.m12, l2w.m22).normalized;
                        lightStruct.geometry.w = light.range;
                        if (light.light.shadows != LightShadows.None)
                        {
                            lightStruct.others.x = lights_table[light.light];
                        }
                    }
                    break;

                    case LightType.Spot:
                    {
                        lightStruct.pos_type   = new Vector4(l2w.m03, l2w.m13, l2w.m23, 2);
                        lightStruct.geometry   = new Vector3(l2w.m02, l2w.m12, l2w.m22).normalized;
                        lightStruct.geometry.w = Mathf.Cos(light.spotAngle / 360 * Mathf.PI);
                    }
                    break;
                    }
                    lightStruct.color   = light.finalColor;
                    lightStruct.color.w = 1;
                    lights_.Add(lightStruct);
                }
            }
            catch (Exception)
            {
                Debug.Log(lights.Count);
                Debug.Log(lights_table.Count);
            }
            if (isGI)
            {
                lightBuffer_GI.data.SetData(lights_);
            }
            else
            {
                lightBuffer.data.SetData(lights_);
            }
        }
        public void UpdatePointLights(ref Dictionary <Light, int> light_table, ref ScriptableRenderContext renderContext, List <Light> plights, Camera camera, ref CommandBuffer setup_properties)
        {
            //todo: now will update every light for every camera, which is not totally necessary.
            if (helper_ == null)
            {
                return;
            }
            if (plights.Count == 0)
            {
                return;
            }
            Transform helper_trans = helper_.transform;

            m_PointShadowArray.TestNeedModify((int)m_asset.pointShadowResolution, (int)m_asset.pointShadowResolution, plights.Count);
            if (m_PointShadowArray.IsValid())
            {
                setup_properties.SetGlobalTexture(shaderPropertyID.pointShadowArray, m_PointShadowArray.data);
            }

            m_pointLightMatrix.TestNeedModify(plights.Count);
            if (m_pointLightMatrix.IsValid())
            {
                setup_properties.SetGlobalBuffer(shaderPropertyID.pointLightMatrixArray, m_pointLightMatrix.data);
            }


            helper_trans.up = Vector3.up;
            helper.aspect   = 1f;
            var cb = CommandBufferPool.Get("Point light shadow map");

            ShadowCascadeMatrix[] light_mats = new ShadowCascadeMatrix[plights.Count];
            string tes = m_asset.enableTessellation ? "_TES" : "";

            for (int i = 0; i < plights.Count; i++)
            {
                var light = plights[i];
                light_table[light] = i;

                helper_trans.position   = light.transform.position;
                helper.orthographicSize = light.range * 2;
                helper.farClipPlane     = light.range;

                cb.SetRenderTarget(m_PointShadowArray.data, 0, CubemapFace.Unknown, i);
                cb.ClearRenderTarget(true, true, Color.clear);
                renderContext.ExecuteCommandBuffer(cb);
                cb.Clear();

                helper_trans.forward = Vector3.forward;

                var mats = new ShadowCascadeMatrix();
                mats.a = helper.worldToCameraMatrix;
                mats.b = GL.GetGPUProjectionMatrix(helper.projectionMatrix, true);
                cb.SetGlobalMatrix(shaderPropertyID.shadow_mat, mats.a);
                cb.SetGlobalMatrix(shaderPropertyID.shadow_mat2, mats.b);
                cb.SetGlobalVector(shaderPropertyID.shadow_Range, new Vector4(helper.farClipPlane, helper.farClipPlane));
                renderContext.ExecuteCommandBuffer(cb);
                cb.Clear();

                var cullResults = new CullResults();
                CullResults.Cull(helper, renderContext, out cullResults);

                var filterSetting = new FilterRenderersSettings(true);
                filterSetting.renderQueueRange = RenderQueueRange.opaque;
                filterSetting.layerMask        = helper.cullingMask;

                var renderSetting = new DrawRendererSettings(camera, new ShaderPassName("VRP_PS_0" + tes));
                renderSetting.sorting.flags = SortFlags.None;
                renderContext.DrawRenderers(cullResults.visibleRenderers, ref renderSetting, filterSetting);

                helper_trans.forward = -Vector3.forward;

                mats.c = helper.worldToCameraMatrix;
                mats.d = mats.b;
                cb.ClearRenderTarget(true, false, Color.clear);
                cb.SetGlobalMatrix("_Shadow_mat", mats.c);
                renderContext.ExecuteCommandBuffer(cb);
                cb.Clear();

                cullResults = new CullResults();
                CullResults.Cull(helper, renderContext, out cullResults);

                renderSetting = new DrawRendererSettings(camera, new ShaderPassName("VRP_PS_1" + tes));
                renderSetting.sorting.flags = SortFlags.None;
                renderContext.DrawRenderers(cullResults.visibleRenderers, ref renderSetting, filterSetting);

                light_mats[i] = mats;
            }
            CommandBufferPool.Release(cb);
            m_pointLightMatrix.data.SetData(light_mats);
        }