public void Render(Light light) { LightVaos vaos = GetVaosForLight(light); if (!vaos.Enabled) { return; } _engine.Device.RasterizerState = _engine.Rs; _engine.Device.DepthStencilState = DepthStencilState.None; _engine.Device.DepthStencilState = light.ShadowType == ShadowType.Occluded ? _dsOccludedShadow : DepthStencilState.None; if (light.CastsShadows) { _fxShadowParamLightPosition.SetValue(light.Position); _fxShadowParamLightRadius.SetValue(light.Radius); // Draw shadows. DynamicVao shadowVao = vaos.ShadowVao; _engine.Device.BlendState = _bsShadow; _engine.Device.SetVertexArrayObject(shadowVao); _fxShadowTech.Passes[0].Apply(); _engine.Device.DrawIndexedPrimitives(shadowVao.PrimitiveTopology, 0, 0, shadowVao.PrimitiveCount); // Draw shadows borders if debugging. if (_engine.Debug) { _engine.Device.RasterizerState = _engine.RsDebug; _engine.Device.BlendState = BlendState.Opaque; _fxShadowTechDebug.Passes[0].Apply(); _engine.Device.DrawIndexedPrimitives(shadowVao.PrimitiveTopology, 0, 0, shadowVao.PrimitiveCount); } } // Draw hulls. bool isShadowTypeSolid = light.ShadowType == ShadowType.Solid; if (light.CastsShadows || isShadowTypeSolid) { if (light.ShadowType == ShadowType.Occluded) { _engine.Device.DepthStencilState = _dsOccludedHull; } DynamicVao hullVao = vaos.HullVao; _engine.Device.RasterizerState = _engine.Rs; _engine.Device.BlendState = _bsHull; _fxHullParamVp.SetValue(_engine.Camera.ViewProjection); _fxHullParamColor.SetValue(isShadowTypeSolid ? TransparentColor : WhiteColor); _engine.Device.SetVertexArrayObject(hullVao); _fxHullTech.Passes[0].Apply(); _engine.Device.DrawIndexedPrimitives(hullVao.PrimitiveTopology, 0, 0, hullVao.PrimitiveCount); } }
private LightVaos GetVaosForLight(Light light) { if (!_lightsVaos.TryGetValue(light, out LightVaos lightVaos)) { lightVaos = new LightVaos(); _lightsVaos[light] = lightVaos; } if (light.Dirty || _engine.Hulls.Dirty) { BuildVaosForLight(light, lightVaos); } return(lightVaos); }
private void BuildVaosForLight(Light light, LightVaos lightVaos) { _hullVertices.Clear(); _shadowVertices.Clear(); _shadowIndices.Clear(); _hullIndices.Clear(); int numSegments = 0; int shadowIndexOffset = 0; int hullIndexOffset = 0; int hullCount = _engine.Hulls.Count; for (int i = 0; i < hullCount; i++) { Hull hull = _engine.Hulls[i]; if (!hull.Enabled || !hull.Valid || light.IgnoredHulls.Contains(hull) || !light.Intersects(hull)) { continue; } Polygon points = hull.WorldPoints; Vector2 prevPoint = points.Items[points.Count - 1]; int pointCount = points.Count; numSegments += pointCount; for (int j = 0; j < pointCount; j++) { Vector2 currentPoint = points.Items[j]; _shadowVertices.Add(new VertexShadow(prevPoint, currentPoint, new Vector2(0.0f, 0.0f))); _shadowVertices.Add(new VertexShadow(prevPoint, currentPoint, new Vector2(1.0f, 0.0f))); _shadowVertices.Add(new VertexShadow(prevPoint, currentPoint, new Vector2(0.0f, 1.0f))); _shadowVertices.Add(new VertexShadow(prevPoint, currentPoint, new Vector2(1.0f, 1.0f))); _shadowIndices.Add(shadowIndexOffset * 4 + 0); _shadowIndices.Add(shadowIndexOffset * 4 + 1); _shadowIndices.Add(shadowIndexOffset * 4 + 2); _shadowIndices.Add(shadowIndexOffset * 4 + 1); _shadowIndices.Add(shadowIndexOffset * 4 + 3); _shadowIndices.Add(shadowIndexOffset * 4 + 2); prevPoint = currentPoint; shadowIndexOffset++; } _hullVertices.AddRange(hull.WorldPoints); int indexCount = hull.Indices.Count; for (int j = 0; j < indexCount; j++) { _hullIndices.Add(hull.Indices.Items[j] + hullIndexOffset); } hullIndexOffset += pointCount; } lightVaos.Enabled = numSegments > 0; if (!lightVaos.Enabled) { return; } if (lightVaos.ShadowVao == null) { lightVaos.ShadowVao = DynamicVao.New( _engine.Device, VertexShadow.Layout, PrimitiveType.TriangleList, _shadowVertices.Count, _shadowIndices.Count, useIndices: true); lightVaos.HullVao = DynamicVao.New( _engine.Device, VertexPosition2.Layout, PrimitiveType.TriangleList, _hullVertices.Count, _hullIndices.Count, useIndices: true); } lightVaos.ShadowVao.SetVertices(_shadowVertices); lightVaos.ShadowVao.SetIndices(_shadowIndices); lightVaos.HullVao.SetVertices(_hullVertices); lightVaos.HullVao.SetIndices(_hullIndices); }