我們正在製作一個運行在Xbox 360上的學校的3D遊戲。我們有一個巨大的關卡,它由大約100個零件組成,每個零件由許多網格組成,很多頂點。我們有一個自定義着色器,通過爲你周圍的等級着色,可以在任何時候發出類似ping效果。我們還有一個3D迷你地圖,因爲遊戲在太空中,你可以在任何方向定向。所以當我們繪製關卡時,我們必須每幀繪製4次,一個繪製主視圖端口,一個繪製主視圖端口中的ping,一個繪製迷你地圖中的水平,一個繪製水平在迷你地圖中的ping。它在一臺快速電腦上每秒運行60幀,但在Xbox上只能運行20幀。我們已經關閉了繪製我們背後的東西,你看不到它,它幫助了一些,但我們仍然需要它加快。通過製作一個網格優化繪製3D模型
這裏是只是出了主視口的Ping水平的主要拉...
//draw the main level in a regular way
foreach (LevelObject part in levelData.LevelParts)
{
partBounds.Center = part.position;
if (viewFrustum.Intersects(partBounds))
{
//Rotate X
Matrix worldMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(part.Xrotate));
//Rotate Z
worldMatrix *= Matrix.CreateRotationZ(MathHelper.ToRadians(part.Zrotate));
//Rotate Y
worldMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(part.Yrotate));
worldMatrix *= Matrix.CreateWorld(part.position, Vector3.Forward, Vector3.Up);
Model Object = levelModels[part.modelName];
//set in the gamers viewport
foreach (ModelMesh mesh in Object.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
//effect.EnableDefaultLighting();
effect.LightingEnabled = true;
effect.AmbientLightColor = new Vector3(0.09f, 0.15f, 0.215f);
effect.DirectionalLight0.DiffuseColor = new Vector3(0.3f, 0.3f, 0.3f);
effect.DirectionalLight0.Direction = viewMatrix.Forward;
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight1.DiffuseColor = new Vector3(0.05f, 0.085f, 0.25f);
effect.DirectionalLight1.Direction = viewMatrix.Down;
effect.DirectionalLight1.Enabled = true;
effect.PreferPerPixelLighting = true;
effect.World = worldMatrix;
effect.View = viewMatrix;
effect.Projection = projectionMatrix;
mesh.Draw();
}
}
}
}
所以,如果在攪拌機我做的水平部分只是一個目那就要少做循環,我不確定這是否會讓它畫得更快。我需要提高繪畫性能的任何想法嗎?這款遊戲是分屏式的,最多可以有4名玩家,這會使等級提高4倍。
以下是完整的繪製函數
public override void Draw(GameTime gameTime)
{
/* NORMAL VIEW */
//set viewport for everyone
for (int i = 0; i < SignedInGamer.SignedInGamers.Count; i++)
{
GraphicsDevice.Viewport = Camera.gameScreenViewPorts[SignedInGamer.SignedInGamers[i]];
Matrix viewMatrix = Camera.viewMatrix[SignedInGamer.SignedInGamers[i]];
Matrix projectionMatrix = Camera.projectionMatrix[SignedInGamer.SignedInGamers[i]];
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
GraphicsDevice.BlendState = BlendState.Opaque;
//view frustrum object for culling
BoundingFrustum viewFrustum = new BoundingFrustum(viewMatrix * projectionMatrix);
BoundingSphere partBounds = new BoundingSphere();
partBounds.Radius = levelData.scale;
//draw the main level in a regular way
foreach (LevelObject part in levelData.LevelParts)
{
partBounds.Center = part.position;
if (viewFrustum.Intersects(partBounds))
{
//Rotate X
Matrix worldMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(part.Xrotate));
//Rotate Z
worldMatrix *= Matrix.CreateRotationZ(MathHelper.ToRadians(part.Zrotate));
//Rotate Y
worldMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(part.Yrotate));
worldMatrix *= Matrix.CreateWorld(part.position, Vector3.Forward, Vector3.Up);
Model Object = levelModels[part.modelName];
//set in the gamers viewport
foreach (ModelMesh mesh in Object.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
//effect.EnableDefaultLighting();
effect.LightingEnabled = true;
effect.AmbientLightColor = new Vector3(0.09f, 0.15f, 0.215f);
effect.DirectionalLight0.DiffuseColor = new Vector3(0.3f, 0.3f, 0.3f);
effect.DirectionalLight0.Direction = viewMatrix.Forward;
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight1.DiffuseColor = new Vector3(0.05f, 0.085f, 0.25f);
effect.DirectionalLight1.Direction = viewMatrix.Down;
effect.DirectionalLight1.Enabled = true;
effect.PreferPerPixelLighting = true;
effect.World = worldMatrix;
effect.View = viewMatrix;
effect.Projection = projectionMatrix;
mesh.Draw();
}
}
}
}
/* PING VIEW */
List<Vector3> pingPos = new List<Vector3>();
List<Vector4> pingColor = new List<Vector4>();
List<float> pingRange = new List<float>();
for (int a = 0; a < Game.Components.Count; a++)
{
if (Game.Components[a] is Ship)
{
pingPos.Add(((Ship)Game.Components[a]).worldMatrix.Translation);
pingColor.Add(new Vector4(
((Ship)Game.Components[a]).playerColor.R,
((Ship)Game.Components[a]).playerColor.G,
((Ship)Game.Components[a]).playerColor.B,
1));
pingRange.Add(((Ship)Game.Components[a]).pingRange * (levelData.scale * 2.0f));
}
}
if (pingPos.Count() > 0)
{
//apply ping lighting stuffs here
pingTest.Parameters["PingPos"].SetValue(pingPos.ToArray());
pingTest.Parameters["PingPosCount"].SetValue(pingPos.Count());
pingTest.Parameters["PingColor"].SetValue(pingColor.ToArray());
pingTest.Parameters["PingColorCount"].SetValue(pingColor.Count());
pingTest.Parameters["PingRange"].SetValue(pingRange.ToArray());
pingTest.Parameters["PingRangeCount"].SetValue(pingRange.Count());
}
foreach (LevelObject part in levelData.LevelParts)
{
partBounds.Center = part.position;
if (viewFrustum.Intersects(partBounds))
{
//Rotate X
Matrix worldMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(part.Xrotate));
//Rotate Z
worldMatrix *= Matrix.CreateRotationZ(MathHelper.ToRadians(part.Zrotate));
//Rotate Y
worldMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(part.Yrotate));
worldMatrix *= Matrix.CreateWorld(part.position, Vector3.Forward, Vector3.Up);
Model Object = levelModels[part.modelName];
foreach (ModelMesh mesh in Object.Meshes)
{
//ok, this is going to be kind of weird, and there's got to be a cleaner
//or better way to do this.
List<Effect> backup = new List<Effect>();
foreach (ModelMeshPart meshpart in mesh.MeshParts)
{
backup.Add(meshpart.Effect);
meshpart.Effect = pingTest;
meshpart.Effect.Parameters["World"].SetValue(worldMatrix * mesh.ParentBone.Transform);
meshpart.Effect.Parameters["View"].SetValue(viewMatrix);
meshpart.Effect.Parameters["Projection"].SetValue(projectionMatrix);
//Matrix worldInverseTransposeMatrix = Matrix.Transpose(Matrix.Invert(mesh.ParentBone.Transform * world));
//pingTest.Parameters["WorldInverseTranspose"].SetValue(worldInverseTransposeMatrix);
}
mesh.Draw();
//reset the basic effect crap
foreach (ModelMeshPart meshpart in mesh.MeshParts)
{
meshpart.Effect = backup.First();
backup.RemoveAt(0);
}
//
}
}
}
//Undo the weird things this shader does
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
/* MINIMAP VIEW */
GraphicsDevice.Viewport = Camera.mapViewports[SignedInGamer.SignedInGamers[i]];
viewMatrix = Camera.mapViewMatrix[SignedInGamer.SignedInGamers[i]];
projectionMatrix = Camera.mapProjectionMatrix[SignedInGamer.SignedInGamers[i]];
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
GraphicsDevice.BlendState = BlendState.Opaque;
//view frustum for the map
BoundingFrustum mapFrustum = new BoundingFrustum(viewMatrix * projectionMatrix);
//draw the main level in a regular way
foreach (LevelObject part in levelData.LevelParts)
{
partBounds.Center = part.position;
if (mapFrustum.Intersects(partBounds))
{
//Rotate X
Matrix worldMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(part.Xrotate));
//Rotate Z
worldMatrix *= Matrix.CreateRotationZ(MathHelper.ToRadians(part.Zrotate));
//Rotate Y
worldMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(part.Yrotate));
worldMatrix *= Matrix.CreateWorld(part.position, Vector3.Forward, Vector3.Up);
Model Object = levelModels[part.modelName];
//set in the gamers viewport
foreach (ModelMesh mesh in Object.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
//effect.EnableDefaultLighting();
effect.LightingEnabled = true;
if (match(part.position/15.0f))
effect.AmbientLightColor = new Vector3(1.0f, 0.30f, 0.43f);
else
effect.AmbientLightColor = new Vector3(0.18f, 0.30f, 0.43f);
//effect.DirectionalLight0.DiffuseColor = new Vector3(0.6f, 0.6f, 0.6f);
effect.DirectionalLight0.DiffuseColor = new Vector3(0.6f, 0.6f, 0.6f);
effect.DirectionalLight0.Direction = viewMatrix.Forward;
effect.DirectionalLight0.Enabled = true;
//effect.DirectionalLight1.DiffuseColor = new Vector3(0.1f, 0.17f, 0.5f);
effect.DirectionalLight1.DiffuseColor = new Vector3(0.1f, 0.17f, 0.5f);
effect.DirectionalLight1.Direction = viewMatrix.Down;
effect.DirectionalLight1.Enabled = true;
effect.PreferPerPixelLighting = true;
effect.World = worldMatrix;
effect.View = viewMatrix;
effect.Projection = projectionMatrix;
mesh.Draw();
}
}
}
}
base.Draw(gameTime);
return;
if (pingPos.Count() > 0)
{
//apply ping lighting stuffs here
pingTest.Parameters["PingPos"].SetValue(pingPos.ToArray());
pingTest.Parameters["PingPosCount"].SetValue(pingPos.Count());
pingTest.Parameters["PingColor"].SetValue(pingColor.ToArray());
pingTest.Parameters["PingColorCount"].SetValue(pingColor.Count());
pingTest.Parameters["PingRange"].SetValue(pingRange.ToArray());
pingTest.Parameters["PingRangeCount"].SetValue(pingRange.Count());
}
foreach (LevelObject part in levelData.LevelParts)
{
partBounds.Center = part.position;
if (mapFrustum.Intersects(partBounds))
{
//Rotate X
Matrix worldMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(part.Xrotate));
//Rotate Z
worldMatrix *= Matrix.CreateRotationZ(MathHelper.ToRadians(part.Zrotate));
//Rotate Y
worldMatrix *= Matrix.CreateRotationY(MathHelper.ToRadians(part.Yrotate));
worldMatrix *= Matrix.CreateWorld(part.position, Vector3.Forward, Vector3.Up);
Model Object = levelModels[part.modelName];
foreach (ModelMesh mesh in Object.Meshes)
{
//ok, this is going to be kind of weird, and there's got to be a cleaner
//or better way to do this.
List<Effect> backup = new List<Effect>();
foreach (ModelMeshPart meshpart in mesh.MeshParts)
{
backup.Add(meshpart.Effect);
meshpart.Effect = pingTest;
meshpart.Effect.Parameters["World"].SetValue(worldMatrix * mesh.ParentBone.Transform);
meshpart.Effect.Parameters["View"].SetValue(viewMatrix);
meshpart.Effect.Parameters["Projection"].SetValue(projectionMatrix);
//Matrix worldInverseTransposeMatrix = Matrix.Transpose(Matrix.Invert(mesh.ParentBone.Transform * world));
//pingTest.Parameters["WorldInverseTranspose"].SetValue(worldInverseTransposeMatrix);
}
mesh.Draw();
//reset the basic effect crap
foreach (ModelMeshPart meshpart in mesh.MeshParts)
{
meshpart.Effect = backup.First();
backup.RemoveAt(0);
}
//*/
}
}
}
//}
//Undo the weird things this shader does
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
base.Draw(gameTime);
}
}
關於該垃圾收集
因此,通過使用這種方法設置載體像effect.DirectionalLight0.DiffuseColor ...
effect.DirectionalLight0.DiffuseColor.X = 0.3f;
effect.DirectionalLight0.DiffuseColor.Y = 0.3f;
effect.DirectionalLight0.DiffuseColor.Z = 0.3f;
而不是這種方法....
effect.DirectionalLight0.DiffuseColor = new Vector3(.3, .3, .3);
我分配較少的內存垃圾收集回暖,但一旦Draw()函數完成被稱爲不將其添加所有的垃圾堆放,以便收集器可以把它撿起來幾乎瞬間?我意識到它爲收藏家增加了一些額外的工作,但它不應該增加那麼多的權利?
使用在未還原的地圖-主? – 2011-05-09 05:14:41