/** * @brief update then given LightShadow (create it if the given on is null) * according to the given Light, ShadingBody and Edge */ static public LightShadow UpdateShadow( LightShadow _toBeUpdate, Light _light, ShadingBody _body, int _edgeIndex) { if (_edgeIndex > _body.GetVerticesNumber()) { return(null); } Vector2 startPoint = _body.GetVertexInWorld(_edgeIndex); Vector2 endPoint = _body.GetVertexInWorld((_edgeIndex + 1) % _body.GetVerticesNumber()); Vector2 startTill = startPoint + _light.GetLightDirection(startPoint) * ShadowDistance; Vector2 endTill = endPoint + _light.GetLightDirection(endPoint) * ShadowDistance; // update _toBeUpdate LightShadow shadow = _toBeUpdate; if (shadow == null) { shadow = new LightShadow(); } shadow.m_vertexList[0] = startPoint; shadow.m_vertexList[1] = startTill; shadow.m_vertexList[2] = endTill; shadow.m_vertexList[3] = endPoint; // TODO: not here shadow.UpdateDrawVertex(); return(shadow); }
/** * @brief if the edge should cast shadow */ virtual public bool ShouldEdgeHasShadow(ShadingBody _shadingBody, int _edge) { Vector2 startPoint = _shadingBody.GetVertexInWorld(_edge); Vector2 edgeVector2 = _shadingBody.GetVertexInWorld((_edge + 1) % _shadingBody.GetVerticesNumber()) - startPoint; Vector3 edgeVector3 = new Vector3(edgeVector2.X, edgeVector2.Y, 0.0f); Vector3 normal = Vector3.Cross(edgeVector3, -Vector3.UnitZ); Vector2 lightDirection = GetLightDirection(startPoint); Vector2 normal2D = new Vector2(normal.X, normal.Y); return(Vector2.Dot(normal2D, lightDirection) < 0.0f); }
/** * @brief render lightmap into m_accumulateLight */ public override void DoRender(int _timeLastFrame) { // Prepare accumulate GraphicsDevice graphicsDevice = Mgr <GraphicsDevice> .Singleton; Renderer.SetColorTarget(m_accumulateLight); RenderAmbientColor(graphicsDevice); Renderer.CancelColorTarget(); // for each light foreach (KeyValuePair <int, Light> keyValue in m_lightDict) { // TODO: test if the light affects current scene // init light map Renderer.SetColorTarget(m_lightMap); graphicsDevice.Clear(Color.Black); // draw light // TODO: draw light keyValue.Value.Draw(_timeLastFrame); // substract shadow if (m_light2ShadingBodyDict.ContainsKey(keyValue.Key)) { foreach (int shadingBodyID in m_light2ShadingBodyDict[keyValue.Key]) { ShadingBody shadingBody = m_shadingBodyDict[shadingBodyID]; for (int i = 0; i < shadingBody.GetVerticesNumber(); ++i) { int lightShadingBodyEdgeID = GetLightShadowBodyEdgeID(keyValue.Key, shadingBodyID, i); if (m_lightShadowEdgeDict.ContainsKey(lightShadingBodyEdgeID)) { m_lightShadowEdgeDict[lightShadingBodyEdgeID].Draw(_timeLastFrame); } } } } Renderer.CancelColorTarget(); // add to accumulate Renderer.SetColorTarget(m_preAccumulateLight); m_accumulateEffect.CurrentTechnique = m_accumulateEffect.Techniques["Main"]; m_accumulateEffect.Parameters["PreColor"].SetValue((Texture2D)m_accumulateLight); m_accumulateEffect.Parameters["LightMap"].SetValue((Texture2D)m_lightMap); m_accumulateEffect.CurrentTechnique.Passes["P0"].Apply(); RenderQuad(); Renderer.CancelColorTarget(); RenderTarget2D temp = m_preAccumulateLight; m_preAccumulateLight = m_accumulateLight; m_accumulateLight = temp; } }
/** * @brief update lightShadow because the given shadingbody has moved * the algorithm check all the lights then update: * 1. m_shadingBody2LightDict * 2. m_light2ShadingBodyDict * 3. m_lightShadwEdgeDict * and it also create and remove LightShadow */ public void UpdateShadowBody(ShadingBody _shadowBody) { HashSet <int> oldLight; if (m_shadingBody2LightDict.ContainsKey(_shadowBody.ID)) { oldLight = m_shadingBody2LightDict[_shadowBody.ID]; } else { oldLight = new HashSet <int>(); } foreach (KeyValuePair <int, Light> keyValue in m_lightDict) { // if body in light if (keyValue.Value.IsBodyInLightRange(_shadowBody.GetVertices(), _shadowBody.GetTransform2World())) { // update shadow int edgeNumber = _shadowBody.GetVerticesNumber(); for (int e = 0; e < edgeNumber; ++e) { int lightShadowBodyEdgeID = GetLightShadowBodyEdgeID(keyValue.Key, _shadowBody.ID, e); // if edge under light if (keyValue.Value.ShouldEdgeHasShadow(_shadowBody, e)) { m_lightShadowEdgeDict[lightShadowBodyEdgeID] = LightShadow.UpdateShadow(m_lightShadowEdgeDict[lightShadowBodyEdgeID], keyValue.Value, _shadowBody, e); m_lightShadowEdgeDict[lightShadowBodyEdgeID].Enable = true; } // else else { // TODO: not only disable, but also remove it m_lightShadowEdgeDict[lightShadowBodyEdgeID].Enable = false; } } // update light 2 shadow and shadow 2 light if (!m_light2ShadingBodyDict.ContainsKey(keyValue.Key)) { m_light2ShadingBodyDict[keyValue.Key] = new HashSet <int>(); } m_light2ShadingBodyDict[keyValue.Key].Add(_shadowBody.ID); if (!m_shadingBody2LightDict.ContainsKey(_shadowBody.ID)) { m_shadingBody2LightDict[_shadowBody.ID] = new HashSet <int>(); } m_shadingBody2LightDict[_shadowBody.ID].Add(keyValue.Key); } // else else { // if light in old-light if (oldLight.Contains(keyValue.Key)) { // remove shadow int edgeNumber = _shadowBody.GetVerticesNumber(); for (int e = 0; e < edgeNumber; ++e) { int lightShadowBodyEdgeID = GetLightShadowBodyEdgeID(keyValue.Key, _shadowBody.ID, e); if (m_lightShadowEdgeDict.ContainsKey(lightShadowBodyEdgeID)) { // TODO: not only disable m_lightShadowEdgeDict[lightShadowBodyEdgeID].Enable = false; } } // update light2 2 shadow and shadow 2 light oldLight.Remove(keyValue.Key); if (m_light2ShadingBodyDict.ContainsKey(keyValue.Key)) { m_light2ShadingBodyDict[keyValue.Key].Remove(_shadowBody.ID); } } } } }
public void RemoveShadingBody(ShadingBody _shadingBody) { int shadingBoydID = _shadingBody.ID; if (m_shadingBodyDict.ContainsKey(shadingBoydID)) { m_shadingBodyDict.Remove(shadingBoydID); } if (m_shadingBody2LightDict.ContainsKey(shadingBoydID)) { HashSet <int> lights = m_shadingBody2LightDict[shadingBoydID]; foreach (int lightID in lights) { // remove from light2ShadingBody // TODO: compromise if (m_light2ShadingBodyDict.ContainsKey(lightID)) { m_light2ShadingBodyDict[lightID].Remove(shadingBoydID); } // remove lightShadow int lightShadingBodyEdgeID = GetLightShadowBodyEdgeID(lightID, shadingBoydID, _shadingBody.GetVerticesNumber()); if (m_lightShadowEdgeDict.ContainsKey(lightShadingBodyEdgeID)) { m_lightShadowEdgeDict.Remove(lightShadingBodyEdgeID); } } m_shadingBody2LightDict.Remove(shadingBoydID); } ReturnID(shadingBoydID, m_freeShadowBodyIDList); return; }
public void RemoveLight(Light _light) { int lightID = _light.ID; if (m_lightDict.ContainsKey(lightID)) { m_lightDict.Remove(lightID); } if (m_light2ShadingBodyDict.ContainsKey(lightID)) { HashSet <int> shadingBodies = m_light2ShadingBodyDict[lightID]; foreach (int shadingBodyID in shadingBodies) { // remove from shadingBody2Light m_shadingBody2LightDict[shadingBodyID].Remove(lightID); // remove lightShadow ShadingBody shadingBody = m_shadingBodyDict[shadingBodyID]; int lightShadingBodyEdgeID = GetLightShadowBodyEdgeID(lightID, shadingBodyID, shadingBody.GetVerticesNumber()); if (m_lightShadowEdgeDict.ContainsKey(lightShadingBodyEdgeID)) { m_lightShadowEdgeDict.Remove(lightShadingBodyEdgeID); } } m_light2ShadingBodyDict.Remove(lightID); } ReturnID(lightID, m_freeLightIDList); return; }