public void RemoveLight(SSLightBase light) { if (!lights.Contains(light)) { throw new Exception("Light not found."); } lights.Remove(light); if (renderConfig.mainShader != null) { renderConfig.mainShader.Activate(); } if (renderConfig.instanceShader != null) { renderConfig.instanceShader.Activate(); } }
public void AddLight(SSLightBase light) { if (lights.Contains(light)) { return; } lights.Add(light); if (renderConfig.mainShader != null) { renderConfig.mainShader.SetupShadowMap(lights); } if (renderConfig.instanceShader != null) { renderConfig.instanceShader.SetupShadowMap(lights); } }
public void RemoveLight(SSLightBase light) { if (!lights.Contains(light)) { throw new Exception ("Light not found."); } lights.Remove(light); if (renderConfig.mainShader != null) { renderConfig.mainShader.Activate(); } if (renderConfig.instanceShader != null) { renderConfig.instanceShader.Activate(); } }
private void ComputeProjections(List <SSObject> objects, SSLightBase light, Matrix4 cameraView, Matrix4 cameraProj) { if (light.GetType() != typeof(SSDirectionalLight)) { throw new NotSupportedException(); } SSDirectionalLight dirLight = (SSDirectionalLight)light; // light-aligned unit vectors Vector3 lightZ = dirLight.Direction.Normalized(); Vector3 lightX, lightY; OpenTKHelper.TwoPerpAxes(lightZ, out lightX, out lightY); // transform matrix from regular space into light aligned space Matrix4 lightTransform = new Matrix4( lightX.X, lightX.Y, lightX.Z, 0f, lightY.X, lightY.Y, lightY.Z, 0f, lightZ.X, lightZ.Y, lightZ.Z, 0f, 0f, 0f, 0f, 0f ); // Find AABB of frustum corners in light coordinates Matrix4 cameraViewProj = cameraView * cameraProj; SSAABB frustumLightBB = SSAABB.FromFrustum(ref lightTransform, ref cameraViewProj); bool shrink = false; SSAABB objsLightBB = new SSAABB(float.PositiveInfinity, float.NegativeInfinity); #if true // (optional) scene dependent optimization // Trim the light-bounding box by the shadow receivers (only in light-space x,y,maxz) SSFrustumCuller cameraFrustum = new SSFrustumCuller(ref cameraViewProj); foreach (var obj in objects) { // pass through all shadow casters and receivers if (obj.renderState.toBeDeleted || !obj.renderState.visible || !obj.renderState.receivesShadows || obj.localBoundingSphereRadius <= 0f) { continue; } else if (cameraFrustum.isSphereInsideFrustum(obj.worldBoundingSphere)) { // determine AABB in light coordinates of the objects so far shrink = true; Vector3 lightAlignedPos = Vector3.Transform(obj.worldBoundingSphereCenter, lightTransform); Vector3 rad = new Vector3(obj.worldBoundingSphereRadius); Vector3 localMin = lightAlignedPos - rad; Vector3 localMax = lightAlignedPos + rad; objsLightBB.UpdateMin(localMin); objsLightBB.UpdateMax(localMax); } } #endif // Optimize the light-frustum-projection bounding box by the object-bounding-box SSAABB resultLightBB = new SSAABB(float.PositiveInfinity, float.NegativeInfinity); if (shrink) { // shrink the XY & far-Z coordinates.. resultLightBB.Min.Xy = Vector2.ComponentMax(frustumLightBB.Min.Xy, objsLightBB.Min.Xy); resultLightBB.Min.Z = objsLightBB.Min.Z; resultLightBB.Max = Vector3.ComponentMin(frustumLightBB.Max, objsLightBB.Max); } else { resultLightBB = frustumLightBB; } // View and projection matrices, used by the scene later viewProjFromLightAlignedBB(ref resultLightBB, ref lightTransform, ref lightY, out m_shadowViewMatrix, out m_shadowProjMatrix); // Now extend Z of the result AABB to cover shadow-casters closer to the light inside the // original box foreach (var obj in objects) { if (obj.renderState.toBeDeleted || !obj.renderState.visible || !obj.renderState.castsShadow || obj.localBoundingSphereRadius <= 0f) { continue; } Vector3 lightAlignedPos = Vector3.Transform(obj.worldBoundingSphereCenter, lightTransform); Vector3 rad = new Vector3(obj.worldBoundingSphereRadius); Vector3 localMin = lightAlignedPos - rad; if (localMin.Z < resultLightBB.Min.Z) { Vector3 localMax = lightAlignedPos + rad; if (OpenTKHelper.RectsOverlap(resultLightBB.Min.Xy, resultLightBB.Max.Xy, localMin.Xy, localMax.Xy)) { resultLightBB.Min.Z = localMin.Z; } } } // Generate frustum culler from the BB extended towards light to include shadow casters Matrix4 frustumView, frustumProj; viewProjFromLightAlignedBB(ref resultLightBB, ref lightTransform, ref lightY, out frustumView, out frustumProj); Matrix4 frustumMatrix = frustumView * frustumProj; FrustumCuller = new SSFrustumCuller(ref frustumMatrix); }
private void ComputeProjections(List<SSObject> objects, SSLightBase light, Matrix4 cameraView, Matrix4 cameraProj) { if (light.GetType() != typeof(SSDirectionalLight)) { throw new NotSupportedException(); } SSDirectionalLight dirLight = (SSDirectionalLight)light; // light-aligned unit vectors Vector3 lightZ = dirLight.Direction.Normalized(); Vector3 lightX, lightY; OpenTKHelper.TwoPerpAxes(lightZ, out lightX, out lightY); // transform matrix from regular space into light aligned space Matrix4 lightTransform = new Matrix4 ( lightX.X, lightX.Y, lightX.Z, 0f, lightY.X, lightY.Y, lightY.Z, 0f, lightZ.X, lightZ.Y, lightZ.Z, 0f, 0f, 0f, 0f, 0f ); // Find AABB of frustum corners in light coordinates Matrix4 cameraViewProj = cameraView * cameraProj; SSAABB frustumLightBB = SSAABB.FromFrustum(ref lightTransform, ref cameraViewProj); bool shrink = false; SSAABB objsLightBB = new SSAABB (float.PositiveInfinity, float.NegativeInfinity); #if true // (optional) scene dependent optimization // Trim the light-bounding box by the shadow receivers (only in light-space x,y,maxz) FrustumCuller cameraFrustum = new FrustumCuller (ref cameraViewProj); foreach (var obj in objects) { // pass through all shadow casters and receivers if (obj.renderState.toBeDeleted || obj.localBoundingSphereRadius <= 0f || !obj.renderState.visible || !obj.renderState.receivesShadows) { continue; } else if (cameraFrustum.isSphereInsideFrustum(obj.worldBoundingSphere)) { // determine AABB in light coordinates of the objects so far shrink = true; Vector3 lightAlignedPos = Vector3.Transform(obj.worldBoundingSphereCenter, lightTransform); Vector3 rad = new Vector3(obj.worldBoundingSphereRadius); Vector3 localMin = lightAlignedPos - rad; Vector3 localMax = lightAlignedPos + rad; objsLightBB.UpdateMin(localMin); objsLightBB.UpdateMax(localMax); } } #endif // Optimize the light-frustum-projection bounding box by the object-bounding-box SSAABB resultLightBB = new SSAABB(float.PositiveInfinity, float.NegativeInfinity); if (shrink) { // shrink the XY & far-Z coordinates.. resultLightBB.Min.Xy = Vector2.ComponentMax(frustumLightBB.Min.Xy, objsLightBB.Min.Xy); resultLightBB.Min.Z = objsLightBB.Min.Z; resultLightBB.Max = Vector3.ComponentMin(frustumLightBB.Max, objsLightBB.Max); } else { resultLightBB = frustumLightBB; } // View and projection matrices, used by the scene later viewProjFromLightAlignedBB(ref resultLightBB, ref lightTransform, ref lightY, out m_shadowViewMatrix, out m_shadowProjMatrix); // Now extend Z of the result AABB to cover shadow-casters closer to the light inside the // original box foreach (var obj in objects) { if (obj.renderState.toBeDeleted || obj.localBoundingSphereRadius <= 0f || !obj.renderState.visible || !obj.renderState.castsShadow) { continue; } Vector3 lightAlignedPos = Vector3.Transform(obj.worldBoundingSphereCenter, lightTransform); Vector3 rad = new Vector3(obj.worldBoundingSphereRadius); Vector3 localMin = lightAlignedPos - rad; if (localMin.Z < resultLightBB.Min.Z) { Vector3 localMax = lightAlignedPos + rad; if (OpenTKHelper.RectsOverlap(resultLightBB.Min.Xy, resultLightBB.Max.Xy, localMin.Xy, localMax.Xy)) { resultLightBB.Min.Z = localMin.Z; } } } // Generate frustum culler from the BB extended towards light to include shadow casters Matrix4 frustumView, frustumProj; viewProjFromLightAlignedBB(ref resultLightBB, ref lightTransform, ref lightY, out frustumView, out frustumProj); Matrix4 frustumMatrix = frustumView * frustumProj; FrustumCuller = new FrustumCuller (ref frustumMatrix); }