private void RenderCascadedShadows(ScriptableRenderContext context) { float tileSize = shadowMapSize / 2; cascadedShadowMap = SetShadowRenderTarget(); shadowBuffer.BeginSample("Render Main Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); Light shadowLight = cull.visibleLights[0].light; shadowBuffer.SetGlobalFloat( shadowBiasID, shadowLight.shadowBias); var shadowSettings = new DrawShadowsSettings(cull, 0); var tileMatrix = Matrix4x4.identity; tileMatrix.m00 = tileMatrix.m11 = 0.5f; for (int i = 0; i < shadowCascades; i++) { Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; cull.ComputeDirectionalShadowMatricesAndCullingPrimitives( 0, i, shadowCascades, shadowCascadeSplit, (int)tileSize , shadowLight.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData); Vector2 tileOffset = ConfigureShadowTile(i, 2, tileSize); shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); cascadeCullingSpheres[i] = shadowSettings.splitData.cullingSphere = splitData.cullingSphere; //储存半径平方 用于比较 cascadeCullingSpheres[i].w *= splitData.cullingSphere.w; context.DrawShadows(ref shadowSettings); CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix , out worldToShadowCascadeMatrices[i]); tileMatrix.m03 = tileOffset.x * 0.5f; tileMatrix.m13 = tileOffset.y * 0.5f; worldToShadowCascadeMatrices[i] = tileMatrix * worldToShadowCascadeMatrices[i]; } shadowBuffer.DisableScissorRect(); shadowBuffer.SetGlobalTexture(cascadedShadowMapID, cascadedShadowMap); shadowBuffer.SetGlobalVectorArray(cascadeCullingSpheresID, cascadeCullingSpheres); shadowBuffer.SetGlobalMatrixArray(worldToShadowCascadeMatricesID, worldToShadowCascadeMatrices); float invShadowMapSize = 1f / shadowMapSize; shadowBuffer.SetGlobalVector(cascadedShadowMapSizedID , new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize)); shadowBuffer.SetGlobalFloat(cascadedShadowStrengthID, shadowLight.shadowStrength); bool hard = shadowLight.shadows == LightShadows.Hard; CoreUtils.SetKeyword(shadowBuffer, cascadedShadowsHardKeyword, hard); CoreUtils.SetKeyword(shadowBuffer, cascadedShadowsSoftKeyword, !hard); shadowBuffer.EndSample("Render Main Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
void RenderAdditionalShadowmapAtlas(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { List <VisibleLight> visibleLights = lightData.visibleLights; bool additionalLightHasSoftShadows = false; CommandBuffer cmd = CommandBufferPool.Get(k_RenderAdditionalLightShadows); using (new ProfilingSample(cmd, k_RenderAdditionalLightShadows)) { int shadowmapWidth = shadowData.additionalLightsShadowmapWidth; int shadowmapHeight = shadowData.additionalLightsShadowmapHeight; m_AdditionalLightsShadowmapTexture = RenderTexture.GetTemporary(shadowmapWidth, shadowmapHeight, k_ShadowmapBufferBits, m_AdditionalShadowmapFormat); m_AdditionalLightsShadowmapTexture.filterMode = FilterMode.Bilinear; m_AdditionalLightsShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_AdditionalLightsShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); for (int i = 0; i < m_AdditionalShadowCastingLightIndices.Count; ++i) { int shadowLightIndex = m_AdditionalShadowCastingLightIndices[i]; VisibleLight shadowLight = visibleLights[shadowLightIndex]; if (m_AdditionalShadowCastingLightIndices.Count > 1) { ShadowUtils.ApplySliceTransform(ref m_AdditionalLightSlices[i], shadowmapWidth, shadowmapHeight); } var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_AdditionalLightSlices[i].projectionMatrix, m_AdditionalLightSlices[i].resolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_AdditionalLightSlices[i], ref settings, m_AdditionalLightSlices[i].projectionMatrix, m_AdditionalLightSlices[i].viewMatrix); additionalLightHasSoftShadows |= shadowLight.light.shadows == LightShadows.Soft; } SetupAdditionalLightsShadowReceiverConstants(cmd, ref shadowData); } // We share soft shadow settings for main light and additional lights to save keywords. // So we check here if pipeline supports soft shadows and either main light or any additional light has soft shadows // to enable the keyword. // TODO: In PC and Consoles we can upload shadow data per light and branch on shader. That will be more likely way faster. bool mainLightHasSoftShadows = shadowData.supportsMainLightShadows && lightData.mainLightIndex != -1 && visibleLights[lightData.mainLightIndex].light.shadows == LightShadows.Soft; bool softShadows = shadowData.supportsSoftShadows && (mainLightHasSoftShadows || additionalLightHasSoftShadows); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, true); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
private void shadow_pass(ref CullResults cull, ref ScriptableRenderContext context) { int shadowLightIndex = 0; int cascadeIdx = 0; int m_ShadowCasterCascadesCount = 1; Vector3 directionalLightCascades = new Vector3(1.0f, 0.0f, 0.0f); int shadowNearPlaneOffset = 0; Matrix4x4 view; Matrix4x4 proj; foreach (var light in cull.visibleLights) { if (light.lightType == LightType.Directional) { DrawShadowsSettings sss = new DrawShadowsSettings(cull, shadowLightIndex); var success = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex, cascadeIdx, m_ShadowCasterCascadesCount, directionalLightCascades, shadowResolution, shadowNearPlaneOffset, out view, out proj, out sss.splitData); //view 光源的视空间 //proj 光源的裁剪空间 if (success) { cmd.Clear(); cmd.name = "clear shadow map"; cmd.SetRenderTarget(_ScreenSpaceShadowMapId); cmd.ClearRenderTarget(true, true, Color.black); context.ExecuteCommandBuffer(cmd); cmd.Clear(); cmd.name = "create shadow map"; cmd.SetViewport(new Rect(0, 0, shadowResolution, shadowResolution)); cmd.SetViewProjectionMatrices(view, proj); context.ExecuteCommandBuffer(cmd); context.DrawShadows(ref sss); context.ExecuteCommandBuffer(cmd); } cmd.Clear(); if (SystemInfo.usesReversedZBuffer) { //Debug.Log("usesReversedZBuffer "); } cmd.SetGlobalMatrix(_mId, proj * view); context.ExecuteCommandBuffer(cmd); } shadowLightIndex++; } }
private void RenderShadowSlice(ref ScriptableRenderContext context, int cascadeIndex, Matrix4x4 proj, Matrix4x4 view, DrawShadowsSettings settings) { var buffer = CommandBufferPool.Get("Prepare Shadowmap Slice"); buffer.SetViewport(new Rect(m_ShadowSlices[cascadeIndex].atlasX, m_ShadowSlices[cascadeIndex].atlasY, m_ShadowSlices[cascadeIndex].shadowResolution, m_ShadowSlices[cascadeIndex].shadowResolution)); buffer.SetViewProjectionMatrices(view, proj); context.ExecuteCommandBuffer(buffer); context.DrawShadows(ref settings); CommandBufferPool.Release(buffer); }
void RenderShadow(ScriptableRenderContext context) { shadowMap = RenderTexture.GetTemporary(this.shadowMapSize, this.shadowMapSize, 16, RenderTextureFormat.Shadowmap); shadowMap.filterMode = FilterMode.Bilinear; shadowMap.wrapMode = TextureWrapMode.Clamp; CoreUtils.SetRenderTarget(shadowBuffer, shadowMap, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth); shadowBuffer.BeginSample("Render Shadow"); // Set View matrix and projection matrix Matrix4x4 viewMatrix, projMatrix; ShadowSplitData shadowSplitData; this.cull.ComputeSpotShadowMatricesAndCullingPrimitives(0, out viewMatrix, out projMatrix, out shadowSplitData); shadowBuffer.SetViewProjectionMatrices(viewMatrix, projMatrix); shadowBuffer.SetGlobalFloat(shadowBiasID, cull.visibleLights[0].light.shadowBias); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); // Draw Shadow Casters var shadowSetting = new DrawShadowsSettings(cull, 0); context.DrawShadows(ref shadowSetting); // Set Shadow map and shadow space matrix if (SystemInfo.usesReversedZBuffer) { projMatrix.m20 = -projMatrix.m20; projMatrix.m21 = -projMatrix.m21; projMatrix.m22 = -projMatrix.m22; projMatrix.m23 = -projMatrix.m23; } Matrix4x4 scaleOffset = Matrix4x4.identity; scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = 0.5f; scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 0.5f; Matrix4x4 worldToShadowMatrix = scaleOffset * projMatrix * viewMatrix; shadowBuffer.SetGlobalMatrix(worldToShadowMatrixID, worldToShadowMatrix); shadowBuffer.SetGlobalTexture(shadowMapID, shadowMap); shadowBuffer.SetGlobalFloat(shadowStrengthID, cull.visibleLights[0].light.shadowStrength); shadowBuffer.EndSample("Render Shadow"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
private void RenderShadowSlice(CommandBuffer cmd, ref ScriptableRenderContext context, ref ShadowSliceData shadowSliceData, Matrix4x4 proj, Matrix4x4 view, DrawShadowsSettings settings) { cmd.SetViewport(new Rect(shadowSliceData.offsetX, shadowSliceData.offsetY, shadowSliceData.resolution, shadowSliceData.resolution)); cmd.EnableScissorRect(new Rect(shadowSliceData.offsetX + 4, shadowSliceData.offsetY + 4, shadowSliceData.resolution - 8, shadowSliceData.resolution - 8)); cmd.SetViewProjectionMatrices(view, proj); context.ExecuteCommandBuffer(cmd); cmd.Clear(); context.DrawShadows(ref settings); cmd.DisableScissorRect(); context.ExecuteCommandBuffer(cmd); cmd.Clear(); }
public void RenderShadows(ScriptableRenderContext renderContext, CommandBuffer cmd, CullResults cullResults) { // Avoid to do any commands if there is no shadow to draw if (m_ShadowRequests.Count == 0) { return; } // TODO remove DrawShadowSettings, lightIndex and splitData when scriptable culling is available DrawShadowsSettings dss = new DrawShadowsSettings(cullResults, 0); // Clear atlas render targets and draw shadows m_Atlas.RenderShadows(renderContext, cmd, dss); m_CascadeAtlas.RenderShadows(renderContext, cmd, dss); }
private void RenderShadowSlice(CommandBuffer cmd, ref ScriptableRenderContext context, int cascadeIndex, Matrix4x4 proj, Matrix4x4 view, DrawShadowsSettings settings) { cmd.SetViewport(new Rect(m_ShadowSlices[cascadeIndex].atlasX, m_ShadowSlices[cascadeIndex].atlasY, m_ShadowSlices[cascadeIndex].shadowResolution, m_ShadowSlices[cascadeIndex].shadowResolution)); cmd.EnableScissorRect(new Rect(m_ShadowSlices[cascadeIndex].atlasX + 4, m_ShadowSlices[cascadeIndex].atlasY + 4, m_ShadowSlices[cascadeIndex].shadowResolution - 8, m_ShadowSlices[cascadeIndex].shadowResolution - 8)); cmd.SetViewProjectionMatrices(view, proj); context.ExecuteCommandBuffer(cmd); cmd.Clear(); context.DrawShadows(ref settings); cmd.DisableScissorRect(); context.ExecuteCommandBuffer(cmd); cmd.Clear(); }
private void RenderShadowSlice(ref ScriptableRenderContext context, Vector3 lightDir, int cascadeIndex, Matrix4x4 proj, Matrix4x4 view, DrawShadowsSettings settings) { var buffer = new CommandBuffer() { name = "Prepare Shadowmap Slice" }; buffer.SetViewport(new Rect(m_ShadowSlices[cascadeIndex].atlasX, m_ShadowSlices[cascadeIndex].atlasY, m_ShadowSlices[cascadeIndex].shadowResolution, m_ShadowSlices[cascadeIndex].shadowResolution)); buffer.SetViewProjectionMatrices(view, proj); context.ExecuteCommandBuffer(buffer); buffer.Dispose(); context.DrawShadows(ref settings); }
public override void Render(ScriptableRenderContext renderContext, Camera[] cameras) { base.Render(renderContext, cameras); foreach (var camera in cameras) { ScriptableCullingParameters cullingParams; if (!CullResults.GetCullingParameters(camera, out cullingParams)) { continue; } cullingParams.shadowDistance = Mathf.Min(2000, camera.farClipPlane); CullResults cull = CullResults.Cull(ref cullingParams, renderContext); renderContext.SetupCameraProperties(camera); var cmd = new CommandBuffer(); cmd.ClearRenderTarget(true, false, m_ClearColor); renderContext.ExecuteCommandBuffer(cmd); cmd.Release(); var settings = new DrawRendererSettings(camera, new ShaderPassName("basic")); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true) { renderQueueRange = RenderQueueRange.opaque }; renderContext.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); var shadowSettings = new DrawShadowsSettings(cull, 0); //renderContext.DrawShadows(ref shadowSettings); renderContext.DrawSkybox(camera); settings.sorting.flags = SortFlags.CommonTransparent; filterSettings.renderQueueRange = RenderQueueRange.transparent; renderContext.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); } renderContext.Submit(); }
void RenderMainLightCascadeShadowmap(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; CommandBuffer cmd = CommandBufferPool.Get(k_RenderMainLightShadowmapTag); using (new ProfilingSample(cmd, k_RenderMainLightShadowmapTag)) { var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); m_MainLightShadowmapTexture = RenderTexture.GetTemporary(shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight, k_ShadowmapBufferBits, m_ShadowmapFormat); m_MainLightShadowmapTexture.filterMode = FilterMode.Bilinear; m_MainLightShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_MainLightShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { settings.splitData.cullingSphere = m_CascadeSplitDistances[cascadeIndex]; Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].resolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], ref settings, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].viewMatrix); } SetupMainLightShadowReceiverConstants(cmd, ref shadowData, shadowLight); } CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadows, true); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, shadowLight.light.shadows == LightShadows.Soft && shadowData.supportsSoftShadows); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
private void RenderShadows(ScriptableRenderContext context) { int split; if (shadowTileCount <= 1) { split = 1; } else if (shadowTileCount <= 4) { split = 2; } else if (shadowTileCount <= 9) { split = 3; } else { split = 4; } //虽然也可以用tex2DArray 但是不支持一些老机型手机 //所以这里用图片分割成4*4块 float tileSize = shadowMapSize / split; float tileScale = 1f / split; globalShadowData.x = tileScale; shadowMap = SetShadowRenderTarget(); shadowBuffer.BeginSample("Render Addition Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); int tileIndex = 0; bool hardShadows = false; bool softShadows = false; for (int i = mainLightExists ? 1 : 0; i < cull.visibleLights.Count && i < maxVisibleLights; i++) { //剔除没有强度的 或者不需要的 if (shadowData[i].x <= 0f) { continue; } Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; //是否能生成有效的矩阵 如果没有 x=0 表示不启用阴影 bool validShadows; if (shadowData[i].z > 0f) { //参数 1:灯光index 2:cascadeIndex 3:cascadeCount 4:cascade 分级距离 //5: 分辨率 6:nearPlane 如果太近不画 validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives( i, 0, 1, Vector3.right, (int)tileSize , cull.visibleLights[i].light.shadowNearPlane , out viewMatrix, out projectionMatrix, out splitData); } else { validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives( i, out viewMatrix, out projectionMatrix, out splitData); } if (!validShadows) { shadowData[i].x = 0f; continue; } //设置渲染到贴图上的区域(起始位置和大小) Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize); shadowData[i].z = tileOffset.x * tileScale; shadowData[i].w = tileOffset.y * tileScale; shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); shadowBuffer.SetGlobalFloat(shadowBiasID, cull.visibleLights[i].light.shadowBias); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); var shadowSettings = new DrawShadowsSettings(cull, i); //用球剔除 xyz是中心点 w是半径 shadowSettings.splitData.cullingSphere = splitData.cullingSphere; context.DrawShadows(ref shadowSettings); CalculateWorldToShadowMatrix( ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]); if (shadowData[i].y <= 0f) { hardShadows = true; } else { softShadows = true; } tileIndex += 1; } //渲染完成禁用裁剪 不然平常渲染也会收到影响 shadowBuffer.DisableScissorRect(); shadowBuffer.SetGlobalTexture(shadowMapID, shadowMap); shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesID, worldToShadowMatrices); shadowBuffer.SetGlobalVectorArray(shadowDataID, shadowData); float invShadowMapSize = 1f / shadowMapSize; shadowBuffer.SetGlobalVector(shadowMapSizeID , new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize)); //if (haveSoftShadow == LightShadows.Soft) //{ // shadowBuffer.EnableShaderKeyword(shadowSoftKeyword); //} //else //{ // shadowBuffer.DisableShaderKeyword(shadowSoftKeyword); //} //下面是上面的封装 CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows); CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows); shadowBuffer.EndSample("Render Addition Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
// 绘制ShadowMap void RenderShadows(ScriptableRenderContext context) { // 计算阴影图集的划分尺度 int split; if (shadowTileCount <= 1) { split = 1; } else if (shadowTileCount <= 4) { split = 2; } else if (shadowTileCount <= 9) { split = 3; } else { split = 4; } // 子图集的大小 float tileSize = shadowMapSize / split; float tileScale = 1f / split; shadowMap = SetShadowRenderTarget(); shadowBuffer.BeginSample("HY Render Shadows"); // 设置全局变量 shadowBuffer.SetGlobalVector(globalShadowDataId, new Vector4(tileScale, shadowDistance * shadowDistance)); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); int tileIndex = 0; bool hardShadows = false; bool softShadows = false; // 如果存在主光,需要跳过 for (int i = mainLightExists ? 1 : 0; i < cull.visibleLights.Count; i++) { if (i == maxVisibleLights) { break; } // 强度不为正,直接跳过 if (shadowData[i].x <= 0f) { continue; } // 获取灯的视矩阵和投影矩阵 Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; bool validShadows; if (shadowData[i].z > 0f) { validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives( i, 0, 1, Vector3.right, (int)tileSize, cull.visibleLights[i].light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData); } else { validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData); } if (!validShadows) { // 获取矩阵失败则强度置0 shadowData[i].x = 0f; continue; } Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize); // 存储地图集的偏移 shadowData[i].z = tileOffset.x * tileScale; shadowData[i].w = tileOffset.y * tileScale; // 设置灯的视矩阵和投影矩阵 shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); // 设置阴影偏移 shadowBuffer.SetGlobalFloat(shadowBiasId, cull.visibleLights[i].light.shadowBias); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); // 绘制阴影 var shadowSettings = new DrawShadowsSettings(cull, i); // 设置方向光的剔除球,其他光不受影响 shadowSettings.splitData.cullingSphere = splitData.cullingSphere; context.DrawShadows(ref shadowSettings); CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]); tileIndex += 1; if (shadowData[i].y <= 0f) { hardShadows = true; } else { softShadows = true; } } // 关闭裁剪 shadowBuffer.DisableScissorRect(); // 设置ShadowMap shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap); // 设置世界空间到阴影空间的转换矩阵 shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices); // 设置阴影数据 shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData); // 设置阴影纹理大小 float invShadowMapSize = 1f / shadowMapSize; shadowBuffer.SetGlobalVector(shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize)); // 设置阴影关键字 CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows); CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows); shadowBuffer.EndSample("HY Render Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
public static void Render(ScriptableRenderContext context, IEnumerable <Camera> cameras, SRP07CustomParameter SRP07CP) { string tx = ""; foreach (Camera camera in cameras) { ScriptableCullingParameters cullingParams; // Stereo-aware culling parameters are configured to perform a single cull for both eyes if (!CullResults.GetCullingParameters(camera, out cullingParams)) { continue; } CullResults cull = new CullResults(); CullResults.Cull(ref cullingParams, context, ref cull); // Setup camera for rendering (sets render target, view/projection matrices and other // per-camera built-in shader variables). context.SetupCameraProperties(camera); // clear depth buffer CommandBuffer cmd = new CommandBuffer(); cmd.ClearRenderTarget(true, !SRP07CP.DrawSkybox, SRP07CP.ClearColor); context.ExecuteCommandBuffer(cmd); cmd.Release(); // Setup global lighting shader variables SetupLightShaderVariables(cull.visibleLights, context); if (SRP07CP.DrawSkybox) { // Draw skybox context.DrawSkybox(camera); } // Setup DrawSettings and FilterSettings ShaderPassName passName = new ShaderPassName("BasicPass"); DrawRendererSettings drawSettings = new DrawRendererSettings(camera, passName); FilterRenderersSettings filterSettings = new FilterRenderersSettings(true); // //////////////////////////////////////////////////////////// VisibleLight[] ls = cull.visibleLights.ToArray(); DrawShadowsSettings[] shadowsSettings = new DrawShadowsSettings[ls.Length]; for (int i = 0; i < shadowsSettings.Length; i++) { shadowsSettings[i] = new DrawShadowsSettings(cull, i); } /* * if(camera == Camera.main) //Only generate result from main cam * { * tx += "DrawShadowsSettings" + "\n"+ "\n"; * * for (int i=0; i<ls.Length; i++) * { * tx += "lightIndex = " + shadowsSettings[i].lightIndex + " (" + ls[i].light.name + ") " + "\n"; * tx += "splitData.cullingPlaneCount = " + shadowsSettings[i].splitData.cullingPlaneCount + "\n"; * tx += "splitData.cullingSphere = " + shadowsSettings[i].splitData.cullingSphere + "\n"+ "\n"; * } * * // Output to text * if (textMesh != null) * { * textMesh.text = tx; * Debug.Log("<color=#0F0>TextMesh is updated</color>"); * } * else * { * tx = "<color=#F00>TextMesh is null</color> Please hit play if you hasn't"; * Debug.Log(tx); * } * } */ // //////////////////////////////////////////////////////////// if (SRP07CP.DrawOpaque) { // Draw opaque objects using BasicPass shader pass drawSettings.sorting.flags = SortFlags.CommonOpaque; filterSettings.renderQueueRange = RenderQueueRange.opaque; context.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings); for (int i = 0; i < shadowsSettings.Length; i++) { //if(ls[i].light.shadows != LightShadows.None) //context.DrawShadows(ref shadowsSettings[i]); } } if (SRP07CP.DrawTransparent) { // Draw transparent objects using BasicPass shader pass drawSettings.sorting.flags = SortFlags.CommonTransparent; filterSettings.renderQueueRange = RenderQueueRange.transparent; context.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings); } context.Submit(); } }
void RenderMainLightCascadeShadowmap(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; Light light = shadowLight.light; Debug.Assert(shadowLight.lightType == LightType.Directional); if (light.shadows == LightShadows.None) { return; } Bounds bounds; if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { return; } CommandBuffer cmd = CommandBufferPool.Get(k_RenderMainLightShadowmapTag); using (new ProfilingSample(cmd, k_RenderMainLightShadowmapTag)) { m_ShadowCasterCascadesCount = shadowData.mainLightShadowCascadesCount; int shadowResolution = ShadowUtils.GetMaxTileResolutionInAtlas(shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight, m_ShadowCasterCascadesCount); float shadowNearPlane = light.shadowNearPlane; Matrix4x4 view, proj; var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); m_MainLightShadowmapTexture = RenderTexture.GetTemporary(shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight, k_ShadowmapBufferBits, m_ShadowmapFormat); m_MainLightShadowmapTexture.filterMode = FilterMode.Bilinear; m_MainLightShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_MainLightShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); bool success = false; for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { success = ShadowUtils.ExtractDirectionalLightMatrix(ref cullResults, ref shadowData, shadowLightIndex, cascadeIndex, shadowResolution, shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex], out view, out proj); if (success) { settings.splitData.cullingSphere = m_CascadeSplitDistances[cascadeIndex]; Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, proj, shadowResolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], ref settings, proj, view); } } if (success) { SetupMainLightShadowReceiverConstants(cmd, ref shadowData, shadowLight); } } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
void RenderLocalShadowmapAtlas(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { List <int> localLightIndices = lightData.visibleLocalLightIndices; List <VisibleLight> visibleLights = lightData.visibleLights; int shadowCastingLightsCount = 0; int localLightsCount = localLightIndices.Count; for (int i = 0; i < localLightsCount; ++i) { VisibleLight shadowLight = visibleLights[localLightIndices[i]]; if (shadowLight.lightType == LightType.Spot && shadowLight.light.shadows != LightShadows.None) { shadowCastingLightsCount++; } } if (shadowCastingLightsCount == 0) { return; } Matrix4x4 view, proj; Bounds bounds; CommandBuffer cmd = CommandBufferPool.Get(k_RenderLocalShadows); using (new ProfilingSample(cmd, k_RenderLocalShadows)) { // TODO: Add support to point light shadows. We make a simplification here that only works // for spot lights and with max spot shadows per pass. int atlasWidth = shadowData.localShadowAtlasWidth; int atlasHeight = shadowData.localShadowAtlasHeight; int sliceResolution = LightweightShadowUtils.GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount); m_LocalShadowmapTexture = RenderTexture.GetTemporary(shadowData.localShadowAtlasWidth, shadowData.localShadowAtlasHeight, k_ShadowmapBufferBits, m_LocalShadowmapFormat); m_LocalShadowmapTexture.filterMode = FilterMode.Bilinear; m_LocalShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_LocalShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); for (int i = 0; i < localLightsCount; ++i) { int shadowLightIndex = localLightIndices[i]; VisibleLight shadowLight = visibleLights[shadowLightIndex]; Light light = shadowLight.light; // TODO: Add support to point light shadows if (shadowLight.lightType != LightType.Spot || shadowLight.light.shadows == LightShadows.None) { continue; } if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { continue; } Matrix4x4 shadowTransform; bool success = LightweightShadowUtils.ExtractSpotLightMatrix(ref cullResults, ref shadowData, shadowLightIndex, out shadowTransform, out view, out proj); if (success) { // This way of computing the shadow slice only work for spots and with most 4 shadow casting lights per pass // Change this when point lights are supported. Debug.Assert(shadowCastingLightsCount <= 4 && shadowLight.lightType == LightType.Spot); // TODO: We need to pass bias and scale list to shader to be able to support multiple // shadow casting local lights. m_LocalLightSlices[i].offsetX = (i % 2) * sliceResolution; m_LocalLightSlices[i].offsetY = (i / 2) * sliceResolution; m_LocalLightSlices[i].resolution = sliceResolution; m_LocalLightSlices[i].shadowTransform = shadowTransform; m_LocalShadowStrength[i] = light.shadowStrength; if (shadowCastingLightsCount > 1) { LightweightShadowUtils.ApplySliceTransform(ref m_LocalLightSlices[i], atlasWidth, atlasHeight); } var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); LightweightShadowUtils.SetupShadowCasterConstants(cmd, ref shadowLight, proj, sliceResolution); LightweightShadowUtils.RenderShadowSlice(cmd, ref context, ref m_LocalLightSlices[i], ref settings, proj, view); } } SetupLocalLightsShadowReceiverConstants(cmd, ref shadowData); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
private void RenderShadows(ScriptableRenderContext renderContext) { shadowMap = RenderTexture.GetTemporary(shadowMapSize, shadowMapSize, 16, RenderTextureFormat.Shadowmap); shadowMap.filterMode = FilterMode.Bilinear; shadowMap.wrapMode = TextureWrapMode.Clamp; //tell the GPU to render to our shaow map,load and store more precise texture CoreUtils.SetRenderTarget(shadowBuffer, shadowMap, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth); shadowBuffer.BeginSample("Render Shadows"); renderContext.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; cull.ComputeSpotShadowMatricesAndCullingPrimitives(0, out viewMatrix, out projectionMatrix, out splitData); shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); shadowBuffer.SetGlobalFloat(shadowBiasId, cull.visibleLights[0].light.shadowBias); renderContext.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); var shadowSettings = new DrawShadowsSettings(cull, 0); renderContext.DrawShadows(ref shadowSettings); //Opengl Z is reversed if (SystemInfo.usesReversedZBuffer) { projectionMatrix.m20 = -projectionMatrix.m20; projectionMatrix.m21 = -projectionMatrix.m21; projectionMatrix.m22 = -projectionMatrix.m22; projectionMatrix.m23 = -projectionMatrix.m23; } //clip space goes from -1 to 1,while texture coordinates and depth go from 0 to 1.so need to tranfer the matrix var scaleOffset = Matrix4x4.identity; scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = 0.5f; scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 0.5f; Matrix4x4 worldToShadowMatrix = scaleOffset * (projectionMatrix * viewMatrix); shadowBuffer.SetGlobalMatrix(worldToShadowMatrixId, worldToShadowMatrix); shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap); shadowBuffer.SetGlobalFloat(shadowStrengthId, cull.visibleLights[0].light.shadowStrength); float invShadowMapSize = 1f / shadowMapSize; shadowBuffer.SetGlobalVector(shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize)); // if(cull.visibleLights[0].light.shadows == LightShadows.Soft){ // shadowBuffer.EnableShaderKeyword(shadowSoftKeyword); // }else // { // shadowBuffer.DisableShaderKeyword(shadowSoftKeyword); // } CoreUtils.SetKeyword(shadowBuffer, shadowSoftKeyword, cull.visibleLights[0].light.shadows == LightShadows.Soft); shadowBuffer.EndSample("Render Shadows"); renderContext.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
private void RenderLocalShadowmapAtlas(ref CullResults cullResults, ref LightData lightData, ref ScriptableRenderContext context) { List <int> localLightIndices = lightData.localLightIndices; List <VisibleLight> visibleLights = lightData.visibleLights; int shadowCastingLightsCount = 0; int localLightsCount = localLightIndices.Count; for (int i = 0; i < localLightsCount; ++i) { VisibleLight shadowLight = visibleLights[localLightIndices[i]]; if (shadowLight.lightType == LightType.Spot && shadowLight.light.shadows != LightShadows.None) { shadowCastingLightsCount++; } } if (shadowCastingLightsCount == 0) { return; } CommandBuffer cmd = CommandBufferPool.Get("Prepare Local Lights Shadowmap"); Matrix4x4 view, proj; Bounds bounds; // TODO: Add support to point light shadows. We make a simplification here that only works // for spot lights and with max spot shadows per pass. int atlasWidth = m_ShadowSettings.localShadowAtlasWidth; int atlasHeight = m_ShadowSettings.localShadowAtlasHeight; int sliceResolution = GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount); int shadowSampling = 0; m_LocalShadowmapTexture = RenderTexture.GetTemporary(m_LocalShadowmapDescriptor); m_LocalShadowmapTexture.filterMode = FilterMode.Bilinear; m_LocalShadowmapTexture.wrapMode = TextureWrapMode.Clamp; CoreUtils.SetRenderTarget(cmd, m_LocalShadowmapTexture, ClearFlag.Depth); for (int i = 0; i < localLightsCount; ++i) { int shadowLightIndex = localLightIndices[i]; VisibleLight shadowLight = visibleLights[shadowLightIndex]; Light light = shadowLight.light; // TODO: Add support to point light shadows if (shadowLight.lightType != LightType.Spot || shadowLight.light.shadows == LightShadows.None) { continue; } if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { continue; } var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); if (cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj, out settings.splitData)) { // This way of computing the shadow slice only work for spots and with most 4 shadow casting lights per pass // Change this when point lights are supported. Debug.Assert(localLightsCount <= 4 && shadowLight.lightType == LightType.Spot); // TODO: We need to pass bias and scale list to shader to be able to support multiple // shadow casting local lights. m_LocalLightSlices[i].offsetX = (i % 2) * sliceResolution; m_LocalLightSlices[i].offsetY = (i / 2) * sliceResolution; m_LocalLightSlices[i].resolution = sliceResolution; m_LocalLightSlices[i].shadowTransform = GetShadowTransform(proj, view); if (shadowCastingLightsCount > 1) { ApplySliceTransform(ref m_LocalLightSlices[i], atlasWidth, atlasHeight); } SetupShadowCasterConstants(cmd, ref shadowLight, proj, sliceResolution); RenderShadowSlice(cmd, ref context, ref m_LocalLightSlices[i], proj, view, settings); m_LocalShadowStrength[i] = light.shadowStrength; shadowSampling = Math.Max(shadowSampling, (int)light.shadows); } } SetupLocalLightsShadowReceiverConstants(cmd, ref context); m_LocalShadowmapQuality = (LightShadows)Math.Min(shadowSampling, (int)m_ShadowSettings.directionalShadowQuality); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
private bool RenderShadows(ref CullResults cullResults, ref VisibleLight shadowLight, int shadowLightIndex, ref ScriptableRenderContext context) { m_ShadowCasterCascadesCount = m_ShadowSettings.directionalLightCascadeCount; if (shadowLight.lightType == LightType.Spot) { m_ShadowCasterCascadesCount = 1; } int shadowResolution = GetMaxTileResolutionInAtlas(m_ShadowSettings.shadowAtlasWidth, m_ShadowSettings.shadowAtlasHeight, m_ShadowCasterCascadesCount); Bounds bounds; if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { return(false); } var setRenderTargetCommandBuffer = CommandBufferPool.Get(); setRenderTargetCommandBuffer.name = "Render packed shadows"; setRenderTargetCommandBuffer.GetTemporaryRT(m_ShadowMapProperty, m_ShadowSettings.shadowAtlasWidth, m_ShadowSettings.shadowAtlasHeight, kShadowDepthBufferBits, FilterMode.Bilinear, RenderTextureFormat.Depth); setRenderTargetCommandBuffer.SetRenderTarget(m_ShadowMapRTID); setRenderTargetCommandBuffer.ClearRenderTarget(true, true, Color.black); context.ExecuteCommandBuffer(setRenderTargetCommandBuffer); CommandBufferPool.Release(setRenderTargetCommandBuffer); float shadowNearPlane = m_Asset.ShadowNearOffset; Vector3 splitRatio = m_ShadowSettings.directionalLightCascades; Matrix4x4 view, proj; var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); bool needRendering = false; if (shadowLight.lightType == LightType.Spot) { needRendering = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj, out settings.splitData); if (!needRendering) { return(false); } SetupShadowSliceTransform(0, shadowResolution, proj, view); RenderShadowSlice(ref context, 0, proj, view, settings); } else if (shadowLight.lightType == LightType.Directional) { for (int cascadeIdx = 0; cascadeIdx < m_ShadowCasterCascadesCount; ++cascadeIdx) { needRendering = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex, cascadeIdx, m_ShadowCasterCascadesCount, splitRatio, shadowResolution, shadowNearPlane, out view, out proj, out settings.splitData); m_DirectionalShadowSplitDistances[cascadeIdx] = settings.splitData.cullingSphere; m_DirectionalShadowSplitDistances[cascadeIdx].w *= settings.splitData.cullingSphere.w; if (!needRendering) { return(false); } SetupShadowSliceTransform(cascadeIdx, shadowResolution, proj, view); RenderShadowSlice(ref context, cascadeIdx, proj, view, settings); } } else { Debug.LogWarning("Only spot and directional shadow casters are supported in lightweight pipeline"); return(false); } return(true); }
void RenderShadows(ScriptableRenderContext context) { int split; if (shadowTileCount <= 1) { split = 1; } else if (shadowTileCount <= 4) { split = 2; } else if (shadowTileCount <= 9) { split = 3; } else { split = 4; } float tileSize = shadowMapSize / split; float tileScale = 1f / split; Rect tileViewport = new Rect(0f, 0f, tileSize, tileSize); shadowMap = RenderTexture.GetTemporary(shadowMapSize, shadowMapSize, 16, RenderTextureFormat.Shadowmap); shadowMap.filterMode = FilterMode.Bilinear; shadowMap.wrapMode = TextureWrapMode.Clamp; CoreUtils.SetRenderTarget(shadowBuffer, shadowMap, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth); shadowBuffer.BeginSample("Render Shadows"); shadowBuffer.SetGlobalVector(globalShadowDataId, new Vector4(tileScale, shadowDistance * shadowDistance)); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); int tileIndex = 0; bool hardShadows = false; bool softShadows = false; for (int i = 0; i < cull.visibleLights.Count; ++i) { if (i == maxVisibleLights) { break; } if (shadowData[i].x <= 0f) { continue; } Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; bool validShadow; if (shadowData[i].z > 0f) { validShadow = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives( i, 0, 1, Vector3.right, (int)tileSize, cull.visibleLights[i].light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData); } else { validShadow = cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData); } if (!validShadow) { shadowData[i].x = 0f; continue; } float tileOffsetX = i % split; float tileOffsetY = i / split; tileViewport.x = tileOffsetX * tileSize; tileViewport.y = tileOffsetY * tileSize; shadowData[i].z = tileOffsetX * tileScale; shadowData[i].w = tileOffsetY * tileScale; shadowBuffer.SetViewport(tileViewport); shadowBuffer.EnableScissorRect(new Rect( tileViewport.x + 4f, tileViewport.y + 4f, tileSize - 8f, tileSize - 8f )); shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); shadowBuffer.SetGlobalFloat( shadowBiasId, cull.visibleLights[i].light.shadowBias ); shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); var shadowSettings = new DrawShadowsSettings(cull, i); shadowSettings.splitData.cullingSphere = splitData.cullingSphere; context.DrawShadows(ref shadowSettings); if (SystemInfo.usesReversedZBuffer) { projectionMatrix.m20 = -projectionMatrix.m20; projectionMatrix.m21 = -projectionMatrix.m21; projectionMatrix.m22 = -projectionMatrix.m22; projectionMatrix.m23 = -projectionMatrix.m23; } var scaleOffset = Matrix4x4.TRS(Vector3.one * 0.5f, Quaternion.identity, Vector3.one * 0.5f); worldToShadowMatrices[i] = scaleOffset * (projectionMatrix * viewMatrix); //if (split > 1) //{ // var tileMatrix = Matrix4x4.identity; // tileMatrix.m00 = tileMatrix.m11 = tileScale; // tileMatrix.m03 = tileOffsetX * tileScale; // tileMatrix.m13 = tileOffsetY * tileScale; // worldToShadowMatrices[i] = tileMatrix * worldToShadowMatrices[i]; //} shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices); tileIndex += 1; if (shadowData[i].y <= 0f) { hardShadows = true; } else { softShadows = true; } } shadowBuffer.DisableScissorRect(); shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap); float invShadowMapSize = 1f / shadowMapSize; shadowBuffer.SetGlobalVector( shadowMapSizeId, new Vector4( invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize ) ); CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows); CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows); shadowBuffer.EndSample("Render Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
void RenderShadows(ScriptableRenderContext context) { int split; if (shadowTileCount <= 1) { split = 1; } else if (shadowTileCount <= 4) { split = 2; } else if (shadowTileCount <= 9) { split = 3; } else { split = 4; } float tileSize = shadowMapSize / split; float tileScale = 1f / split; shadowMap = SetShadowRenderTarget(); shadowBuffer.BeginSample("Render Shadows"); shadowBuffer.SetGlobalVector(globalShadowDataId, new Vector4(tileScale, shadowDistance * shadowDistance)); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); bool softShadows = false; bool hardShadows = false; int tileIndex = 0; for (int i = mainLightExists ? 1 : 0; i < cull.visibleLights.Count; i++) { if (i == MAX_VISIBLE_LIGHTS) { break; } if (shadowData[i].x <= 0f) { continue; } Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; bool validShadows = false; if (shadowData[i].z > 0f) { validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(i, 0, 1, Vector3.right, (int)tileSize, cull.visibleLights[i].light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData); } else { validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData); } if (!validShadows) { shadowData[i].x = 0f; continue; } Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize); shadowData[i].z = tileOffset.x * tileScale; shadowData[i].w = tileOffset.x * tileScale; shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); var shadowSettings = new DrawShadowsSettings(cull, i); shadowSettings.splitData.cullingSphere = splitData.cullingSphere; context.DrawShadows(ref shadowSettings); CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]); if (shadowData[i].y <= 0f) { hardShadows = true; } else { softShadows = true; } shadowBuffer.SetGlobalFloat(shadowBiasId, cull.visibleLights[i].light.shadowBias); tileIndex += 1; } CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows); CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows); shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices); shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData); float invShadowMapSize = 1f / shadowMapSize; shadowBuffer.SetGlobalVector(shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize)); shadowBuffer.DisableScissorRect(); shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap); shadowBuffer.EndSample("Render Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
void RenderDirectionalCascadeShadowmap(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { LightShadows shadowQuality = LightShadows.None; int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; Light light = shadowLight.light; Debug.Assert(shadowLight.lightType == LightType.Directional); if (light.shadows == LightShadows.None) { return; } Bounds bounds; if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { return; } CommandBuffer cmd = CommandBufferPool.Get(k_RenderDirectionalShadowmapTag); using (new ProfilingSample(cmd, k_RenderDirectionalShadowmapTag)) { m_ShadowCasterCascadesCount = shadowData.directionalLightCascadeCount; int shadowResolution = LightweightShadowUtils.GetMaxTileResolutionInAtlas(shadowData.directionalShadowAtlasWidth, shadowData.directionalShadowAtlasHeight, m_ShadowCasterCascadesCount); float shadowNearPlane = light.shadowNearPlane; Matrix4x4 view, proj; var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); m_DirectionalShadowmapTexture = RenderTexture.GetTemporary(shadowData.directionalShadowAtlasWidth, shadowData.directionalShadowAtlasHeight, k_ShadowmapBufferBits, m_ShadowmapFormat); m_DirectionalShadowmapTexture.filterMode = FilterMode.Bilinear; m_DirectionalShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_DirectionalShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); bool success = false; for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { success = LightweightShadowUtils.ExtractDirectionalLightMatrix(ref cullResults, ref shadowData, shadowLightIndex, cascadeIndex, shadowResolution, shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex], out view, out proj); if (success) { LightweightShadowUtils.SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution); LightweightShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], proj, view, settings); } } if (success) { shadowQuality = (shadowData.supportsSoftShadows) ? light.shadows : LightShadows.Hard; SetupDirectionalShadowReceiverConstants(cmd, ref shadowData, shadowLight); } } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); // TODO: We should have RenderingData as a readonly but currently we need this to pass shadow rendering to litpass shadowData.renderedDirectionalShadowQuality = shadowQuality; }
/// <inheritdoc/> public override void Execute(ScriptableRenderer renderer, ScriptableRenderContext context, ref RenderingData renderingData) { if (renderer == null) { throw new ArgumentNullException("renderer"); } if (!renderingData.shadowData.supportsMainCharacterShadows) { return; } LightData lightData = renderingData.lightData; int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; ShadowData shadowData = renderingData.shadowData; if (!GetVPMatrix(shadowLight.light)) { return; } CommandBuffer cmd = CommandBufferPool.Get(k_RenderMainCharacterShadowmapTag); using (new ProfilingSample(cmd, k_RenderMainCharacterShadowmapTag)) { m_MainCharacterShadowmapTexture = RenderTexture.GetTemporary(shadowData.mainCharacterShadowmapWidth, shadowData.mainCharacterShadowmapHeight, k_ShadowmapBufferBits, m_ShadowmapFormat); m_MainCharacterShadowmapTexture.filterMode = FilterMode.Bilinear; m_MainCharacterShadowmapTexture.wrapMode = TextureWrapMode.Clamp; m_MainCharacterShadowmapTexture.name = "m_MainCharacterShadowmapTexture"; SetRenderTarget(cmd, m_MainCharacterShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_ProjMatrix, shadowData.mainCharacterShadowmapWidth); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); cmd.SetViewProjectionMatrices(m_ViewMatrix, m_ProjMatrix); context.ExecuteCommandBuffer(cmd); cmd.Clear(); //foreach (var r in _Renderers) //{ // for (int i = 0, imax = r.sharedMaterials.Length; i < imax; i++) // { // cmd.DrawRenderer(r, r.sharedMaterials[i], i, r.sharedMaterials[i].FindPass("ShadowCaster")); // } //} ShadowSliceData slice = new ShadowSliceData() { offsetX = 0, offsetY = 0, resolution = shadowData.mainCharacterShadowmapWidth }; DrawShadowsSettings settings = new DrawShadowsSettings(renderingData.cullResults, shadowLightIndex); settings.splitData.cullingSphere = m_CullingSphere; ShadowUtils.RenderShadowSlice(cmd, ref context, ref slice, ref settings, m_ProjMatrix, m_ViewMatrix); context.ExecuteCommandBuffer(cmd); cmd.Clear(); SetupMainCharacterShadowReceiverConstants(cmd, ref shadowData, shadowLight); } CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainCharacterShadows, true); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, shadowLight.light.shadows == LightShadows.Soft && shadowData.supportsSoftShadows); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
public static void Render(ScriptableRenderContext context, IEnumerable<Camera> cameras) { foreach (Camera camera in cameras) { ScriptableCullingParameters cullingParams; // Stereo-aware culling parameters are configured to perform a single cull for both eyes if (!CullResults.GetCullingParameters(camera, out cullingParams)) continue; CullResults cull = new CullResults(); CullResults.Cull(ref cullingParams, context, ref cull); // Setup camera for rendering (sets render target, view/projection matrices and other // per-camera built-in shader variables). context.SetupCameraProperties(camera); // clear depth buffer CommandBuffer cmd = new CommandBuffer(); cmd.ClearRenderTarget(true, false, Color.grey); context.ExecuteCommandBuffer(cmd); cmd.Release(); // Setup global lighting shader variables //SetupLightShaderVariables(cull.visibleLights, context); // Draw skybox context.DrawSkybox(camera); // Setup DrawSettings and FilterSettings ShaderPassName passName = new ShaderPassName("BasicPass"); DrawRendererSettings drawSettings = new DrawRendererSettings(camera, passName); FilterRenderersSettings filterSettings = new FilterRenderersSettings(true); // Draw opaque objects using BasicPass shader pass drawSettings.sorting.flags = SortFlags.CommonOpaque; filterSettings.renderQueueRange = RenderQueueRange.opaque; context.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings); // Draw shadow VisibleLight[] ls = cull.visibleLights.ToArray(); SetupLightShaderVariables(cull.visibleLights, context); DrawShadowsSettings[] shadowsSettings = new DrawShadowsSettings[ls.Length]; for (int i=0; i<shadowsSettings.Length; i++) { shadowsSettings[i] = new DrawShadowsSettings(cull, i); if(ls[i].light.shadows != LightShadows.None) { context.DrawShadows(ref shadowsSettings[i]); Debug.Log("draw shadow for light "+i); } } // Draw transparent objects using BasicPass shader pass //drawSettings.sorting.flags = SortFlags.CommonTransparent; //filterSettings.renderQueueRange = RenderQueueRange.transparent; //context.DrawRenderers(cull.visibleRenderers, ref drawSettings, filterSettings); context.Submit(); } }
private bool RenderDirectionalCascadeShadowmap(ref CullResults cullResults, ref LightData lightData, ref ScriptableRenderContext context) { int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return(false); } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; Light light = shadowLight.light; Debug.Assert(shadowLight.lightType == LightType.Directional); if (light.shadows == LightShadows.None) { return(false); } CommandBuffer cmd = CommandBufferPool.Get("Prepare Directional Shadowmap"); m_ShadowCasterCascadesCount = m_ShadowSettings.directionalLightCascadeCount; int shadowResolution = GetMaxTileResolutionInAtlas(m_ShadowSettings.directionalShadowAtlasWidth, m_ShadowSettings.directionalShadowAtlasHeight, m_ShadowCasterCascadesCount); float shadowNearPlane = light.shadowNearPlane; Bounds bounds; if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { return(false); } Matrix4x4 view, proj; var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); m_DirectionalShadowmapTexture = RenderTexture.GetTemporary(m_DirectionalShadowmapDescriptor); m_DirectionalShadowmapTexture.filterMode = FilterMode.Bilinear; m_DirectionalShadowmapTexture.wrapMode = TextureWrapMode.Clamp; CoreUtils.SetRenderTarget(cmd, m_DirectionalShadowmapTexture, ClearFlag.Depth); bool success = false; for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex, cascadeIndex, m_ShadowCasterCascadesCount, m_ShadowSettings.directionalLightCascades, shadowResolution, shadowNearPlane, out view, out proj, out settings.splitData); float cullingSphereRadius = settings.splitData.cullingSphere.w; m_CascadeSplitDistances[cascadeIndex] = settings.splitData.cullingSphere; m_CascadeSplitRadii[cascadeIndex] = cullingSphereRadius * cullingSphereRadius; if (!success) { break; } m_CascadeSlices[cascadeIndex].offsetX = (cascadeIndex % 2) * shadowResolution; m_CascadeSlices[cascadeIndex].offsetY = (cascadeIndex / 2) * shadowResolution; m_CascadeSlices[cascadeIndex].resolution = shadowResolution; m_CascadeSlices[cascadeIndex].shadowTransform = GetShadowTransform(proj, view); // If we have shadow cascades baked into the atlas we bake cascade transform // in each shadow matrix to save shader ALU and L/S if (m_ShadowCasterCascadesCount > 1) { ApplySliceTransform(ref m_CascadeSlices[cascadeIndex], m_ShadowSettings.directionalShadowAtlasWidth, m_ShadowSettings.directionalShadowAtlasHeight); } SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution); RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], proj, view, settings); } if (success) { m_DirectionalShadowmapQuality = (m_ShadowSettings.directionalShadowQuality != LightShadows.Soft) ? LightShadows.Hard : light.shadows; // In order to avoid shader variants explosion we only do hard shadows when sampling shadowmap in the lit pass. // GLES2 platform is forced to hard single cascade shadows. if (!m_ShadowSettings.screenSpace) { m_DirectionalShadowmapQuality = LightShadows.Hard; } SetupDirectionalShadowReceiverConstants(cmd, shadowLight, ref context); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); return(success); }
/// <inheritdoc/> public override void Execute(ScriptableRenderer renderer, ScriptableRenderContext context, ref RenderingData renderingData) { if (renderer == null) { throw new ArgumentNullException("renderer"); } if (!renderingData.shadowData.supportsDeepShadowMaps) { return; } LightData lightData = renderingData.lightData; int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; ShadowData shadowData = renderingData.shadowData; if (!GetVPMatrix(shadowLight.light)) { return; } if (null == _ResetCompute) { _ResetCompute = renderer.GetCompute(ComputeHandle.ResetDeepShadowDataCompute); KernelResetBuffer = _ResetCompute.FindKernel("KernelResetBuffer"); } CommandBuffer cmd = CommandBufferPool.Get(k_RenderDeepShadowCaster); using (new ProfilingSample(cmd, k_RenderDeepShadowCaster)) { int deepShadowMapsSize = shadowData.deepShadowMapsSize; int deepShadowMapsDepth = shadowData.deepShadowMapsDepth; // Reset cmd.SetComputeBufferParam(_ResetCompute, KernelResetBuffer, "_CountBuffer", _CountBuffer); cmd.SetComputeBufferParam(_ResetCompute, KernelResetBuffer, "_DataBuffer", _DataBuffer); cmd.SetComputeIntParam(_ResetCompute, "_DeepShadowMapSize", deepShadowMapsSize); cmd.SetComputeIntParam(_ResetCompute, "_DeepShadowMapDepth", deepShadowMapsDepth); cmd.DispatchCompute(_ResetCompute, KernelResetBuffer, deepShadowMapsSize / 8, deepShadowMapsSize / 8, 1); _Temp = RenderTexture.GetTemporary(deepShadowMapsSize, deepShadowMapsSize, 0, RenderTextureFormat.R8); //Without rt, the second row of the vp matrix is negated // Cast SetRenderTarget(cmd, _Temp, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare, ClearFlag.Color, Color.black, TextureDimension.Tex2D); cmd.SetViewport(new Rect(Vector2.zero, Vector2.one * deepShadowMapsSize)); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, _ProjMatrix, shadowData.deepShadowMapsSize); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); cmd.SetViewProjectionMatrices(_ViewMatrix, _ProjMatrix); cmd.SetRandomWriteTarget(1, _CountBuffer); cmd.SetRandomWriteTarget(2, _DataBuffer); cmd.SetGlobalInt("_DeepShadowMapSize", deepShadowMapsSize); cmd.SetGlobalInt("_DeepShadowMapDepth", deepShadowMapsDepth); context.ExecuteCommandBuffer(cmd); cmd.Clear(); //foreach (var r in _Renderers) //{ // for (int i = 0, imax = r.sharedMaterials.Length; i < imax; i++) // { // cmd.DrawRenderer(r, r.sharedMaterials[i], i, r.sharedMaterials[i].FindPass("DeepShadowCaster")); // } //} ShadowSliceData slice = new ShadowSliceData() { offsetX = 0, offsetY = 0, resolution = deepShadowMapsSize, }; cmd.SetGlobalMatrix("_DeepShadowMapsWorldToShadow", _DeepShadowMatrix); DrawShadowsSettings settings = new DrawShadowsSettings(renderingData.cullResults, shadowLightIndex); settings.splitData.cullingSphere = _CullingSphere; cmd.EnableShaderKeyword("_DEEP_SHADOW_CASTER"); cmd.SetGlobalInt("_ShadowCasterZWrite", 0); ShadowUtils.RenderShadowSlice(cmd, ref context, ref slice, ref settings, _ProjMatrix, _ViewMatrix); cmd.DisableShaderKeyword("_DEEP_SHADOW_CASTER"); cmd.SetGlobalInt("_ShadowCasterZWrite", 1); context.ExecuteCommandBuffer(cmd); cmd.Clear(); // For Resolve SetupDeepShadowMapResolverConstants(cmd, ref shadowData, shadowLight); cmd.ClearRandomWriteTargets(); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
override public void Update(FrameId frameId, ScriptableRenderContext renderContext, CullResults cullResults, VisibleLight[] lights) { var profilingSample = new Utilities.ProfilingSample("Shadowmap" + m_TexSlot, renderContext); if (!string.IsNullOrEmpty(m_ShaderKeyword)) { var cb = new CommandBuffer(); cb.name = "Shadowmap.EnableShadowKeyword"; cb.EnableShaderKeyword(m_ShaderKeyword); renderContext.ExecuteCommandBuffer(cb); cb.Dispose(); } // loop for generating each individual shadowmap uint curSlice = uint.MaxValue; Bounds bounds; DrawShadowsSettings dss = new DrawShadowsSettings(cullResults, 0); for (uint i = 0; i < m_ActiveEntriesCount; ++i) { if (!cullResults.GetShadowCasterBounds(m_EntryCache[i].key.visibleIdx, out bounds)) { continue; } var cb = new CommandBuffer(); uint entrySlice = m_EntryCache[i].current.slice; if (entrySlice != curSlice) { Debug.Assert(curSlice == uint.MaxValue || entrySlice >= curSlice, "Entries in the entry cache are not ordered in slice order."); cb.name = "Shadowmap.Update.Slice" + entrySlice; if (curSlice != uint.MaxValue) { PostUpdate(frameId, cb, curSlice); } curSlice = entrySlice; PreUpdate(frameId, cb, curSlice); } cb.name = "Shadowmap.Update - slice: " + curSlice + ", vp.x: " + m_EntryCache[i].current.viewport.x + ", vp.y: " + m_EntryCache[i].current.viewport.y + ", vp.w: " + m_EntryCache[i].current.viewport.width + ", vp.h: " + m_EntryCache[i].current.viewport.height; cb.SetViewport(m_EntryCache[i].current.viewport); cb.SetViewProjectionMatrices(m_EntryCache[i].current.view, m_EntryCache[i].current.proj); cb.SetGlobalVector("g_vLightDirWs", m_EntryCache[i].current.lightDir); renderContext.ExecuteCommandBuffer(cb); cb.Dispose(); dss.lightIndex = m_EntryCache[i].key.visibleIdx; dss.splitData = m_EntryCache[i].current.splitData; renderContext.DrawShadows(ref dss); // <- if this was a call on the commandbuffer we would get away with using just once commandbuffer for the entire shadowmap, instead of one per face } // post update if (!string.IsNullOrEmpty(m_ShaderKeyword)) { var cb = new CommandBuffer(); cb.name = "Shadowmap.DisableShaderKeyword"; cb.DisableShaderKeyword(m_ShaderKeyword); renderContext.ExecuteCommandBuffer(cb); cb.Dispose(); } m_ActiveEntriesCount = 0; profilingSample.Dispose(); }
public void RenderShadows(ScriptableRenderContext renderContext, CommandBuffer cmd, DrawShadowsSettings dss) { cmd.SetRenderTarget(identifier); cmd.SetGlobalVector(HDShaderIDs._ShadowAtlasSize, new Vector4(m_Width, m_Height, 1.0f / m_Width, 1.0f / m_Height)); foreach (var shadowRequest in shadowRequests) { cmd.SetViewport(shadowRequest.atlasViewport); cmd.SetViewProjectionMatrices(shadowRequest.view, shadowRequest.projection); cmd.SetGlobalFloat(HDShaderIDs._ZClip, shadowRequest.zClip ? 1.0f : 0.0f); CoreUtils.DrawFullScreen(cmd, m_ClearMaterial, null, 0); dss.lightIndex = shadowRequest.lightIndex; dss.splitData = shadowRequest.splitData; // TODO: remove this execute when DrawShadows will use a CommandBuffer renderContext.ExecuteCommandBuffer(cmd); cmd.Clear(); renderContext.DrawShadows(ref dss); } cmd.SetGlobalFloat(HDShaderIDs._ZClip, 1.0f); // Re-enable zclip globally }
void RenderShadows(ScriptableRenderContext context) { int split; //split to N*N tiles if (shadowTileCount <= 1) { split = 1; } else if (shadowTileCount <= 4) { split = 2; } else if (shadowTileCount <= 9) { split = 3; } else { split = 4; } float tileSize = shadowMapSize / split; //maximum light = 16 float tileScale = 1f / split; globalShadowData.x = tileScale; shadowMap = SetShadowRenderTarget(); shadowBuffer.BeginSample("Render Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); int tileIndex = 0; bool hardShadows = false; bool softShadows = false; for (int i = mainLightExists ? 1 : 0; i < cull.visibleLights.Count; i++) { if (i == maxVisibleLights) { break; } //shadowStrength <=0 indicates the light needs no shadowmap if (shadowData[i].x <= 0f) { continue; } //render shadowMap for light i Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; bool validShadows; if (shadowData[i].z > 0f) { validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives( i, 0, 1, Vector3.right, (int)tileSize, cull.visibleLights[i].light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData); } else { validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives( i, out viewMatrix, out projectionMatrix, out splitData); } if (!validShadows) { shadowData[i].x = 0f; continue; } Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize); shadowData[i].z = tileOffset.x * tileScale; shadowData[i].w = tileOffset.y * tileScale; shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); shadowBuffer.SetGlobalFloat( shadowBiasId, cull.visibleLights[i].light.shadowBias ); // shadow bias context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); var shadowSettings = new DrawShadowsSettings(cull, i); shadowSettings.splitData.cullingSphere = splitData.cullingSphere; context.DrawShadows(ref shadowSettings); CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]); tileIndex += 1; //for generate shader keyword of all soft/all hard shadows if (shadowData[i].y <= 0f) { hardShadows = true; } else { softShadows = true; } } shadowBuffer.DisableScissorRect(); //sample shadowMap shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap); shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices); //_ShadowData , including shadow strength shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData); //soft shadows, tent filter inputs float invShadowMapSize = 1f / shadowMapSize; shadowBuffer.SetGlobalVector( shadowMapSizeId, new Vector4( invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize ) ); CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows); CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows); shadowBuffer.EndSample("Render Shadows"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }
//Starts Rendering Part public static void Render(ScriptableRenderContext context, IEnumerable <Camera> cameras) { //For shadowmapping, the matrices from the light's point of view Matrix4x4 view = Matrix4x4.identity; Matrix4x4 proj = Matrix4x4.identity; bool successShadowMap = false; foreach (Camera camera in cameras) { bool isSceneViewCam = camera.cameraType == CameraType.SceneView; //************************** UGUI Geometry on scene view ************************* #if UNITY_EDITOR if (isSceneViewCam) { ScriptableRenderContext.EmitWorldGeometryForSceneView(camera); } #endif //************************** Culling **************************************** ScriptableCullingParameters cullingParams; if (!CullResults.GetCullingParameters(camera, out cullingParams)) { continue; } CullResults cull = new CullResults(); CullResults.Cull(ref cullingParams, context, ref cull); //************************** Lighting Variables ***************************** CommandBuffer cmdLighting = new CommandBuffer(); cmdLighting.name = "(" + camera.name + ")" + "Lighting variable"; int mainLightIndex = -1; Light mainLight = null; Vector4[] lightPositions = new Vector4[8]; Vector4[] lightColors = new Vector4[8]; Vector4[] lightAttn = new Vector4[8]; Vector4[] lightSpotDir = new Vector4[8]; //Initialise values for (int i = 0; i < 8; i++) { lightPositions[i] = new Vector4(0.0f, 0.0f, 1.0f, 0.0f); lightColors[i] = Color.black; lightAttn[i] = new Vector4(0.0f, 1.0f, 0.0f, 1.0f); lightSpotDir[i] = new Vector4(0.0f, 0.0f, 1.0f, 0.0f); } for (int i = 0; i < cull.visibleLights.Count; i++) { VisibleLight light = cull.visibleLights[i]; if (mainLightIndex == -1) //Directional light { if (light.lightType == LightType.Directional) { Vector4 dir = light.localToWorld.GetColumn(2); lightPositions[0] = new Vector4(-dir.x, -dir.y, -dir.z, 0); lightColors[0] = light.light.color; float lightRangeSqr = light.range * light.range; float fadeStartDistanceSqr = 0.8f * 0.8f * lightRangeSqr; float fadeRangeSqr = (fadeStartDistanceSqr - lightRangeSqr); float oneOverFadeRangeSqr = 1.0f / fadeRangeSqr; float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr; float quadAtten = 25.0f / lightRangeSqr; lightAttn[0] = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, 1.0f); cmdLighting.SetGlobalVector("_LightColor0", lightColors[0]); cmdLighting.SetGlobalVector("_WorldSpaceLightPos0", lightPositions[0]); mainLight = light.light; mainLightIndex = i; } } else { continue;//so far just do only 1 directional light } } cmdLighting.SetGlobalVectorArray("unity_LightPosition", lightPositions); cmdLighting.SetGlobalVectorArray("unity_LightColor", lightColors); cmdLighting.SetGlobalVectorArray("unity_LightAtten", lightAttn); cmdLighting.SetGlobalVectorArray("unity_SpotDirection", lightSpotDir); context.ExecuteCommandBuffer(cmdLighting); cmdLighting.Release(); //************************** Draw Settings ************************************ FilterRenderersSettings filterSettings = new FilterRenderersSettings(true); DrawRendererSettings drawSettingsDefault = new DrawRendererSettings(camera, passNameDefault); drawSettingsDefault.rendererConfiguration = renderConfig; drawSettingsDefault.flags = DrawRendererFlags.EnableDynamicBatching; drawSettingsDefault.SetShaderPassName(5, m_UnlitPassName); DrawRendererSettings drawSettingsBase = new DrawRendererSettings(camera, passNameBase); drawSettingsBase.flags = DrawRendererFlags.EnableDynamicBatching; drawSettingsBase.rendererConfiguration = renderConfig; DrawRendererSettings drawSettingsAdd = new DrawRendererSettings(camera, passNameAdd); drawSettingsAdd.flags = DrawRendererFlags.EnableDynamicBatching; drawSettingsAdd.rendererConfiguration = renderConfig; DrawRendererSettings drawSettingsDepth = new DrawRendererSettings(camera, passNameShadow); drawSettingsDepth.flags = DrawRendererFlags.EnableDynamicBatching; //drawSettingsBase.rendererConfiguration = renderConfig; //************************** Set TempRT ************************************ CommandBuffer cmdTempId = new CommandBuffer(); cmdTempId.name = "(" + camera.name + ")" + "Setup TempRT"; //Depth RenderTextureDescriptor depthRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight); depthRTDesc.colorFormat = m_DepthFormat; depthRTDesc.depthBufferBits = depthBufferBits; cmdTempId.GetTemporaryRT(m_DepthRTid, depthRTDesc, FilterMode.Bilinear); //Color RenderTextureDescriptor colorRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight); colorRTDesc.colorFormat = m_ColorFormat; colorRTDesc.depthBufferBits = depthBufferBits; //have depth because we don't want to ruin the _CameraDepthTexture colorRTDesc.sRGB = true; colorRTDesc.msaaSamples = 1; colorRTDesc.enableRandomWrite = false; cmdTempId.GetTemporaryRT(m_ColorRTid, colorRTDesc, FilterMode.Bilinear); //Shadow RenderTextureDescriptor shadowRTDesc = new RenderTextureDescriptor(m_ShadowRes, m_ShadowRes); shadowRTDesc.colorFormat = m_ShadowFormat; shadowRTDesc.depthBufferBits = depthBufferBits; //have depth because it is also a depth texture shadowRTDesc.msaaSamples = 1; shadowRTDesc.enableRandomWrite = false; cmdTempId.GetTemporaryRT(m_ShadowMapLightid, shadowRTDesc, FilterMode.Bilinear);//depth per light //ScreenSpaceShadowMap RenderTextureDescriptor shadowMapRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight); shadowMapRTDesc.colorFormat = m_ShadowMapFormat; shadowMapRTDesc.depthBufferBits = 0; shadowMapRTDesc.msaaSamples = 1; shadowMapRTDesc.enableRandomWrite = false; cmdTempId.GetTemporaryRT(m_ShadowMapid, shadowMapRTDesc, FilterMode.Bilinear);//screen space shadow context.ExecuteCommandBuffer(cmdTempId); cmdTempId.Release(); //************************** Do shadow? ************************************ Bounds bounds; bool doShadow = cull.GetShadowCasterBounds(mainLightIndex, out bounds); //************************** Shadow Mapping ************************************ if (doShadow && !isSceneViewCam) { DrawShadowsSettings shadowSettings = new DrawShadowsSettings(cull, mainLightIndex); successShadowMap = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(mainLightIndex, 0, 1, new Vector3(1, 0, 0), m_ShadowRes, mainLight.shadowNearPlane, out view, out proj, out shadowSettings.splitData); CommandBuffer cmdShadow = new CommandBuffer(); cmdShadow.name = "(" + camera.name + ")" + "Shadow Mapping"; cmdShadow.SetRenderTarget(m_ShadowMapLight); cmdShadow.ClearRenderTarget(true, true, Color.black); //Change the view to light's point of view cmdShadow.SetViewport(new Rect(0, 0, m_ShadowRes, m_ShadowRes)); cmdShadow.EnableScissorRect(new Rect(4, 4, m_ShadowRes - 8, m_ShadowRes - 8)); cmdShadow.SetViewProjectionMatrices(view, proj); context.ExecuteCommandBuffer(cmdShadow); cmdShadow.Clear(); //Render Shadowmap context.DrawShadows(ref shadowSettings); cmdShadow.DisableScissorRect(); cmdShadow.SetGlobalTexture(m_ShadowMapLightid, m_ShadowMapLight); context.ExecuteCommandBuffer(cmdShadow); cmdShadow.Clear(); cmdShadow.Release(); } //************************** Camera Parameters ************************************ context.SetupCameraProperties(camera); //************************** Depth (for CameraDepthTexture) ************************************ CommandBuffer cmdDepthOpaque = new CommandBuffer(); cmdDepthOpaque.name = "(" + camera.name + ")" + "Make CameraDepthTexture"; cmdDepthOpaque.SetRenderTarget(m_DepthRT); cmdDepthOpaque.ClearRenderTarget(true, true, Color.black); context.ExecuteCommandBuffer(cmdDepthOpaque); cmdDepthOpaque.Clear(); filterSettings.renderQueueRange = RenderQueueRange.opaque; drawSettingsDepth.sorting.flags = SortFlags.CommonOpaque; context.DrawRenderers(cull.visibleRenderers, ref drawSettingsDepth, filterSettings); cmdDepthOpaque.SetGlobalTexture(m_DepthRTid, m_DepthRT); context.ExecuteCommandBuffer(cmdDepthOpaque); cmdDepthOpaque.Release(); //************************** Screen Space Shadow ************************************ if (doShadow) { CommandBuffer cmdShadow2 = new CommandBuffer(); cmdShadow2.name = "(" + camera.name + ")" + "Screen Space Shadow"; //Bias if (mainLight != null) { float sign = (SystemInfo.usesReversedZBuffer) ? 1.0f : -1.0f; if (isSceneViewCam) { sign = -sign * 0.01f; } float bias = mainLight.shadowBias * proj.m22 * sign; cmdShadow2.SetGlobalFloat("_ShadowBias", bias); } //Shadow Transform if (successShadowMap) { cmdShadow2.EnableShaderKeyword("SHADOWS_SCREEN"); cmdShadow2.EnableShaderKeyword("LIGHTMAP_SHADOW_MIXING"); if (SystemInfo.usesReversedZBuffer) { proj.m20 = -proj.m20; proj.m21 = -proj.m21; proj.m22 = -proj.m22; proj.m23 = -proj.m23; } Matrix4x4 WorldToShadow = proj * view; float f = 0.5f; var textureScaleAndBias = Matrix4x4.identity; textureScaleAndBias.m00 = f; textureScaleAndBias.m11 = f; textureScaleAndBias.m22 = f; textureScaleAndBias.m03 = f; textureScaleAndBias.m23 = f; textureScaleAndBias.m13 = f; WorldToShadow = textureScaleAndBias * WorldToShadow; cmdShadow2.SetGlobalMatrix("_WorldToShadow", WorldToShadow); cmdShadow2.SetGlobalFloat("_ShadowStrength", mainLight.shadowStrength); } //Render the screen-space shadow cmdShadow2.Blit(m_ShadowMap, m_ShadowMap, m_ScreenSpaceShadowsMaterial); cmdShadow2.SetGlobalTexture(m_ShadowMapid, m_ShadowMap); context.ExecuteCommandBuffer(cmdShadow2); cmdShadow2.Release(); } //************************** Clear ************************************ CommandBuffer cmd = new CommandBuffer(); cmd.name = "(" + camera.name + ")" + "Clear Flag"; cmd.SetRenderTarget(m_ColorRT); ClearFlag(cmd, camera, camera.backgroundColor); context.ExecuteCommandBuffer(cmd); cmd.Release(); //************************** Skybox ************************************ if (camera.clearFlags == CameraClearFlags.Skybox) { context.DrawSkybox(camera); } //************************** Opaque ************************************ filterSettings.renderQueueRange = RenderQueueRange.opaque; // DEFAULT pass, draw shaders without a pass name drawSettingsDefault.sorting.flags = SortFlags.CommonOpaque; context.DrawRenderers(cull.visibleRenderers, ref drawSettingsDefault, filterSettings); // BASE pass drawSettingsBase.sorting.flags = SortFlags.CommonOpaque; context.DrawRenderers(cull.visibleRenderers, ref drawSettingsBase, filterSettings); // ADD pass drawSettingsAdd.sorting.flags = SortFlags.CommonOpaque; context.DrawRenderers(cull.visibleRenderers, ref drawSettingsAdd, filterSettings); //************************** Blit to Camera Target ************************************ // so that reflection probes will work + screen view buttons CommandBuffer cmdColorOpaque = new CommandBuffer(); cmdColorOpaque.name = "(" + camera.name + ")" + "After opaque"; //This blit is necessary for Windows...It makes sure the Z is correct for transparent objects cmdColorOpaque.Blit(m_ColorRT, BuiltinRenderTextureType.CameraTarget); cmdColorOpaque.SetRenderTarget(m_ColorRT); //"Grab" pass cmdColorOpaque.SetGlobalTexture(m_GrabOpaqueRTid, m_ColorRT); context.ExecuteCommandBuffer(cmdColorOpaque); cmdColorOpaque.Release(); //************************** Transparent ************************************ filterSettings.renderQueueRange = RenderQueueRange.transparent; // DEFAULT pass drawSettingsDefault.sorting.flags = SortFlags.CommonTransparent; context.DrawRenderers(cull.visibleRenderers, ref drawSettingsDefault, filterSettings); // BASE pass drawSettingsBase.sorting.flags = SortFlags.CommonTransparent; context.DrawRenderers(cull.visibleRenderers, ref drawSettingsBase, filterSettings); //************************** Blit to Camera Target ************************************ // so that reflection probes will work + screen view buttons CommandBuffer cmdColor = new CommandBuffer(); cmdColor.name = "(" + camera.name + ")" + "After transparent"; cmdColor.Blit(m_ColorRT, BuiltinRenderTextureType.CameraTarget); cmdColor.SetRenderTarget(m_ColorRT); context.ExecuteCommandBuffer(cmdColor); cmdColor.Release(); //************************** Post-processing ************************************ m_CameraPostProcessLayer = camera.GetComponent <PostProcessLayer>(); if (m_CameraPostProcessLayer != null && m_CameraPostProcessLayer.enabled) { CommandBuffer cmdpp = new CommandBuffer(); cmdpp.name = "(" + camera.name + ")" + "Post-processing"; m_PostProcessRenderContext.Reset(); m_PostProcessRenderContext.camera = camera; m_PostProcessRenderContext.source = m_ColorRT; m_PostProcessRenderContext.sourceFormat = m_ColorFormat; m_PostProcessRenderContext.destination = BuiltinRenderTextureType.CameraTarget; m_PostProcessRenderContext.command = cmdpp; m_PostProcessRenderContext.flip = camera.targetTexture == null; m_CameraPostProcessLayer.Render(m_PostProcessRenderContext); //Target is already CameraTarget context.ExecuteCommandBuffer(cmdpp); cmdpp.Release(); } //************************** Scene View Fix ************************************ #if UNITY_EDITOR if (isSceneViewCam) //Copy depth to backbuffer's depth buffer { CommandBuffer cmdSceneDepth = new CommandBuffer(); cmdSceneDepth.name = "(" + camera.name + ")" + "Copy Depth to CameraTarget"; cmdSceneDepth.Blit(m_DepthRT, BuiltinRenderTextureType.CameraTarget, m_CopyDepthMaterial); context.ExecuteCommandBuffer(cmdSceneDepth); cmdSceneDepth.Release(); } #endif //************************** Clean Up ************************************ CommandBuffer cmdclean = new CommandBuffer(); cmdclean.name = "(" + camera.name + ")" + "Clean Up"; cmdclean.ReleaseTemporaryRT(m_ColorRTid); cmdclean.ReleaseTemporaryRT(m_DepthRTid); cmdclean.ReleaseTemporaryRT(m_ShadowMapid); cmdclean.ReleaseTemporaryRT(m_ShadowMapLightid); context.ExecuteCommandBuffer(cmdclean); cmdclean.Release(); context.Submit(); } }