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(); }
public static bool ExtractDirectionalLightMatrix(ref CullResults cullResults, ref ShadowData shadowData, int shadowLightIndex, int cascadeIndex, int shadowResolution, float shadowNearPlane, out Vector4 cascadeSplitDistance, out ShadowSliceData shadowSliceData, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix) { ShadowSplitData splitData; bool success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex, cascadeIndex, shadowData.directionalLightCascadeCount, shadowData.directionalLightCascades, shadowResolution, shadowNearPlane, out viewMatrix, out projMatrix, out splitData); float cullingSphereRadius = splitData.cullingSphere.w; cascadeSplitDistance = splitData.cullingSphere; cascadeSplitDistance.w = cullingSphereRadius * cullingSphereRadius; shadowSliceData.offsetX = (cascadeIndex % 2) * shadowResolution; shadowSliceData.offsetY = (cascadeIndex / 2) * shadowResolution; shadowSliceData.resolution = shadowResolution; shadowSliceData.shadowTransform = GetShadowTransform(projMatrix, viewMatrix); // 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 (shadowData.directionalLightCascadeCount > 1) { ApplySliceTransform(ref shadowSliceData, shadowData.directionalShadowAtlasWidth, shadowData.directionalShadowAtlasHeight); } return(success); }
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++; } }
public static Matrix4x4 ExtractDirectionalLightMatrix(VisibleLight vl, uint cascadeIdx, int cascadeCount, Vector3 splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex) { Debug.Assert(width == height, "Currently the cascaded shadow mapping code requires square cascades."); splitData = new ShadowSplitData(); splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity); splitData.cullingPlaneCount = 0; // get lightDir lightDir = vl.light.transform.forward; // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well // For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here. // Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details. cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIdx, cascadeCount, splitRatio, (int)width, nearPlaneOffset, out view, out proj, out splitData); // and the compound return(proj * view); }
public static bool ExtractDirectionalLightMatrix(ref CullResults cullResults, ref ShadowData shadowData, int shadowLightIndex, int cascadeIndex, int shadowResolution, float shadowNearPlane, float shadowFarPlane, out Vector4 cascadeSplitDistance, out ShadowSliceData shadowSliceData, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix) { ShadowSplitData splitData; Vector3 splitRotio = Vector3.one; if (shadowNearPlane > 1f) { float r = Mathf.Pow(shadowFarPlane / shadowNearPlane, 1f / shadowData.directionalLightCascadeCount); splitRotio = new Vector3(shadowNearPlane * r, shadowNearPlane * r * r, shadowNearPlane * r * r * r) / shadowFarPlane; } else { if (shadowData.directionalLightCascadeCount == 1) { splitRotio = new Vector3(1f, 0f, 0f); } else if (shadowData.directionalLightCascadeCount == 2) { splitRotio = new Vector3(0.25f, 1f, 0f); } else { splitRotio = new Vector3(0.067f, 0.2f, 0.467f); } } bool success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex, cascadeIndex, shadowData.directionalLightCascadeCount, splitRotio, shadowResolution, shadowNearPlane, out viewMatrix, out projMatrix, out splitData); cascadeSplitDistance = splitData.cullingSphere; shadowSliceData.offsetX = (cascadeIndex % 2) * shadowResolution; shadowSliceData.offsetY = (cascadeIndex / 2) * shadowResolution; shadowSliceData.resolution = shadowResolution; shadowSliceData.shadowTransform = GetShadowTransform(projMatrix, viewMatrix); if (shadowData.directionalLightCascadeCount > 1) { ApplySliceTransform(ref shadowSliceData, shadowData.directionalShadowAltasRes, shadowData.directionalShadowAltasRes); } return(success); }
public static Matrix4x4 ExtractDirectionalLightMatrix(VisibleLight vl, uint cascadeIdx, int cascadeCount, float[] splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex) { Debug.Assert(width == height, "Currently the cascaded shadow mapping code requires square cascades."); splitData = new ShadowSplitData(); splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity); splitData.cullingPlaneCount = 0; // get lightDir lightDir = vl.light.transform.forward; // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well // For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here. // Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details. Vector3 ratios = new Vector3(); for (int i = 0, cnt = splitRatio.Length < 3 ? splitRatio.Length : 3; i < cnt; i++) { ratios[i] = splitRatio[i]; } cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIdx, cascadeCount, ratios, (int)width, nearPlaneOffset, out view, out proj, out splitData); // and the compound (deviceProj will potentially inverse-Z) deviceProj = GL.GetGPUProjectionMatrix(proj, false); InvertOrthographic(ref deviceProj, ref view, out vpinverse); return(deviceProj * view); }
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(); }
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(); }
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); }
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); }
//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(); } }
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(); }
// 绘制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(); }
private bool RenderShadows(ref CullResults cullResults, ref VisibleLight shadowLight, int shadowLightIndex, ref ScriptableRenderContext context, Color backgroundColor) { m_ShadowCasterCascadesCount = m_ShadowSettings.directionalLightCascadeCount; if (shadowLight.lightType == UnityEngine.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); } float shadowNearPlane = m_Asset.ShadowNearOffset; Matrix4x4 view, proj; var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); bool success = false; var cmd = CommandBufferPool.Get("Prepare Shadowmap"); RenderTextureDescriptor shadowmapDescriptor = new RenderTextureDescriptor(m_ShadowSettings.shadowAtlasWidth, m_ShadowSettings.shadowAtlasHeight, m_ShadowSettings.shadowmapTextureFormat, kShadowBufferBits); shadowmapDescriptor.shadowSamplingMode = ShadowSamplingMode.CompareDepths; m_ShadowMapRT = RenderTexture.GetTemporary(shadowmapDescriptor); m_ShadowMapRT.filterMode = FilterMode.Bilinear; m_ShadowMapRT.wrapMode = TextureWrapMode.Clamp; // LightweightPipeline.SetRenderTarget is meant to be used with camera targets, not shadowmaps CoreUtils.SetRenderTarget(cmd, m_ShadowMapRT, ClearFlag.Depth, CoreUtils.ConvertSRGBToActiveColorSpace(backgroundColor)); if (shadowLight.lightType == UnityEngine.LightType.Spot) { success = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj, out settings.splitData); if (success) { SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution); SetupShadowSliceTransform(0, shadowResolution, proj, view); RenderShadowSlice(cmd, ref context, 0, proj, view, settings); } } else if (shadowLight.lightType == UnityEngine.LightType.Directional) { for (int cascadeIdx = 0; cascadeIdx < m_ShadowCasterCascadesCount; ++cascadeIdx) { success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex, cascadeIdx, m_ShadowCasterCascadesCount, m_ShadowSettings.directionalLightCascades, shadowResolution, shadowNearPlane, out view, out proj, out settings.splitData); float cullingSphereRadius = settings.splitData.cullingSphere.w; m_DirectionalShadowSplitDistances[cascadeIdx] = settings.splitData.cullingSphere; m_DirectionalShadowSplitRadii[cascadeIdx] = cullingSphereRadius * cullingSphereRadius; if (!success) { break; } SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution); SetupShadowSliceTransform(cascadeIdx, shadowResolution, proj, view); RenderShadowSlice(cmd, ref context, cascadeIdx, proj, view, settings); } } else { Debug.LogWarning("Only spot and directional shadow casters are supported in lightweight pipeline"); } if (success) { SetupShadowReceiverConstants(cmd, shadowLight, ref context); } CommandBufferPool.Release(cmd); return(success); }
//--------------------------------------------------------------------------------------------------------------------------------------------------- // Render shadows //--------------------------------------------------------------------------------------------------------------------------------------------------- void RenderPackedShadows(RenderLoop loop, CullResults cullResults, ref ShadowOutput packedShadows) { var setRenderTargetCommandBuffer = new CommandBuffer(); setRenderTargetCommandBuffer.name = "Render packed shadows"; setRenderTargetCommandBuffer.GetTemporaryRT(m_ShadowTexName, m_Settings.shadowAtlasWidth, m_Settings.shadowAtlasHeight, k_DepthBuffer, FilterMode.Bilinear, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear); setRenderTargetCommandBuffer.SetRenderTarget(new RenderTargetIdentifier(m_ShadowTexName)); setRenderTargetCommandBuffer.ClearRenderTarget(true, true, Color.green); loop.ExecuteCommandBuffer(setRenderTargetCommandBuffer); setRenderTargetCommandBuffer.Dispose(); VisibleLight[] visibleLights = cullResults.visibleLights; var shadowSlices = packedShadows.shadowSlices; // Render each light's shadow buffer into a subrect of the shared depth texture for (int lightIndex = 0; lightIndex < packedShadows.shadowLights.Length; lightIndex++) { int shadowSliceCount = packedShadows.shadowLights[lightIndex].shadowSliceCount; if (shadowSliceCount == 0) { continue; } Profiler.BeginSample("Shadows.GetShadowCasterBounds"); Bounds bounds; if (!cullResults.GetShadowCasterBounds(lightIndex, out bounds)) { Profiler.EndSample(); return; } Profiler.EndSample(); Profiler.BeginSample("Shadows.DrawShadows"); Matrix4x4 proj; Matrix4x4 view; var lightType = visibleLights[lightIndex].lightType; var lightDirection = visibleLights[lightIndex].light.transform.forward; var shadowNearClip = visibleLights[lightIndex].light.shadowNearPlane; int shadowSliceIndex = packedShadows.GetShadowSliceIndex(lightIndex, 0); if (lightType == LightType.Spot) { var settings = new DrawShadowsSettings(cullResults, lightIndex); bool needRendering = cullResults.ComputeSpotShadowsMatricesAndCullingPrimitives(lightIndex, out view, out proj, out settings.splitData); SetupShadowSplitMatrices(ref packedShadows.shadowSlices[shadowSliceIndex], proj, view); if (needRendering) { RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings); } } else if (lightType == LightType.Directional) { Vector3 splitRatio = m_Settings.directionalLightCascades; for (int s = 0; s < 4; ++s) { packedShadows.directionalShadowSplitSphereSqr[s] = new Vector4(0, 0, 0, float.NegativeInfinity); } for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++) { var settings = new DrawShadowsSettings(cullResults, lightIndex); var shadowResolution = shadowSlices[shadowSliceIndex].shadowResolution; bool needRendering = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, s, shadowSliceCount, splitRatio, shadowResolution, shadowNearClip, out view, out proj, out settings.splitData); packedShadows.directionalShadowSplitSphereSqr[s] = settings.splitData.cullingSphere; packedShadows.directionalShadowSplitSphereSqr[s].w *= packedShadows.directionalShadowSplitSphereSqr[s].w; SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view); if (needRendering) { RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings); } } } else if (lightType == LightType.Point) { for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++) { var settings = new DrawShadowsSettings(cullResults, lightIndex); bool needRendering = cullResults.ComputePointShadowsMatricesAndCullingPrimitives(lightIndex, (CubemapFace)s, 2.0f, out view, out proj, out settings.splitData); SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view); if (needRendering) { RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings); } } } Profiler.EndSample(); } }