/// <summary> /// numberOfBuffers is the amount of vertex buffers used by the particle system for multi buffering. /// Multi buffering can avoid stalling of the GPU but will also increases it's memory consumption. /// If you want to avoid stalling create the same amount of buffers as your maximum rendered emitters at the /// same time. /// For example allocating one buffer with 16383 particles takes up 2048KB(2MB) GPU memory. /// This call requires that there is a GL context /// </summary> /// <param name="numberOfBuffers">the amount of vertex buffers used by the particle system for multi buffering.</param> /// <param name="maxParticlesPerBuffer">Maximum number of particles that you will be able to display.</param> public static void Init(int numberOfBuffers = 2, int maxParticlesPerBuffer = MaxPossibleParticles) { _numberOfVertexBuffers = numberOfBuffers; if (maxParticlesPerBuffer > MaxPossibleParticles) { maxParticlesPerBuffer = MaxPossibleParticles; Debug.WriteLine("StardustStarlingRenderer WARNING: Tried to render than possible particles, setting value to max"); } _maxParticles = maxParticlesPerBuffer; SparrowParticleBuffers.CreateBuffers(maxParticlesPerBuffer, numberOfBuffers); if (!_initCalled) { for (int i = 0; i < 0x800; ++i) { SCosLut[i & 0x7FF] = (float)Math.Cos(i * 0.00306796157577128245943617517898); // 0.003067 = 2PI/2048 SSinLut[i & 0x7FF] = (float)Math.Sin(i * 0.00306796157577128245943617517898); } // handle a lost device context SparrowSharp.ContextCreated += SparrowSharpOnContextCreated; _initCalled = true; } }
private static void SparrowSharpOnContextCreated() { SparrowParticleBuffers.CreateBuffers(_maxParticles, _numberOfVertexBuffers); }
private void RenderCustom(Painter painter, int mNumBatchedParticles, float parentAlpha) { if (_mNumParticles == 0 || SparrowParticleBuffers.BuffersCreated == false) { return; } if (mNumBatchedParticles > _maxParticles) { Debug.WriteLine("Over " + _maxParticles + " particles! Aborting rendering"); return; } SparrowParticleBuffers.SwitchVertexBuffer(); painter.FinishMeshBatch(); painter.DrawCount += 1; painter.PrepareToDraw(); global::Sparrow.Display.BlendMode.Get(BlendMode).Activate(); RenderAlpha[0] = RenderAlpha[1] = RenderAlpha[2] = PremultiplyAlpha ? parentAlpha : 1; RenderAlpha[3] = parentAlpha; var program = ParticleProgram.GetProgram(); program.Activate(); int uAlpha = program.Uniforms["uAlpha"]; Gl.Uniform4(uAlpha, RenderAlpha[0], RenderAlpha[1], RenderAlpha[2], RenderAlpha[3]); int uMvpMatrix = program.Uniforms["uMvpMatrix"]; Gl.UniformMatrix4(uMvpMatrix, false, painter.State.MvpMatrix3D.RawData); //context.setTextureAt(0, mTexture.Base); Gl.BindBuffer(BufferTarget.ArrayBuffer, SparrowParticleBuffers.VertexBuffer); Gl.BufferData(BufferTarget.ArrayBuffer, (uint)(_vertexes.Length * sizeof(float)), _vertexes, BufferUsage.DynamicDraw); uint attribPosition = (uint)program.Attributes["aPosition"]; Gl.EnableVertexAttribArray(attribPosition); Gl.VertexAttribPointer(attribPosition, 2, VertexAttribType.Float, false, 32, (IntPtr)0); uint attribColor = (uint)program.Attributes["aColor"]; Gl.EnableVertexAttribArray(attribColor); Gl.VertexAttribPointer(attribColor, 4, VertexAttribType.Float, false, 32, (IntPtr)8); uint aTexCoords = (uint)program.Attributes["aTexCoords"]; Gl.EnableVertexAttribArray(aTexCoords); Gl.VertexAttribPointer(aTexCoords, 2, VertexAttribType.Float, false, 32, (IntPtr)24); Gl.ActiveTexture(TextureUnit.Texture0); RenderUtil.SetSamplerStateAt(_mTexture.Base, _mTexture.NumMipMaps > 0, TexSmoothing); Gl.BindBuffer(BufferTarget.ElementArrayBuffer, SparrowParticleBuffers.IndexBuffer); // TODO limit max number of particles Gl.DrawElements(PrimitiveType.Triangles, (_mNumParticles + mNumBatchedParticles) * 6, DrawElementsType.UnsignedShort, IntPtr.Zero); Gl.DisableVertexAttribArray(attribPosition); Gl.DisableVertexAttribArray(attribColor); Gl.DisableVertexAttribArray(aTexCoords); Gl.BindTexture(TextureTarget.Texture2d, 0); }