public override DrawGroup <Geometry> ApplyChanges() { if (!dataModified) { return(this); } int vertexCount = (int)count * TotalVertices; vertexPositionBuffer?.Dispose(); vertexPositionBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexPosition), vertexCount, BufferUsage.WriteOnly); vertexPositionBuffer.SetData(vertexPositions, 0, vertexCount); transformBuffer?.Dispose(); transformBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTransform), vertexCount, BufferUsage.WriteOnly); transformBuffer.SetData(transforms, 0, vertexCount); colorBuffer?.Dispose(); colorBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexColor), vertexCount, BufferUsage.WriteOnly); colorBuffer.SetData(colors, 0, vertexCount); vertexBufferBindings = new VertexBufferBinding[] { new VertexBufferBinding(vertexPositionBuffer), new VertexBufferBinding(transformBuffer), new VertexBufferBinding(colorBuffer), }; dataModified = false; return(this); }
public void Dispose() { IsDisposed = true; vertexBuffer?.Dispose(); indexBuffer?.Dispose(); }
private void InitTransforms(VertexBuffer modelVertices) { Array.Resize(ref instanceTransforms, Instances.Count); for (int i = 0; i < Instances.Count; i++) { instanceTransforms[i] = Instances[i]; } if ((instanceVertexBuffer == null) || instanceTransforms.Length > instanceVertexBuffer.VertexCount) { instanceVertexBuffer?.Dispose(); instanceVertexBuffer = new DynamicVertexBuffer(graphics, InstanceVertexDeclaration, instanceTransforms.Length, BufferUsage.WriteOnly); } instanceVertexBuffer.SetData( instanceTransforms, 0, instanceTransforms.Length, SetDataOptions.Discard); graphics.SetVertexBuffers( new VertexBufferBinding(modelVertices, 0, 0), new VertexBufferBinding(instanceVertexBuffer, 0, 1) ); }
public override DrawGroup <Sprite> ApplyChanges() { if (!dataModified) { return(this); } int vertexCount = (int)count * 4; transformBuffer?.Dispose(); transformBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTransform), (int)count, BufferUsage.WriteOnly); transformBuffer.SetData(transforms, 0, (int)count); colorBuffer?.Dispose(); colorBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexColor), (int)count, BufferUsage.WriteOnly); colorBuffer.SetData(colors, 0, (int)count); textureCoordBuffer?.Dispose(); textureCoordBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTexture), vertexCount, BufferUsage.WriteOnly); textureCoordBuffer.SetData(textureCoords, 0, vertexCount); vertexBufferBindings = new VertexBufferBinding[] { new VertexBufferBinding(sharedGeometry.VertexPositionBuffer), new VertexBufferBinding(transformBuffer, 0, 1), new VertexBufferBinding(colorBuffer, 0, 1), new VertexBufferBinding(textureCoordBuffer) }; dataModified = false; return(this); }
public static void SetVertices <T>(GraphicsDevice device, ref DynamicVertexBuffer buffer, VertexDeclaration declaration, T[] data) where T : struct { // If we have more instances than room in our vertex buffer, grow it to the necessary size. if (buffer == null || data.Length > buffer.VertexCount) { buffer?.Dispose(); buffer = new DynamicVertexBuffer(device, declaration, data.Length, BufferUsage.WriteOnly); } // Transfer the latest instance transform matrices into the instanceVertexBuffer. buffer.SetData(data, 0, data.Length, SetDataOptions.Discard); }
private void UpdateBuffer() { transformBuffer?.Dispose(); transformBuffer = new DynamicVertexBuffer(Engine.Graphics.GraphicsDevice, typeof(VertexTransformColor), transforms.Length, BufferUsage.WriteOnly); transformBuffer.SetData(transforms); vertexBufferBindings = new VertexBufferBinding[] { new VertexBufferBinding(sharedShapeData.Geometry), new VertexBufferBinding(transformBuffer, 0, 1) }; }
private void EnsureBufferSize(int vbs, int ibs) { if (_vertexBuffer == null || _vertexBuffer.VertexCount < vbs) { _vertexBuffer?.Dispose(); _vertexBuffer = new DynamicVertexBuffer(GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vbs, BufferUsage.WriteOnly); } if (_indexBuffer == null || _indexBuffer.IndexCount < ibs) { _indexBuffer?.Dispose(); _indexBuffer = new DynamicIndexBuffer(GraphicsDevice, IndexElementSize.ThirtyTwoBits, ibs, BufferUsage.WriteOnly); } }
public void Remove() { if (!lightSourceParams.Persistent) { LightSprite?.Remove(); OverrideLightTexture?.Remove(); } DeformableLightSprite?.Remove(); DeformableLightSprite = null; lightVolumeBuffer?.Dispose(); lightVolumeBuffer = null; lightVolumeIndexBuffer?.Dispose(); lightVolumeIndexBuffer = null; GameMain.LightManager.RemoveLight(this); }
/// <summary> /// Updates the vertex-buffer with the newest information /// </summary> public void Update() { GameObject[] safe = GameObjects.ToArray(); // Store the size VertexBufferSize = safe.Length; // Vertex-buffer with 0 elements fails => handle this by explicitly doing nothing. // Important: Now there is most likely an instance remaining in the buffer => handle this case in the draw if (safe.Length == 0) { return; } // Update the size (which is only done if needed) and transfer all needed values for the vertex-description Array.Resize(ref VertexInformation, VertexBufferSize); for (int i = 0; i < VertexBufferSize; ++i) { if (safe[i] == null) { continue; } VertexInformation[i].Matrix = safe[i].transform.World; VertexInformation[i].Alpha = safe[i].Alpha; } // Re-Initialize the vertex-buffer if needed if (VertexBuffer == null || VertexBufferSize > VertexBuffer.VertexCount) { VertexBuffer?.Dispose(); VertexBuffer = new DynamicVertexBuffer(Graphics.gD, VertexPositionAlpha.InstanceVertexDeclaration, VertexBufferSize, BufferUsage.WriteOnly); } // Transfer the latest instance gameObject matrices into the vertex-buffer. VertexBuffer.SetData(VertexInformation, 0, VertexInformation.Length, SetDataOptions.Discard); }
private void CreateVertexBufferBindings() { if (Entities.Count <= 0) { return; } transformBuffer?.Dispose(); transformBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTransform), transformData.Length, BufferUsage.WriteOnly); transformBuffer.SetData(transformData); colorBuffer?.Dispose(); colorBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexColor), colorData.Length, BufferUsage.WriteOnly); colorBuffer.SetData(colorData); vertexBufferBindings = new VertexBufferBinding[] { new VertexBufferBinding(geometry.VertexPositionBuffer), new VertexBufferBinding(transformBuffer, 0, 1), new VertexBufferBinding(colorBuffer, 0, 1) }; }
internal void GetInstanceBuffer(ref Vector3 cameraPosition, bool forceUpdate, out VertexBuffer vertexBuffer, out int vertexCount) { if (instanceTransforms == null || instanceTransforms.Length <= 0) { vertexBuffer = null; vertexCount = 0; return; } instanceTransformsNeedsUpdate |= forceUpdate; if (instanceBuffer == null || instanceTransformsNeedsUpdate || instanceBuffer.VertexCount < instanceTransforms.Length) { if (vertexDeclaration == null) { vertexDeclaration = new VertexDeclaration ( new VertexElement(0, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 4), new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 5), new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 6), new VertexElement(48, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 7) ); } if (instanceBuffer != null) { instanceBuffer.Dispose(); } instanceBuffer = new DynamicVertexBuffer(GraphicsDevice, vertexDeclaration, instanceTransforms.Length, BufferUsage.WriteOnly); instanceTransformsNeedsUpdate = true; } vertexCount = instanceCount; vertexBuffer = instanceBuffer; if (instanceTransformsNeedsUpdate || instanceBuffer.IsContentLost) { instanceTransformsNeedsUpdate = false; var data = instanceTransforms; instanceCount = vertexCount = instanceTransforms.Length; if (ViewDistance.HasValue) { Matrix worldToLocal = AbsoluteTransform; Matrix.Invert(ref worldToLocal, out worldToLocal); Vector3.Transform(ref cameraPosition, ref worldToLocal, out cameraPosition); PopulateVisibleInstances(ref cameraPosition); data = VisibleInstanceTransforms; instanceCount = vertexCount = VisibleInstanceCount; if (instanceCount <= 0) { return; } } instanceBuffer.SetData(data, 0, instanceCount, SetDataOptions.Discard); } }
private static void DrawInstancedTowers(int playerNum, int towerType, int amount) { //int amount = units[playerNum][unitType].Count; if (amount == 0) return; instanceVertexBuffer = null; ///////////////////////////////////////////////////////////////////FIX THIS! // If we have more instances than room in our vertex buffer, grow it to the neccessary size. if ((instanceVertexBuffer == null) || (amount > instanceVertexBuffer.VertexCount)) { if (instanceVertexBuffer != null) instanceVertexBuffer.Dispose(); instanceVertexBuffer = new DynamicVertexBuffer(ScreenManager.Game.GraphicsDevice, instanceVertexDeclaration, amount, BufferUsage.WriteOnly); } // Transfer the latest instance transform matrices into the instanceVertexBuffer. instanceVertexBuffer.SetData(towerTransforms, 0, amount, SetDataOptions.Discard); for (int i = 0; i < instancedModels[towerType][playerNum].Meshes.Count; i++) { for (int j = 0; j < instancedModels[towerType][playerNum].Meshes[i].MeshParts.Count; j++) { // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer. ScreenManager.Game.GraphicsDevice.SetVertexBuffers( new VertexBufferBinding(instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].VertexBuffer, instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].VertexOffset, 0), new VertexBufferBinding(instanceVertexBuffer, 0, 1) ); ScreenManager.Game.GraphicsDevice.Indices = instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].IndexBuffer; // Set up the instance rendering effect. Effect effect = instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].Effect; effect.CurrentTechnique = effect.Techniques["HardwareInstancing"]; effect.Parameters["World"].SetValue(instancedModelBones[towerType][playerNum][instancedModels[towerType][playerNum].Meshes[i].ParentBone.Index]); effect.Parameters["View"].SetValue(cameraManager.ViewMatrix); effect.Parameters["Projection"].SetValue(cameraManager.ProjectionMatrix); // Draw all the instance copies in a single call. for (int k = 0; k < effect.CurrentTechnique.Passes.Count; k++) { effect.CurrentTechnique.Passes[k].Apply(); ScreenManager.Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].NumVertices, instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].StartIndex, instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].PrimitiveCount, amount); } } } }
private void DrawBatch(DrawingContext context, ref PrimitiveGroupEntry entry, Material material) { if (entry.VertexCount <= 0 && entry.IndexCount <= 0) { return; } material.texture = entry.Texture; material.world = entry.World.HasValue ? entry.World.Value * AbsoluteTransform : AbsoluteTransform; material.BeginApply(context); #if !WINDOWS_PHONE if (entry.LineWidth > 0) { if (thickLineMaterial == null) { thickLineMaterial = new ThickLineMaterial(graphics); } thickLineMaterial.Thickness = entry.LineWidth; thickLineMaterial.world = material.world; thickLineMaterial.BeginApply(context); } #endif var vertexBufferSize = vertexSegments[entry.Segment + 1] - vertexSegments[entry.Segment]; #if SILVERLIGHT if (vertexBuffer == null || vertexBuffer.VertexCount < vertexBufferSize) #else if (vertexBuffer == null || vertexBuffer.VertexCount < vertexBufferSize || vertexBuffer.IsContentLost) #endif { if (vertexBuffer != null) { vertexBuffer.Dispose(); } vertexBuffer = new DynamicVertexBuffer(graphics, typeof(VertexPositionColorNormalTexture), Math.Max(initialBufferCapacity, vertexBufferSize), BufferUsage.WriteOnly); } context.SetVertexBuffer(null, 0); vertexBuffer.SetData(vertexData, vertexSegments[entry.Segment], vertexBufferSize, SetDataOptions.Discard); // Previous segments are not used, so use SetDataOption.Discard to boost performance. context.SetVertexBuffer(vertexBuffer, 0); if (entry.IndexCount > 0) { var indexBufferSize = indexSegments[entry.Segment + 1] - indexSegments[entry.Segment]; #if SILVERLIGHT if (indexBuffer == null || indexBuffer.IndexCount < indexBufferSize) #else if (indexBuffer == null || indexBuffer.IndexCount < indexBufferSize || indexBuffer.IsContentLost) #endif { if (indexBuffer != null) { indexBuffer.Dispose(); } indexBuffer = new DynamicIndexBuffer(graphics, IndexElementSize.SixteenBits, Math.Max(initialBufferCapacity, indexBufferSize), BufferUsage.WriteOnly); } graphics.Indices = null; indexBuffer.SetData(indexData, indexSegments[entry.Segment], indexBufferSize, SetDataOptions.Discard); var primitiveCount = Helper.GetPrimitiveCount(entry.PrimitiveType, entry.IndexCount); graphics.Indices = indexBuffer; graphics.DrawIndexedPrimitives(entry.PrimitiveType, 0, entry.StartVertex, entry.VertexCount, entry.StartIndex, primitiveCount); } else { var primitiveCount = Helper.GetPrimitiveCount(entry.PrimitiveType, entry.VertexCount); graphics.DrawPrimitives(entry.PrimitiveType, entry.StartVertex, primitiveCount); } material.EndApply(context); }
private void CalculateLightVertices(List <Vector2> rayCastHits) { List <VertexPositionColorTexture> vertices = new List <VertexPositionColorTexture>(); 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 VertexPositionColorTexture(new Vector3(position.X, position.Y, 0), Color.White, new Vector2(0.5f, 0.5f) + uvOffset)); // 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; 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) * 2.0f; diff += uvOffset; } //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; //finally, create the vertices VertexPositionColorTexture fullVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0), Color.White, new Vector2(0.5f, 0.5f) + diff); VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0), Color.White * 0.0f, new Vector2(0.5f, 0.5f) + diff); vertices.Add(fullVert); vertices.Add(fadeVert); } // Compute the indices to form triangles List <short> indices = new List <short>(); for (int i = 0; i < rayCastHits.Count - 1; i++) { //main light body indices.Add(0); indices.Add((short)((i * 2 + 3) % vertices.Count)); indices.Add((short)((i * 2 + 1) % vertices.Count)); //faded light indices.Add((short)((i * 2 + 1) % vertices.Count)); indices.Add((short)((i * 2 + 3) % vertices.Count)); indices.Add((short)((i * 2 + 4) % vertices.Count)); indices.Add((short)((i * 2 + 2) % vertices.Count)); indices.Add((short)((i * 2 + 1) % vertices.Count)); indices.Add((short)((i * 2 + 4) % vertices.Count)); } //main light body indices.Add(0); indices.Add((short)(1)); indices.Add((short)(vertices.Count - 2)); //faded light indices.Add((short)(1)); indices.Add((short)(vertices.Count - 1)); indices.Add((short)(vertices.Count - 2)); indices.Add((short)(1)); indices.Add((short)(2)); 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, 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.ToArray()); lightVolumeIndexBuffer.SetData <short>(indices.ToArray()); }
public virtual void Draw(GameTime gameTime, Effect thisEffect) { if (instanceTransformMatrices.Count == 0) { return; } // If we have more instances than room in our vertex buffer, grow it to the neccessary size. if ((instanceVertexBuffer == null) || (instanceTransformMatrices.Count > instanceVertexBuffer.VertexCount)) { if (instanceVertexBuffer != null) { instanceVertexBuffer.Dispose(); } instanceVertexBuffer = new DynamicVertexBuffer(GraphicsDevice, instanceVertexDeclaration, instanceTransformMatrices.Count, BufferUsage.WriteOnly); } // Transfer the latest instance transform matrices into the instanceVertexBuffer. instanceVertexBuffer.SetData(instanceTransformMatrices.Values.ToArray(), 0, instanceTransformMatrices.Count, SetDataOptions.Discard); bones = animationPlayer.GetSkinTransforms(); if (thisEffect.Parameters["Bones"] != null) { thisEffect.Parameters["Bones"].SetValue(bones); } for (int m = 0; m < thisMesh.Meshes.Count; m++) { int pcnt = 0; for (int mp = 0; mp < thisMesh.Meshes[m].MeshParts.Count; mp++) { if (thisEffect.CurrentTechnique.Name == "ShadowMapH") // Shadow Map { } else { thisEffect.CurrentTechnique = thisEffect.Techniques["BasicTextureH"]; if (thisEffect.Parameters["vp"] != null) { thisEffect.Parameters["vp"].SetValue(Camera.View * Camera.Projection); } if (thisEffect.Parameters["v"] != null) { thisEffect.Parameters["v"].SetValue(Camera.View); } if (thisEffect.Parameters["p"] != null) { thisEffect.Parameters["p"].SetValue(Camera.Projection); } thisEffect.Parameters["color"].SetValue(Color.White.ToVector3()); // Texture if (TextureMaterials.Count > 0 && pcnt < TextureMaterials.Count) { thisEffect.Parameters["textureMat"].SetValue(AssetManager.GetAsset <Texture2D>(TextureMaterials[pcnt])); } else { if (((SkinnedEffect)thisMesh.Meshes[m].MeshParts[mp].Effect).Texture != null) { thisEffect.Parameters["textureMat"].SetValue(((SkinnedEffect)thisMesh.Meshes[m].MeshParts[mp].Effect).Texture); } else { thisEffect.Parameters["textureMat"].SetValue(blank); } } // Normals if (NormalMaterials.Count > 0 && pcnt < NormalMaterials.Count) { thisEffect.Parameters["BumpMap"].SetValue(AssetManager.GetAsset <Texture2D>(NormalMaterials[pcnt])); } else { thisEffect.Parameters["BumpMap"].SetValue(blank); } // Specula if (SpeculaMaterials.Count > 0 && pcnt < SpeculaMaterials.Count) { thisEffect.Parameters["specularMap"].SetValue(AssetManager.GetAsset <Texture2D>(SpeculaMaterials[pcnt])); } else { thisEffect.Parameters["specularMap"].SetValue(blank); } // Glow if (GlowMaterials.Count > 0 && pcnt < GlowMaterials.Count) { thisEffect.Parameters["glowMap"].SetValue(AssetManager.GetAsset <Texture2D>(GlowMaterials[pcnt])); } else { thisEffect.Parameters["glowMap"].SetValue(blank); } // Reflection if (ReflectionMaterials.Count > 0 && pcnt < ReflectionMaterials.Count) { thisEffect.Parameters["reflectionMap"].SetValue(AssetManager.GetAsset <Texture2D>(ReflectionMaterials[pcnt])); } else { thisEffect.Parameters["reflectionMap"].SetValue(blank); } pcnt++; } thisEffect.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.SetVertexBuffers( new VertexBufferBinding(partVertexBuffer[mp], 0, 0), new VertexBufferBinding(instanceVertexBuffer, 0, 1) ); GraphicsDevice.Indices = indexBuffer; Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, partVertexBuffer[mp].VertexCount, 0, partVertexBuffer[mp].VertexCount / 3, instanceTransformMatrices.Count); } } if (RenderBounds) { DrawBounds(); } }
private void DrawInstances() { if (instances.Count == 0) { return; } numPolygons = 0; // Gather instance transform matrices into a single array. Array.Resize(ref instanceVertices, instances.Count); for (int i = 0; i < instances.Count; i++) { instanceVertices[i].Transform = instances[i].Transform; instanceVertices[i].Size = instances[i].Size; instanceVertices[i].Color = instances[i].Color; } // Draw all instances using hardware instancing // If we have more instances than room in our vertex buffer, grow it to the neccessary size. if ((instanceVertexBuffer == null) || (instanceVertices.Length > instanceVertexBuffer.VertexCount)) { if (instanceVertexBuffer != null) { instanceVertexBuffer.Dispose(); } instanceVertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(TowerInstanceVertex), instanceVertices.Length, BufferUsage.WriteOnly); } // Transfer the latest instance transform matrices into the instanceVertexBuffer. instanceVertexBuffer.SetData(instanceVertices, 0, instanceVertices.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(Matrix.Identity); effect.Parameters["View"].SetValue(camera.View); effect.Parameters["Projection"].SetValue(camera.Projection); effect.Parameters["NormalMap"].SetValue(normalMap); effect.Parameters["DiffuseMap"].SetValue(diffuseMap); // 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, instanceVertices.Length); } numPolygons += meshPart.PrimitiveCount * instanceVertices.Length; } } }
static unsafe void RunCompute(Sample sample, bool indirectSupported) { // build vertex layouts var quadLayout = new VertexLayout(); quadLayout.Begin() .Add(VertexAttributeUsage.Position, 2, VertexAttributeType.Float) .End(); var computeLayout = new VertexLayout(); computeLayout.Begin() .Add(VertexAttributeUsage.TexCoord0, 4, VertexAttributeType.Float) .End(); // static quad data var vb = new VertexBuffer(MemoryBlock.FromArray(QuadVertices), quadLayout); var ib = new IndexBuffer(MemoryBlock.FromArray(QuadIndices)); // create compute buffers var currPositionBuffer0 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); var currPositionBuffer1 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); var prevPositionBuffer0 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); var prevPositionBuffer1 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite); // load shaders var particleProgram = ResourceLoader.LoadProgram("vs_particle", "fs_particle"); var initInstancesProgram = ResourceLoader.LoadProgram("cs_init_instances"); var updateInstancesProgram = ResourceLoader.LoadProgram("cs_update_instances"); // indirect rendering support var indirectProgram = SharpBgfx.Program.Invalid; var indirectBuffer = IndirectBuffer.Invalid; bool useIndirect = false; if (indirectSupported) { indirectProgram = ResourceLoader.LoadProgram("cs_indirect"); indirectBuffer = new IndirectBuffer(2); useIndirect = true; } // setup params uniforms var paramData = new ParamsData { TimeStep = 0.0157f, DispatchSize = 32, Gravity = 0.109f, Damping = 0.25f, ParticleIntensity = 0.64f, ParticleSize = 0.279f, BaseSeed = 57, ParticlePower = 3.5f, InitialSpeed = 3.2f, InitialShape = 1, MaxAccel = 100.0f }; // have the compute shader run initialization var u_params = new Uniform("u_params", UniformType.Vector4, 3); Bgfx.SetUniform(u_params, ¶mData, 3); Bgfx.SetComputeBuffer(0, prevPositionBuffer0, ComputeBufferAccess.Write); Bgfx.SetComputeBuffer(1, currPositionBuffer0, ComputeBufferAccess.Write); Bgfx.Dispatch(0, initInstancesProgram, MaxParticleCount / ThreadGroupUpdateSize); // start the frame clock var clock = new Clock(); clock.Start(); // main loop while (sample.ProcessEvents(ResetFlags.Vsync)) { // tick the clock var elapsed = clock.Frame(); var time = clock.TotalTime(); // write some debug text Bgfx.DebugTextClear(); Bgfx.DebugTextWrite(0, 1, DebugColor.White, DebugColor.Blue, "SharpBgfx/Samples/24-NBody"); Bgfx.DebugTextWrite(0, 2, DebugColor.White, DebugColor.Cyan, "Description: N-body simulation with compute shaders using buffers."); Bgfx.DebugTextWrite(0, 3, DebugColor.White, DebugColor.Cyan, "Frame: {0:F3} ms", elapsed * 1000); // fill the indirect buffer if we're using it if (useIndirect) { Bgfx.SetUniform(u_params, ¶mData, 3); Bgfx.SetComputeBuffer(0, indirectBuffer, ComputeBufferAccess.Write); Bgfx.Dispatch(0, indirectProgram); } // update particle positions Bgfx.SetComputeBuffer(0, prevPositionBuffer0, ComputeBufferAccess.Read); Bgfx.SetComputeBuffer(1, currPositionBuffer0, ComputeBufferAccess.Read); Bgfx.SetComputeBuffer(2, prevPositionBuffer1, ComputeBufferAccess.Write); Bgfx.SetComputeBuffer(3, currPositionBuffer1, ComputeBufferAccess.Write); Bgfx.SetUniform(u_params, ¶mData, 3); if (useIndirect) { Bgfx.Dispatch(0, updateInstancesProgram, indirectBuffer, 1); } else { Bgfx.Dispatch(0, updateInstancesProgram, paramData.DispatchSize); } // ping-pong the buffers for next frame Swap(ref currPositionBuffer0, ref currPositionBuffer1); Swap(ref prevPositionBuffer0, ref prevPositionBuffer1); // view transforms for particle rendering var viewMatrix = Matrix4x4.CreateLookAt(new Vector3(0.0f, 0.0f, -45.0f), -Vector3.UnitZ, Vector3.UnitY); var projMatrix = Matrix4x4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)sample.WindowWidth / sample.WindowHeight, 0.1f, 10000.0f); Bgfx.SetViewTransform(0, &viewMatrix.M11, &projMatrix.M11); Bgfx.SetViewRect(0, 0, 0, sample.WindowWidth, sample.WindowHeight); // draw the particles Bgfx.SetVertexBuffer(vb); Bgfx.SetIndexBuffer(ib); Bgfx.SetInstanceDataBuffer(currPositionBuffer0, 0, paramData.DispatchSize * ThreadGroupUpdateSize); Bgfx.SetRenderState(RenderState.ColorWrite | RenderState.BlendAdd | RenderState.DepthTestAlways); if (useIndirect) { Bgfx.Submit(0, particleProgram, indirectBuffer); } else { Bgfx.Submit(0, particleProgram); } // done with frame Bgfx.Frame(); } // cleanup if (indirectSupported) { indirectProgram.Dispose(); indirectBuffer.Dispose(); } u_params.Dispose(); currPositionBuffer0.Dispose(); currPositionBuffer1.Dispose(); prevPositionBuffer0.Dispose(); prevPositionBuffer1.Dispose(); updateInstancesProgram.Dispose(); initInstancesProgram.Dispose(); particleProgram.Dispose(); ib.Dispose(); vb.Dispose(); }
public bool Render() { if (Transformations.Length == 0) { return(false); } if ((InstancedVertexBuffer == null) || (Transformations.Length > InstancedVertexBuffer.VertexCount)) { if (InstancedVertexBuffer != null) { InstancedVertexBuffer.Dispose(); InstancedTextureBuffer.Dispose(); } InstancedVertexBuffer = new DynamicVertexBuffer(Device, InstancedVertexDeclaration, Transformations.Length, BufferUsage.WriteOnly); InstancedTextureBuffer = new DynamicVertexBuffer(Device, InstancedTextureIDs, Textures.Length, BufferUsage.WriteOnly); } for (int i = 0; i < Texture2Ds.Length; i++) { Device.Textures[i] = Texture2Ds[i]; } InstancedVertexBuffer.SetData <Matrix>(Transformations, 0, Transformations.Length, SetDataOptions.Discard); InstancedTextureBuffer.SetData <Vector2>(Textures, 0, Textures.Length, SetDataOptions.Discard); foreach (var mesh in Model.Meshes) { foreach (var meshPart in mesh.MeshParts) { Device.SetVertexBuffers( new VertexBufferBinding(meshPart.VertexBuffer, 0, 0), new VertexBufferBinding(InstancedVertexBuffer, 0, 1), new VertexBufferBinding(InstancedTextureBuffer, 0, 1)); Device.Indices = meshPart.IndexBuffer; InstancingShader.CurrentTechnique = InstancingShader.Techniques["HardwareInstancing"]; InstancingShader.Parameters["World"].SetValue(WorldMatrix); InstancingShader.Parameters["View"].SetValue(Camera3D.ViewMatrix); InstancingShader.Parameters["Projection"].SetValue(Camera3D.ProjectionMatrix); InstancingShader.Parameters["EyePosition"].SetValue(Camera3D.CameraPosition); InstancingShader.Parameters["FogEnabled"].SetValue(1.0f); InstancingShader.Parameters["FogColor"].SetValue(Color.CornflowerBlue.ToVector3()); InstancingShader.Parameters["FogStart"].SetValue(0.0f); InstancingShader.Parameters["FogEnd"].SetValue(Camera3D.RenderDistance); foreach (EffectPass pass in InstancingShader.CurrentTechnique.Passes) { pass.Apply(); Device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 1, 0, 12, Transformations.Length); } } } return(true); }
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; }
} // AddParticle #endregion #region Dispose /// <summary> /// Dispose managed resources. /// </summary> protected override void DisposeManagedResources() { vertexBuffer.Dispose(); indexBuffer.Dispose(); } // DisposeManagedResources
public void Dispose() { _effect.Dispose(); _instanceVertexDeclaration.Dispose(); _instanceBuffer.Dispose(); }
public override void DrawDistortion(LinkedList <BasicShipGameObject> ships, Camera3D DrawCamera) { if (ships.Count == 0) { return; } Game1.graphicsDevice.BlendState = BlendState.AlphaBlend; Game1.graphicsDevice.DepthStencilState = DepthStencilState.None; if (!Applied) { ApplyEffectParameters(); } DistortionEffectContainer.ViewParam.SetValue(DrawCamera.ViewMatrix); DistortionEffectContainer.ProjectionParam.SetValue(DrawCamera.ProjectionMatrix); DistortionEffectContainer.WorldParam.SetValue(ModelTransformMatrix); if (!DistortionBufferReady) { DistortionBufferReady = true; Array.Resize(ref DistortionShipVertecies, ships.Count); int i = 0; foreach (BasicShipGameObject s in ships) { DistortionShipVertecies[i].WorldMatrix = s.WorldMatrix; DistortionShipVertecies[i++].color = s.MyColor; } if ((DistortionvertexBuffer == null) || (ships.Count > DistortionvertexBuffer.VertexCount)) { if (DistortionvertexBuffer != null) { DistortionvertexBuffer.Dispose(); } DistortionvertexBuffer = new DynamicVertexBuffer(Game1.graphicsDevice, ShipVertex.shipVertexDeclaration, DistortionShipVertecies.Length, BufferUsage.WriteOnly); } DistortionvertexBuffer.SetData(DistortionShipVertecies, 0, DistortionShipVertecies.Length, SetDataOptions.Discard); } else if (DistortionvertexBuffer.IsContentLost) { DistortionvertexBuffer.SetData(DistortionShipVertecies, 0, DistortionShipVertecies.Length, SetDataOptions.Discard); } foreach (ModelMesh mesh in ShipModel.Meshes) { foreach (ModelMeshPart meshPart in mesh.MeshParts) { Game1.graphicsDevice.SetVertexBuffers( new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0), new VertexBufferBinding(DistortionvertexBuffer, 0, 1) ); Game1.graphicsDevice.Indices = meshPart.IndexBuffer; foreach (EffectPass pass in DistortionEffectContainer.DistortionEffect.CurrentTechnique.Passes) { pass.Apply(); Game1.graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, DistortionShipVertecies.Length); } } } }
protected override void OnDispose() { transformBuffer.Dispose(); colorBuffer.Dispose(); textureCoordBuffer.Dispose(); }
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()); }
protected override void DisposeNative() { nativeVertexBuffer.Dispose(); nativeIndexBuffer.Dispose(); }
public void Dispose() { vertexBuffer.Dispose(); particles = null; }
public void DrawInstanced(Camera3D DrawCamera) { if (BulletCount == 0) { return; } ViewParam.SetValue(DrawCamera.ViewMatrix); ProjectionParam.SetValue(DrawCamera.ProjectionMatrix); WorldParam.SetValue(Matrix.Identity); ShipEffect.CurrentTechnique = ForwardInstancedTechnique; if (!BufferReady) { BufferReady = true; Array.Resize(ref ModelTransforms, Bullets.Count); int i = 0; foreach (Bullet s in Bullets) { ModelTransforms[i++] = s.WorldMatrix; } if ((vertexBuffer == null) || (Bullets.Count > vertexBuffer.VertexCount)) { if (vertexBuffer != null) { vertexBuffer.Dispose(); } vertexBuffer = new DynamicVertexBuffer(Game1.graphicsDevice, instanceVertexDeclaration, ModelTransforms.Length, BufferUsage.WriteOnly); } vertexBuffer.SetData(ModelTransforms, 0, ModelTransforms.Length, SetDataOptions.Discard); } else if (vertexBuffer.IsContentLost) { vertexBuffer.SetData(ModelTransforms, 0, ModelTransforms.Length, SetDataOptions.Discard); } foreach (ModelMesh mesh in BulletModel.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 ShipEffect.CurrentTechnique.Passes) { pass.Apply(); Game1.graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, ModelTransforms.Length); } } } }
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; }
/// <summary> /// Resets the vertex buffer object from the verticies. /// <param Name="device">GPU to draw with.</param></summary> public virtual void ResetBuffer(GraphicsDevice device) { //if(DwarfGame.ExitGame) //{ // return; //} //lock (VertexLock) { if (VertexBuffer != null && !VertexBuffer.IsDisposed) { VertexBuffer.Dispose(); } VertexBuffer = null; if (IndexBuffer != null && !IndexBuffer.IsDisposed) { IndexBuffer.Dispose(); } IndexBuffer = null; if (IndexCount <= 0 && Indexes != null) { IndexCount = Indexes.Length; } if (VertexCount <= 0 && Vertices != null) { VertexCount = Vertices.Length; } if (Vertices != null) { try { DynamicVertexBuffer newBuff = new DynamicVertexBuffer(device, ExtendedVertex.VertexDeclaration, Vertices.Length, BufferUsage.WriteOnly); newBuff.SetData(Vertices, 0, VertexCount); VertexBuffer = newBuff; } catch (Exception exception) { Console.Out.WriteLine(exception.ToString()); VertexBuffer = null; } } if (Indexes != null) { try { DynamicIndexBuffer newIndexBuff = new DynamicIndexBuffer(device, typeof(ushort), Indexes.Length, BufferUsage.None); newIndexBuff.SetData(Indexes, 0, IndexCount); IndexBuffer = newIndexBuff; } catch (Exception exception) { Console.Out.WriteLine(exception.ToString()); IndexBuffer = null; } } } }
protected override void OnDispose() { vertexPositionBuffer.Dispose(); transformBuffer.Dispose(); colorBuffer.Dispose(); }
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(); } } }