你正在尋找被稱爲貼花的技術。
你要提取的地形,在這裏圓將繪製的部分,應用適當的紋理那部分並繪製它與地形共混。
對於基於一個統一的網格地形的情況下,這將如下所示:
你有貼花和其半徑的中心位置。然後,您可以確定網格中的最小和最大行/列,以便單元格包含每個繪製的區域。從這些頂點創建一個新的頂點緩衝區。位置可以從高度圖中讀取。你必須改變紋理座標,所以紋理將被放置在正確的位置。假定的中心位置具有座標(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