/// <summary> /// <see cref="PrepareForDraw"/> prepares and updates the Material, ShapeBuilder and VertexBuilder if necessary /// </summary> public void PrepareForDraw(out bool vertexBufferHasChanged, out int vertexSize, out int vertexCount) { var fieldsList = new ParticlePoolFieldsList(pool); // User changes to materials might cause vertex layout change Material.PrepareVertexLayout(fieldsList); // User changes to shape builders might cause vertex layout change ShapeBuilder.PrepareVertexLayout(fieldsList); // Recalculate the required vertex count and stride VertexBuilder.SetRequiredQuads(ShapeBuilder.QuadsPerParticle, pool.LivingParticles, pool.ParticleCapacity); vertexBufferHasChanged = (Material.HasVertexLayoutChanged || ShapeBuilder.VertexLayoutHasChanged || VertexBuilder.IsBufferDirty); // Update the vertex builder and the vertex layout if needed if (vertexBufferHasChanged) { VertexBuilder.ResetVertexElementList(); Material.UpdateVertexBuilder(VertexBuilder); ShapeBuilder.UpdateVertexBuilder(VertexBuilder); VertexBuilder.UpdateVertexLayout(); } vertexSize = VertexBuilder.VertexDeclaration.CalculateSize(); vertexCount = VertexBuilder.VertexCount; VertexBuilder.SetDirty(false); }
/// <summary> /// <see cref="PrepareForDraw"/> prepares and updates the Material, ShapeBuilder and VertexBuilder if necessary /// </summary> public void PrepareForDraw() { Material.PrepareForDraw(VertexBuilder, ParticleSorter); ShapeBuilder.PrepareForDraw(VertexBuilder, ParticleSorter); // Update the vertex builder and the vertex layout if needed if (Material.HasVertexLayoutChanged || ShapeBuilder.VertexLayoutHasChanged) { VertexBuilder.ResetVertexElementList(); Material.UpdateVertexBuilder(VertexBuilder); ShapeBuilder.UpdateVertexBuilder(VertexBuilder); VertexBuilder.UpdateVertexLayout(); } VertexBuilder.SetRequiredQuads(ShapeBuilder.QuadsPerParticle, pool.LivingParticles, pool.ParticleCapacity); }
/// <summary> /// Build the vertex buffer from particle data /// Should come before <see cref="KickVertexBuffer"/> /// </summary> /// <param name="device">The graphics device, used to rebuild vertex layouts and shaders if needed</param> /// <param name="invViewMatrix">The current camera's inverse view matrix</param> public void BuildVertexBuffer(GraphicsDevice device, ref Matrix invViewMatrix) { // Get camera-space X and Y axes for billboard expansion and sort the particles if needed var unitX = new Vector3(invViewMatrix.M11, invViewMatrix.M12, invViewMatrix.M13); var unitY = new Vector3(invViewMatrix.M21, invViewMatrix.M22, invViewMatrix.M23); depthSortVector = Vector3.Cross(unitX, unitY); ParticleSorter.Sort(); // If the particles are in world space they don't need to be fixed as their coordinates are already in world space // If the particles are in local space they need to be drawn in world space using the emitter's current location matrix var posIdentity = new Vector3(0, 0, 0); var rotIdentity = new Quaternion(0, 0, 0, 1); var scaleIdentity = 1f; if (simulationSpace == EmitterSimulationSpace.Local) { posIdentity = drawPosition; rotIdentity = drawRotation; scaleIdentity = drawScale; } PrepareForDraw(); vertexBuilder.SetRequiredQuads(ShapeBuilder.QuadsPerParticle, pool.LivingParticles, pool.ParticleCapacity); vertexBuilder.MapBuffer(device); ShapeBuilder.BuildVertexBuffer(vertexBuilder, unitX, unitY, ref posIdentity, ref rotIdentity, scaleIdentity, ParticleSorter); vertexBuilder.RestartBuffer(); Material.PatchVertexBuffer(vertexBuilder, unitX, unitY, ParticleSorter); vertexBuilder.UnmapBuffer(device); }