你正在寻找被称为贴花的技术。
你要提取的地形,在这里圆将绘制的部分,应用适当的纹理那部分并绘制它与地形共混。
对于基于一个统一的网格地形的情况下,这将如下所示:
你有贴花和其半径的中心位置。然后,您可以确定网格中的最小和最大行/列,以便单元格包含每个绘制的区域。从这些顶点创建一个新的顶点缓冲区。位置可以从高度图中读取。你必须改变纹理坐标,所以纹理将被放置在正确的位置。假定的中心位置具有坐标(0.5, 0.5)
,中心位置+(半径,半径)已经坐标(1, 1)
等。有了这个,你应该能够找到每个顶点纹理坐标的方程。
在上面的例子中,左上角红色的顶点约为(-0.12, -0.05)
纹理坐标然后你有地形的亚格子。将贴花纹理应用于它。设置适当的深度偏差(您必须尝试一些值)。在大多数情况下,负SlopeScaleDepthBias将起作用。关闭采样器中的纹理坐标环绕。绘制子网格。
这里的一些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
而这里的根据C#代码。
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);
}
我以前没有使用着色器。你能通过传递像素着色器来说明你的意思吗?着色器是一个对象吗?谢谢 – Dangerbunny 2012-08-09 00:56:25
着色器是在GPU中执行的代码,并与效果相关联,您可以编写自己的效果...虽然您应该先学习着色器基础知识,但您可以在此处找到关于着色器的一些信息,由我自己http://stackoverflow.com/questions/8000164/how-to-draw-a-circle-on-3d-terrain-in-xna – Blau 2012-08-09 10:30:30
这完美的作品,谢谢你!我也不敢相信我没有看到其他帖子,这几乎是我的问题X) – Dangerbunny 2012-08-09 21:02:35