Visual studio 2010 在XNA 4.0中,以给定点为半径着色地形模型
我正在VisualStudio2010中使用XNA4.0框架编写一个游戏。我有一个从高度图生成的三维地形模型。我试图实现的是在给定半径内围绕某个点着色此模型,最终目标是向玩家显示单位在给定回合中可以移动的半径。目前我用于绘制模型的方法如下:Visual studio 2010 在XNA 4.0中,以给定点为半径着色地形模型,visual-studio-2010,3d,xna,xna-4.0,3d-model,Visual Studio 2010,3d,Xna,Xna 4.0,3d Model,我正在VisualStudio2010中使用XNA4.0框架编写一个游戏。我有一个从高度图生成的三维地形模型。我试图实现的是在给定半径内围绕某个点着色此模型,最终目标是向玩家显示单位在给定回合中可以移动的半径。目前我用于绘制模型的方法如下: void DrawModel(Model model, Matrix worldMatrix) { Matrix[] boneTransforms = new Matrix[model.Bones.Count]; mo
void DrawModel(Model model, Matrix worldMatrix)
{
Matrix[] boneTransforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(boneTransforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = boneTransforms[mesh.ParentBone.Index] * worldMatrix;
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.EnableDefaultLighting();
effect.EmissiveColor = Color.Green.ToVector3();
effect.PreferPerPixelLighting = true;
// Set the fog to match the black background color
effect.FogEnabled = true;
effect.FogColor = Color.CornflowerBlue.ToVector3();
effect.FogStart = 1000;
effect.FogEnd = 3200;
}
mesh.Draw();
}
}
此外,如果相关的话,我按照本教程创建了我的高度地图和地形
提前感谢您的帮助 您正在寻找的技术称为贴花 您必须提取将绘制圆的地形部分,对该部分应用适当的纹理,并将其与地形混合绘制 对于基于统一栅格的地形,如下所示: 您有贴花的中心位置及其半径。然后可以确定栅格中的最小和最大行/列,以便单元格包含每个绘制的区域。从这些顶点创建新的顶点缓冲区。可以从高度图中读取位置。您必须更改纹理坐标,以便将纹理放置在正确的位置。假设中心位置有坐标
(0.5,0.5)
,中心位置+(半径,半径)有坐标(1,1)
,依此类推。有了它,您应该能够找到每个顶点的纹理坐标方程
在上面的示例中,左上角的红色顶点的纹理坐标约为(-0.12,-0.05)
然后是地形的子网格。对其应用贴图纹理。设置适当的深度偏差(您必须尝试一些值)。在大多数情况下,负斜率CaledepthBias将起作用。在采样器中禁用纹理坐标换行。绘制子网格
下面是我为此编写的一些VB SlimDX代码:
Public Sub Init()
Verts = (Math.Ceiling(2 * Radius / TriAngleWidth) + 2) ^ 2
Tris = (Math.Ceiling(2 * Radius / TriAngleWidth) + 1) ^ 2 * 2
Dim Indices(Tris * 3 - 1) As Integer
Dim curN As Integer
Dim w As Integer
w = (Math.Ceiling(2 * Radius / TriAngleWidth) + 2)
For y As Integer = 0 To w - 2
For x As Integer = 0 To w - 2
Indices(curN) = x + y * w : curN += 1
Indices(curN) = x + (y + 1) * w : curN += 1
Indices(curN) = (x + 1) + (y) * w : curN += 1
Indices(curN) = x + (y + 1) * w : curN += 1
Indices(curN) = (x + 1) + (y + 1) * w : curN += 1
Indices(curN) = (x + 1) + y * w : curN += 1
Next
Next
VB = New Buffer(D3DDevice, New BufferDescription(Verts * VertexPosTexColor.Struct.SizeOfBytes, ResourceUsage.Dynamic, BindFlags.VertexBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, VertexPosTexColor.Struct.SizeOfBytes))
IB = New Buffer(D3DDevice, New DataStream(Indices, False, False), New BufferDescription(4 * Tris * 3, ResourceUsage.Default, BindFlags.IndexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 4))
End Sub
Public Sub Update()
Dim Vertex(Verts - 1) As VertexPosTexColor.Struct
Dim curN As Integer
Dim rad As Single 'The decal radius
Dim height As Single
Dim p As Vector2
Dim yx, yz As Integer
Dim t As Vector2 'texture coordinates
Dim center As Vector2 'decal center
For y As Integer = Math.Floor((center.Y - rad) / TriAngleWidth) To Math.Floor((center.Y - rad) / TriAngleWidth) + Math.Ceiling(2 * rad / TriAngleWidth) + 1
For x As Integer = Math.Floor((center.X - rad) / TriAngleWidth) To Math.Floor((center.X - rad) / TriAngleWidth) + Math.Ceiling(2 * rad / TriAngleWidth) + 1
p.X = x * TriAngleWidth
p.Y = y * TriAngleWidth
yx = x : yz = y
If yx < 0 Then yx = 0
If yx > HeightMap.GetUpperBound(0) Then yx = HeightMap.GetUpperBound(0)
If yz < 0 Then yz = 0
If yz > HeightMap.GetUpperBound(1) Then yz = HeightMap.GetUpperBound(1)
height = HeightMap(yx, yz)
t.X = (p.X - center.X) / (2 * rad) + 0.5
t.Y = (p.Y - center.Y) / (2 * rad) + 0.5
Vertex(curN) = New VertexPosTexColor.Struct With {.Position = New Vector3(p.X, hoehe, p.Y), .TexCoord = t, .Color = New Color4(1, 1, 1, 1)} : curN += 1
Next
Next
Dim data = D3DContext.MapSubresource(VB, MapMode.WriteDiscard, MapFlags.None)
data.Data.WriteRange(Vertex)
D3DContext.UnmapSubresource(VB, 0)
End Sub
Public Sub Init()
顶点=(数学天花板(2*半径/三角形宽度)+2)^2
Tris=(数学天花板(2*半径/三角形宽度)+1)^2*2
作为整数的Dim索引(Tris*3-1)
作为整数的Dim curN
作为整数的Dim w
w=(数学天花板(2*半径/三角形宽度)+2)
对于y,作为整数=0到w-2
对于x作为整数=0到w-2
指数(curN)=x+y*w:curN+=1
指数(curN)=x+(y+1)*w:curN+=1
指数(curN)=(x+1)+(y)*w:curN+=1
指数(curN)=x+(y+1)*w:curN+=1
指数(curN)=(x+1)+(y+1)*w:curN+=1
指数(curN)=(x+1)+y*w:curN+=1
下一个
下一个
VB=新缓冲区(D3DDevice,新缓冲区描述(Verts*VertexoColor.Struct.SizeOfBytes,ResourceUsage.Dynamic,BindFlags.VertexBuffer,CpuAccessFlags.Write,ResourceOptionFlags.None,VertexoColor.Struct.SizeOfBytes))
IB=新缓冲区(D3DDevice,新数据流(索引,False,False),新缓冲区描述(4*Tris*3,ResourceUsage.Default,BindFlags.IndexBuffer,CpuAccessFlags.None,ResourceOptionFlags.None,4))
端接头
公共子更新()
将顶点(顶点-1)调暗为VertexColor.Struct
作为整数的Dim curN
将rad调暗为单个“贴花半径”
低矮如单身
将p作为向量2
Dim yx,yz为整数
将t设置为矢量2'纹理坐标
将中心调暗为Vector2'贴花中心
对于y作为整数=数学地板((center.y-rad)/TriAngleWidth)到数学地板((center.y-rad)/TriAngleWidth)+数学天花板(2*rad/TriAngleWidth)+1
对于x作为整数=数学地板((center.x-rad)/TriAngleWidth)到数学地板((center.x-rad)/TriAngleWidth)+数学天花板(2*rad/TriAngleWidth)+1
p、 X=X*三角形宽度
p、 Y=Y*三角形宽度
yx=x:yz=y
如果yx<0,则yx=0
如果yx>HeightMap.GetUpperBound(0),则yx=HeightMap.GetUpperBound(0)
如果yz<0,则yz=0
如果yz>HeightMap.GetUpperBound(1),则yz=HeightMap.GetUpperBound(1)
高度=高度图(yx,yz)
t、 X=(p.X-center.X)/(2*rad)+0.5
t、 Y=(p.Y-center.Y)/(2*rad)+0.5
顶点(curN)=新的Vertexocolor.Struct,带有{.Position=New Vector3(p.X,hoehe,p.Y),.TexCoord=t,.Color=New Color4(1,1,1,1)}:curN+=1
下一个
下一个
Dim data=D3DContext.MapSubresource(VB,MapMode.WriteDiscard,MapFlags.None)
data.data.WriteRange(顶点)
D3DContext.UnmasupbreSource(VB,0)
端接头
这是相应的C代码
public void Init()
{
顶点=数学功率(数学天花板(2*半径/三角形宽度)+2,2);
Tris=数学功率(数学天花板(2*半径/三角形宽度)+1,2)*2;
int[]索引=新的int[Tris*3];
int curN;
int w;
w=(数学天花板(2*半径/三角形宽度)+2);
对于(int y=0;y,您可以使用着色器来实现这一点
只需将圆心和半径的世界位置作为参数传递,
让像素着色器接收从顶点着色器插值的像素世界位置作为纹理坐标。。。
然后只需检查像素位置到中心的距离,如果像素位置在范围内,则用颜色将其着色…好的,我已经四处寻找如何实现这种技术,但我没有找到好的资源。你能建议一种方法来实现这一点或实现这一目的的资源吗?谢谢,真的很难找到关于这一点,我为你使用常规网格的情况添加了解释。希望有帮助。我支持你创建VertexBuffer,我假设它填充了整个高度图上每个顶点的矢量,对吗?之后你就失去了我X)如何访问模型的纹理坐标?很抱歉,我是3D领域的初学者。另外,我不懂VB,我正在使用c#atm。谢谢你的耐心,你帮了我很大的忙
public void Init()
{
Verts = Math.Pow(Math.Ceiling(2 * Radius / TriAngleWidth) + 2, 2);
Tris = Math.Pow(Math.Ceiling(2 * Radius / TriAngleWidth) + 1, 2) * 2;
int[] Indices = new int[Tris * 3];
int curN;
int w;
w = (Math.Ceiling(2 * Radius / TriAngleWidth) + 2);
for(int y = 0; y <= w - 2; ++y)
{
for(int x = 0; x <= w - 2; ++x)
{
Indices[curN] = x + y * w ; curN += 1;
Indices[curN] = x + (y + 1) * w ; curN += 1;
Indices[curN] = (x + 1) + (y) * w ; curN += 1;
Indices[curN] = x + (y + 1) * w ; curN += 1;
Indices[curN] = (x + 1) + (y + 1) * w ; curN += 1;
Indices[curN] = (x + 1) + y * w ; curN += 1;
}
}
VB = new Buffer(D3DDevice, new BufferDescription(Verts * VertexPosTexColor.Struct.SizeOfBytes, ResourceUsage.Dynamic, BindFlags.VertexBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, VertexPosTexColor.Struct.SizeOfBytes));
IB = new Buffer(D3DDevice, new DataStream(Indices, False, False), new BufferDescription(4 * Tris * 3, ResourceUsage.Default, BindFlags.IndexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 4));
}
public void Update()
{
VertexPosTexColor.Struct[] Vertex = new VertexPosTexColor.Struct[Verts] ;
int curN;
float rad; //The decal radius
float height;
Vector2 p;
int yx, yz;
Vector2 t; //texture coordinates
Vector2 center; //decal center
for(int y = Math.Floor((center.Y - rad) / TriAngleWidth); y <= Math.Floor((center.Y - rad) / TriAngleWidth) + Math.Ceiling(2 * rad / TriAngleWidth) + 1; ++y)
for(int x = Math.Floor((center.X - rad) / TriAngleWidth); x <= Math.Floor((center.X - rad) / TriAngleWidth) + Math.Ceiling(2 * rad / TriAngleWidth) + 1; ++x)
{
p.X = x * TriAngleWidth;
p.Y = y * TriAngleWidth;
yx = x ; yz = y;
if( yx < 0)
yx = 0;
if (yx > HeightMap.GetUpperBound(0))
yx = HeightMap.GetUpperBound(0);
if (yz < 0)
yz = 0;
if (yz > HeightMap.GetUpperBound(1))
yz = HeightMap.GetUpperBound(1);
height = HeightMap[yx, yz];
t.X = (p.X - center.X) / (2 * rad) + 0.5;
t.Y = (p.Y - center.Y) / (2 * rad) + 0.5;
Vertex[curN] = new VertexPosTexColor.Struct() {Position = new Vector3(p.X, hoehe, p.Y), TexCoord = t, Color = New Color4(1, 1, 1, 1)}; curN += 1;
}
}
var data = D3DContext.MapSubresource(VB, MapMode.WriteDiscard, MapFlags.None);
data.Data.WriteRange(Vertex);
D3DContext.UnmapSubresource(VB, 0);
}