public Vector3 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, slopeScaleBias = light.shadowBias, nearPlaneOffset = light.shadowNearPlane }; return(new Vector3( light.shadowStrength, settings.directional.cascadeCount * shadowedDirectionalLightCount++, light.shadowNormalBias )); } else { return(Vector3.zero); } }
void RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = shadowedDirectionalLights[index]; var shadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex); var cascadeCount = settings.directional.cascadeCount; int tileOffset = index * cascadeCount; Vector3 ratios = settings.directional.CascadeRatios; float cullingFactor = Mathf.Max(0, 0.8f - settings.directional.cascadeFade); for (int i = 0; i < cascadeCount; i++) { cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData); splitData.shadowCascadeBlendCullingFactor = cullingFactor; shadowSettings.splitData = splitData; if (index == 0) { SetCascadeData(i, splitData.cullingSphere, tileSize); } int tileOffIndex = tileOffset + i; dirShadowMatrices[tileOffIndex] = ConvertToAtlasMatrix(projectionMatrix * viewMatrix, SetTileViewport(tileOffIndex, split, tileSize), split); buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); buffer.SetGlobalDepthBias(0f, light.slopeScaleBias); ExecuteBuffer(); context.DrawShadows(ref shadowSettings); buffer.SetGlobalDepthBias(0f, 0f); } }
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)); }
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 RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = ShadowedDirectionalLights[index]; var shadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex); int cascadeCount = settings.directional.cascadeCount; int tileOffset = index * cascadeCount; for (int i = 0; i < cascadeCount; i++) { cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( light.visibleLightIndex, i, cascadeCount, cascadeRatio, tileSize, 0f, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, out ShadowSplitData shadowSplitData ); shadowSettings.splitData = shadowSplitData; int tileIndex = tileOffset + i; dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix( projMatrix * viewMatrix, SetTileViewport(tileIndex, split, tileSize), split ); buffer.SetViewProjectionMatrices(viewMatrix, projMatrix); ExecuteBuffer(); context.DrawShadows(ref shadowSettings); } }
void RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = ShadowedDirectionalLights[index]; //create a shadowdrawsetting based on the light index var shadowDSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex) { useRenderingLayerMaskTest = true }; //make shadow effcted by rendering layer mask //take into count that each light will render max 4 cascades int cascadeCount = shadowSettings.directional.cascadeCount; int tileOffset = index * cascadeCount; Vector3 ratios = shadowSettings.directional.CascadeRatios; //cal the cascade culling factor, make it 0.8-fade to make sure casters in transition not being culled float cullingfactor = Mathf.Max(0f, 0.8f - shadowSettings.directional.cascadeFade); float tileScale = 1f / split; //get the lightviewMatrix, lightprojectionMatrix, clip space box for the dirctional lights for (int i = 0; i < cascadeCount; i++) { cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData); //make UNITY to cull some shadow caster in large cascade if the smaller cascade is enough splitData.shadowCascadeBlendCullingFactor = cullingfactor; shadowDSettings.splitData = splitData; //assign the cascade culling sphere, all lights uses the same culling spheres and same cascade datas if (index == 0) { SetCascadeData(i, splitData.cullingSphere, tileSize); } int tileIdex = tileOffset + i; //set the render view port and get the offset for modify the dir shadow matrix //set the matrix from wolrd space to shadow Atlas space dirShadowMatrices[tileIdex] = ConvertToAtlasMatrix( projectionMatrix * viewMatrix, SetTileViewport(tileIdex, split, tileSize), tileScale ); //set the ViewProjectionMatrices for the buffer buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); //experimental depth bias //buffer.SetGlobalDepthBias(50000f, 0f); //using slop bias buffer.SetGlobalDepthBias(0f, light.slopScaleBias); ExecuteBuffer(); //draw shadow caster on the buffer context.DrawShadows(ref shadowDSettings); //Debug.Log(shadowDSettings buffer.SetGlobalDepthBias(0f, 0f); } }
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 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; } }
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 }; } }
void RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = ShadowedDirectionalLights[index]; var shadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex); cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( light.visibleLightIndex, 0, 1, Vector3.zero, tileSize, 0f, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData ); shadowSettings.splitData = splitData; SetTileViewport(index, split, tileSize); buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); ExecuteBuffer(); context.DrawShadows(ref shadowSettings); }
public void RenderDirectionalShadows(int index, int splitCount, int size) { ShadowedDirectionalLight light = ShadowedDirectionalLights[index]; var shadowSetting = new ShadowDrawingSettings(_results, light.visibleLightIndex); //https://docs.unity3d.com/2019.1/Documentation/ScriptReference/Rendering.CullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives.html //利用光源的方向(-transform.forward)方向可以求出view matrix,nearclip 和 最远的阴影距离等可以求出project matrix等等 _results.ComputeDirectionalShadowMatricesAndCullingPrimitives(light.visibleLightIndex, 0, 1, Vector3.zero, size, 0, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, out ShadowSplitData shadowSplitData); shadowSetting.splitData = shadowSplitData; SetTileViewport(index, splitCount, size); _commandBuffer.SetViewProjectionMatrices(viewMatrix, projMatrix); ExecuteCommandBuffer(); _context.DrawShadows(ref shadowSetting); }
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); }
/// <summary> /// 处理每一栈平行光的shadowmap /// </summary> /// <param name="index"></param> /// <param name="split"></param> /// <param name="tileSize"></param> void RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = shadowmapLights[index]; //前两个参数为剪裁结果和投影光在有效光中的索引 ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex); int cascadeCount = shadowSetting.directional.CascadeCount; Vector3 ratios = shadowSetting.directional.CascadeRatios; int tileOffset = index * cascadeCount; for (int i = 0; i < cascadeCount; i++) { //其中第二三四参数为级联索引、级联数和级联比率,我们暂时不考虑,直接传入0,1,vector3.zero即可。然后是每个分块的阴影图分辨率,阴影近裁面偏移。之后输出所需的3个参数。 cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData); //Unity通过为每个级联创建一个裁切球来确定覆盖的区域, 裁切球的作用还可以用来确定从哪个级联进行采样 if (index == 0) { Vector4 cullingSphere = splitData.cullingSphere; //一个像素对应的距离大小 float texelSize = 2f * cullingSphere.w / tileSize; float filterSize = texelSize * ((float)shadowSetting.directional.filter + 1f); cullingSphere.w -= filterSize; cullingSphere.w *= cullingSphere.w; cascadeCullingSpheres[i] = cullingSphere; castedNormalBias[i] = filterSize * 1.4142136f; } //获取世界转灯光空间矩阵,用于采样阴影图 int tileIndex = tileOffset + i; Matrix4x4 vp = projectionMatrix * viewMatrix; shadowmapMatrices[tileIndex] = vp.ConvertToAtlasMatrix(tileIndex, split, tileSize, out Rect viewport); //设置当前联级区域的viewport? buffer.SetViewport(viewport); //更改渲染阴影的灯光相机VP矩阵 buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); buffer.SetGlobalDepthBias(0, light.slopeScaleBias); ExecuteBufferAndClear(); //最后一个参数设置为true,为使用shadowlayermask进行过滤 shadowSettings.useRenderingLayerMaskTest = true; //还有一个参数为级联阴影数据。 shadowSettings.splitData = splitData; context.DrawShadows(ref shadowSettings); buffer.SetGlobalDepthBias(0f, 0f); } }
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 RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = _shadowedDirectionalLights[index]; var shadowSettings = new ShadowDrawingSettings(_cullingResults, light.visibleLightIndex); int splitCount = _settings.directional.cascadeCount; Vector3 splitRatios = _settings.directional.CascadeRatios; float cullingFactor = Mathf.Max(0f, 0.8f - _settings.directional.cascadeFade); for (int i = 0; i < splitCount; i++) { _cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( light.visibleLightIndex, splitIndex: i, splitCount, splitRatios, shadowResolution: tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData ); splitData.shadowCascadeBlendCullingFactor = cullingFactor; _settings.SplitData = splitData; if (index == 0) { SetCascadeData(i, splitData.cullingSphere, tileSize); } int tileIndex = index * splitCount + i; var tileOffset = GetTileViewportOffset(tileIndex, split); SetTileViewport(tileOffset, tileSize); _dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix(worldToLight: projectionMatrix * viewMatrix, tileOffset, split); _buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); _buffer.SetGlobalDepthBias(0f, light.slopeScaleBias); ExecuteBuffer(); _context.DrawShadows(ref shadowSettings); _buffer.SetGlobalDepthBias(0f, 0f); } }
void RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = ShadowedDirectionalLights[index]; var shadowSettings = new ShadowDrawingSettings(_cullingResults, light.visibleLightIndex); int cascadeCount = _settings.directional.cascadeCount; int tileOffset = index * cascadeCount; Vector3 ratios = _settings.directional.CascadeRatios; float cullingFactor = Mathf.Max(0f, 0.8f - _settings.directional.cascadeFade); for (int i = 0; i < cascadeCount; i++) { // 阴影贴图的原理是,从灯光的角度渲染场景,只存储深度信息,用结果标记出来,光线在击中某物体之前会传播多远 // 但是定向光没有真实位置,我们要做的是找出与灯光方向匹配的视图/投影矩阵,并为我们提供一个裁剪空间立方体 // 该立方体与包含可见光阴影的摄像机可见区域重合 _cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData); // 避免对每个光源渲染相同的阴影投射器不止一次,如果可以保证从较小的级联中覆盖某些阴影投射器,就可以尝试从较大的级联中剔除掉 // 某些阴影投射器 splitData.shadowCascadeBlendCullingFactor = cullingFactor; shadowSettings.splitData = splitData; if (index == 0) { SetCascadeData(i, splitData.cullingSphere, tileSize); // Vector4 cullingSphere = splitData.cullingSphere; } int tileIndex = tileOffset + i; // SetTileViewport(index, split, tileSize); // dirShadowMatrices[index] = projectionMatrix * viewMatrix; dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix(projectionMatrix * viewMatrix, SetTileViewport(tileIndex, split, tileSize), split); buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); // buffer.SetGlobalDepthBias(500000f, 0f); // buffer.SetGlobalDepthBias(0f, 3f); buffer.SetGlobalDepthBias(0f, light.slopeScaleBias); ExecuteBuffer(); _context.DrawShadows(ref shadowSettings); buffer.SetGlobalDepthBias(0f, 0f); } }
private void RenderDirectionalShadows(int index, int split, int tileSize) { ShadowedDirectionalLight light = shadowedDirectionalLights[index]; ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex) { useRenderingLayerMaskTest = true }; int cascadeCount = this.shadowSettings.directional.cascadeCount; int tileOffset = index * cascadeCount; Vector3 ratios = this.shadowSettings.directional.CascadeRatios; float cullingFactor = Mathf.Max(0f, 0.8f - this.shadowSettings.directional.cascadeFade); float tileScale = 1f / split; for (int i = 0; i < cascadeCount; ++i) { cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData); splitData.shadowCascadeBlendCullingFactor = cullingFactor; shadowSettings.splitData = splitData; int tileIndex = tileOffset + i; if (index == 0) { //Vector4 cullingSphere = splitData.cullingSphere; //cullingSphere.w *= cullingSphere.w; //cascadeCullingSpheres[i] = cullingSphere; SetCascadeData(i, splitData.cullingSphere, tileSize); } //SetTileViewport(index, split, tileSize); //dirShadowMatrices[index] = projectionMatrix * viewMatrix; dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix(projectionMatrix * viewMatrix, SetTileViewport(tileIndex, split, tileSize), tileScale); buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); buffer.SetGlobalDepthBias(0f, light.slopeScaleBias); ExecuteBuffer(); context.DrawShadows(ref shadowSettings); buffer.SetGlobalDepthBias(0f, 0f); } }
void RenderDirectionalShadows(int index, int tileSize) { ShadowedDirectionalLight light = ShadowedDirectionalLights[index]; ///ShadowDrawingSettings built-in var shadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex); ///The idea of a shadow map is that we render the scene from the light's point of view, ///only storing the depth information. ///The result tells us how far the light travels before it hits something. cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( light.visibleLightIndex, 0, 1, Vector3.zero, tileSize, 0f, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix, out ShadowSplitData splitData ); ///The split data contains information about how shadow-casting objects should be culled shadowSettings.splitData = splitData; buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix); ExecuteBuffer(); context.DrawShadows(ref shadowSettings); }
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)); } }