//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.mainLightShadowCascadesCount, shadowData.mainLightShadowCascadesSplit, 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.viewMatrix = viewMatrix; //shadowSliceData.projectionMatrix = projMatrix; //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.mainLightShadowCascadesCount > 1) // ApplySliceTransform(ref shadowSliceData, shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight); //return success; //return false; //} public static bool ExtractSpotLightMatrix(ref CullResults cullResults, ref ShadowData shadowData, int shadowLightIndex, out Matrix4x4 shadowMatrix, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix) { ShadowSplitData splitData; bool success = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out viewMatrix, out projMatrix, out splitData); shadowMatrix = GetShadowTransform(projMatrix, viewMatrix); return(success); }
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 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 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(); }
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(); }
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); }
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(); }
// 绘制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(); }
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; Rect tileViewport = new Rect(0f, 0f, tileSize, tileSize); //width, height, precision, type shadowMap = RenderTexture.GetTemporary(shadowMapSize, shadowMapSize, 16, RenderTextureFormat.Shadowmap); shadowMap.filterMode = FilterMode.Bilinear; shadowMap.wrapMode = TextureWrapMode.Clamp; //set GPU prepared for shadowMap CoreUtils.SetRenderTarget(shadowBuffer, shadowMap, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth); shadowBuffer.BeginSample("Render Shadows"); 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; } //shadowStrength <=0 indicates the light needs no shadowmap if (shadowData[i].x <= 0f) { continue; } //render shadowMap for light i Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; if (!cull.ComputeSpotShadowMatricesAndCullingPrimitives( i, out viewMatrix, out projectionMatrix, out splitData )) { shadowData[i].x = 0f; continue; } ; float tileOffsetX = tileIndex % split; float tileOffsetY = tileIndex / split; tileViewport.x = tileOffsetX * tileSize; tileViewport.y = tileOffsetY * tileSize; if (split > 1) { //camera viewport does not affect light VP matrix shadowBuffer.SetViewport(tileViewport); //scissor edges for soft shadow filter does not get cross multiple shadowmaps 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 ); // shadow bias context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); var shadowSettings = new DrawShadowsSettings(cull, i); context.DrawShadows(ref shadowSettings); //prepare worldToShadowMatrices for shadow receiver if (SystemInfo.usesReversedZBuffer) //if use z=-1 for near clip plane { projectionMatrix.m20 = -projectionMatrix.m20; projectionMatrix.m21 = -projectionMatrix.m21; projectionMatrix.m22 = -projectionMatrix.m22; projectionMatrix.m23 = -projectionMatrix.m23; } //[-1,1] in clip space to [0,1] in texture space // var scaleOffset = Matrix4x4.TRS(Vector3.one * 0.5f, Quaternion.identity, Vector3.one * 0.5f); var scaleOffset = Matrix4x4.identity; scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = 0.5f; scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 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]; } tileIndex += 1; //for generate shader keyword of all soft/all hard shadows if (shadowData[i].y <= 0f) { hardShadows = true; } else { softShadows = true; } } if (split > 1) { 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(); }
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); }
//------------------------------------------------------------------------------ private void RenderShadows(ScriptableRenderContext context) { shadowMap = RenderTexture.GetTemporary( 512, 512, 16, RenderTextureFormat.Shadowmap ); shadowMap.filterMode = FilterMode.Bilinear; shadowMap.wrapMode = TextureWrapMode.Clamp; CoreUtils.SetRenderTarget( shadowBuffer, shadowMap, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth ); shadowBuffer.BeginSample("Shadow Map"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); // configure view & proj matrices from POV of light that's casting shadows Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; cullResults.ComputeSpotShadowMatricesAndCullingPrimitives( shadowCastingLightIndex, out viewMatrix, out projectionMatrix, out splitData ); shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); // draw all shadow-casting objects var shadowSettings = new DrawShadowsSettings( cullResults, shadowCastingLightIndex ); context.DrawShadows(ref shadowSettings); // setup shadow projection matrix // account for z-direction setting if (SystemInfo.usesReversedZBuffer) { projectionMatrix.m20 = -projectionMatrix.m20; projectionMatrix.m21 = -projectionMatrix.m21; projectionMatrix.m22 = -projectionMatrix.m22; projectionMatrix.m23 = -projectionMatrix.m23; } // clip space is (-1, 1), but depth coordinates are (0, 1) // so bake the conversion into our matrix var scaleOffset = Matrix4x4.identity; scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = 0.5f; scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 0.5f; // make shadow map available as global shader property Matrix4x4 worldtoShadowMatrix = scaleOffset * (projectionMatrix * viewMatrix); shadowBuffer.SetGlobalMatrix(worldToShadowMatrixId, worldtoShadowMatrix); shadowBuffer.SetGlobalTexture(shadowMapID, shadowMap); shadowBuffer.EndSample("Shadow Map"); context.ExecuteCommandBuffer(shadowBuffer); shadowBuffer.Clear(); }