问题描述
好的,大概有24个小时了,我已经浏览了许多有关XNA 4中纹理地形的网站和教程.我相信我已经很接近我的解决方案了,但是我想我终于找到了墙.我大部分时间都在使用Riemers XNA教程,现在让我发布一些代码,以便大家知道我在做什么:
这是完成所有操作的方法(除了绘制):
私有 无效 LoadVertices() { VertexPositionNormalTexture [] terrainVertices = SetUpTerrainVertices(); int [] terrainIndices = SetUpTerrainIndices(); terrainVertices = CalculateNormals(terrainVertices,terrainIndices); CopyToTerrainBuffers(terrainVertices,terrainIndices); }
现在是方法"SetUpTerrainVerticies":
私有 VertexPositionNormalTexture [] SetUpTerrainVertices() { VertexPositionNormalTexture [] terrainVertices = 新 VertexPositionNormalTexture [terrainWidth * terrainHeight]; for ( int x = 0 ; x < terrainWidth; x ++) { for ( int y = 0 ; y < terrainHeight; y ++) { 位置= 新 Vector3(x,heightData [x,y],-y); terrainVertices [x + y * terrainWidth] .TextureCoordinate.X =( float )x/ 30 .0f; terrainVertices [x + y * terrainWidth] .TextureCoordinate.Y =( float )y/ 30 .0f; } } 返回 terrainVertices; }
和SetUpTerrainIndicies():
私有 int [] SetUpTerrainIndices() { int []索引= 新 int [ (terrainWidth- 1 )*(terrainHeight- 1 )* 6 ]; int 计数器= 0 ; for ( int y = 0 ; y < terrainHeight- 1 ; y ++) { for ( int x = 0 ; x < terrainWidth- 1 ; x ++) { int lowerLeft = x + y * terrainWidth; int lowerRight =(x + 1 )+ y * terrainWidth; int topLeft = x +(y + 1 )* terrainWidth; int topRight =(x + 1 )+(y + 1 )* terrainWidth; index [counter ++] = topLeft; index [counter ++] = lowerRight; index [counter ++] = lowerLeft; index [counter ++] = topLeft; index [counter ++] = topRight; index [counter ++] = lowerRight; } } 返回索引; }
CalculateNormals():
private VertexPositionNormalTexture[] CalculateNormals(VertexPositionNormalTexture[] vertices, int[] indices) { for (int i = 0; i < vertices.Length; i++) vertices[i].Normal = new Vector3(0, 0, 0); for (int i = 0; i < indices.Length / 3; i++) { int index1 = indices[i * 3]; int index2 = indices[i * 3 + 1]; int index3 = indices[i * 3 + 2]; Vector3 side1 = vertices[index1].Position - vertices[index3].Position; Vector3 side2 = vertices[index1].Position - vertices[index2].Position; Vector3 normal = Vector3.Cross(side1, side2); vertices[index1].Normal += normal; vertices[index2].Normal += normal; vertices[index3].Normal += normal; } for (int i = 0; i < vertices.Length; i++) vertices[i].Normal.Normalize(); return vertices; }
最后,CopyToTerrainBuffers():
私有 void CopyToTerrainBuffers(VertexPositionNormalTexture []顶点, int []索引) { terrainVertexBuffer = 新 VertexBuffer(设备, typeof (VertexPositionNormalTexture),vertices.Length,BufferUsage.WriteOnly); terrainVertexBuffer.SetData(vertices); terrainIndexBuffer = 新 IndexBuffer(设备, typeof ( int ),indexs.Length,BufferUsage.WriteOnly); terrainIndexBuffer.SetData(indices); }
至于.fx文件本身,我不认为这是问题所在,因为除了显示纹理之外,我还可以执行所有操作.
现在这里也是绘图代码:
myEffect.Parameters["xView"].SetValue(camera.viewMatrix); myEffect.Parameters["xProjection"].SetValue(camera.projectionMatrix); myEffect.Parameters["xWorld"].SetValue(mapMatrix); myEffect.Parameters["xEnableLighting"].SetValue(true); Vector3 lightDirection = new Vector3(1.0f, -1.0f, -1.0f); lightDirection.Normalize(); myEffect.Parameters["xLightDirection"].SetValue(lightDirection); myEffect.Parameters["xAmbient"].SetValue(0.1f); myEffect.CurrentTechnique = myEffect.Techniques["Textured"]; myEffect.Parameters["xTexture"].SetValue(grassTexture); foreach (EffectPass pass in myEffect.CurrentTechnique.Passes) { pass.Apply(); device.SetVertexBuffer(terrainVertexBuffer); device.Indices = terrainIndexBuffer; int noVertices = terrainVertexBuffer.VertexCount; int noTriangles = terrainIndexBuffer.IndexCount / sizeof(int) / 3; device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, noVertices, 0, noTriangles); }
当我运行此程序时,我看到的只是一个黑屏.如果我绘制的没有纹理(仅彩色),则可以正常工作,并且我看到的地图是白色的,就像我告诉过的那样.
感谢您的任何帮助,我濒临简单地复制并粘贴其他人的示例项目,然后在不知道其工作原理的基础上构建>.<< br mode ="hold"/> ;
提前非常感谢您,我可能在某个地方犯了一个愚蠢的错误.我几天前才刚刚开始XNA 3D编程,所以我不会感到惊讶:这个问题真是愚蠢(正如我所假设的).我没有将地图放在屏幕上,无法让我的相机看到>.<< br mode ="hold"/>
我通过在执行所有纹理渲染之前添加以下行来解决我的问题:
mapMatrix = Matrix.CreateTranslation(-terrainWidth / 2.0f, 0, terrainLength / 2.0f);
感谢所有花时间阅读我的帖子的人:P
Okay guys for probably 24 hours now I''ve been going through numerous websites and tutorials on textured terrain in XNA 4. I believe I''ve gotten pretty close to my solution however I think I''ve finally hit a wall. I''ve been using Riemers XNA tutorials for the most part, now let me post a bit of code so you guys can see what I''m doing:
Here''s the method that does it all (besides draw):
private void LoadVertices() { VertexPositionNormalTexture[] terrainVertices = SetUpTerrainVertices(); int[] terrainIndices = SetUpTerrainIndices(); terrainVertices = CalculateNormals(terrainVertices, terrainIndices); CopyToTerrainBuffers(terrainVertices, terrainIndices); }
Now here''s the method "SetUpTerrainVerticies":
private VertexPositionNormalTexture[] SetUpTerrainVertices() { VertexPositionNormalTexture[] terrainVertices = new VertexPositionNormalTexture[terrainWidth * terrainHeight]; for (int x = 0; x < terrainWidth; x++) { for (int y = 0; y < terrainHeight; y++) { terrainVertices[x + y * terrainWidth].Position = new Vector3(x, heightData[x, y], -y); terrainVertices[x + y * terrainWidth].TextureCoordinate.X = (float)x / 30.0f; terrainVertices[x + y * terrainWidth].TextureCoordinate.Y = (float)y / 30.0f; } } return terrainVertices; }
And SetUpTerrainIndicies():
private int[] SetUpTerrainIndices() { int[] indices = new int[(terrainWidth - 1) * (terrainHeight - 1) * 6]; int counter = 0; for (int y = 0; y < terrainHeight - 1; y++) { for (int x = 0; x < terrainWidth - 1; x++) { int lowerLeft = x + y * terrainWidth; int lowerRight = (x + 1) + y * terrainWidth; int topLeft = x + (y + 1) * terrainWidth; int topRight = (x + 1) + (y + 1) * terrainWidth; indices[counter++] = topLeft; indices[counter++] = lowerRight; indices[counter++] = lowerLeft; indices[counter++] = topLeft; indices[counter++] = topRight; indices[counter++] = lowerRight; } } return indices; }
CalculateNormals():
private VertexPositionNormalTexture[] CalculateNormals(VertexPositionNormalTexture[] vertices, int[] indices) { for (int i = 0; i < vertices.Length; i++) vertices[i].Normal = new Vector3(0, 0, 0); for (int i = 0; i < indices.Length / 3; i++) { int index1 = indices[i * 3]; int index2 = indices[i * 3 + 1]; int index3 = indices[i * 3 + 2]; Vector3 side1 = vertices[index1].Position - vertices[index3].Position; Vector3 side2 = vertices[index1].Position - vertices[index2].Position; Vector3 normal = Vector3.Cross(side1, side2); vertices[index1].Normal += normal; vertices[index2].Normal += normal; vertices[index3].Normal += normal; } for (int i = 0; i < vertices.Length; i++) vertices[i].Normal.Normalize(); return vertices; }
And lastly, CopyToTerrainBuffers():
private void CopyToTerrainBuffers(VertexPositionNormalTexture[] vertices, int[] indices) { terrainVertexBuffer = new VertexBuffer(device, typeof(VertexPositionNormalTexture), vertices.Length, BufferUsage.WriteOnly); terrainVertexBuffer.SetData(vertices); terrainIndexBuffer = new IndexBuffer(device, typeof(int), indices.Length, BufferUsage.WriteOnly); terrainIndexBuffer.SetData(indices); }
As for the .fx file itself, I don''t believe it is the problem because I''m able to do everything besides displaying the texture.
Now here''s the drawing code aswell:
myEffect.Parameters["xView"].SetValue(camera.viewMatrix); myEffect.Parameters["xProjection"].SetValue(camera.projectionMatrix); myEffect.Parameters["xWorld"].SetValue(mapMatrix); myEffect.Parameters["xEnableLighting"].SetValue(true); Vector3 lightDirection = new Vector3(1.0f, -1.0f, -1.0f); lightDirection.Normalize(); myEffect.Parameters["xLightDirection"].SetValue(lightDirection); myEffect.Parameters["xAmbient"].SetValue(0.1f); myEffect.CurrentTechnique = myEffect.Techniques["Textured"]; myEffect.Parameters["xTexture"].SetValue(grassTexture); foreach (EffectPass pass in myEffect.CurrentTechnique.Passes) { pass.Apply(); device.SetVertexBuffer(terrainVertexBuffer); device.Indices = terrainIndexBuffer; int noVertices = terrainVertexBuffer.VertexCount; int noTriangles = terrainIndexBuffer.IndexCount / sizeof(int) / 3; device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, noVertices, 0, noTriangles); }
When I run this all I see is a black screen. If I draw without textures (just colored) it works fine and I see my map colored white like I told it to.
Any help is appreciated, I''m on the verge of simply copy and pasting someone else''s sample project and building on top of that without knowing how it works >.<<br mode="hold" />
Thank you so much in advance, I''m probably making a silly mistake somewhere. I just started XNA 3D programming a couple days ago so I wouldn''t be surprised :P
这篇关于需要帮助使用着色器XNA 4.0显示纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!