unsafe ConstantsBufferId GetShadowConstants(ICascadeShadowMap csm, ref MyShadowsSettings settings) { const int MAX_SLICES_COUNT = 8; MyRenderProxy.Assert(csm.SlicesCount <= MAX_SLICES_COUNT, "It is not supported more than 8 slices per cascade shadow map"); int size = sizeof(Matrix)*MAX_SLICES_COUNT + sizeof(Vector4)*MAX_SLICES_COUNT; ConstantsBufferId cb = MyCommon.GetObjectCB(size); var mapping = MyMapping.MapDiscard(cb); for (int i = 0; i < csm.SlicesCount; i++) { // Set matrices: Matrix matrix = csm.GetSlice(i).MatrixWorldAt0ToShadowSpace; matrix = matrix*Matrix.CreateTranslation(1, -1, 0); Vector2 scalingFactor = new Vector2(0.5f, -0.5f); matrix = matrix * Matrix.CreateScale(scalingFactor.X, scalingFactor.Y, 1); matrix = Matrix.Transpose(matrix); mapping.WriteAndPosition(ref matrix); // Set normal offsets: mapping.WriteAndPosition(ref settings.Cascades[i].ShadowNormalOffset); float zero = 0; for (int j = 1; j < 4; j++) mapping.WriteAndPosition(ref zero); } mapping.Unmap(); return cb; }
public void CopyFrom(MyShadowsSettings settings) { //ShadowCascadeSmallSkipThresholds = settings.ShadowCascadeSmallSkipThresholds; //ShadowCascadeFrozen = settings.ShadowCascadeFrozen; Data = settings.Data; NewData = settings.NewData; Cascades = settings.Cascades; }
public void Draw(IRtvTexture outTex, IDepthStencil stencil, ICascadeShadowMap csm, ref MyShadowsSettings settings) { MyRenderContext RC = MyRender11.RC; RC.SetBlendState(null); RC.SetRtv(outTex); RC.PixelShader.Set(m_ps); RC.PixelShader.SetSrv(0, stencil.SrvDepth); RC.PixelShader.SetSrv(1, stencil.SrvStencil); RC.PixelShader.SetSrv(2, csm.DepthArrayTexture); RC.PixelShader.SetSrv(3, MyGBuffer.Main.GBuffer1); RC.PixelShader.SetConstantBuffer(MyCommon.FRAME_SLOT, MyCommon.FrameConstants); RC.PixelShader.SetConstantBuffer(1, GetShadowConstants(csm, ref settings)); RC.PixelShader.SetSampler(6, MySamplerStateManager.Shadowmap); MyScreenPass.DrawFullscreenQuad(); RC.ResetTargets(); }
public void Update(ref MyShadowsSettings settings) { CsmPlacementStrategy.Update(m_volumes, ref settings, DepthArrayTexture.Size.X); }
public void ApplyPostprocess(MyPostprocessShadows.Type type, IRtvTexture outTex, IDepthStencil stencil, ICascadeShadowMap csm, ref MyShadowsSettings settings) { MyPostprocessShadows postprocess = null; switch (type) { case MyPostprocessShadows.Type.HARD: postprocess = m_postprocessHardShadows; break; case MyPostprocessShadows.Type.SIMPLE: postprocess = m_postprocessSimpleShadows; break; default: MyRenderProxy.Assert(false); break; } postprocess.Draw(outTex, stencil, csm, ref settings); }
public MyEnvironmentDefinition() { ShadowSettings = new MyShadowsSettings(); }
public void SetSettings(MyShadowsSettings settings) { m_settings = settings; ShadowCore.Settings = settings; }
public static void UpdateShadowsSettings(MyShadowsSettings settings) { var message = MessagePool.Get<MyRenderMessageUpdateShadowSettings>(MyRenderMessageEnum.UpdateShadowSettings); message.Settings.CopyFrom(settings); EnqueueMessage(message); }
public MyVisualSettingsDefinition() { ShadowSettings = new MyShadowsSettings(); }
public unsafe void Update(MyShadowVolume[] volumes, ref MyShadowsSettings settings, float shadowmapResolution) { bool stabilize = true; float cascadesNearClip = 1f; float shadowChangeDelayMultiplier = 180; const float directionDifferenceThreshold = 0.0175f; float backOffset = MyRender11.RenderSettings.ShadowQuality.BackOffset(); float shadowmapSize = MyRender11.RenderSettings.ShadowQuality.ShadowCascadeResolution(); Array.Resize(ref m_shadowCascadeSplitDepths, volumes.Length + 1); Array.Resize(ref m_shadowCascadeUpdatePositions, volumes.Length); Array.Resize(ref m_shadowCascadeFramesSinceLightUpdate, volumes.Length); Array.Resize(ref m_shadowCascadeLightDirections, volumes.Length); for (int cascadeIndex = 0; cascadeIndex < volumes.Length; ++cascadeIndex) m_shadowCascadeSplitDepths[cascadeIndex] = MyRender11.RenderSettings.ShadowQuality.ShadowCascadeSplit(cascadeIndex); double unitWidth = 1.0 / MyRender11.Environment.Matrices.Projection.M11; double unitHeight = 1.0 / MyRender11.Environment.Matrices.Projection.M22; Vector3D* untransformedVertices = stackalloc Vector3D[4]; untransformedVertices[0] = new Vector3D(-unitWidth, -unitHeight, -1); untransformedVertices[1] = new Vector3D(-unitWidth, unitHeight, -1); untransformedVertices[2] = new Vector3D(unitWidth, unitHeight, -1); untransformedVertices[3] = new Vector3D(unitWidth, -unitHeight, -1); MatrixD* cascadesMatrices = stackalloc MatrixD[volumes.Length]; for (int cascadeIndex = 0; cascadeIndex < volumes.Length; ++cascadeIndex) { ++m_shadowCascadeFramesSinceLightUpdate[cascadeIndex]; if (m_shadowCascadeFramesSinceLightUpdate[cascadeIndex] > cascadeIndex * shadowChangeDelayMultiplier || MyRender11.Environment.Data.EnvironmentLight.SunLightDirection.Dot(m_shadowCascadeLightDirections[cascadeIndex]) < (1 - directionDifferenceThreshold)) { m_shadowCascadeLightDirections[cascadeIndex] = MyRender11.Environment.Data.EnvironmentLight.SunLightDirection; m_shadowCascadeFramesSinceLightUpdate[cascadeIndex] = 0; } } for (int cascadeIndex = 0; cascadeIndex < volumes.Length; ++cascadeIndex) { for (int vertexIndex = 0; vertexIndex < 4; ++vertexIndex) { m_frustumVerticesWS[vertexIndex] = untransformedVertices[vertexIndex] * m_shadowCascadeSplitDepths[cascadeIndex]; m_frustumVerticesWS[vertexIndex + 4] = untransformedVertices[vertexIndex] * m_shadowCascadeSplitDepths[cascadeIndex + 1]; } bool skipCascade = MyCommon.FrameCounter % (ulong)m_shadowCascadeUpdateIntervals[cascadeIndex].Item1 != (ulong)m_shadowCascadeUpdateIntervals[cascadeIndex].Item2; bool forceUpdate = m_shadowCascadeSplitDepths[cascadeIndex] > 1000f && Vector3D.DistanceSquared(m_shadowCascadeUpdatePositions[cascadeIndex], MyRender11.Environment.Matrices.CameraPosition) > Math.Pow(1000, 2); // if (!forceUpdate && skipCascade && !settings.Data.UpdateCascadesEveryFrame) continue; //if (settings.ShadowCascadeFrozen[cascadeIndex]) // continue; m_shadowCascadeUpdatePositions[cascadeIndex] = MyRender11.Environment.Matrices.CameraPosition; MatrixD invView = MyRender11.Environment.Matrices.InvView; Vector3D.Transform(m_frustumVerticesWS, ref invView, m_frustumVerticesWS); var bSphere = BoundingSphereD.CreateFromPoints(m_frustumVerticesWS); if (stabilize) { bSphere.Center = bSphere.Center.Round(); bSphere.Radius = Math.Ceiling(bSphere.Radius); } var shadowCameraPosWS = bSphere.Center + m_shadowCascadeLightDirections[cascadeIndex] * (bSphere.Radius + cascadesNearClip); var lightView = VRageMath.MatrixD.CreateLookAt(shadowCameraPosWS, shadowCameraPosWS - m_shadowCascadeLightDirections[cascadeIndex], Math.Abs(Vector3.UnitY.Dot(m_shadowCascadeLightDirections[cascadeIndex])) < 0.99f ? Vector3.UnitY : Vector3.UnitX); var offset = bSphere.Radius + cascadesNearClip + backOffset; Vector3D vMin = new Vector3D(-bSphere.Radius, -bSphere.Radius, cascadesNearClip); Vector3D vMax = new Vector3D(bSphere.Radius, bSphere.Radius, offset + bSphere.Radius); var cascadeProjection = MatrixD.CreateOrthographicOffCenter(vMin.X, vMax.X, vMin.Y, vMax.Y, vMax.Z, vMin.Z); cascadesMatrices[cascadeIndex] = lightView * cascadeProjection; var transformed = Vector3D.Transform(Vector3D.Zero, cascadesMatrices[cascadeIndex]) * shadowmapSize / 2; var smOffset = (transformed.Round() - transformed) * 2 / shadowmapSize; // stabilize 1st cascade only if (stabilize) { cascadeProjection.M41 += smOffset.X; cascadeProjection.M42 += smOffset.Y; cascadesMatrices[cascadeIndex] = lightView * cascadeProjection; } Matrix matrixTranslation = Matrix.CreateTranslation(MyRender11.Environment.Matrices.CameraPosition); cascadesMatrices[cascadeIndex] = matrixTranslation * cascadesMatrices[cascadeIndex]; volumes[cascadeIndex].SetMatrixWorldAt0ToShadow(cascadesMatrices[cascadeIndex]); } }
public void Update(MyShadowVolume[] volumes, ref MyShadowsSettings settings, float shadowmapResolution) { // Update sun position: if (!settings.NewData.FreezeSunDirection) { Vector3D currentSunLightDir = MyRender11.Environment.Data.EnvironmentLight.SunLightDirection; Vector3D prevSunLightDir = m_sunDirection; currentSunLightDir.Normalize(); prevSunLightDir.Normalize(); double diffAngle = 360.0 / Math.PI * Math.Acos(Vector3D.Dot(prevSunLightDir, currentSunLightDir)); if (diffAngle >= settings.NewData.SunAngleThreshold) m_sunDirection = MyRender11.Environment.Data.EnvironmentLight.SunLightDirection; } double unitWidth = 1.0/MyRender11.Environment.Matrices.Projection.M11; double unitHeight = 1.0/MyRender11.Environment.Matrices.Projection.M22; for (int cascadeIndex = 0; cascadeIndex < volumes.Length; ++cascadeIndex) { // Update primitive vertices that are inside of frustrum matrix: float baseDist = settings.Cascades[cascadeIndex].FullCoverageDepth; float baseCut = (cascadeIndex == 0) ? 0 : settings.Cascades[cascadeIndex - 1].FullCoverageDepth; Vector3D[] verts; float extDepth = settings.Cascades[cascadeIndex].ExtendedCoverageDepth; if (!settings.NewData.StabilizeRotation) verts = MyCsmPlacementStrategyUtil.CreateCutPyramidExt(unitWidth, unitHeight, baseDist, baseCut, extDepth); else { double coneRadius = Math.Sqrt((unitWidth * unitWidth) + (unitHeight * unitHeight)); verts = MyCsmPlacementStrategyUtil.CreateCutConeExt(coneRadius, baseDist, baseCut, extDepth); } double shadowVolumeSize = GetStableShadowVolumeSize(verts, shadowmapResolution); MatrixD invView = MyRender11.Environment.Matrices.InvView; Vector3D.Transform(verts, ref invView, verts); float zOffset = settings.NewData.ZOffset; MatrixD shadowMatrixWorld; if (!settings.NewData.StabilizeMovement) shadowMatrixWorld = CreateRigidLightMatrix(verts, m_sunDirection, zOffset); else shadowMatrixWorld = CreateStableLightMatrix(verts, m_sunDirection, zOffset, shadowVolumeSize, shadowmapResolution); Matrix matrixTranslation = Matrix.CreateTranslation(MyRender11.Environment.Matrices.CameraPosition); Matrix shadowMatrixWorldAt0 = matrixTranslation*shadowMatrixWorld; volumes[cascadeIndex].SetMatrixWorldAt0ToShadow(shadowMatrixWorldAt0); } }