public Vector4 ReserveDirectionalShadows(Light light, int visibleLightIndex) { if (shadowedDirectionalLightCount < maxShadowedDirectionalLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0f //&& //cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b) ) { float maskChannel = -1; LightBakingOutput lightBaking = light.bakingOutput; if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed && lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask) { useShadowMask = true; maskChannel = lightBaking.occlusionMaskChannel; } if (!cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)) { return(new Vector4(-light.shadowStrength, 0f, 0f, maskChannel)); } shadowedDirectionalLights[shadowedDirectionalLightCount] = new ShadowedDirectionalLight { visibleLightIndex = visibleLightIndex, slopeScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane }; return(new Vector4(light.shadowStrength, shadowSettings.directional.cascadeCount * shadowedDirectionalLightCount++, light.shadowNormalBias, maskChannel)); } return(new Vector4(0f, 0f, 0f, -1f)); }
/// <summary> /// 储备方向光阴影 Vector2存取强度和光线的索引 支持四盏光的ShadowMask /// </summary> /// <param name="light"></param> /// <param name="visibleLightIndex"></param> public Vector4 ReserveDirectionalShadows(Light light, int visibleLightIndex) { //检测阴影强度 None &&cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b) if (shadowedDirLightCount < maxShadowedDirLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0f) { float maskChannel = -1; //shadowMask LightBakingOutput lightBaking = light.bakingOutput; if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed && lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask) { useShadowMask = true; maskChannel = lightBaking.occlusionMaskChannel; } //直接Return 出去 不需要Cacade数据 阴影跑出CullSphere里面 if (!cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)) { //负数防止Shader 采样ShadowMap return(new Vector4(-light.shadowStrength, 0f, 0f, maskChannel)); } ShadowDirectionalLights[shadowedDirLightCount] = new ShadowDirectionalLight { visibleLightIndex = visibleLightIndex, slopeScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane }; //* 级联ShadowMap的数量 return(new Vector4(light.shadowStrength, settings.directional.cascadeCount * shadowedDirLightCount++, light.shadowNormalBias, maskChannel)); } return(new Vector4(0f, 0f, 0f, -1f)); }
public override void HandleDirectional(VisibleLight light, int index, CullingResults results) { if (index == 0) { shadowmapLightCount = 0; } //判断如果不超数,灯光投影设置开,投影强度不为0且投影在视锥体内 if (shadowmapLightCount < shadowSetting.directional.maxShadowedDirectionalLightCount && light.light.shadows != LightShadows.None && light.light.shadowStrength > 0f && results.GetShadowCasterBounds(index, out Bounds b)) { //给投影灯组添加该投影灯 shadowmapLights[shadowmapLightCount] = new ShadowedDirectionalLight { visibleLightIndex = index, slopeScaleBias = light.light.shadowBias, nearPlaneOffset = light.light.shadowNearPlane }; //返回灯光的阴影强度和shadowmaId allDirectionalLightShadowData[index] = new Vector3(light.light.shadowStrength, shadowmapLightCount++, light.light.shadowNormalBias); } else { allDirectionalLightShadowData[index] = Vector2.zero; } }
void SetupSpotShadow(ref ScriptableRenderContext context, ref CullingResults cullingResults, int shadowMapSize, int index, ref VisibleLight visibleLight) { Bounds shadowBounds; if (visibleLight.light.shadows != LightShadows.None && cullingResults.GetShadowCasterBounds(index, out shadowBounds)) { ShadowLight shadowLight = new ShadowLight(); shadowLight.cascades = new ShadowCascade[1]; shadowLight.cullingSpheres = null; shadowLight.tileSize = shadowMapSize; Matrix4x4 viewMatrix; Matrix4x4 projectionMatrix; ShadowSplitData splitData; if (cullingResults.ComputeSpotShadowMatricesAndCullingPrimitives(index, out viewMatrix, out projectionMatrix, out splitData)) { ShadowCascade shadowCascade = new ShadowCascade(); shadowCascade.viewMatrix = viewMatrix; shadowCascade.projectionMatrix = projectionMatrix; shadowCascade.worldToShadowMatrix = CreateWorldToShadowMatrix(viewMatrix, projectionMatrix); shadowCascade.tileOffset = Vector2Int.zero; shadowCascade.splitData = splitData; shadowLight.cascades[0] = shadowCascade; } shadowData.lights[index] = shadowLight; } }
void SetupShadow(Light light, ref CullingResults cullResults, ref CShadowSetting shadowSetting, int visibleLightIndex) { if (visibleLightIndex < CShadowPass.MAX_SHADOW_DIRECTIONAL_LIGHT_COUNT && light.shadows != LightShadows.None && light.shadowStrength > 0f && cullResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b) ) { lightShadowDatas.Add(new ShadowLightData(visibleLightIndex)); } }
public Vector3 ReserveDirectionalShadows(Light light, int visibleLightIndex) { if ( shadowedDirLightCount < maxShadowedDirLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0f && cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b) ) { shadowedDirectionalLights[shadowedDirLightCount] = new ShadowedDirectionalLight { visibleLightIndex = visibleLightIndex, slopeScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane, lightType = light.type }; return(new Vector3(light.shadowStrength, settings.directional.cascadeCount * shadowedDirLightCount++, light.shadowNormalBias)); } return(Vector3.zero); }
public void ReserveDirectionalShadows(Light light, int visibleLightIndex) { if (ShadowedDirectionalLightCount < maxShadowedDirectionalLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0f && cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)) { ShadowedDirectionalLights[ShadowedDirectionalLightCount++] = new ShadowedDirectionalLight { visibleLightIndex = visibleLightIndex }; } }
public Vector4 ReserveDirectioanlShadows(Light light, int visibleLightIndex) { if (ShadowedDirectionalLightCount < maxShadowedDirectionalLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0f //&& //cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b) ) //the getshadowCasterBound will return false if the light does not effect any oject(can cast shadow) in shadow range { float maskChannel = -1; //we will decide wether to use the shadow mask depend on if the lights are using thi shadow mask LightBakingOutput lightBaking = light.bakingOutput; if (lightBaking.lightmapBakeType == LightmapBakeType.Mixed && lightBaking.mixedLightingMode == MixedLightingMode.Shadowmask) { useShadowMask = true; maskChannel = lightBaking.occlusionMaskChannel; } //Inform Shader the light does not affect anything, used for baked light attenuation if (!cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)) { return(new Vector4(-light.shadowStrength, 0f, maskChannel)); } ShadowedDirectionalLights[ShadowedDirectionalLightCount] = new ShadowedDirectionalLight { visibleLightIndex = visibleLightIndex, slopScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane }; return(new Vector4(light.shadowStrength, shadowSettings.directional.cascadeCount * ShadowedDirectionalLightCount++, light.shadowNormalBias, maskChannel)); } else { return(new Vector4(0f, 0f, 0f, -1f)); } }
private void RenderPointLightShadow(CullingResults cull, int shadowLightCount, Light[] shadowLights, int[] shadowLightIndices) { var pointLightShadowmapDescriptor = new RenderTextureDescriptor(@params.pointLightParams.shadowResolution, @params.pointLightParams.shadowResolution, RenderTextureFormat.RHalf, 16) { autoGenerateMips = false, bindMS = false, dimension = TextureDimension.CubeArray, volumeDepth = shadowLightCount * 6, enableRandomWrite = false, msaaSamples = 1, shadowSamplingMode = ShadowSamplingMode.None, sRGB = false, useMipMap = false, vrUsage = VRTextureUsage.None }; _currentBuffer.GetTemporaryRT(ShaderManager.POINT_LIGHT_SHADOWMAP_ARRAY, pointLightShadowmapDescriptor, FilterMode.Bilinear); for (var i = 0; i < shadowLightCount; i++) { if (!cull.GetShadowCasterBounds(shadowLightIndices[i], out var shadowBounds)) continue; var light = shadowLights[i]; _currentBuffer.SetGlobalFloat(ShaderManager.SHADOW_BIAS, light.shadowBias); _currentBuffer.SetGlobalFloat(ShaderManager.SHADOW_NORMAL_BIAS, light.shadowNormalBias); var shadowSettings = new ShadowDrawingSettings(cull, shadowLightIndices[i]); for (var j = 0; j < 6; j++) { var shadowSlice = i * 6 + j; ResetRenderTarget(PointLightShadowmapArrayId, CubemapFace.Unknown, shadowSlice, true, true, 1, Color.white); if (!cull.ComputePointShadowMatricesAndCullingPrimitives(shadowLightIndices[i], (CubemapFace) j, 0, out var viewMatrix, out var projectionMatrix, out var splitData)) { ExecuteCurrentBuffer(); continue; } shadowSettings.splitData = splitData; Vector3 position = light.transform.position; _currentBuffer.SetGlobalVector(ShaderManager.LIGHT_POS, new Vector4(position.x, position.y, position.z, light.range)); _currentBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); ExecuteCurrentBuffer(); _context.DrawShadows(ref shadowSettings); } } var inverseShadowmapSize = 1f / @params.pointLightParams.shadowResolution; _currentBuffer.SetGlobalVector(ShaderManager.POINT_LIGHT_SHADOWMAP_SIZE, new Vector4(inverseShadowmapSize, inverseShadowmapSize, @params.pointLightParams.shadowResolution, @params.pointLightParams.shadowResolution)); if (@params.pointLightParams.softShadow) _currentBuffer.EnableShaderKeyword(ShaderManager.POINT_LIGHT_SOFT_SHADOWS); else _currentBuffer.DisableShaderKeyword(ShaderManager.POINT_LIGHT_SOFT_SHADOWS); ExecuteCurrentBuffer(); }
public void ReserveDirectionalShadows(Light light, int index) { if (_shadowedDirectionalLightCount < MaxShadowedDirectionalLightCount && light.shadows != LightShadows.None && light.intensity > 0 && _results.GetShadowCasterBounds(index, out Bounds outBounds)) { ShadowedDirectionalLights[_shadowedDirectionalLightCount] = new ShadowedDirectionalLight() { visibleLightIndex = index }; ++_shadowedDirectionalLightCount; } }
Vector4 ConfigureShadows(int lightIndex, Light shadowLight) { Vector4 shadow = Vector4.zero; Bounds shadowBounds; if (shadowLight.shadows != LightShadows.None && culling.GetShadowCasterBounds(lightIndex, out shadowBounds)) { shadowTileCount += 1; shadow.x = shadowLight.shadowStrength; shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f; } return(shadow); }
public Vector4 GetDirectionalShadowData(int visibleLightIndex) { Vector4 shadowData = new Vector4(-1, 0, 0, -1); Light dirLight = _cullResults.visibleLights[visibleLightIndex].light; if (dirLight.type != LightType.Directional) { return(shadowData); } if (dirLight.bakingOutput.lightmapBakeType == LightmapBakeType.Mixed && dirLight.bakingOutput.mixedLightingMode == MixedLightingMode.Shadowmask) { shadowData.y = dirLight.shadowStrength; // when mixed light who' s shadow has baked to shadow mask did't cast shadow at run time, we want to use shadow in shadow mask shadowData.w = dirLight.bakingOutput.occlusionMaskChannel; _mixedLightUseShadowMask = true; } if (_shadowedDirLightCount >= MAX_NUM_DIRECTIONAL_SHADOWS || dirLight.shadows == LightShadows.None || dirLight.shadowStrength <= 0 || !_cullResults.GetShadowCasterBounds(visibleLightIndex, out Bounds bounds)) { return(shadowData); } _shadowedDirLights[_shadowedDirLightCount] = new ShadowedLight() { visibleIndex = visibleLightIndex, light = dirLight }; shadowData.x = _shadowedDirLightCount * MAX_NUM_DIRECTIONAL_CASCADES; shadowData.y = dirLight.shadowStrength; shadowData.z = dirLight.shadowNormalBias * 2f - 1f; _shadowedDirLightCount++; return(shadowData); }
public void ReserveDirectionalShadows(Light light, int visibleLightIndex) { ///it's possible that a visible light ends up not affecting any objects that cast shadows, ///either because they're configured not to or because the light only affects objects beyond the max shadow distance. if (ShadowedDirectionalLightCount < maxShadowedDirectionalLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0f && cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)) { ShadowedDirectionalLights[ShadowedDirectionalLightCount++] = new ShadowedDirectionalLight { visibleLightIndex = visibleLightIndex }; } }
Vector4 ConfigureShadows(int lightIndex, Light shadowLight) { //shadows Vector4 shadow = Vector4.zero; Bounds shadowBounds; //if the light has shadows enabled and the shadows are contacting something thats visible if (shadowLight.shadows != LightShadows.None && cull.GetShadowCasterBounds(lightIndex, out shadowBounds)) { shadowTileCount += 1; shadow.x = shadowLight.shadowStrength; shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f; } return(shadow); }
public Vector2 ReserveDirectionalShadows(Light light, int visibleLightIndex) { if (ShadowedDirectionalLightCount < maxShadowedDirectionalLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0.0f && cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds b)) { ShadowedDirectionalLights[ShadowedDirectionalLightCount] = new ShadowedDirectionalLight { visibleLightIndex = visibleLightIndex }; return(new Vector2(light.shadowStrength, settings.directional.cascadeCount * ShadowedDirectionalLightCount++)); } return(Vector2.zero); }
public Vector2 ReserveDirectionalShadows(Light light, int visibleLightIndex) { // Check if the light can project a shadow and if the rendered elements are within bounds. if (shadowDirectionalLightCount < MaxShadowedDirectonalLightCount && light.shadows != LightShadows.None && light.shadowStrength > 0 && cullingResults.GetShadowCasterBounds(visibleLightIndex, out Bounds bounds)) { ShadowedDirectionalLights[shadowDirectionalLightCount] = new ShadowedDirectionalLight { VisibleLightIndex = visibleLightIndex }; return(new Vector2(light.shadowStrength, shadowDirectionalLightCount++)); } ; return(Vector2.zero); }
void SetupDirectionalShadow(ref ScriptableRenderContext context, ref CullingResults cullingResults, int shadowMapSize, int index, ref VisibleLight visibleLight) { Bounds shadowBounds; if (visibleLight.light.shadows != LightShadows.None && cullingResults.GetShadowCasterBounds(index, out shadowBounds)) { ShadowLight shadowLight = new ShadowLight(); shadowLight.cascades = new ShadowCascade[4]; shadowLight.cullingSpheres = new Vector4[4]; shadowLight.tileSize = shadowMapSize / 2; for (int j = 0; j < 4; j++) { Matrix4x4 viewMatrix; Matrix4x4 projectionMatrix; ShadowSplitData splitData; if (cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(index, j, 4, fourCascadesSplit, shadowLight.tileSize, visibleLight.light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData)) { Vector2Int tileOffset = new Vector2Int(j % 2, j / 2); Matrix4x4 tileMatrix = Matrix4x4.identity; tileMatrix.m00 = tileMatrix.m11 = 0.5f; tileMatrix.m03 = tileOffset.x * 0.5f; tileMatrix.m13 = tileOffset.y * 0.5f; ShadowCascade shadowCascade = new ShadowCascade(); shadowCascade.viewMatrix = viewMatrix; shadowCascade.projectionMatrix = projectionMatrix; shadowCascade.worldToShadowMatrix = tileMatrix * CreateWorldToShadowMatrix(viewMatrix, projectionMatrix); shadowCascade.tileOffset = tileOffset; shadowCascade.splitData = splitData; shadowLight.cullingSpheres[j] = splitData.cullingSphere; shadowLight.cullingSpheres[j].w *= shadowLight.cullingSpheres[j].w; shadowLight.cascades[j] = shadowCascade; } } shadowData.lights[index] = shadowLight; } }
private void SetUpRealtimeShadowVariables(Camera cam, ScriptableRenderContext context, CullingResults cull, Light light, int lightIndex) { Bounds bounds; bool doShadow = light.shadows != LightShadows.None && cull.GetShadowCasterBounds(lightIndex, out bounds); //************************** Shadow Mapping ************************************ if (doShadow) { ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cull, lightIndex); //For shadowmapping, the matrices from the light's point of view Matrix4x4 view = Matrix4x4.identity; Matrix4x4 proj = Matrix4x4.identity; ShadowSplitData splitData; bool successShadowMap = false; if (light.type == LightType.Directional) { successShadowMap = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives ( lightIndex, 0, 1, new Vector3(1, 0, 0), m_ShadowRes, light.shadowNearPlane, out view, out proj, out splitData ); shadowSettings.splitData = splitData; } else { return; } if (successShadowMap) { CommandBuffer cmdShadow = new CommandBuffer(); cmdShadow.name = "Shadow Mapping: light" + lightIndex; 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); //Set shadowmap texture cmdShadow.DisableScissorRect(); cmdShadow.SetViewProjectionMatrices(cam.worldToCameraMatrix, cam.projectionMatrix); cmdShadow.SetGlobalTexture(m_ShadowMapLightid, m_ShadowMapLight); context.ExecuteCommandBuffer(cmdShadow); cmdShadow.Clear(); cmdShadow.Release(); //Screen Space Shadow ================================================= CommandBuffer cmdShadow2 = new CommandBuffer(); cmdShadow2.name = "Screen Space Shadow: light" + lightIndex; //Bias float sign = (SystemInfo.usesReversedZBuffer) ? 1.0f : -1.0f; float bias = light.shadowBias * proj.m22 * sign; cmdShadow2.SetGlobalFloat("_ShadowBias", bias); //Shadow Transform 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", light.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(); } } }
public void ReserveShadows(Camera camera, HDShadowManager shadowManager, HDShadowInitParameters initParameters, CullingResults cullResults, FrameSettings frameSettings, int lightIndex) { Bounds bounds; float cameraDistance = Vector3.Distance(camera.transform.position, transform.position); #if ENABLE_RAYTRACING m_WillRenderShadows = m_Light.shadows != LightShadows.None && frameSettings.IsEnabled(FrameSettingsField.Shadow) && lightTypeExtent == LightTypeExtent.Punctual; #else m_WillRenderShadows = m_Light.shadows != LightShadows.None && frameSettings.IsEnabled(FrameSettingsField.Shadow) && !IsAreaLight(lightTypeExtent); #endif m_WillRenderShadows &= cullResults.GetShadowCasterBounds(lightIndex, out bounds); // When creating a new light, at the first frame, there is no AdditionalShadowData so we can't really render shadows m_WillRenderShadows &= m_ShadowData != null && m_ShadowData.shadowDimmer > 0; // If the shadow is too far away, we don't render it if (m_ShadowData != null) { m_WillRenderShadows &= m_Light.type == LightType.Directional || cameraDistance < (m_ShadowData.shadowFadeDistance); } if (!m_WillRenderShadows) { return; } // Create shadow requests array using the light type if (shadowRequests == null || m_ShadowRequestIndices == null) { const int maxLightShadowRequestsCount = 6; shadowRequests = new HDShadowRequest[maxLightShadowRequestsCount]; m_ShadowRequestIndices = new int[maxLightShadowRequestsCount]; for (int i = 0; i < maxLightShadowRequestsCount; i++) { shadowRequests[i] = new HDShadowRequest(); } } Vector2 viewportSize = new Vector2(m_ShadowData.shadowResolution, m_ShadowData.shadowResolution); // Compute dynamic shadow resolution if (initParameters.useDynamicViewportRescale && m_Light.type != LightType.Directional) { // resize viewport size by the normalized size of the light on screen // When we will have access to the non screen clamped bounding sphere light size, we could use it to scale the shadow map resolution // For the moment, this will be enough viewportSize *= Mathf.Lerp(64f / viewportSize.x, 1f, m_Light.range / (camera.transform.position - transform.position).magnitude); viewportSize = Vector2.Max(new Vector2(64f, 64f) / viewportSize, viewportSize); // Prevent flickering caused by the floating size of the viewport viewportSize.x = Mathf.Round(viewportSize.x); viewportSize.y = Mathf.Round(viewportSize.y); } viewportSize = Vector2.Max(viewportSize, new Vector2(16, 16)); // Update the directional shadow atlas size if (m_Light.type == LightType.Directional) { shadowManager.UpdateDirectionalShadowResolution((int)viewportSize.x, m_ShadowSettings.cascadeShadowSplitCount); } // Reserver wanted resolution in the shadow atlas bool allowResize = m_Light.type != LightType.Directional; int count = GetShadowRequestCount(); for (int index = 0; index < count; index++) { m_ShadowRequestIndices[index] = shadowManager.ReserveShadowResolutions(viewportSize, allowResize); } }
public void DrawMainDirShadow(int lightIndex) { var light = cullingResults.visibleLights[lightIndex].light; if (light.shadows == LightShadows.None) { return; } if (!cullingResults.GetShadowCasterBounds(lightIndex, out _)) { Debug.Log("return"); return; } buffer.SetGlobalTexture(ShaderPropIDs.MainShadowAtlas, mainShadowAtlas); buffer.SetRenderTarget(mainShadowAtlas, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); buffer.ClearRenderTarget(true, false, Color.clear); context.ExecuteCommandBuffer(buffer); buffer.Clear(); Vector3 splitRatio = new Vector3(settings.mainLightsShadowSetting.SplitRatio1, settings.mainLightsShadowSetting.SplitRatio2, settings.mainLightsShadowSetting.SplitRatio3); int split; switch (settings.mainLightsShadowSetting.Cascades) { case CascadeMap.TwoCascades: { split = 2; //splitRatio.y = 1.0f; break; } case CascadeMap.FourCascades: { split = 2; break; } default: { split = 1; splitRatio.x = 1.0f; break; } } int cascadedCount = (int)settings.mainLightsShadowSetting.Cascades; int tileSize = Mathf.FloorToInt((int)settings.mainLightsShadowSetting.Resolution / split); for (int i = 0; i < cascadedCount; i++) { if (!cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, i, 4, splitRatio, (int)settings.mainLightsShadowSetting.Resolution, light.shadowNearPlane, out var viewMatrix, out var projMatrix, out var shadowSplitData)) { Debug.Log("CascadeShadowCullingError"); } buffer.SetViewProjectionMatrices(viewMatrix, projMatrix); ShadowDrawingSettings shadowDrawingSettings = new ShadowDrawingSettings(cullingResults, lightIndex) { splitData = shadowSplitData }; var rect = GetTileViewport(i, split, tileSize, out var offset); buffer.SetViewport(rect); buffer.SetGlobalDepthBias(1f, settings.SlopeBias); context.ExecuteCommandBuffer(buffer); context.DrawShadows(ref shadowDrawingSettings); buffer.Clear(); var cullingSphere = shadowSplitData.cullingSphere; cullingSphere.w = Mathf.Pow(cullingSphere.w, 2); cascadeCullingSphere[i] = cullingSphere; MainShadowVPMatrixArray[i] = ConvertToAtlasMatrix(projMatrix * viewMatrix, offset, split); } buffer.SetGlobalInt(ShaderPropIDs.CascadeCount, cascadedCount); float f = 1f - settings.mainLightsShadowSetting.CascdeFading; buffer.SetGlobalVector(ShaderPropIDs.CascadeDistanceFade, new Vector4(1f / settings.mainLightsShadowSetting.MaxDistance, 1f / settings.mainLightsShadowSetting.CascdeFading, 1f / (1f - f * f))); buffer.SetGlobalVectorArray(ShaderPropIDs.CascadeCullingSphereArray, cascadeCullingSphere); buffer.SetGlobalMatrixArray(ShaderPropIDs.MainShadowVPMatrixArray, MainShadowVPMatrixArray); buffer.SetGlobalFloat(ShaderPropIDs.NormalBias, settings.NormalBias); context.ExecuteCommandBuffer(buffer); buffer.Clear(); }
void ConfigureLights() { shadowTileCount = 0; for (int i = 0; i < _cullingResults.visibleLights.Length; i++) { if (i == maxVisibleLights) { break; } VisibleLight light = _cullingResults.visibleLights[i]; visibleLightColors[i] = light.finalColor; Vector4 attenuation = Vector4.zero; attenuation.w = 1f; Vector4 shadow = Vector4.zero; if (light.lightType == LightType.Directional) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightDirectionsOrPositions[i] = v; } else { visibleLightDirectionsOrPositions[i] = light.localToWorldMatrix.GetColumn(3); attenuation.x = 1f / Mathf.Max(light.range * light.range, 0.00001f); if (light.lightType == LightType.Spot) { Vector4 v = light.localToWorldMatrix.GetColumn(2); v.x = -v.x; v.y = -v.y; v.z = -v.z; visibleLightSpotDirections[i] = v; float outerRad = Mathf.Deg2Rad * 0.5f * light.spotAngle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan)); float angleRange = Mathf.Max(innerCos - outerCos, 0.001f); attenuation.z = 1f / angleRange; attenuation.w = -outerCos * attenuation.z; Light shadowLight = light.light; Bounds shadowBounds; if (shadowLight.shadows != LightShadows.None && _cullingResults.GetShadowCasterBounds(i, out shadowBounds)) { shadowTileCount += 1; shadow.x = shadowLight.shadowStrength; shadow.y = shadowLight.shadows == LightShadows.Soft ? 1f : 0f; } } } visibleLightAttenuations[i] = attenuation; shadowData[i] = shadow; } if (_cullingResults.visibleLights.Length > maxVisibleLights) { var lightIndices = _cullingResults.GetLightIndexMap(Allocator.Temp); for (int i = maxVisibleLights; i < _cullingResults.visibleLights.Length; i++) { lightIndices[i] = -1; } _cullingResults.SetLightIndexMap(lightIndices); } }
/// <summary> /// 渲染阴影 /// </summary> /// <param name="_context"></param> private void renderShadows() { int split; if (m_shadowTileCount <= 1) { split = 1; } else if (m_shadowTileCount <= 4) { split = 2; } else if (m_shadowTileCount <= 9) { split = 3; } else { split = 4; } Matrix4x4 viewMatrix, projectionMatrix; ShadowSplitData splitData; float tileSize = m_rpp.shadowMapSize / split; float tileScale = 1.0f / split; m_shadowMap = setShadowRenderTarget(); m_shadowBuffer.BeginSample("Render Shadows"); m_shadowBuffer.SetGlobalVector(m_globalShadowDataId, new Vector4(tileScale, m_rpp.shadowDistance * m_rpp.shadowDistance)); executeBuffer(m_shadowBuffer); m_shadowBuffer.ClearRenderTarget(true, true, Color.clear, 1); executeBuffer(m_shadowBuffer); Matrix4x4[] worldToShadowMatrices = new Matrix4x4[m_cullingResults.visibleLights.Length]; int tileIndex = 0; bool hardShadows = false; bool softShadows = false; //主灯光跳过构建 for (int i = m_mainLightExits ? 1 : 0; i < m_cullingResults.visibleLights.Length; i++) { if (i == m_maxVisibleLights) { break; } if (m_shadowData[i].x <= 0f) { continue; } bool bScb = m_cullingResults.GetShadowCasterBounds(i, out Bounds outBounds); bool bHaveShadow; //通过阴影数据判断是方向光还是聚光灯 if (m_shadowData[i].z > 0.0f) { bHaveShadow = m_cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(i, 0, 1, Vector3.right, (int)tileSize, m_cullingResults.visibleLights[i].light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData); } else { bHaveShadow = m_cullingResults.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData); } if (!(bHaveShadow && bScb)) { m_shadowData[i].x = 0.0f; continue; } Vector2 tileOffset = configureShadowTile(tileIndex, split, tileSize); m_shadowData[i].z = tileOffset.x * tileScale; m_shadowData[i].w = tileOffset.y * tileScale; m_shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); m_shadowBuffer.SetGlobalFloat(m_shadowBiasId, m_cullingResults.visibleLights[i].light.shadowBias); executeBuffer(m_shadowBuffer); //绘制阴影贴图 var shadowSetting = new ShadowDrawingSettings(m_cullingResults, i); shadowSetting.splitData = splitData; m_context.DrawShadows(ref shadowSetting); //检查Z轴是否反向 //将深度从-1 - 1 映射到 0 - 1 calculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]); tileIndex += 1; if (m_shadowData[i].y <= 0.0f) { hardShadows = true; } else { softShadows = true; } } //关闭裁剪 m_shadowBuffer.DisableScissorRect(); m_shadowBuffer.SetGlobalTexture(m_shadowMapId, m_shadowMap); m_shadowBuffer.SetGlobalVectorArray(m_shadowDataId, m_shadowData); m_shadowBuffer.SetGlobalMatrixArray(m_worldToShadowMatricesId, worldToShadowMatrices); float invShadowMapSize = 1.0f / m_rpp.shadowMapSize; m_shadowBuffer.SetGlobalVector(m_shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize, m_rpp.shadowMapSize, m_rpp.shadowMapSize)); CoreUtils.SetKeyword(m_shadowBuffer, m_shadowsHardKeyWord, hardShadows); CoreUtils.SetKeyword(m_shadowBuffer, m_shadowsSoftKeyWord, softShadows); m_shadowBuffer.EndSample("Render Shadows"); executeBuffer(m_shadowBuffer); }
// シャドウマップのセットアップ private void SetupShadowMap(ScriptableRenderContext context, Camera camera, CommandBuffer cb) { // コマンドバッファ利用の準備 cb.Clear(); // // <comment> // ライト情報を取得しています // 今回は最初に見つかった平行光源をシャドウライトとして利用します // int lightIndex = -1; for (int h = 0; h < cullResults.visibleLights.Length; ++h) { // 今回のライトを取得 VisibleLight currLight = cullResults.visibleLights[h]; Light light = currLight.light; if (light == null) { continue; } // シャドウを落とす? if (light.shadows == LightShadows.None) { continue; } if (light.shadowStrength <= 0.0f) { continue; } // 今回は平行光源のみ if (light.type != LightType.Directional) { continue; } // バウンド判定 Bounds bounds; if (!cullResults.GetShadowCasterBounds(h, out bounds)) { continue; } // 使用ライトの決定 lightIndex = h; break; } // もしシャドウが無さそうな時はダミーテクスチャを設定して終わり if (lightIndex < 0) { cb.SetGlobalTexture("_ShadowMap", Texture2D.whiteTexture); context.ExecuteCommandBuffer(cb); return; } // 各種パラメータの算出と設定 ShadowSplitData shadowSplitData; { // パラメータ算出 Matrix4x4 viewMatrix; Matrix4x4 projMatrix; cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( lightIndex, // int activeLightIndex, 0, // int splitIndex, 1, // int splitCount, new Vector3(1.0f, 0.0f, 0.0f), // Vector3 splitRatio, 1024, // int shadowResolution, QualitySettings.shadowNearPlaneOffset, // float shadowNearPlaneOffset, out viewMatrix, // out Matrix4x4 viewMatrix, out projMatrix, // out Matrix4x4 projMatrix, out shadowSplitData // out Experimental.Rendering.ShadowSplitData shadowSplitData ); // マトリクスを作ってグローバル化 Matrix4x4 matView = viewMatrix; Matrix4x4 matProj = projMatrix; Matrix4x4 matProj_shader = GL.GetGPUProjectionMatrix(matProj, true); Matrix4x4 matVP = matProj_shader * matView; cb.SetGlobalMatrix("_ShadowLightView", matView); cb.SetGlobalMatrix("_ShadowLightProj", matProj_shader); cb.SetGlobalMatrix("_ShadowLightVP", matVP); // シャドウマップのグローバル化 cb.SetGlobalTexture("_ShadowMap", RTI[(int)RenderTextureKind.ShadowMap]); } // RenderTarget設定(R8フォーマットのシャドウマップ)してクリア処理 cb.SetRenderTarget(RTI[(int)RenderTextureKind.ShadowMap]); cb.ClearRenderTarget(true, true, Color.white, 1.0f); context.ExecuteCommandBuffer(cb); // 描画 var settings = new ShadowDrawingSettings(cullResults, lightIndex); settings.splitData = shadowSplitData; context.DrawShadows(ref settings); }