public void CalcVertexBuffer() { if (instanceVertexBuffer != null) instanceVertexBuffer.Dispose(); instanceVertexBuffer = new DynamicVertexBuffer(BaseClass.Device, instanceVertexDeclaration, instanceTransformMatrices.Count, BufferUsage.WriteOnly); instanceVertexBuffer.SetData(instanceTransformMatrices.Values.ToArray(), 0, instanceTransformMatrices.Count, SetDataOptions.Discard); }
public void StoreOnGPU(GraphicsDevice device) { GPUMode = true; GPUBlendVertexBuffer = new DynamicVertexBuffer(device, MeshVertex.SizeInBytes * BlendVertexBuffer.Length, BufferUsage.None); GPUBlendVertexBuffer.SetData(BlendVertexBuffer); GPUIndexBuffer = new IndexBuffer(device, sizeof(short) * IndexBuffer.Length, BufferUsage.None, IndexElementSize.SixteenBits); GPUIndexBuffer.SetData(IndexBuffer); }
protected override void Initialize() { //Создаем буффер индексов и вершин graphics.GraphicsDevice.Flush(); vertexBuffer = new DynamicVertexBuffer(graphics.GraphicsDevice, typeof(VertexPositionNormalTexture), vertex.Length, BufferUsage.WriteOnly); indexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(int), indices.Length, BufferUsage.WriteOnly); //Создаем вершины для наших частиц. CreateVertex(); //Переносим данные в буффер для видеокарты. indexBuffer.SetData(indices); vertexBuffer.SetData(vertex); //Вызываем иниталайз для базового класса и всех компоненетов, если они у нас есть. base.Initialize(); }
/// <summary> /// コンストラクタ /// </summary> /// <param name="triangleCount">三角形の個数</param> /// <param name="vertices">頂点配列</param> /// <param name="indexBuffer">インデックスバッファ</param> public MMDCPUModelPartP(int triangleCount, MMDVertex[] vertices,int[] vertMap, IndexBuffer indexBuffer) : base(triangleCount, vertices.Length, vertMap, indexBuffer) { this.vertices = vertices; //GPUリソース作成 gpuVertices = new VertexPosition[vertices.Length]; vertexBuffer = new DynamicVertexBuffer(indexBuffer.GraphicsDevice, typeof(VertexPosition), vertices.Length, BufferUsage.WriteOnly); //初期値代入 for (int i = 0; i < vertices.Length; i++) { gpuVertices[i].Position = vertices[i].Position; } // put the vertices into our vertex buffer vertexBuffer.SetData(gpuVertices, 0, vertexCount, SetDataOptions.Discard); }
private void SetUpBuffers() { v_buffer = new DynamicVertexBuffer(Game.device, VertexPositionTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly); i_buffer = new DynamicIndexBuffer(Game.device, typeof(int), indices.Length, BufferUsage.WriteOnly); v_buffer.SetData(vertices); i_buffer.SetData(indices); }
public void AddParticle(Vector3 Position, Vector3 Velocity) { for (int p = 0; p < particleArray.Length; p += 4) { for (int thisP = 0; thisP < 4; thisP++) { if (p == nextParticle && myLastpos != targetPos) { particleArray[p + thisP].Position = Position; particleArray[p + thisP].Color = particleColor; } particleArray[p + thisP].SpriteSize = (Vector3.Distance(particleArray[p + thisP].Position, targetPos) / myScale.X); } } nextParticle++; if (nextParticle >= particleArray.Length / 4) nextParticle = 0; vb = new DynamicVertexBuffer(REngine.Instance._game.GraphicsDevice, typeof(BillboardParticleElement), 4 * partCount, BufferUsage.WriteOnly); vb.SetData(particleArray); }
private static void InitVertexBuffer() { GraphicsDevice device = Core.GetDevice(); m_VB = new DynamicVertexBuffer(device, JellyVertex.VertexDeclaration, TOTAL_LEDS * 4, BufferUsage.WriteOnly); // 4 verts per quad / particle m_Lights = new JellyVertex[TOTAL_LEDS * 4]; // corners never change for (int i = 0; i < TOTAL_LEDS; i++) { m_Lights[i * 4 + 0].Corner = new Short2(-1, -1); m_Lights[i * 4 + 1].Corner = new Short2(1, -1); m_Lights[i * 4 + 2].Corner = new Short2(1, 1); m_Lights[i * 4 + 3].Corner = new Short2(-1, 1); } // create the actual dome structure float cos = 1.0f; float sin = 1.0f; float radiansBetweenRibs= (float)(2 * Math.PI / NUM_RIBS); float radiansBetweenRows = (float)((Math.PI / 2) / LEDS_PER_RIB); float radius = 250.0f; float height = 250.0f; int curLight = 0; for (int rib = 0; rib < NUM_RIBS; ++rib) { double ribAngle = rib * radiansBetweenRibs; cos = (float)Math.Cos(ribAngle); sin = (float)Math.Sin(ribAngle); for (int led = 0; led < LEDS_PER_RIB; ++led) { float rowRadius = (float)Math.Cos(led * radiansBetweenRows) * radius + 1.0f; float rowHeight = (float)Math.Sin(led * radiansBetweenRows) * height; Vector3 pos = new Vector3(cos * rowRadius, sin * rowRadius, rowHeight); int index = curLight * 4; m_Lights[index + 0].Color = Color.Black; m_Lights[index + 1].Color = Color.Black; m_Lights[index + 2].Color = Color.Black; m_Lights[index + 3].Color = Color.Black; m_Lights[index + 0].Position = pos; m_Lights[index + 1].Position = pos; m_Lights[index + 2].Position = pos; m_Lights[index + 3].Position = pos; ++curLight; } } m_VB.SetData(m_Lights); }
/// <summary> /// Update the vertex buffer from the local vertex data. /// </summary> /// <param name="numActive"></param> private void UpdateBuffer(int numActive) { int numVerts = numActive * 4; vbuf.SetData <BeamVertex>(verts, 0, numVerts, SetDataOptions.NoOverwrite); }
/// <summary> /// Initialization new RenderVertices /// </summary> /// <param name="g"></param> private void InitializeVertice(GraphicsDevice g) { if(_graphic==null) _graphic = g; //RenderVertices.RemoveAll( // delegate(VertexPositionNormalTexture matcher) // { // return true; // }); //for (int i = 0; i < Vertices.Count; i++) //{ // VertexPositionNormalTexture tmp = new VertexPositionNormalTexture(); // tmp.Position = Vertices.ToArray()[i].Position; // tmp.Normal = Vertices.ToArray()[i].Normal; // RenderVertices.Add(tmp); //} //RenderVertices = Vertices; this._indexBuffer = new IndexBuffer(_graphic, typeof(ushort),_indices.Count, BufferUsage.None); VertexBuffer = new DynamicVertexBuffer(_indexBuffer.GraphicsDevice, typeof(VertexPositionNormalTexture), this._vertices.Count, BufferUsage.WriteOnly); _indexBuffer.SetData(this._indices.ToArray()); VertexBuffer.SetData(Vertices.ToArray(), 0, _vertices.Count, SetDataOptions.Discard); }
public void DrawInstanced(Camera3D DrawCamera) { if (UnitChildren.Count == 0) { return; } Game1.graphicsDevice.BlendState = BlendState.Additive; Game1.graphicsDevice.DepthStencilState = DepthStencilState.None; if (!Applied) { ApplyEffectParameters(); } ViewParam.SetValue(DrawCamera.ViewMatrix); ProjectionParam.SetValue(DrawCamera.ProjectionMatrix); ViewPosParam.SetValue(DrawCamera.Position); if (!BufferReady) { BufferReady = true; Array.Resize(ref ShieldVertecies, UnitChildren.Count); int i = 0; foreach (UnitBasic s in UnitChildren) { ShieldVertecies[i].WorldMatrix = s.WorldMatrix; ShieldVertecies[i].color = s.GetShieldColor() * 0.5f; i++; } if ((vertexBuffer == null) || (UnitChildren.Count > vertexBuffer.VertexCount)) { if (vertexBuffer != null) { vertexBuffer.Dispose(); } vertexBuffer = new DynamicVertexBuffer(Game1.graphicsDevice, ShieldVertex.shieldVertexDeclaration, ShieldVertecies.Length, BufferUsage.WriteOnly); } vertexBuffer.SetData(ShieldVertecies, 0, ShieldVertecies.Length, SetDataOptions.Discard); } else if (vertexBuffer.IsContentLost) { vertexBuffer.SetData(ShieldVertecies, 0, ShieldVertecies.Length, SetDataOptions.Discard); } foreach (ModelMesh mesh in ShieldModel.Meshes) { foreach (ModelMeshPart meshPart in mesh.MeshParts) { Game1.graphicsDevice.SetVertexBuffers( new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0), new VertexBufferBinding(vertexBuffer, 0, 1) ); Game1.graphicsDevice.Indices = meshPart.IndexBuffer; foreach (EffectPass pass in ShieldEffect.CurrentTechnique.Passes) { pass.Apply(); Game1.graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, ShieldVertecies.Length); } } } Game1.graphicsDevice.BlendState = BlendState.AlphaBlend; }
public void Render( GraphicsDevice graphics, Shader effect, Camera cam, string mode) { effect.EnableWind = EnableWind; Camera = cam; if (HardwareInstancingSupported && (instanceBuffer == null || instanceBuffer.IsContentLost || instanceBuffer.IsDisposed)) { instanceBuffer = new DynamicVertexBuffer(graphics, InstancedVertex.VertexDeclaration, numInstances, BufferUsage.None); } if (SortedData.Data.Count > 0 && numActiveInstances > 0) { graphics.RasterizerState = rasterState; effect.CurrentTechnique = effect.Techniques[mode]; effect.EnableLighting = true; effect.VertexColorTint = Color.White; if (Texture == null || Texture.GraphicsDevice.IsDisposed) { Texture = AssetManager.GetContentTexture(TextureAsset); } if (Model.VertexBuffer == null || Model.IndexBuffer == null || Model.VertexBuffer.IsDisposed || Model.VertexBuffer.IsContentLost) { Model.ResetBuffer(graphics); Model.Texture = Texture; } bool hasIndex = Model.IndexBuffer != null; graphics.Indices = Model.IndexBuffer; BlendState blendState = graphics.BlendState; graphics.BlendState = BlendMode; effect.MainTexture = Texture; effect.LightRamp = Color.White; if (HardwareInstancingSupported) { instanceBuffer.SetData(instanceVertexes, 0, SortedData.Data.Count, SetDataOptions.Discard); graphics.SetVertexBuffers(Model.VertexBuffer, new VertexBufferBinding(instanceBuffer, 0, 1)); try { DrawInstanced(graphics, effect, cam); } catch (NoSuitableGraphicsDeviceException exception) { System.Console.WriteLine(exception.ToString()); HardwareInstancingSupported = false; } } else { // Fallback case when hardware instancing is not supported effect.SetTexturedTechnique(); DrawNonInstanced(graphics, effect, cam); } effect.SetTexturedTechnique(); effect.World = Matrix.Identity; graphics.BlendState = blendState; } effect.EnableWind = false; }
public override void Flush(GraphicsDevice Device, Shader Effect, Camera Camera, InstanceRenderMode Mode) { if (InstanceCount == 0) { return; } if (NeedsRendered || (AtlasTexture != null && (AtlasTexture.IsDisposed || AtlasTexture.GraphicsDevice.IsDisposed))) { if (RawAtlas == null || RawAtlas.Textures.Count == 0) { RebuildAtlas(); if (RawAtlas == null || RawAtlas.Textures.Count == 0) { // WTF. InstanceCount = 0; return; } } AtlasTexture = new Texture2D(Device, RawAtlas.Dimensions.Width, RawAtlas.Dimensions.Height); foreach (var texture in RawAtlas.Textures) { var realTexture = texture.RealTexture; var textureData = new Color[realTexture.Width * realTexture.Height]; realTexture.GetData(textureData); // Paste texture data into atlas. AtlasTexture.SetData(0, texture.Rect, textureData, 0, realTexture.Width * realTexture.Height); } NeedsRendered = false; } if (InstanceBuffer == null) { InstanceBuffer = new DynamicVertexBuffer(Device, TiledInstancedVertex.VertexDeclaration, InstanceQueueSize, BufferUsage.None); } Device.RasterizerState = new RasterizerState { CullMode = CullMode.None }; if (Mode == InstanceRenderMode.Normal) { Effect.SetTiledInstancedTechnique(); } else { Effect.CurrentTechnique = Effect.Techniques[Shader.Technique.SelectionBufferTiledInstanced]; } Effect.EnableWind = RenderData.EnableWind; Effect.EnableLighting = true; Effect.VertexColorTint = Color.White; if (RenderData.Model.VertexBuffer == null || RenderData.Model.IndexBuffer == null || (RenderData.Model.VertexBuffer != null && RenderData.Model.VertexBuffer.IsContentLost) || (RenderData.Model.IndexBuffer != null && RenderData.Model.IndexBuffer.IsContentLost)) { RenderData.Model.ResetBuffer(Device); } Device.Indices = RenderData.Model.IndexBuffer; BlendState blendState = Device.BlendState; Device.BlendState = Mode == InstanceRenderMode.Normal ? BlendState.NonPremultiplied : BlendState.Opaque; Effect.MainTexture = AtlasTexture; Effect.LightRamp = Color.White; InstanceBuffer.SetData(Instances, 0, InstanceCount, SetDataOptions.Discard); Device.SetVertexBuffers(RenderData.Model.VertexBuffer, new VertexBufferBinding(InstanceBuffer, 0, 1)); var ghostEnabled = Effect.GhostClippingEnabled; Effect.GhostClippingEnabled = RenderData.EnableGhostClipping && ghostEnabled; foreach (EffectPass pass in Effect.CurrentTechnique.Passes) { pass.Apply(); Device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, RenderData.Model.VertexCount, 0, RenderData.Model.Indexes.Length / 3, InstanceCount); } Effect.GhostClippingEnabled = ghostEnabled; Effect.SetTexturedTechnique(); Effect.World = Matrix.Identity; Device.BlendState = blendState; Effect.EnableWind = false; InstanceCount = 0; }
/// <summary> /// Draws the particle system. /// </summary> public override void Draw(GameTime gameTime) { GraphicsDevice device = GraphicsDevice; // Restore the vertex buffer contents if the graphics device was lost. if (vertexBuffer.IsContentLost) { vertexBuffer.SetData(particles); } // If there are any particles waiting in the newly added queue, // we'd better upload them to the GPU ready for drawing. if (firstNewParticle != firstFreeParticle) { AddNewParticlesToVertexBuffer(); } // If there are any active particles, draw them now! if (firstActiveParticle != firstFreeParticle) { device.BlendState = settings.BlendState; device.DepthStencilState = DepthStencilState.DepthRead; // Set an effect parameter describing the viewport size. This is // needed to convert particle sizes into screen space point sizes. effectViewportScaleParameter.SetValue(new Vector2(0.5f / device.Viewport.AspectRatio, -0.5f)); // Set an effect parameter describing the current time. All the vertex // shader particle animation is keyed off this value. effectTimeParameter.SetValue(currentTime); // Set the particle vertex and index buffer. device.SetVertexBuffer(vertexBuffer); device.Indices = indexBuffer; // Activate the particle effect. foreach (EffectPass pass in particleEffect.CurrentTechnique.Passes) { pass.Apply(); if (firstActiveParticle < firstFreeParticle) { // If the active particles are all in one consecutive range, // we can draw them all in a single call. device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, firstActiveParticle * 4, (firstFreeParticle - firstActiveParticle) * 4, firstActiveParticle * 6, (firstFreeParticle - firstActiveParticle) * 2); } else { // If the active particle range wraps past the end of the queue // back to the start, we must split them over two draw calls. device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, firstActiveParticle * 4, (settings.MaxParticles - firstActiveParticle) * 4, firstActiveParticle * 6, (settings.MaxParticles - firstActiveParticle) * 2); if (firstFreeParticle > 0) { device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, firstFreeParticle * 4, 0, firstFreeParticle * 2); } } } // Reset some of the renderstates that we changed, // so as not to mess up any other subsequent drawing. device.DepthStencilState = DepthStencilState.Default; } drawCounter++; }
public void FlushRequests(IGameContext gameContext, IRenderContext renderContext) { LastBatchCount = 0; LastApplyCount = 0; LastBatchSaveCount = 0; if (renderContext.IsCurrentRenderPass <I3DBatchedRenderPass>()) { using (_profiler.Measure("render-flush")) { foreach (var kv in _requestLookup) { if (_requestInstances[kv.Key].Count == 0) { continue; } LastBatchCount++; LastBatchSaveCount += (ulong)(_requestInstances[kv.Key].Count - 1); var request = kv.Value; int pc; SetupForRequest(renderContext, request, out pc, false); request.Effect.NativeEffect.Parameters["View"]?.SetValue(renderContext.View); request.Effect.NativeEffect.Parameters["Projection"]?.SetValue(renderContext.Projection); List <Matrix> filteredInstances; if (kv.Value.BoundingRegion != null) { // TODO: Reduce allocations here. filteredInstances = new List <Matrix>(_requestInstances[kv.Key].Count); foreach (var ri in _requestInstances[kv.Key]) { if (kv.Value.BoundingRegion.Intersects(renderContext.BoundingFrustum, Vector3.Transform(Vector3.Zero, ri))) { filteredInstances.Add(ri); } } if (filteredInstances.Count == 0) { continue; } } else { filteredInstances = _requestInstances[kv.Key]; } #if PLATFORM_WINDOWS var allowInstancedCalls = true; #else var allowInstancedCalls = false; #endif if (allowInstancedCalls && request.Effect.NativeEffect.Techniques[request.TechniqueName + "Batched"] != null) { #if PLATFORM_WINDOWS if (_vertexBuffer == null || filteredInstances.Count > _vertexBufferLastInstanceCount) { _vertexBuffer?.Dispose(); _vertexBuffer = new DynamicVertexBuffer( renderContext.GraphicsDevice, _vertexDeclaration, filteredInstances.Count, BufferUsage.WriteOnly); _vertexBufferLastInstanceCount = filteredInstances.Count; } _vertexBuffer.SetData(filteredInstances.ToArray(), 0, filteredInstances.Count); renderContext.GraphicsDevice.SetVertexBuffers( new VertexBufferBinding(request.MeshVertexBuffer), new VertexBufferBinding(_vertexBuffer, 0, 1)); foreach (var pass in request.Effect.NativeEffect.Techniques[request.TechniqueName + "Batched"].Passes) { pass.Apply(); renderContext.GraphicsDevice.DrawInstancedPrimitives( request.PrimitiveType, 0, 0, pc, filteredInstances.Count); } #endif } else { // If there's less than 5 instances, just push the draw calls to the GPU. if (filteredInstances.Count <= 5 || !request.SupportsComputingInstancesToCustomBuffers) { renderContext.GraphicsDevice.SetVertexBuffer(request.MeshVertexBuffer); foreach (var instance in filteredInstances) { request.Effect.NativeEffect.Parameters["World"]?.SetValue(instance); foreach (var pass in request.Effect.NativeEffect.Techniques[request.TechniqueName].Passes) { pass.Apply(); LastApplyCount++; renderContext.GraphicsDevice.DrawIndexedPrimitives( request.PrimitiveType, 0, 0, pc); } } } else { var buffersNeedComputing = false; var vertexBuffer = _renderAutoCache.AutoCache("renderbatcher-" + kv.Key, new object[] { filteredInstances.Count, request.MeshVertexBuffer.VertexCount, request.MeshVertexBuffer.VertexDeclaration }, gameContext, () => { buffersNeedComputing = true; return(new VertexBuffer( renderContext.GraphicsDevice, request.MeshVertexBuffer.VertexDeclaration, filteredInstances.Count * request.MeshVertexBuffer.VertexCount, BufferUsage.WriteOnly)); }); var indexBuffer = _renderAutoCache.AutoCache("renderbatcher-" + kv.Key, new object[] { filteredInstances.Count, request.MeshVertexBuffer.VertexCount, }, gameContext, () => { buffersNeedComputing = true; return(new IndexBuffer( renderContext.GraphicsDevice, IndexElementSize.ThirtyTwoBits, filteredInstances.Count * request.MeshIndexBuffer.IndexCount, BufferUsage.WriteOnly)); }); if (buffersNeedComputing) { // Compute a pre-transformed vertex and index buffer for rendering. request.ComputeInstancesToCustomBuffers( filteredInstances, vertexBuffer, indexBuffer); } renderContext.GraphicsDevice.SetVertexBuffer(vertexBuffer); renderContext.GraphicsDevice.Indices = indexBuffer; request.Effect.NativeEffect.Parameters["World"]?.SetValue(Matrix.Identity); foreach ( var pass in request.Effect.NativeEffect.Techniques[request.TechniqueName].Passes ) { pass.Apply(); renderContext.GraphicsDevice.DrawIndexedPrimitives( request.PrimitiveType, 0, 0, pc * filteredInstances.Count); } } } filteredInstances.Clear(); } _requestLookup.Clear(); _requestInstances.Clear(); } } }
void VertexBuffer_ContentLost(object sender, EventArgs e) { VertexBuffer.SetData(0, Vertices, 0, Vertices.Length, VertexStride, SetDataOptions.NoOverwrite); }
public void Hook(RTSRenderer renderer, GameState s, int ti, int unit) { // Filter For Unit Types RTSTeam team = s.teams[ti]; Data = team.Race.Units[unit]; // Always Add A Unit To List When Spawned team.OnUnitSpawn += OnUnitSpawn; // Create Instance Buffer visible = new List<RTSUnit>(); instVerts = new VertexRTSAnimInst[Data.MaxCount]; instances = new List<RTSUnit>(Data.MaxCount); dead = new List<RTSUnit>(); for(int i = 0; i < team.Units.Count; i++) { OnUnitSpawn(team.Units[i]); } for(int i = 0; i < instVerts.Length; i++) instVerts[i] = new VertexRTSAnimInst(Matrix.Identity, 0); dvbInstances = renderer.CreateDynamicVertexBuffer(VertexRTSAnimInst.Declaration, instVerts.Length, BufferUsage.WriteOnly); dvbInstances.SetData(instVerts); dvbInstances.ContentLost += (sender, args) => { rebuildDVB = true; }; rebuildDVB = false; }
/// <summary> /// Build the mesh used to draw all trails /// </summary> private void BuildMesh() { if (this.mesh != null) { this.DestroyMesh(); } // Indices this.indices = new ushort[this.nIndices]; DynamicIndexBuffer indexBuffer = new DynamicIndexBuffer(this.indices); this.RenderManager.GraphicsDevice.BindIndexBuffer(indexBuffer); // Vertices this.vertices = new VertexPositionColorTexture[this.nVertices]; DynamicVertexBuffer vertexBuffer = new DynamicVertexBuffer(VertexPositionColorTexture.VertexFormat); vertexBuffer.SetData(this.vertices); this.GraphicsDevice.BindVertexBuffer(vertexBuffer); this.mesh = new Mesh(0, nVertices, 0, nIndices / 3, vertexBuffer, indexBuffer, PrimitiveType.TriangleStrip) { DisableBatch = true }; }
/// <summary> /// Draws the particle system. /// </summary> public override void Draw(GameTime gameTime) { try { GraphicsDevice device = GraphicsDevice; SetCamera(Camera.View, Camera.Projection); // Restore the vertex buffer contents if the graphics device was lost. if (vertexBuffer.IsContentLost) { vertexBuffer.SetData(particles); } // If there are any particles waiting in the newly added queue, // we'd better upload them to the GPU ready for drawing. if (firstNewParticle != firstFreeParticle) { AddNewParticlesToVertexBuffer(); } // If there are any active particles, draw them now! if (firstActiveParticle != firstFreeParticle) { SetParticleRenderStates(device); // Set an effect parameter describing the viewport size. This is needed // to convert particle sizes into screen space point sprite sizes. effectViewportHeightParameter.SetValue(device.Viewport.Height); // Set an effect parameter describing the current time. All the vertex // shader particle animation is keyed off this value. effectTimeParameter.SetValue(currentTime); // Set the particle vertex buffer and vertex declaration. device.SetVertexBuffer(vertexBuffer); //foreach (EffectPass pass in particleEffect.CurrentTechnique.Passes) for (int i = 0; i < particleEffect.CurrentTechnique.Passes.Count; ++i) { particleEffect.CurrentTechnique.Passes[i].Apply(); #if SDL2 if (firstActiveParticle < firstFreeParticle) { // If the active particles are all in one consecutive range, // we can draw them all in a single call. device.DrawPrimitives(PrimitiveType.PointListEXT, firstActiveParticle, firstFreeParticle - firstActiveParticle); } else { // If the active particle range wraps past the end of the queue // back to the start, we must split them over two draw calls. device.DrawPrimitives(PrimitiveType.PointListEXT, firstActiveParticle, particles.Length - firstActiveParticle); if (firstFreeParticle > 0) { device.DrawPrimitives(PrimitiveType.PointListEXT, 0, firstFreeParticle); } } #endif } // Reset a couple of the more unusual renderstates that we changed, // so as not to mess up any other subsequent drawing. PointSpriteHelper.Disable(); if (device.DepthStencilState.DepthBufferEnable) { device.DepthStencilState = DepthStencilState.Default; } else { device.DepthStencilState = Helpers.DepthWrite; } } } catch { } drawCounter++; }
void VertexBuffer_ContentLost() { VertexBuffer.SetData(0, Vertices, 0, Vertices.Length, ParticleVertex.VertexStride, SetDataOptions.NoOverwrite); }
private static void InitVertexBuffer() { GraphicsDevice device = Core.GetDevice(); m_VB = new DynamicVertexBuffer(device, JellyVertex.VertexDeclaration, TOTAL_LEDS * 4, BufferUsage.WriteOnly); // 4 verts per quad / particle m_Lights = new JellyVertex[4 * TOTAL_LEDS]; // corners never change for (int i = 0; i < TOTAL_LEDS; i++) { m_Lights[i * 4 + 0].Corner = new Short2(-1, -1); m_Lights[i * 4 + 1].Corner = new Short2(1, -1); m_Lights[i * 4 + 2].Corner = new Short2(1, 1); m_Lights[i * 4 + 3].Corner = new Short2(-1, 1); } // create the actual dome structure //float cos = 1.0f; //float sin = 1.0f; float radiansBetweenRibs = (float)(2 * Math.PI / NUM_RIBS); float radiansBetweenRows = (float)((Math.PI / 2) / LEDS_PER_RIB); float radiusDome = 250.0f; float heightDome = 250.0f; int index = 0; for (int rib = 0; rib < NUM_RIBS; ++rib) { double ribAngle = rib * radiansBetweenRibs; float cos = (float)Math.Cos(ribAngle); float sin = (float)Math.Sin(ribAngle); for (int led = 0; led < LEDS_PER_RIB; ++led, index += 4) { float rowRadius = (float)Math.Cos(led * radiansBetweenRows) * radiusDome + 1.0f; float rowHeight = (float)Math.Sin(led * radiansBetweenRows) * heightDome; Vector3 pos = new Vector3(cos * rowRadius, sin * rowRadius, rowHeight); m_Lights[index + 0].Color = Color.White; m_Lights[index + 1].Color = Color.White; m_Lights[index + 2].Color = Color.White; m_Lights[index + 3].Color = Color.White; m_Lights[index + 0].Position = pos; m_Lights[index + 1].Position = pos; m_Lights[index + 2].Position = pos; m_Lights[index + 3].Position = pos; } } // Init our pendant indicators // H float radiusPendants = 280.0f; float heightPendants = 16.0f; // Angle over which we want to render the pendants: float arcPendants = (float)Math.PI / 2; float radiansBetweenPendants = (float)(arcPendants / NUM_PENDANTS_MAX); // float radiansBetweenPendantLEDs = (float)((Math.PI / 2) / LEDS_PER_PENDANT_MAX); // The radius between pendant LEDs is spacing between LEDs in a pendant: float radiusBetweenPendantLEDs = 8.0f; // 32.0f / LEDS_PER_PENDANT_MAX; m_PendantLightIndexOffset = index / 4; for (int pendant = 0; pendant < NUM_PENDANTS_MAX; ++pendant) { // 3D-position: X and Y are on the ground, Z is up towards top of dome double angle = ((pendant + 0.5) * radiansBetweenPendants) + (Math.PI / 4); float cos = (float)Math.Cos(angle); float sin = (float)Math.Sin(angle); for (int led = 0; led < LEDS_PER_PENDANT_MAX; ++led, index += 4) { float rowRadius = radiusPendants + led * radiusBetweenPendantLEDs; // (float)Math.Cos(led * radiansBetweenPendantLEDs) * radiusPendants + 1.0f; float rowHeight = heightPendants; // *(float)Math.Sin(led * radiansBetweenPendantLEDs); Vector3 pos = new Vector3(cos * rowRadius, sin * rowRadius, rowHeight); m_Lights[index + 0].Color = Color.White; m_Lights[index + 1].Color = Color.White; m_Lights[index + 2].Color = Color.White; m_Lights[index + 3].Color = Color.White; m_Lights[index + 0].Position = pos; m_Lights[index + 1].Position = pos; m_Lights[index + 2].Position = pos; m_Lights[index + 3].Position = pos; } } // Init our satellites: float arcSatellites = 2.0f * (float)Math.PI; float radiansBetweenSatelliteLEDs = (float)(arcSatellites / LEDS_PER_SATELLITE); float radiusSatellites = 64.0f; float xOffsetSatellites = 280.0f; float yOffsetSatellites = 280.0f; float zOffsetSatellites = 0.0f; m_SatelliteLightIndexOffset = index / 4; for (int satellite = 0; satellite < NUM_SATELLITES; ++satellite) { // 3D-position: X and Y are on the ground, Z is up towards top of dome float xOffset = (satellite == 0) ? xOffsetSatellites : -xOffsetSatellites; for (int led = 0; led < LEDS_PER_SATELLITE; ++led, index += 4) { double angle = (led * radiansBetweenSatelliteLEDs);// +(Math.PI / 4); float cos = (float)Math.Cos(angle); float sin = (float)Math.Sin(angle); Vector3 pos = new Vector3(xOffset + cos * radiusSatellites, yOffsetSatellites + sin * radiusSatellites, zOffsetSatellites); m_Lights[index + 0].Color = Color.White; m_Lights[index + 1].Color = Color.White; m_Lights[index + 2].Color = Color.White; m_Lights[index + 3].Color = Color.White; m_Lights[index + 0].Position = pos; m_Lights[index + 1].Position = pos; m_Lights[index + 2].Position = pos; m_Lights[index + 3].Position = pos; } } m_VB.SetData(m_Lights); }
private void CalculateLightVertices(List <Vector2> rayCastHits) { vertexCount = rayCastHits.Count * 2 + 1; indexCount = (rayCastHits.Count) * 9; //recreate arrays if they're too small or excessively large if (vertices == null || vertices.Length < vertexCount || vertices.Length > vertexCount * 3) { vertices = new VertexPositionColorTexture[vertexCount]; indices = new short[indexCount]; } Vector2 drawPos = position; if (ParentSub != null) { drawPos += ParentSub.DrawPosition; } float cosAngle = (float)Math.Cos(Rotation); float sinAngle = -(float)Math.Sin(Rotation); Vector2 uvOffset = Vector2.Zero; Vector2 overrideTextureDims = Vector2.One; if (OverrideLightTexture != null) { overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height); Vector2 origin = OverrideLightTexture.Origin; if (LightSpriteEffect == SpriteEffects.FlipHorizontally) { origin.X = OverrideLightTexture.SourceRect.Width - origin.X; } if (LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = OverrideLightTexture.SourceRect.Height - origin.Y; } uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f); } // Add a vertex for the center of the mesh vertices[0] = new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0), Color.White, GetUV(new Vector2(0.5f, 0.5f) + uvOffset, LightSpriteEffect)); //hacky fix to exc excessively large light volumes (they used to be up to 4x the range of the light if there was nothing to block the rays). //might want to tweak the raycast logic in a way that this isn't necessary float boundRadius = Range * 1.1f / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y))); Rectangle boundArea = new Rectangle((int)(drawPos.X - boundRadius), (int)(drawPos.Y + boundRadius), (int)(boundRadius * 2), (int)(boundRadius * 2)); for (int i = 0; i < rayCastHits.Count; i++) { if (MathUtils.GetLineRectangleIntersection(drawPos, rayCastHits[i], boundArea, out Vector2 intersection)) { rayCastHits[i] = intersection; } } // Add all the other encounter points as vertices // storing their world position as UV coordinates for (int i = 0; i < rayCastHits.Count; i++) { Vector2 vertex = rayCastHits[i]; //we'll use the previous and next vertices to calculate the normals //of the two segments this vertex belongs to //so we can add new vertices based on these normals Vector2 prevVertex = rayCastHits[i > 0 ? i - 1 : rayCastHits.Count - 1]; Vector2 nextVertex = rayCastHits[i < rayCastHits.Count - 1 ? i + 1 : 0]; Vector2 rawDiff = vertex - drawPos; //calculate normal of first segment Vector2 nDiff1 = vertex - nextVertex; float tx = nDiff1.X; nDiff1.X = -nDiff1.Y; nDiff1.Y = tx; nDiff1 /= Math.Max(Math.Abs(nDiff1.X), Math.Abs(nDiff1.Y)); //if the normal is pointing towards the light origin //rather than away from it, invert it if (Vector2.DistanceSquared(nDiff1, rawDiff) > Vector2.DistanceSquared(-nDiff1, rawDiff)) { nDiff1 = -nDiff1; } //calculate normal of second segment Vector2 nDiff2 = prevVertex - vertex; tx = nDiff2.X; nDiff2.X = -nDiff2.Y; nDiff2.Y = tx; nDiff2 /= Math.Max(Math.Abs(nDiff2.X), Math.Abs(nDiff2.Y)); //if the normal is pointing towards the light origin //rather than away from it, invert it if (Vector2.DistanceSquared(nDiff2, rawDiff) > Vector2.DistanceSquared(-nDiff2, rawDiff)) { nDiff2 = -nDiff2; } //add the normals together and use some magic numbers to create //a somewhat useful/good-looking blur Vector2 nDiff = nDiff1 + nDiff2; nDiff /= Math.Max(Math.Abs(nDiff.X), Math.Abs(nDiff.Y)); nDiff *= 50.0f; Vector2 diff = rawDiff; diff /= Range * 2.0f; if (OverrideLightTexture != null) { //calculate texture coordinates based on the light's rotation Vector2 originDiff = diff; diff.X = originDiff.X * cosAngle - originDiff.Y * sinAngle; diff.Y = originDiff.X * sinAngle + originDiff.Y * cosAngle; diff *= (overrideTextureDims / OverrideLightTexture.size);// / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y))); diff += uvOffset; } //finally, create the vertices VertexPositionColorTexture fullVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0), Color.White, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect)); VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0), Color.White * 0.0f, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect)); vertices[1 + i * 2] = fullVert; vertices[1 + i * 2 + 1] = fadeVert; } // Compute the indices to form triangles for (int i = 0; i < rayCastHits.Count - 1; i++) { //main light body indices[i * 9] = 0; indices[i * 9 + 1] = (short)((i * 2 + 3) % vertexCount); indices[i * 9 + 2] = (short)((i * 2 + 1) % vertexCount); //faded light indices[i * 9 + 3] = (short)((i * 2 + 1) % vertexCount); indices[i * 9 + 4] = (short)((i * 2 + 3) % vertexCount); indices[i * 9 + 5] = (short)((i * 2 + 4) % vertexCount); indices[i * 9 + 6] = (short)((i * 2 + 2) % vertexCount); indices[i * 9 + 7] = (short)((i * 2 + 1) % vertexCount); indices[i * 9 + 8] = (short)((i * 2 + 4) % vertexCount); } //main light body indices[(rayCastHits.Count - 1) * 9] = 0; indices[(rayCastHits.Count - 1) * 9 + 1] = (short)(1); indices[(rayCastHits.Count - 1) * 9 + 2] = (short)(vertexCount - 2); //faded light indices[(rayCastHits.Count - 1) * 9 + 3] = (short)(1); indices[(rayCastHits.Count - 1) * 9 + 4] = (short)(vertexCount - 1); indices[(rayCastHits.Count - 1) * 9 + 5] = (short)(vertexCount - 2); indices[(rayCastHits.Count - 1) * 9 + 6] = (short)(1); indices[(rayCastHits.Count - 1) * 9 + 7] = (short)(2); indices[(rayCastHits.Count - 1) * 9 + 8] = (short)(vertexCount - 1); //TODO: a better way to determine the size of the vertex buffer and handle changes in size? //now we just create a buffer for 64 verts and make it larger if needed if (lightVolumeBuffer == null) { lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount * 1.5)), BufferUsage.None); lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64 * 3, (int)(indexCount * 1.5)), BufferUsage.None); } else if (vertexCount > lightVolumeBuffer.VertexCount || indexCount > lightVolumeIndexBuffer.IndexCount) { lightVolumeBuffer.Dispose(); lightVolumeIndexBuffer.Dispose(); lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount * 1.5), BufferUsage.None); lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None); } lightVolumeBuffer.SetData <VertexPositionColorTexture>(vertices, 0, vertexCount); lightVolumeIndexBuffer.SetData <short>(indices, 0, indexCount); Vector2 GetUV(Vector2 vert, SpriteEffects effects) { if (effects == SpriteEffects.FlipHorizontally) { vert.X = 1.0f - vert.X; } else if (effects == SpriteEffects.FlipVertically) { vert.Y = 1.0f - vert.Y; } else if (effects == (SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically)) { vert.X = 1.0f - vert.X; vert.Y = 1.0f - vert.Y; } vert.Y = 1.0f - vert.Y; return(vert); } translateVertices = Vector2.Zero; rotateVertices = 0.0f; prevCalculatedPosition = position; prevCalculatedRotation = rotation; }
/// <summary> /// Taken from XNA model instancing example /// Efficiently draws several copies of a piece of geometry using hardware instancing. /// </summary> void DrawModelHardwareInstancing(Model model, Matrix[] modelBones, Matrix[] instances, Matrix view, Matrix projection, byte[] blockTypeArray) { if (instances.Length == 0) { return; } //create lists for instances with different textures ArrayList grassInstances = new ArrayList(); ArrayList stoneInstances = new ArrayList(); ArrayList woodInstances = new ArrayList(); // If we have more instances than room in our vertex buffer, grow it to the neccessary size. if ((instanceVertexBuffer == null) || (instances.Length > instanceVertexBuffer.VertexCount)) { if (instanceVertexBuffer != null) { instanceVertexBuffer.Dispose(); } instanceVertexBuffer = new DynamicVertexBuffer(GraphicsDevice, instanceVertexDeclaration, instances.Length, BufferUsage.WriteOnly); } // Transfer the latest instance transform matrices into the instanceVertexBuffer. instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard); foreach (ModelMesh mesh in model.Meshes) { foreach (ModelMeshPart meshPart in mesh.MeshParts) { // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer. GraphicsDevice.SetVertexBuffers( new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0), new VertexBufferBinding(instanceVertexBuffer, 0, 1) ); GraphicsDevice.Indices = meshPart.IndexBuffer; // Set up the instance rendering effect. Effect effect = meshPart.Effect; effect.CurrentTechnique = effect.Techniques["HardwareInstancing"]; effect.Parameters["World"].SetValue(modelBones[mesh.ParentBone.Index]); effect.Parameters["View"].SetValue(view); effect.Parameters["Projection"].SetValue(projection); for (int index = 0; index < instances.Length; index++) { //separate different textures blocks switch (blockTypeArray[index]) { case 2: case 31: case 9: grassInstances.Add(instances[index]); break; case 1: case 4: case 35: case 42: case 44: case 98: case 109: stoneInstances.Add(instances[index]); break; case 5: case 17: case 20: case 53: case 85: case 126: woodInstances.Add(instances[index]); break; default: grassInstances.Add(instances[index]); break; } } //draw GRASS // Transfer the current instance transform matrices into the instanceVertexBuffer. Matrix[] grassInstancesArray = new Matrix[grassInstances.Count]; for (int i = 0; i < grassInstancesArray.Length; i++) { grassInstancesArray[i] = (Matrix)grassInstances[i]; } effect.Parameters["Texture"].SetValue(grassTexture); drawTexturedInstancedPrimitives(grassInstancesArray, effect, meshPart); //draw STONE // Transfer the current instance transform matrices into the instanceVertexBuffer. Matrix[] stoneInstancesArray = new Matrix[stoneInstances.Count]; for (int i = 0; i < stoneInstancesArray.Length; i++) { stoneInstancesArray[i] = (Matrix)stoneInstances[i]; } effect.Parameters["Texture"].SetValue(stoneTexture); drawTexturedInstancedPrimitives(stoneInstancesArray, effect, meshPart); //draw WOOD // Transfer the current instance transform matrices into the instanceVertexBuffer. Matrix[] woodInstancesArray = new Matrix[woodInstances.Count]; for (int i = 0; i < woodInstancesArray.Length; i++) { woodInstancesArray[i] = (Matrix)woodInstances[i]; } effect.Parameters["Texture"].SetValue(woodTexture); drawTexturedInstancedPrimitives(woodInstancesArray, effect, meshPart); // Draw all the instance copies in a single call. foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, Math.Min(1048574, instances.Length)); //TODO: should have warning or something when too big } } } }
/// <summary> /// コンテンツ読み込みのタイミングにフレームワークから呼び出されます /// </summary> protected override void LoadContent() { PrinceInitialize(); Prince.Initialize_element(); StageModelInitialize(); #region 追加の読み込み basicEffect = new BasicEffect(GraphicsDevice); // 頂点カラーを有効にする basicEffect.VertexColorEnabled = true; basicEffect.View = camera.View; basicEffect.Projection = camera.Projection; // 頂点バッファ作成 totalOfVertex = numberOfVertex * numberOfBox; vertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(VertexPositionColor), totalOfVertex, BufferUsage.None); vertexes = new VertexPositionColor[totalOfVertex]; // 箱の初期位置 boxPosition1 = new Vector3(-20.0f, -10.0f, 0.0f); boxPosition2 = new Vector3(200.0f, 0.0f, 0.0f); boxPosition3 = new Vector3(100.0f, 0.0f, 300.0f); CreateBox(0, boxSize, boxPosition1); // 箱1 CreateBox(1, boxSize, boxPosition2); // 箱2 // 頂点バッファをセット vertexBuffer.SetData(vertexes, 0, vertexBuffer.VertexCount, SetDataOptions.NoOverwrite); box1.Min = new Vector3(-boxSize * 0.5f) + boxPosition1; box1.Max = new Vector3(boxSize * 0.5f) + boxPosition1; box2.Min = new Vector3(-boxSize * 0.5f) + boxPosition2; box2.Max = new Vector3(boxSize * 0.5f) + boxPosition2; #endregion #region ミツハシの弄った場所。 #region 土Position stageRoadPositon[0] = new Vector3(1340.0f, -390.0f, 0.0f); stageRoadPositon[1] = new Vector3(1360.0f, -390.0f, 0.0f); stageRoadPositon[2] = new Vector3(1380.0f, -390.0f, 0.0f); stageRoadPositon[3] = new Vector3(1400.0f, -390.0f, 0.0f); stageRoadPositon[4] = new Vector3(1420.0f, -390.0f, 0.0f); stageRoadPositon[5] = new Vector3(1440.0f, -390.0f, 0.0f); stageRoadPositon[6] = new Vector3(1440.0f, -370.0f, 0.0f); stageRoadPositon[7] = new Vector3(1460.0f, -350.0f, 0.0f); stageRoadPositon[8] = new Vector3(1460.0f, -370.0f, 0.0f); stageRoadPositon[9] = new Vector3(1480.0f, -330.0f, 0.0f); stageRoadPositon[10] = new Vector3(1480.0f, -350.0f, 0.0f); stageRoadPositon[11] = new Vector3(1480.0f, -370.0f, 0.0f); stageRoadPositon[12] = new Vector3(1480.0f, -390.0f, 0.0f); stageRoadPositon[13] = new Vector3(1340.0f, -270.0f, 0.0f); stageRoadPositon[14] = new Vector3(1340.0f, -290.0f, 0.0f); stageRoadPositon[15] = new Vector3(1340.0f, -310.0f, 0.0f); stageRoadPositon[16] = new Vector3(1360.0f, -290.0f, 0.0f); stageRoadPositon[17] = new Vector3(1360.0f, -310.0f, 0.0f); stageRoadPositon[18] = new Vector3(1380.0f, -290.0f, 0.0f); stageRoadPositon[19] = new Vector3(1380.0f, -310.0f, 0.0f); stageRoadPositon[20] = new Vector3(1440.0f, -310.0f, 0.0f); stageRoadPositon[21] = new Vector3(1380.0f, -250.0f, 0.0f); stageRoadPositon[22] = new Vector3(1400.0f, -250.0f, 0.0f); stageRoadPositon[23] = new Vector3(1420.0f, -250.0f, 0.0f); stageRoadPositon[24] = new Vector3(1440.0f, -250.0f, 0.0f); stageRoadPositon[25] = new Vector3(1460.0f, -250.0f, 0.0f); stageRoadPositon[26] = new Vector3(1480.0f, -250.0f, 0.0f); stageRoadPositon[27] = new Vector3(1500.0f, -250.0f, 0.0f); stageRoadPositon[28] = new Vector3(1580.0f, -310.0f, 0.0f); stageRoadPositon[29] = new Vector3(1580.0f, -330.0f, 0.0f); stageRoadPositon[30] = new Vector3(1580.0f, -350.0f, 0.0f); stageRoadPositon[31] = new Vector3(1580.0f, -370.0f, 0.0f); stageRoadPositon[32] = new Vector3(1580.0f, -390.0f, 0.0f); stageRoadPositon[33] = new Vector3(1600.0f, -290.0f, 0.0f); stageRoadPositon[34] = new Vector3(1620.0f, -290.0f, 0.0f); stageRoadPositon[35] = new Vector3(1640.0f, -290.0f, 0.0f); stageRoadPositon[36] = new Vector3(1660.0f, -290.0f, 0.0f); stageRoadPositon[37] = new Vector3(1680.0f, -290.0f, 0.0f); stageRoadPositon[38] = new Vector3(1700.0f, -210.0f, 0.0f); stageRoadPositon[39] = new Vector3(1700.0f, -230.0f, 0.0f); stageRoadPositon[40] = new Vector3(1700.0f, -250.0f, 0.0f); stageRoadPositon[41] = new Vector3(1700.0f, -270.0f, 0.0f); stageRoadPositon[42] = new Vector3(1700.0f, -290.0f, 0.0f); stageRoadPositon[43] = new Vector3(1320.0f, 10.0f, 0.0f); stageRoadPositon[44] = new Vector3(1320.0f, -10.0f, 0.0f); stageRoadPositon[45] = new Vector3(1320.0f, -30.0f, 0.0f); stageRoadPositon[46] = new Vector3(1320.0f, -50.0f, 0.0f); stageRoadPositon[47] = new Vector3(1320.0f, -70.0f, 0.0f); stageRoadPositon[48] = new Vector3(1320.0f, -90.0f, 0.0f); stageRoadPositon[49] = new Vector3(1320.0f, -110.0f, 0.0f); stageRoadPositon[50] = new Vector3(1320.0f, -130.0f, 0.0f); stageRoadPositon[51] = new Vector3(1320.0f, -150.0f, 0.0f); stageRoadPositon[52] = new Vector3(1320.0f, -170.0f, 0.0f); stageRoadPositon[53] = new Vector3(1320.0f, -190.0f, 0.0f); stageRoadPositon[54] = new Vector3(1320.0f, -210.0f, 0.0f); stageRoadPositon[55] = new Vector3(1320.0f, -230.0f, 0.0f); stageRoadPositon[56] = new Vector3(1320.0f, -250.0f, 0.0f); #endregion #region 石Position stageStonePosition[0] = new Vector3(1220.0f, -190.0f, 0.0f); stageStonePosition[1] = new Vector3(1240.0f, -190.0f, 0.0f); stageStonePosition[2] = new Vector3(1240.0f, -210.0f, 0.0f); stageStonePosition[3] = new Vector3(1240.0f, -230.0f, 0.0f); stageStonePosition[4] = new Vector3(1240.0f, -250.0f, 0.0f); stageStonePosition[5] = new Vector3(1240.0f, -270.0f, 0.0f); stageStonePosition[6] = new Vector3(1260.0f, -270.0f, 0.0f); stageStonePosition[7] = new Vector3(1280.0f, -270.0f, 0.0f); stageStonePosition[8] = new Vector3(1300.0f, -270.0f, 0.0f); stageStonePosition[9] = new Vector3(1320.0f, -270.0f, 0.0f); stageStonePosition[10] = new Vector3(1280.0f, -330.0f, 0.0f); stageStonePosition[11] = new Vector3(1280.0f, -350.0f, 0.0f); stageStonePosition[12] = new Vector3(1280.0f, -370.0f, 0.0f); stageStonePosition[13] = new Vector3(1280.0f, -390.0f, 0.0f); stageStonePosition[14] = new Vector3(1580.0f, -290.0f, 0.0f); #endregion #region //針position stageNeedlePosition[0] = new Vector3(1220.0f, -330.0f, 0.0f); stageNeedlePosition[1] = new Vector3(1240.0f, -330.0f, 0.0f); stageNeedlePosition[2] = new Vector3(1260.0f, -330.0f, 0.0f); stageNeedlePosition[3] = new Vector3(1300.0f, -390.0f, 0.0f); stageNeedlePosition[4] = new Vector3(1320.0f, -390.0f, 0.0f); stageNeedlePosition[5] = new Vector3(1400.0f, -310.0f, 0.0f); stageNeedlePosition[6] = new Vector3(1420.0f, -310.0f, 0.0f); stageNeedlePosition[7] = new Vector3(1500.0f, -390.0f, 0.0f); stageNeedlePosition[8] = new Vector3(1520.0f, -390.0f, 0.0f); stageNeedlePosition[9] = new Vector3(1540.0f, -390.0f, 0.0f); stageNeedlePosition[10] = new Vector3(1560.0f, -390.0f, 0.0f); stageNeedlePosition[11] = new Vector3(1580.0f, -270.0f, 0.0f); #endregion for (int count = 0; count < 57; count++) { stageRoad[count].Min = new Vector3(-boxSize * 0.5f) + stageRoadPositon[count]; stageRoad[count].Max = new Vector3(boxSize * 0.5f) + stageRoadPositon[count]; } for (int count = 0; count < 15; count++) { stageStone[count].Min = new Vector3(-boxSize * 0.5f) + stageStonePosition[count]; stageStone[count].Max = new Vector3(boxSize * 0.05f) + stageStonePosition[count]; } for (int count = 0; count < 12; count++) { stageNeedle[count].Min = new Vector3(-boxSize * 0.5f) + stageNeedlePosition[count]; stageNeedle[count].Max = new Vector3(boxSize * 0.5f) + stageNeedlePosition[count]; } #endregion }
private void RenderFilledItems(GraphicsDevice graphicsDevice, ref Matrix world, ref Matrix view, ref Matrix projection) { if (_batchFilledItems.Count == 0) { return; } if (_vertexBuffer == null || _vertexBuffer.VertexCount < _filledVerticesCount) { _vertexBuffer = new DynamicVertexBuffer(graphicsDevice, VertexPositionColorTexture.VertexDeclaration, _filledVerticesCount, BufferUsage.WriteOnly); } if (_indexBuffer == null || _indexBuffer.IndexCount < _filledIndicesCount) { _indexBuffer = new DynamicIndexBuffer(graphicsDevice, IndexElementSize.ThirtyTwoBits, _filledIndicesCount, BufferUsage.WriteOnly); } int vertexId = 0, indexId = 0; int[] indices = new int[_filledIndicesCount]; VertexPositionColorTexture[] vertices = new VertexPositionColorTexture[_filledVerticesCount]; foreach (PrimitiveBatchItem batchItem in _batchFilledItems) { System.Array.Copy(batchItem.VertexData, 0, vertices, vertexId, batchItem.VertexData.Length); for (int i = 0; i < batchItem.IndexData.Length; i++) { indices[indexId + i] = vertexId + batchItem.IndexData[i]; } vertexId += batchItem.VertexData.Length; indexId += batchItem.IndexData.Length; } _vertexBuffer.SetData( vertices, 0, vertices.Length, SetDataOptions.Discard ); _indexBuffer.SetData( indices, 0, indices.Length, SetDataOptions.Discard ); BasicShader shader = Shader as BasicShader; // transformations shader.World = world; shader.View = view; shader.Projection = projection; shader.DiffuseColor = Color.White; shader.Alpha = 1f; shader.TextureEnabled = false; graphicsDevice.RasterizerState = RasterizerState.CullNone; graphicsDevice.DepthStencilState = DepthStencilState.None; foreach (object pass in shader) { graphicsDevice.Indices = _indexBuffer; graphicsDevice.SetVertexBuffer(_vertexBuffer); graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _vertexBuffer.VertexCount, 0, indexId / 3); } shader.ResetParameters(); #if DEBUG TotalFilledDrawCalls++; #endif }
/// <summary> /// Set the current settings to the particle system attached /// </summary> private void LoadParticleSystem() { this.random = WaveServices.Random; if (this.mesh != null) { if (this.mesh.IndexBuffer != null) { this.GraphicsDevice.DestroyIndexBuffer(this.mesh.IndexBuffer); } if (this.mesh.VertexBuffer != null) { this.GraphicsDevice.DestroyVertexBuffer(this.mesh.VertexBuffer); } this.mesh = null; } this.settings = this.System; this.numParticles = this.System.NumParticles; this.numPrimitives = this.numParticles * 2; this.numVertices = this.numParticles * 4; this.numIndices = this.numParticles * 6; this.particles = new Particle[this.numParticles]; // Sets the time passed between 2 particles creation. this.emitLapse = (this.settings.EmitRate > 0) ? 1000 / this.settings.EmitRate : 0; // Create Indexbuffer ushort[] indices = new ushort[this.numIndices]; for (int i = 0; i < this.numParticles; i++) { indices[(i * 6) + 0] = (ushort)((i * 4) + 0); indices[(i * 6) + 1] = (ushort)((i * 4) + 2); indices[(i * 6) + 2] = (ushort)((i * 4) + 1); indices[(i * 6) + 3] = (ushort)((i * 4) + 0); indices[(i * 6) + 4] = (ushort)((i * 4) + 3); indices[(i * 6) + 5] = (ushort)((i * 4) + 2); } IndexBuffer indexBuffer = new IndexBuffer(indices); // Initialize Particles for (int i = 0; i < this.numParticles; i++) { double life = (this.settings.EmitRate > 0) ? -1 : TimeSpan.FromMilliseconds(this.random.NextDouble() * (this.numParticles * InitTimeMultipler)).TotalMilliseconds; this.particles[i] = new Particle() { Alive = true, Life = life }; } this.vertices = new VertexPositionColorTexture[this.numVertices]; // Initializes the coordinate textures of the vertices for (int i = 0; i < this.numVertices; i++) { this.vertices[i++].TexCoord = TEXCOORD1; this.vertices[i++].TexCoord = TEXCOORD2; this.vertices[i++].TexCoord = TEXCOORD3; this.vertices[i].TexCoord = TEXCOORD4; } DynamicVertexBuffer vertexBuffer = new DynamicVertexBuffer(VertexPositionColorTexture.VertexFormat); vertexBuffer.SetData(this.vertices, this.numVertices); this.mesh = new Mesh(0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3, vertexBuffer, indexBuffer, PrimitiveType.TriangleList); }
/// <summary> /// コンストラクタ /// </summary> /// <param name="triangleCount">三角形の個数</param> /// <param name="vertices">頂点配列</param> /// <param name="indexBuffer">インデックスバッファ</param> public MMDCPUModelPartPNmTxVc(int triangleCount, MMDVertexNmTxVc[] vertices, int[] vertMap, IndexBuffer indexBuffer) : base(triangleCount, vertices.Length, vertMap, indexBuffer) { this.vertices = vertices; //GPUリソース作成 gpuVertices = new VertexPositionNormalTextureColor[vertices.Length]; vertexBuffer = new DynamicVertexBuffer(indexBuffer.GraphicsDevice, typeof(VertexPositionNormalTextureColor), vertices.Length, BufferUsage.WriteOnly); //初期値代入 for (int i = 0; i < vertices.Length; i++) { gpuVertices[i].Position = vertices[i].Position; gpuVertices[i].Normal = vertices[i].Normal; gpuVertices[i].Color = new Color(vertices[i].VertexColor); gpuVertices[i].TextureCoordinate = vertices[i].TextureCoordinate; } // put the vertices into our vertex buffer vertexBuffer.SetData(gpuVertices, 0, vertexCount, SetDataOptions.Discard); }
private void CalculateLightVertices(List <Vector2> rayCastHits) { List <VertexPositionTexture> vertices = new List <VertexPositionTexture>(); Vector2 drawPos = position; if (ParentSub != null) { drawPos += ParentSub.DrawPosition; } float cosAngle = (float)Math.Cos(Rotation); float sinAngle = -(float)Math.Sin(Rotation); Vector2 uvOffset = Vector2.Zero; Vector2 overrideTextureDims = Vector2.One; if (overrideLightTexture != null) { overrideTextureDims = new Vector2(overrideLightTexture.SourceRect.Width, overrideLightTexture.SourceRect.Height); uvOffset = (overrideLightTexture.Origin / overrideTextureDims) - new Vector2(0.5f, 0.5f); } // Add a vertex for the center of the mesh vertices.Add(new VertexPositionTexture(new Vector3(position.X, position.Y, 0), new Vector2(0.5f, 0.5f) + uvOffset)); // Add all the other encounter points as vertices // storing their world position as UV coordinates foreach (Vector2 vertex in rayCastHits) { Vector2 rawDiff = vertex - drawPos; Vector2 diff = rawDiff; diff /= range * 2.0f; if (overrideLightTexture != null) { Vector2 originDiff = diff; diff.X = originDiff.X * cosAngle - originDiff.Y * sinAngle; diff.Y = originDiff.X * sinAngle + originDiff.Y * cosAngle; diff *= (overrideTextureDims / overrideLightTexture.size) * 2.0f; diff += uvOffset; } vertices.Add(new VertexPositionTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0), new Vector2(0.5f, 0.5f) + diff)); } // Compute the indices to form triangles List <short> indices = new List <short>(); for (int i = 0; i < rayCastHits.Count - 1; i++) { indices.Add(0); indices.Add((short)((i + 2) % vertices.Count)); indices.Add((short)((i + 1) % vertices.Count)); } indices.Add(0); indices.Add((short)(1)); indices.Add((short)(vertices.Count - 1)); vertexCount = vertices.Count; indexCount = indices.Count; //TODO: a better way to determine the size of the vertex buffer and handle changes in size? //now we just create a buffer for 64 verts and make it larger if needed if (lightVolumeBuffer == null) { lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount * 1.5)), BufferUsage.None); lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64 * 3, (int)(indexCount * 1.5)), BufferUsage.None); } else if (vertexCount > lightVolumeBuffer.VertexCount) { lightVolumeBuffer.Dispose(); lightVolumeIndexBuffer.Dispose(); lightVolumeBuffer = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionTexture.VertexDeclaration, (int)(vertexCount * 1.5), BufferUsage.None); lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None); } lightVolumeBuffer.SetData <VertexPositionTexture>(vertices.ToArray()); lightVolumeIndexBuffer.SetData <short>(indices.ToArray()); }
public Renderer() { planeCam = new Camera { View = Matrix.CreateLookAt(new Vector3(0, 0, 10), new Vector3(0, 0, 0), Vector3.Up), Projection = Matrix.CreateOrthographic(1f, 1f, 1f, 100.0f)}; Device = Game1.Instance.GraphicsDevice; instanceVertexBuffer = new DynamicVertexBuffer( Game1.Instance.GraphicsDevice, typeof(InstanceData), 1, BufferUsage.WriteOnly); instanceVertexBuffer.SetData( new []{new InstanceData { World = Matrix.Identity }}, 0, 1, SetDataOptions.Discard); }
/// <summary> /// Performs rendering of particles. /// </summary> /// <param name="iterator">The particle iterator object.</param> /// <param name="context">The render context containing rendering information.</param> protected override void Render(ref RenderContext context, ref ParticleIterator iterator) { Int32 vertexCount = 0; Vector3 cameraPos = context.CameraPosition; Vector3 rotationAxis = context.BillboardRotationalAxis; bool squareTexture = (context.Texture.Height == context.Texture.Width); float aspectRatio = context.Texture.Height / (float)context.Texture.Width ; SetDataOptions setDataOptions = SetDataOptions.NoOverwrite; //Use the SpriteBatch style of filling buffers //http://blogs.msdn.com/b/shawnhar/archive/2010/07/07/setdataoptions-nooverwrite-versus-discard.aspx if (_vertexBufferPosition + context.Count * VerticesPerParticle > NumVertices) { //Too much to fit in the remaining space - start at the beginning and discard _vertexBufferPosition = 0; setDataOptions = SetDataOptions.Discard; } #if UNSAFE unsafe { fixed (ParticleVertex* vertexArray = Vertices) { ParticleVertex* verts = vertexArray +_vertexBufferPosition; #else int vertexIndex = _vertexBufferPosition; #endif var particle = iterator.First; do { #if UNSAFE Single scale = particle->Scale; Vector3 position = particle->Position; Vector3 rotation = particle->Rotation; Vector4 colour = particle->Colour; //Work out our world transform - and set a flag to avoid some multiplies if world ends up as zero bool worldIsNotIdentity = true; Matrix effectWorld; if (context.WorldIsIdentity) { if (particle->EffectProxyIndex > 0) { effectWorld = ParticleEffectProxy.Proxies[particle->EffectProxyIndex].World; } else { worldIsNotIdentity = false; effectWorld = Matrix.Identity; //Makes the compiler happy though we will never actually use it. } } else { effectWorld = particle->EffectProxyIndex > 0 ? ParticleEffectProxy.Proxies[particle->EffectProxyIndex].FinalWorld : context.World; } #else Single scale = particle.Scale; Vector3 position = particle.Position; Vector3 rotation = particle.Rotation; Vector4 colour = particle.Colour; //If we have a proxy then multiply in the proxy world matrix bool worldIsNotIdentity = true; Matrix effectWorld; if (context.WorldIsIdentity) { if (particle.EffectProxyIndex > 0) { effectWorld = ParticleEffectProxy.Proxies[particle.EffectProxyIndex].World; } else { worldIsNotIdentity = false; effectWorld = Matrix.Identity; //Makes the compiler happy though we will never actually use it. } } else { effectWorld = particle.EffectProxyIndex > 0 ? ParticleEffectProxy.Proxies[particle.EffectProxyIndex].FinalWorld : context.World; } #endif //Individual particle transformations - scale and rotation //The Rotation setup will fill in the top 3x3 so we just need to initialise 44 var transform = new Matrix {M44 = 1}; float scaleX = scale; float scaleY = squareTexture ? scale : scale * aspectRatio; //ScaleZ is always 1 so no need multiple into M_3 //Inline the rotation and scale calculations and do each element in one go //Fast rotation matrix - see http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations //This set matches //Matrix temp2 = Matrix.CreateRotationX(rotation.X) * Matrix.CreateRotationY(rotation.Y) * Matrix.CreateRotationZ(rotation.Z); //Matches math od Rotx*RotY*RotZ //var cosX = (float) Math.Cos(rotation.X); //var cosY = (float) Math.Cos(rotation.Y); //var cosZ = (float) Math.Cos(rotation.Z); //var sinX = (float) Math.Sin(rotation.X); //var sinY = (float) Math.Sin(rotation.Y); //var sinZ = (float) Math.Sin(rotation.Z); //transform.M11 = cosY*cosZ; //transform.M12 = cosY * sinZ; //transform.M13 = -sinY; //transform.M21 = sinX*sinY*cosZ - cosX * sinZ; //transform.M22 = sinX*sinY*sinZ + cosX*cosZ; //transform.M23 = sinX*cosY; //transform.M31 = cosX*sinY*cosZ + sinX * sinZ; //transform.M32 = cosX*sinY*sinZ - sinX * cosZ; //transform.M33 = cosX * cosY; //This set matches //Matrix temp2 = Matrix.CreateScale(new VEctor3(scaleX, scaleY,1) * Matrix.CreateRotationZ(rotation.Z) * Matrix.CreateRotationX(rotation.Y) * Matrix.CreateRotationY(rotation.X) ; //Matches YawPitchRoll order //Matrix temp = Matrix.CreateScale(new VEctor3(scaleX, scaleY,1) * Matrix.CreateFromYawPitchRoll(rotation.X, rotation.Y, rotation.Z); //TODO - can we optimise out a rotation e.g.fast path if rotation.Y=0 etc //TODO - can we optimise out rotation(s) if we know its a billboard? That overwrites much of the transform var cosX = (float)Math.Cos(rotation.Y); var cosY = (float)Math.Cos(rotation.X); var cosZ = (float)Math.Cos(rotation.Z); var sinX = (float)Math.Sin(rotation.Y); var sinY = (float)Math.Sin(rotation.X); var sinZ = (float)Math.Sin(rotation.Z); var cosYcosZ = cosY*cosZ; var cosYsinZ = cosY*sinZ; var sinXsinY = sinX*sinY; transform.M11 = (cosYcosZ + sinXsinY * sinZ) * scaleX; transform.M12 = (cosX * sinZ) * scaleX; transform.M13 = (sinX * cosYsinZ - sinY * cosZ) * scaleX; transform.M21 = (sinXsinY * cosZ - cosYsinZ) * scaleY; transform.M22 = (cosX * cosZ) *scaleY; transform.M23 = (sinY * sinZ + sinX * cosYcosZ) * scaleY; transform.M31 = cosX * sinY; transform.M32 = -sinX; transform.M33 = cosX * cosY; switch (context.BillboardStyle) { case BillboardStyle.None: //Position the particle without a multiplication! transform.M41 = position.X; transform.M42 = position.Y; transform.M43 = position.Z; //Just apply the world //TODO - we can just do this in Basic effect instead of per vertex - only if there is no proxy, sort of a fast path! if (worldIsNotIdentity) { Matrix.Multiply(ref transform, ref effectWorld, out transform); } break; default: //Its billboarded Vector3 worldPos; if (worldIsNotIdentity) { Vector3.Transform(ref position, ref effectWorld, out worldPos); } else { worldPos = position; } //Apply the billboard (which includes the world translation) Matrix billboardMatrix; if (context.BillboardStyle == BillboardStyle.Spherical) { //Spherical billboards (always face the camera) Matrix.CreateBillboard(ref worldPos, ref cameraPos, ref Up, Forward, out billboardMatrix); } else { //HACK: For progenitor DBP use the velocity as the axis for a per particle axis if (context.UseVelocityAsBillboardAxis) { #if UNSAFE Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref particle->Velocity, Forward, null, out billboardMatrix); #else Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref particle.Velocity, Forward, null, out billboardMatrix); #endif } else { //Cylindrical billboards have a vector they are allowed to rotate around Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref rotationAxis, Forward, null, out billboardMatrix); } } Matrix.Multiply(ref transform, ref billboardMatrix, out transform); break; } Vector3 v1; Vector3 v2; Vector3 v3; Vector3 v4; Vector3.Transform(ref inv1, ref transform, out v1); Vector3.Transform(ref inv2, ref transform, out v2); Vector3.Transform(ref inv3, ref transform, out v3); Vector3.Transform(ref inv4, ref transform, out v4); #if UNSAFE //inline particle value assignments - removes 4 calls with their parameters and its a struct anyway verts->Position.X = v1.X; verts->Position.Y = v1.Y; verts->Position.Z = v1.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v2.X; verts->Position.Y = v2.Y; verts->Position.Z = v2.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v3.X; verts->Position.Y = v3.Y; verts->Position.Z = v3.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v4.X; verts->Position.Y = v4.Y; verts->Position.Z = v4.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; #else //inline particle value assignments - removes 4 calls with their parameters and its a struct anyway this.Vertices[vertexIndex].Position = v1; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv1; this.Vertices[vertexIndex].Position = v2; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv2; this.Vertices[vertexIndex].Position = v3; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv3; this.Vertices[vertexIndex].Position = v4; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv4; #endif vertexCount += 4; } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif base.GraphicsDeviceService.GraphicsDevice.BlendState = context.BlendState; this.BasicEffect.Texture = context.Texture; //Xbox need the vertex buffer to be set to null before SetData is called //Windows does not //TODO: Is this a bug? see http://forums.create.msdn.com/forums/p/61885/399495.aspx#399495 #if XBOX if (setDataOptions == SetDataOptions.Discard) { base.GraphicsDeviceService.GraphicsDevice.SetVertexBuffer(null); } #endif _vertexBuffer.SetData(_vertexBufferPosition * ParticleVertex.Size, Vertices, _vertexBufferPosition, vertexCount, ParticleVertex.Size, setDataOptions); Debug.WriteLine(String.Format("position: {0} Count: {1} Hint: {2}", _vertexBufferPosition, vertexCount, setDataOptions)); base.GraphicsDeviceService.GraphicsDevice.SetVertexBuffer(_vertexBuffer); foreach (EffectPass pass in this.BasicEffect.CurrentTechnique.Passes) { pass.Apply(); base.GraphicsDeviceService.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, _vertexBufferPosition, vertexCount, _vertexBufferPosition/4*6, vertexCount/2); } //Move to the next free part of the array _vertexBufferPosition += vertexCount; #if UNSAFE } } #endif }
public void Hook(RTSRenderer renderer, GameState s, int ti, int fti, int building) { // Filter For Unit Types RTSTeam team = s.teams[ti]; Data = team.Race.Buildings[building]; fTeam = s.teams[fti]; eTeamIndex = ti; fTeamIndex = fti; bType = building; // Create Instance Buffer visible = new List<VisibleBuilding>(); instVerts = new VertexRTSAnimInst[Data.MaxCount]; for(int i = 0; i < instVerts.Length; i++) instVerts[i] = new VertexRTSAnimInst(Matrix.Identity, 1); dvbInstances = renderer.CreateDynamicVertexBuffer(VertexRTSAnimInst.Declaration, instVerts.Length, BufferUsage.WriteOnly); dvbInstances.SetData(instVerts); dvbInstances.ContentLost += (sender, args) => { rebuildDVB = true; }; rebuildDVB = false; }
/// <summary> /// Draws the particle system. /// </summary> public void Render() { GraphicsDevice device = GameEngine.Device; ICamera camera = GameEngine.Camera; effectViewParameter.SetValue(camera.View); effectProjectionParameter.SetValue(camera.Projection); // Restore the vertex buffer contents if the graphics device was lost. if (vertexBuffer.IsContentLost) { vertexBuffer.SetData(particles); } // If there are any particles waiting in the newly added queue, // we'd better upload them to the GPU ready for drawing. if (firstNewParticle != firstFreeParticle) { AddNewParticlesToVertexBuffer(); } // If there are any active particles, draw them now! if (firstActiveParticle != firstFreeParticle) { //SetParticleRenderStates(device.RenderState); // Set an effect parameter describing the viewport size. This is // needed to convert particle sizes into screen space point sizes. effectViewportScaleParameter.SetValue(new Vector2(0.5f / device.Viewport.AspectRatio, -0.5f)); // Set an effect parameter describing the current time. All the vertex // shader particle animation is keyed off this value. effectTimeParameter.SetValue(currentTime); // Set the particle vertex and index buffer. // device.Vertices[0].SetSource(vertexBuffer, 0, ParticleVertex.SizeInBytes); device.Indices = indexBuffer; // device.VertexDeclaration = _vertexDeclaration; //particleEffect.Begin(); // Activate the particle effect. foreach (EffectPass pass in particleEffect.CurrentTechnique.Passes) { //pass.Begin(); if (firstActiveParticle < firstFreeParticle) { // If the active particles are all in one consecutive range, // we can draw them all in a single call. device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, firstActiveParticle * 4, (firstFreeParticle - firstActiveParticle) * 4, firstActiveParticle * 6, (firstFreeParticle - firstActiveParticle) * 2); } else { // If the active particle range wraps past the end of the queue // back to the start, we must split them over two draw calls. device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, firstActiveParticle * 4, (settings.MaxParticles - firstActiveParticle) * 4, firstActiveParticle * 6, (settings.MaxParticles - firstActiveParticle) * 2); if (firstFreeParticle > 0) { device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, firstFreeParticle * 4, 0, firstFreeParticle * 2); } } //pass.End(); } //particleEffect.End(); // Reset some of the renderstates that we changed, // so as not to mess up any other subsequent drawing. //device.RenderState.DepthBufferWriteEnable = true; } drawCounter++; }
public void Update() { for (int p = 0; p < particleArray.Length; p += 4) { for (int thisP = 0; thisP < 4; thisP++) { if (p == nextParticle && myLastpos != targetPos) { particleArray[p + thisP].Position = myLastpos; particleArray[p + thisP].Color = particleColor; } particleArray[p + thisP].SpriteSize = Size; } } nextParticle++; if (nextParticle >= particleArray.Length / 4) nextParticle = 0; vb = new DynamicVertexBuffer(REngine.Instance._game.GraphicsDevice, typeof(BillboardParticleElement), 4 * partCount, BufferUsage.WriteOnly); vb.SetData(particleArray); myLastpos = targetPos; }
private void InitializeBuffers() { Vertex[] vertices = new Vertex[Size * Size]; for (int i = 0; i < Size; i++) for (int j = 0; j < Size; j++) vertices[i + j * Size].Position = new Vector3(i, 0.0f, -j); int[] indices = new int[(Size - 1) * (Size - 1) * 6]; int count = 0; for (int i = 0; i < Size - 1; i++) for (int j = 0; j < Size - 1; j++) { indices[count++] = GetIndex(i, j); indices[count++] = GetIndex(i, j + 1); indices[count++] = GetIndex(i + 1, j); indices[count++] = GetIndex(i, j + 1); indices[count++] = GetIndex(i + 1, j + 1); indices[count++] = GetIndex(i + 1, j); } int maxIndices = (Size - 1) * (Size - 1) * 6; VertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(Vertex), vertices.Length, BufferUsage.None); IndexBuffer = new DynamicIndexBuffer(GraphicsDevice, typeof(int), maxIndices, BufferUsage.None); BasicIndexBuffer = new IndexBuffer(GraphicsDevice, typeof(int), maxIndices, BufferUsage.None); VertexBuffer.SetData<Vertex>(vertices); BasicIndexBuffer.SetData<int>(indices); }
/*public void Transform(Bone bone) { var binding = BoneBindings.FirstOrDefault(x => x.BoneName.Equals(bone.Name, StringComparison.InvariantCultureIgnoreCase)); if (binding != null) { for (var i = 0; i < binding.RealVertexCount; i++) { var vertexIndex = binding.FirstRealVertex + i; var blendVertexIndex = vertexIndex;//binding.FirstBlendVertex + i; var realVertex = RealVertexBuffer[vertexIndex]; //var matrix = Matrix.CreateTranslation(realVertex.Position) * bone.AbsoluteMatrix; //Position var newPosition = Vector3.Transform(realVertex.Position, bone.AbsoluteMatrix); BlendVertexBuffer[blendVertexIndex].Position = newPosition; //Normals var matrix = Matrix.CreateTranslation( new Vector3(realVertex.Normal.X, realVertex.Normal.Y, realVertex.Normal.Z)) * bone.AbsoluteMatrix; } for (var i = 0; i < binding.BlendVertexCount; i++) { var blendVertexIndex = binding.FirstBlendVertex + i; var realVertex = UntransformedBlendVerts[blendVertexIndex]; //Position var newPosition = Vector3.Transform(realVertex, bone.AbsoluteMatrix); TransformedBlendVerts[blendVertexIndex] = newPosition; //todo, alter normals too. would it be correct to linear interpolate that too? it seems like doing that might be kinda stupid } } foreach (var child in bone.Children) { Transform(child); } if (bone.Name.Equals("ROOT", StringComparison.InvariantCultureIgnoreCase)) { for (int i = 0; i < BlendData.Length; i++) { var data = BlendData[i]; var vert = TransformedBlendVerts[i]; BlendVertexBuffer[data.OtherVertex].Position = Vector3.Lerp(BlendVertexBuffer[data.OtherVertex].Position, vert, data.Weight); } InvalidateMesh(); } }*/ public void StoreOnGPU(GraphicsDevice device) { GPUMode = true; GPUVertexBuffer = new DynamicVertexBuffer(device, typeof(VitaboyVertex), VertexBuffer.Length, BufferUsage.None); GPUVertexBuffer.SetData(VertexBuffer); GPUIndexBuffer = new IndexBuffer(device, IndexElementSize.SixteenBits, IndexBuffer.Length, BufferUsage.None); GPUIndexBuffer.SetData(IndexBuffer); }
public static void Render(GraphicsDevice device, Shader effect, bool delete) { BlendState origBlen = device.BlendState; device.BlendState = BlendState.NonPremultiplied; RasterizerState newState = RasterizerState.CullNone; RasterizerState oldState = device.RasterizerState; device.RasterizerState = newState; effect.CurrentTechnique = effect.Techniques[Shader.Technique.Untextured]; effect.World = Matrix.Identity; DrawCommand3D.LineStrip strips = new DrawCommand3D.LineStrip() { Vertices = new List <VertexPositionColor>() }; foreach (DrawCommand3D command in Commands) { if (command.DrawAccumlatedStrips) { command.AccumulateStrips(strips); } } if (strips.Vertices.Count > 0 && (StripVertices == null || strips.Vertices.Count > StripVertices.Count())) { StripVertices = new VertexPositionColor[strips.Vertices.Count * 2]; StripBuffer = new DynamicVertexBuffer(device, VertexPositionColor.VertexDeclaration, strips.Vertices.Count * 2, BufferUsage.WriteOnly); } if (strips.Vertices.Count > 0) { strips.Vertices.CopyTo(StripVertices); MaxStripVertex = strips.Vertices.Count; if (MaxStripVertex > 0 && StripBuffer != null) { StripBuffer.SetData(StripVertices, 0, MaxStripVertex); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.SetVertexBuffer(StripBuffer); device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, strips.Vertices.Count - 2); } } } effect.CurrentTechnique = effect.Techniques[Shader.Technique.Textured]; foreach (DrawCommand3D command in Commands) { if (!command.DrawAccumlatedStrips) { command.Render(device, effect); } } if (oldState != null) { device.RasterizerState = oldState; } if (origBlen != null) { device.BlendState = origBlen; } if (!delete) { return; } while (Commands.Count > 0) { DrawCommand3D result = null; Commands.TryTake(out result); } }
/// <summary> /// Build the mesh used to draw the particles /// </summary> private void BuildMesh() { if (this.mesh != null) { this.DestroyMesh(); } this.maxProjectiles = this.manager.Capacity; int nVertices = VerticesPerProjectile * this.maxProjectiles; int nIndices = IndicesPerProjectile * this.maxProjectiles; // Indices ushort[] indices = new ushort[nIndices]; for (int i = 0; i < this.maxProjectiles; i++) { indices[(i * IndicesPerProjectile) + 0] = (ushort)(i * 4); indices[(i * IndicesPerProjectile) + 1] = (ushort)((i * 4) + 1); indices[(i * IndicesPerProjectile) + 2] = (ushort)((i * 4) + 2); indices[(i * IndicesPerProjectile) + 3] = (ushort)((i * 4) + 2); indices[(i * IndicesPerProjectile) + 4] = (ushort)((i * 4) + 3); indices[(i * IndicesPerProjectile) + 5] = (ushort)(i * 4); } IndexBuffer indexBuffer = new IndexBuffer(indices); this.RenderManager.GraphicsDevice.BindIndexBuffer(indexBuffer); // Vertices this.vertices = new VertexPositionColorTexture[nVertices]; for (int i = 0; i < this.maxProjectiles; i++) { vertices[(i * VerticesPerProjectile) + 0].TexCoord = Vector2.Zero; vertices[(i * VerticesPerProjectile) + 0].Color = Color.White; vertices[(i * VerticesPerProjectile) + 1].TexCoord = Vector2.UnitX; vertices[(i * VerticesPerProjectile) + 1].Color = Color.White; vertices[(i * VerticesPerProjectile) + 2].TexCoord = Vector2.One; vertices[(i * VerticesPerProjectile) + 2].Color = Color.White; vertices[(i * VerticesPerProjectile) + 3].TexCoord = Vector2.UnitY; vertices[(i * VerticesPerProjectile) + 3].Color = Color.White; } DynamicVertexBuffer vertexBuffer = new DynamicVertexBuffer(VertexPositionColorTexture.VertexFormat); vertexBuffer.SetData(this.vertices); this.GraphicsDevice.BindVertexBuffer(vertexBuffer); this.mesh = new Mesh(0, nVertices, 0, nIndices / 3, vertexBuffer, indexBuffer, PrimitiveType.TriangleList) { DisableBatch = true }; }
/// <summary> /// Draws the particle system. /// </summary> public override void Draw(GameTime gameTime) { GraphicsDevice device = GraphicsDevice; // Restore the vertex buffer contents if the graphics device was lost. if (vertexBuffer.IsContentLost) { vertexBuffer.SetData(particles); } // If there are any particles waiting in the newly added queue, // we'd better upload them to the GPU ready for drawing. if (firstNewParticle != firstFreeParticle) { AddNewParticlesToVertexBuffer(); } // If there are any active particles, draw them now! if (firstActiveParticle != firstFreeParticle) { SetParticleRenderStates(device.RenderState); // Set an effect parameter describing the viewport size. This is needed // to convert particle sizes into screen space point sprite sizes. effectViewportHeightParameter.SetValue(device.Viewport.Height); // Set an effect parameter describing the current time. All the vertex // shader particle animation is keyed off this value. effectTimeParameter.SetValue(currentTime); // Set the particle vertex buffer and vertex declaration. device.Vertices[0].SetSource(vertexBuffer, 0, ParticleVertex.SizeInBytes); device.VertexDeclaration = vertexDeclaration; // Activate the particle effect. particleEffect.Begin(); foreach (EffectPass pass in particleEffect.CurrentTechnique.Passes) { pass.Begin(); if (firstActiveParticle < firstFreeParticle) { // If the active particles are all in one consecutive range, // we can draw them all in a single call. device.DrawPrimitives(PrimitiveType.PointList, firstActiveParticle, firstFreeParticle - firstActiveParticle); } else { // If the active particle range wraps past the end of the queue // back to the start, we must split them over two draw calls. device.DrawPrimitives(PrimitiveType.PointList, firstActiveParticle, particles.Length - firstActiveParticle); if (firstFreeParticle > 0) { device.DrawPrimitives(PrimitiveType.PointList, 0, firstFreeParticle); } } pass.End(); } particleEffect.End(); // Reset a couple of the more unusual renderstates that we changed, // so as not to mess up any other subsequent drawing. device.RenderState.PointSpriteEnable = false; device.RenderState.DepthBufferWriteEnable = true; } drawCounter++; }
/// <summary> /// Set the current settings to the particle system attached /// </summary> private void LoadParticleSystem() { this.random = WaveServices.Random; if (this.mesh != null) { if (this.mesh.IndexBuffer != null) { this.GraphicsDevice.DestroyIndexBuffer(this.mesh.IndexBuffer); } if (this.mesh.VertexBuffer != null) { this.GraphicsDevice.DestroyVertexBuffer(this.mesh.VertexBuffer); } this.mesh = null; } this.settings = this.System; this.numParticles = this.System.NumParticles; this.numPrimitives = this.numParticles * 2; this.numVertices = this.numParticles * 4; this.numIndices = this.numParticles * 6; this.particles = new Particle[this.numParticles]; // Create Indexbuffer ushort[] indices = new ushort[this.numIndices]; for (int i = 0; i < this.numParticles; i++) { indices[(i * 6) + 0] = (ushort)((i * 4) + 0); indices[(i * 6) + 1] = (ushort)((i * 4) + 2); indices[(i * 6) + 2] = (ushort)((i * 4) + 1); indices[(i * 6) + 3] = (ushort)((i * 4) + 0); indices[(i * 6) + 4] = (ushort)((i * 4) + 3); indices[(i * 6) + 5] = (ushort)((i * 4) + 2); } IndexBuffer indexBuffer = new IndexBuffer(indices); // Initialize Particles for (int i = 0; i < this.numParticles; i++) { double life = (this.settings.EmitRate > 0) ? -1 : TimeSpan.FromSeconds(this.random.NextDouble() * (this.numParticles * InitTimeMultipler)).TotalSeconds; this.particles[i] = new Particle() { Alive = true, Life = life }; } this.vertices = new VertexPositionNormalColorTexture[this.numVertices]; DynamicVertexBuffer vertexBuffer = new DynamicVertexBuffer(VertexPositionNormalColorTexture.VertexFormat); vertexBuffer.SetData(this.vertices, this.numVertices); this.mesh = new Mesh(0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3, vertexBuffer, indexBuffer, PrimitiveType.TriangleList) { DisableBatch = true }; }
private void Flush( InstanceGroup Group, GraphicsDevice Device, Shader Effect, Camera Camera, RenderMode Mode) { if (InstanceBuffer == null) { InstanceBuffer = new DynamicVertexBuffer(Device, InstancedVertex.VertexDeclaration, InstanceQueueSize, BufferUsage.None); } Effect.EnableWind = Group.RenderData.EnableWind; Device.RasterizerState = new RasterizerState { CullMode = CullMode.None }; if (Mode == RenderMode.Normal) { Effect.SetInstancedTechnique(); } else { Effect.CurrentTechnique = Effect.Techniques[Shader.Technique.SelectionBufferInstanced]; } Effect.EnableLighting = true; Effect.VertexColorTint = Color.White; if (Group.RenderData.Model.VertexBuffer == null || Group.RenderData.Model.IndexBuffer == null) { Group.RenderData.Model.ResetBuffer(Device); } bool hasIndex = Group.RenderData.Model.IndexBuffer != null; Device.Indices = Group.RenderData.Model.IndexBuffer; BlendState blendState = Device.BlendState; Device.BlendState = Mode == RenderMode.Normal ? Group.RenderData.BlendMode : BlendState.Opaque; Effect.MainTexture = Group.RenderData.Model.Texture; Effect.LightRampTint = Color.White; InstanceBuffer.SetData(Group.Instances, 0, Group.InstanceCount, SetDataOptions.Discard); Device.SetVertexBuffers(Group.RenderData.Model.VertexBuffer, new VertexBufferBinding( InstanceBuffer, 0, 1)); foreach (EffectPass pass in Effect.CurrentTechnique.Passes) { pass.Apply(); Device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, Group.RenderData.Model.VertexCount, 0, Group.RenderData.Model.Indexes.Length / 3, Group.InstanceCount); } Effect.SetTexturedTechnique(); Effect.World = Matrix.Identity; Device.BlendState = blendState; Effect.EnableWind = false; Group.InstanceCount = 0; }
public static void Render(Matrix view, Matrix proj) { if (!m_RenderEnabled) return; GraphicsDevice device = Core.GetDevice(); m_DomeEffect.Parameters["View"].SetValue(view); m_DomeEffect.Parameters["Projection"].SetValue(proj); m_DomeEffect.Parameters["ViewportScale"].SetValue(new Vector2(0.5f / device.Viewport.AspectRatio, -0.5f)); // Restore the vertex buffer contents if the graphics device was lost. if (m_VB.IsContentLost) { m_VB = new DynamicVertexBuffer(device, JellyVertex.VertexDeclaration, TOTAL_LEDS * 4, BufferUsage.WriteOnly); m_VB.SetData(m_Lights); } device.BlendState = BlendState.Opaque; device.DepthStencilState = DepthStencilState.DepthRead; // Set the vertex and index buffer. device.SetVertexBuffer(m_VB); device.Indices = m_IB; // Activate the particle effect. foreach (EffectPass pass in m_DomeEffect.CurrentTechnique.Passes) { pass.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, TOTAL_LEDS * 4, 0, TOTAL_LEDS * 2); } device.DepthStencilState = DepthStencilState.Default; device.SetVertexBuffer(null); }
/// <summary> /// Set the current settings to the particle system attached /// </summary> private void LoadParticleSystem() { if (this.mesh != null) { if (this.mesh.IndexBuffer != null) { this.GraphicsDevice.DestroyIndexBuffer(this.mesh.IndexBuffer); } if (this.mesh.VertexBuffer != null) { this.GraphicsDevice.DestroyVertexBuffer(this.mesh.VertexBuffer); } this.mesh = null; } this.settings = this.System; this.numParticles = this.System.NumParticles; this.numPrimitives = this.numParticles * 2; this.numVertices = this.numParticles * 4; this.numIndices = this.numParticles * 6; this.particles = new Particle[this.numParticles]; // Create Indexbuffer ushort[] indices = new ushort[this.numIndices]; for (int i = 0; i < this.numParticles; i++) { indices[(i * 6) + 0] = (ushort)((i * 4) + 0); indices[(i * 6) + 1] = (ushort)((i * 4) + 2); indices[(i * 6) + 2] = (ushort)((i * 4) + 1); indices[(i * 6) + 3] = (ushort)((i * 4) + 0); indices[(i * 6) + 4] = (ushort)((i * 4) + 3); indices[(i * 6) + 5] = (ushort)((i * 4) + 2); } IndexBuffer indexBuffer = new IndexBuffer(indices); // Initialize Particles for (int i = 0; i < this.numParticles; i++) { double life = (this.settings.EmitRate > 0) ? -1 : TimeSpan.FromSeconds(this.random.NextDouble() * (this.numParticles * InitTimeMultipler)).TotalSeconds; this.particles[i] = new Particle() { Alive = true, Life = life }; } this.vertices = new VertexPositionNormalColorTexture[this.numVertices]; DynamicVertexBuffer vertexBuffer = new DynamicVertexBuffer(VertexPositionNormalColorTexture.VertexFormat); vertexBuffer.SetData(this.vertices, this.numVertices); this.mesh = new Mesh(0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3, vertexBuffer, indexBuffer, PrimitiveType.TriangleList) { DisableBatch = true }; }
// Create a dynamic vertex buffer. The arguments texture and region are used to flag a content reload if the device is lost. private DynamicVertexBuffer CreateVertexBufferFromFaceList(Dictionary<uint, bool> faceList, int texture, int region) { if (faceList.Count == 0) return null; VertexPositionTextureShade[] vertexList = new VertexPositionTextureShade[faceList.Count * 6]; ulong vertexPointer = 0; foreach (uint faceInfo in faceList.Keys) { BuildFaceVertices(ref vertexList, vertexPointer, faceInfo, texture == (int)BlockTexture.Spikes); vertexPointer += 6; } DynamicVertexBuffer vertexBuffer = new DynamicVertexBuffer(gameInstance.GraphicsDevice, vertexList.Length * VertexPositionTextureShade.SizeInBytes, BufferUsage.WriteOnly); vertexBuffer.ContentLost += new EventHandler(vertexBuffer_ContentLost); vertexBuffer.Tag = new DynamicVertexBufferTag(this, texture, region); vertexBuffer.SetData(vertexList); return vertexBuffer; }
internal ParticleEmitter(int maxNumOfParticles, Effect effect, Texture2D texture1, Texture2D texture2 = null) : base("particleEmitter", new Actor(new DummyAnimation())) { //This makes particles draw on top of all objects Static = true; //sets max number of particles this.maxNumOfParticles = maxNumOfParticles; //instantiate array of particle vertices & indicies particleVertices = new ParticleVertexFormat[maxNumOfParticles * 4]; particleIndices = new int[maxNumOfParticles * 6]; //instantiate array of time to lives to all particles expirationTime = new int[maxNumOfParticles]; numOfActiveParticles = 0; //Allocate memory on gpu for vertices & indicies vertexBuffer = new DynamicVertexBuffer(This.Game.GraphicsDevice, ParticleVertexFormat.VertexDeclaration, particleVertices.Length, BufferUsage.WriteOnly); indexBuffer = new IndexBuffer(This.Game.GraphicsDevice, typeof(int), particleIndices.Length, BufferUsage.WriteOnly); //create all indices (they never change) for (int i = 0; i < maxNumOfParticles; i++) setIndices(i); //give buffer's their data vertexBuffer.SetData(particleVertices); indexBuffer.SetData(particleIndices); //load Texture this.texture1 = texture1; this.texture2 = texture2; //load the HLSL code this.effect = effect.Clone(); sendConstantsToGPU(); collisionObjects.Add(new Collision_BoundingCircle(1, Vector2.Zero, 10)); this.CollisionList = 2; }
public void Build() { if (vertices.Count == 0) return; VertexBuffer = new DynamicVertexBuffer(Game.graphics.GraphicsDevice, VertexPositionNormalColor.VertexDeclaration, vertices.Count, BufferUsage.WriteOnly); VertexBuffer.SetData<VertexPositionNormalColor>(vertices.ToArray()); }
private void dynVertBuffer_ContentLost(object sender, EventArgs e) { dynVertBuffer.SetData(vertices, 0, vertices.Length, SetDataOptions.NoOverwrite); }